Reference

Collections

How to define and use collections in dnax Framework.

Collections define the data structure for your API. They are defined as TypeScript files in the collections/ directory.

Defining a Collection

import { define } from '@dnax/core';

export default define.Collection({
  slug: 'users',
  type: 'document',
  fields: [
    { name: 'name', type: 'string', required: true },
    { name: 'email', type: 'email', required: true, unique: true },
    { name: 'password', type: 'password', required: true },
    { name: 'role', type: 'enum', enumOptions: { items: ['admin', 'user', 'guest'] } },
    { name: 'status', type: 'enum', enumOptions: { items: ['active', 'inactive'] } },
  ],
});

Save this as collections/users.model.ts.

Collection Options

OptionTypeDefaultDescription
slugstring-Collection name (required)
type'document' | 'media''document'Collection type
fieldsField[]-Field definitions
apiobject-API configuration
actionsobject-Custom actions
hooksobject-Lifecycle hooks

Field Types

The following field types are supported:

TypeDescription
stringString value
numberNumber value
integerInteger value
booleanBoolean value
emailEmail address
passwordHashed password
uuidUUID string
urlURL string
dateDate value
datetime-localDateTime value
enumEnumeration
arrayArray of values
jsonJSON object
relationshipReference to another collection
randomAuto-generated value
ipv4IPv4 address
ipv6IPv6 address
geojson.PointGeoJSON Point
geojson.LineStringGeoJSON LineString
geojson.PolygonGeoJSON Polygon

Field Options

Each field can have these options:

{
  name: string;        // Field name (required)
  type: FieldType;    // Field type (required)
  description?: string;
  required?: boolean;
  unique?: boolean;
  nullable?: boolean;
  defaultValue?: any;
  index?: boolean;
  indexOptions?: {
    expireAfterSeconds?: number;
    sparse?: boolean;
    unique?: boolean;
  };
  enumOptions?: {
    items: string[];     // Allowed values
    multiple?: boolean;  // Allow multiple selections
  };
  relation?: {
    to: string;         // Target collection
    hasMany?: boolean;  // One-to-many relationship
    pipeline?: any[];   // Aggregation pipeline
  };
  randomOptions?: {
    type: 'uuid' | 'string' | 'number';
    prefix?: string;
    toNumber?: boolean;
  };
}

Example: Blog Posts

export default define.Collection({
  slug: 'posts',
  fields: [
    { name: 'title', type: 'string', required: true },
    { name: 'slug', type: 'string', required: true, unique: true },
    { name: 'content', type: 'string', required: true },
    { name: 'excerpt', type: 'string' },
    { name: 'featuredImage', type: 'string' },
    { name: 'author', type: 'relationship', relation: { to: 'users', hasMany: false } },
    { name: 'tags', type: 'array' },
    { name: 'status', type: 'enum', enumOptions: { items: ['draft', 'published', 'archived'] } },
    { name: 'publishedAt', type: 'datetime-local' },
    { name: 'views', type: 'number', defaultValue: 0 },
  ],
});

Example: Products with Inventory

export default define.Collection({
  slug: 'products',
  fields: [
    { name: 'name', type: 'string', required: true },
    { name: 'sku', type: 'string', required: true, unique: true },
    { name: 'price', type: 'number', required: true },
    { name: 'description', type: 'string' },
    { name: 'category', type: 'enum', enumOptions: { items: ['electronics', 'clothing', 'food'] } },
    { name: 'stock', type: 'number', defaultValue: 0 },
    { name: 'images', type: 'array' },
    { name: 'isActive', type: 'boolean', defaultValue: true },
  ],
});
Copyright © 2026