ποΈ Collection ManagerΒΆ
π― OverviewΒΆ
The Collection Manager is a powerful component of the API Gateway that enables dynamic creation and management of data structures (collections). Collections are equivalent to database tables, but can be created, modified, and deleted programmatically through the API, eliminating the need for manual database migrations or schema changes.
π PurposeΒΆ
The Collection Manager provides: - Dynamic Schema Creation: Create database tables on-the-fly via API - Automatic REST API Generation: Each collection gets full CRUD endpoints automatically - Field Management: Add, modify, and remove fields from collections - Relationship Management: Define complex relationships between collections - Schema Migration: Automatic database schema synchronization - Type Safety: Strong typing and validation for all fields
ποΈ ArchitectureΒΆ
graph TB
API[API Request]
subgraph "Collection Manager"
CollectionAPI[Collection API]
FieldManager[Field Manager]
SchemaValidator[Schema Validator]
MigrationEngine[Migration Engine]
ResourceGenerator[Resource Generator]
end
subgraph "Generated Resources"
CRUD[CRUD Operations]
Endpoints[REST Endpoints]
Swagger[Swagger Docs]
end
subgraph "Data Layer"
Metadata[(Schema Metadata)]
AppDB[(Application Database)]
end
API --> CollectionAPI
CollectionAPI --> SchemaValidator
SchemaValidator --> FieldManager
FieldManager --> MigrationEngine
MigrationEngine --> Metadata
MigrationEngine --> AppDB
ResourceGenerator --> CRUD
ResourceGenerator --> Endpoints
ResourceGenerator --> Swagger
CollectionAPI --> ResourceGenerator
classDef manager fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
classDef resource fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef data fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
class CollectionAPI,FieldManager,SchemaValidator,MigrationEngine,ResourceGenerator manager
class CRUD,Endpoints,Swagger resource
class Metadata,AppDB data π Key ConceptsΒΆ
π¦ CollectionsΒΆ
Collections are dynamic data structures that: - Define a table structure in the database - Automatically generate REST API endpoints - Support relationships with other collections - Include validation and constraints - Can be created, modified, and deleted via API
Properties: - name: Unique identifier (e.g., "articles", "users") - title: Human-readable display name - fields: Array of field definitions - options: Additional configuration (timestamps, soft deletes, etc.)
π·οΈ FieldsΒΆ
Fields define the columns/properties of a collection: - Each field has a type (string, integer, date, etc.) - Fields can be required, unique, or have default values - Support for relationships (belongsTo, hasMany, etc.) - Custom validation rules - UI hints for form generation
π‘ Collection Management APIΒΆ
π List All CollectionsΒΆ
Response:
{
"data": [
{
"name": "articles",
"title": "Articles",
"fields": [
{
"name": "id",
"type": "integer",
"primaryKey": true,
"autoIncrement": true
},
{
"name": "title",
"type": "string",
"required": true
},
{
"name": "content",
"type": "text"
}
],
"options": {
"timestamps": true,
"paranoid": false
}
}
]
}
β Create a CollectionΒΆ
POST /api/collections:create
X-App: main
Authorization: Bearer {api-key}
Content-Type: application/json
{
"name": "blog_posts",
"title": "Blog Posts",
"description": "Collection for blog articles",
"fields": [
{
"name": "title",
"type": "string",
"required": true,
"unique": false
},
{
"name": "slug",
"type": "string",
"required": true,
"unique": true
},
{
"name": "content",
"type": "text",
"required": false
},
{
"name": "excerpt",
"type": "text"
},
{
"name": "status",
"type": "string",
"defaultValue": "draft"
},
{
"name": "publishedAt",
"type": "datetime"
},
{
"name": "viewCount",
"type": "integer",
"defaultValue": 0
},
{
"name": "author",
"type": "belongsTo",
"target": "users",
"foreignKey": "authorId"
},
{
"name": "tags",
"type": "belongsToMany",
"target": "tags",
"through": "blog_posts_tags"
}
],
"options": {
"timestamps": true,
"paranoid": true
}
}
What happens automatically: 1. β
Database table is created 2. β
REST endpoints are generated (/api/blog_posts:list, :create, etc.) 3. β
Swagger documentation is updated 4. β
Validation rules are configured 5. β
Relationship joins are set up
π Update a CollectionΒΆ
POST /api/collections:update?filterByTk=blog_posts
X-App: main
Authorization: Bearer {api-key}
Content-Type: application/json
{
"title": "Blog Articles",
"description": "Published blog content and drafts"
}
Note: Updating a collection modifies metadata only. To change fields, use the Field Management API.
ποΈ Delete a CollectionΒΆ
β οΈ Warning: This will: - Drop the database table - Delete all data in the collection - Remove all REST endpoints - Remove Swagger documentation
Safe deletion with cascade:
This also removes relationships and dependent collections.
π·οΈ Field TypesΒΆ
π Basic Field TypesΒΆ
| Type | Description | Database Type | Example |
|---|---|---|---|
string | Short text | VARCHAR(255) | "Hello World" |
text | Long text | TEXT | "Long article content..." |
integer | Whole number | INTEGER | 42 |
bigInt | Large integer | BIGINT | 9007199254740991 |
float | Decimal number | FLOAT | 3.14159 |
double | Double precision | DOUBLE | 3.141592653589793 |
boolean | True/False | BOOLEAN | true |
date | Date only | DATE | "2025-01-15" |
time | Time only | TIME | "14:30:00" |
datetime | Date and time | DATETIME/TIMESTAMP | "2025-01-15T14:30:00Z" |
json | JSON data | JSON/JSONB | {"key": "value"} |
array | Array/List | JSON/ARRAY | [1, 2, 3] |
π Relationship Field TypesΒΆ
| Type | Description | Use Case | Example |
|---|---|---|---|
belongsTo | Many-to-One | Each post has one author | Post β User |
hasOne | One-to-One | User has one profile | User β Profile |
hasMany | One-to-Many | Post has many comments | Post β Comments |
belongsToMany | Many-to-Many | Post has many tags | Post β Tags |
π Special Field TypesΒΆ
| Type | Description | Behavior |
|---|---|---|
uid | Unique Identifier | Auto-generated UUID |
password | Password field | Auto-hashed before storage |
email | Email address | Validated format |
url | URL field | Validated format |
phone | Phone number | Validated format |
color | Color code | Hex color validation |
π οΈ Field Management APIΒΆ
β Add Field to CollectionΒΆ
POST /api/fields:create
X-App: main
Authorization: Bearer {api-key}
Content-Type: application/json
{
"collectionName": "blog_posts",
"name": "featuredImage",
"type": "string",
"description": "URL to featured image",
"required": false,
"defaultValue": null
}
π Update FieldΒΆ
POST /api/fields:update
X-App: main
Authorization: Bearer {api-key}
Content-Type: application/json
{
"collectionName": "blog_posts",
"name": "featuredImage",
"description": "Featured image URL or path",
"uiSchema": {
"x-component": "Upload",
"x-component-props": {
"accept": "image/*"
}
}
}
ποΈ Remove FieldΒΆ
POST /api/fields:destroy
X-App: main
Authorization: Bearer {api-key}
Content-Type: application/json
{
"collectionName": "blog_posts",
"name": "featuredImage"
}
β οΈ Warning: Removes the column from the database and deletes all data in that field.
π Relationship ManagementΒΆ
π One-to-Many Relationship (hasMany)ΒΆ
Scenario: Posts have many comments
# Add relationship field to posts collection
POST /api/fields:create
X-App: main
Content-Type: application/json
{
"collectionName": "blog_posts",
"name": "comments",
"type": "hasMany",
"target": "comments",
"foreignKey": "postId",
"sourceKey": "id"
}
Usage:
# Get post with comments
GET /api/blog_posts:get?filterByTk=1&appends=comments
X-App: main
# List comments of a post
GET /api/blog_posts/1/comments:list
X-App: main
# Create comment on a post
POST /api/blog_posts/1/comments:create
X-App: main
{
"content": "Great article!",
"authorId": 5
}
π Many-to-One Relationship (belongsTo)ΒΆ
Scenario: Each comment belongs to one user (author)
POST /api/fields:create
X-App: main
Content-Type: application/json
{
"collectionName": "comments",
"name": "author",
"type": "belongsTo",
"target": "users",
"foreignKey": "authorId",
"targetKey": "id"
}
Usage:
# Get comment with author info
GET /api/comments:get?filterByTk=1&appends=author
X-App: main
# Set comment author
POST /api/comments/1/author:set?filterByTk=5
X-App: main
π Many-to-Many Relationship (belongsToMany)ΒΆ
Scenario: Posts can have multiple tags, tags can belong to multiple posts
# Add relationship to posts
POST /api/fields:create
X-App: main
Content-Type: application/json
{
"collectionName": "blog_posts",
"name": "tags",
"type": "belongsToMany",
"target": "tags",
"through": "blog_posts_tags",
"foreignKey": "postId",
"otherKey": "tagId"
}
# Add reverse relationship to tags
POST /api/fields:create
X-App: main
Content-Type: application/json
{
"collectionName": "tags",
"name": "posts",
"type": "belongsToMany",
"target": "blog_posts",
"through": "blog_posts_tags",
"foreignKey": "tagId",
"otherKey": "postId"
}
Usage:
# Add tags to post
POST /api/blog_posts/1/tags:add
X-App: main
{
"values": [2, 5, 8] # Tag IDs
}
# Set tags (replace all)
POST /api/blog_posts/1/tags:set
X-App: main
{
"values": [2, 5, 8]
}
# Remove tags from post
POST /api/blog_posts/1/tags:remove
X-App: main
{
"values": [5]
}
# List tags of a post
GET /api/blog_posts/1/tags:list
X-App: main
π One-to-One Relationship (hasOne)ΒΆ
Scenario: User has one profile
POST /api/fields:create
X-App: main
Content-Type: application/json
{
"collectionName": "users",
"name": "profile",
"type": "hasOne",
"target": "user_profiles",
"foreignKey": "userId",
"sourceKey": "id"
}
Usage:
# Get user with profile
GET /api/users:get?filterByTk=1&appends=profile
X-App: main
# Update user profile
POST /api/users/1/profile:update
X-App: main
{
"bio": "Full Stack Developer",
"website": "https://example.com"
}
βοΈ Field OptionsΒΆ
Common Field OptionsΒΆ
{
"name": "title",
"type": "string",
// Validation
"required": true,
"unique": true,
// Default value
"defaultValue": "Untitled",
// Database constraints
"allowNull": false,
"primaryKey": false,
"autoIncrement": false,
// Display
"description": "Post title",
"uiSchema": {
"title": "Title",
"x-component": "Input",
"x-component-props": {
"placeholder": "Enter title..."
}
}
}
String Field OptionsΒΆ
{
"name": "email",
"type": "string",
"required": true,
"unique": true,
// String-specific
"maxLength": 255,
"pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
}
Number Field OptionsΒΆ
{
"name": "price",
"type": "float",
// Number-specific
"min": 0,
"max": 999999.99,
"precision": 2,
"scale": 2
}
Date/Time Field OptionsΒΆ
{
"name": "publishedAt",
"type": "datetime",
// Date-specific
"dateOnly": false,
"autoNow": false, // Set to current time on create
"autoNowAdd": false // Set to current time on every update
}
π― Built-in Collection FeaturesΒΆ
β° TimestampsΒΆ
Automatically add createdAt and updatedAt fields:
ποΈ Soft Deletes (Paranoid)ΒΆ
Add deletedAt field for soft deletion:
{
"name": "articles",
"title": "Articles",
"fields": [...],
"options": {
"timestamps": true,
"paranoid": true
}
}
Records are marked as deleted but not actually removed from database.
π LoggingΒΆ
Track all changes to records:
π‘ Best PracticesΒΆ
π― Collection DesignΒΆ
DO: - β
Use clear, descriptive names (snake_case or camelCase) - β
Add descriptions to collections and fields - β
Define required: true for mandatory fields - β
Use unique: true for fields that must be unique - β
Set appropriate default values - β
Enable timestamps for audit trails - β
Plan relationships before creation
DON'T: - β Use reserved keywords as names - β Create overly complex nested structures - β Skip field validation - β Forget to document field purposes - β Create circular dependencies in relationships
π Relationship DesignΒΆ
DO: - β Choose the correct relationship type - β Name relationship fields intuitively - β Consider query performance implications - β Use through tables for many-to-many - β Set up bidirectional relationships when needed
DON'T: - β Create unnecessary relationships - β Use many-to-many for one-to-many scenarios - β Forget to index foreign keys - β Create deeply nested relationship chains
β‘ PerformanceΒΆ
DO: - β Add indexes to frequently queried fields - β Use appropriate field types - β Normalize data structures - β Consider query patterns when designing
DON'T: - β Over-index (slows down writes) - β Use text fields for short strings - β Create too many relationships per collection - β Skip database optimization
π Complete Example: Blog SystemΒΆ
Step 1: Create Users CollectionΒΆ
POST /api/collections:create
X-App: main
{
"name": "users",
"title": "Users",
"fields": [
{"name": "email", "type": "email", "required": true, "unique": true},
{"name": "username", "type": "string", "required": true, "unique": true},
{"name": "password", "type": "password", "required": true},
{"name": "name", "type": "string", "required": true},
{"name": "bio", "type": "text"}
],
"options": {"timestamps": true}
}
Step 2: Create Tags CollectionΒΆ
POST /api/collections:create
X-App: main
{
"name": "tags",
"title": "Tags",
"fields": [
{"name": "name", "type": "string", "required": true, "unique": true},
{"name": "slug", "type": "string", "required": true, "unique": true},
{"name": "description", "type": "text"}
],
"options": {"timestamps": true}
}
Step 3: Create Blog Posts CollectionΒΆ
POST /api/collections:create
X-App: main
{
"name": "blog_posts",
"title": "Blog Posts",
"fields": [
{"name": "title", "type": "string", "required": true},
{"name": "slug", "type": "string", "required": true, "unique": true},
{"name": "content", "type": "text", "required": true},
{"name": "excerpt", "type": "text"},
{"name": "status", "type": "string", "defaultValue": "draft"},
{"name": "publishedAt", "type": "datetime"},
{"name": "viewCount", "type": "integer", "defaultValue": 0},
{
"name": "author",
"type": "belongsTo",
"target": "users",
"foreignKey": "authorId"
},
{
"name": "tags",
"type": "belongsToMany",
"target": "tags",
"through": "blog_posts_tags"
}
],
"options": {
"timestamps": true,
"paranoid": true
}
}
Step 4: Create Comments CollectionΒΆ
POST /api/collections:create
X-App: main
{
"name": "comments",
"title": "Comments",
"fields": [
{"name": "content", "type": "text", "required": true},
{
"name": "post",
"type": "belongsTo",
"target": "blog_posts",
"foreignKey": "postId"
},
{
"name": "author",
"type": "belongsTo",
"target": "users",
"foreignKey": "authorId"
}
],
"options": {
"timestamps": true,
"paranoid": true
}
}
Step 5: Add Reverse RelationshipsΒΆ
# Add comments relationship to blog_posts
POST /api/fields:create
X-App: main
{
"collectionName": "blog_posts",
"name": "comments",
"type": "hasMany",
"target": "comments",
"foreignKey": "postId"
}
# Add posts relationship to users
POST /api/fields:create
X-App: main
{
"collectionName": "users",
"name": "posts",
"type": "hasMany",
"target": "blog_posts",
"foreignKey": "authorId"
}
# Add reverse relationship for tags
POST /api/fields:create
X-App: main
{
"collectionName": "tags",
"name": "posts",
"type": "belongsToMany",
"target": "blog_posts",
"through": "blog_posts_tags",
"foreignKey": "tagId",
"otherKey": "postId"
}
Now you have a complete blog system with automatic REST APIs for all CRUD operations!
π Related DocumentationΒΆ
- API Gateway: Overall API architecture
- CRUD Operations: Using the generated APIs
- Authentication: Securing collection access
- Permissions: Fine-grained access control
Note: The Collection Manager provides the foundation for Continuum's flexible, API-first data management approach, enabling rapid development without traditional database migrations.