Dyrecteddyrected
API Reference

Field Types Reference

Field behavior, modeling guidance, examples, and generated public contracts.

Fields define both stored data and the editing experience. Choose a field for the value you want the API to return, then use admin options to improve how editors enter it. Do not choose a storage shape solely because it looks convenient in the Admin UI.

Base properties (all fields)

Named fields use name as their stored key and should always have an explicit human-readable label. required, unique, defaultValue, access, and server hooks affect data behavior; most admin options affect presentation only.

{
  name: 'title',
  type: 'text',
  label: 'Title',
  required: true,
  unique: true,
  admin: { description: 'Shown as the public page heading.' },
}

Required and unique indicators help editors understand constraints, but the server remains authoritative.

Internally, the public Field union is now composed of named variants such as TextField, BooleanField, SelectField, and RelationshipField. Most projects continue to use the Field union indirectly through defineCollection() and defineGlobal(), but the named variants matter for generated docs, SDK tooling, and custom type-level utilities.

Text fields

text

Use text for a single line such as a title, slug, short label, or identifier.

{
  name: 'title',
  type: 'text',
  label: 'Title',
  required: true,
  admin: { placeholder: 'Enter a title…' },
}

Size and word limits

maxLength and maxWords are first-class field properties for supported text inputs. The Admin UI uses them to show live character and word counters. If a write must be rejected when a limit is exceeded, enforce that in a collection or field hook for now.

{
  name: 'excerpt',
  type: 'textarea',
  label: 'Excerpt',
  maxLength: 160,
  maxWords: 30,
}

textarea

Use textarea for longer plain text where formatting is neither needed nor desirable.

{
  name: 'summary',
  type: 'textarea',
  label: 'Summary',
  admin: { description: 'A short plain-text summary for cards.' },
}

richText

richText stores a Tiptap/ProseMirror JSON document. It is not an HTML string. Render it with a compatible rich-text renderer or transform it in a trusted server boundary.

{ name: 'body', type: 'richText', label: 'Body', required: true }

email

Use email for editor-supplied email addresses. Auth collections inject their own authentication fields, so do not redefine email or password merely to enable login.

{ name: 'contactEmail', type: 'email', label: 'Contact email' }

icon

The icon field stores the selected Lucide component name as a string. Resolve only known exports in the frontend and provide a fallback for names removed by an icon-library upgrade.

{ name: 'featureIcon', type: 'icon', label: 'Feature icon' }
import * as icons from 'lucide-react'

export function DynamicIcon({ name }: { name: string }) {
  const Icon = icons[name as keyof typeof icons]
  return typeof Icon === 'function' ? <Icon aria-hidden /> : null
}

url

The URL field can represent external links or internal document references. It returns a structured object, not a bare string.

{ name: 'callToAction', type: 'url', label: 'Call to action' }

Stored shape

{
  "type": "internal",
  "url": "/blog/a-post",
  "relationTo": "posts",
  "value": "post-id",
  "label": "Read the post"
}

For external links, use the returned url. For internal links, configure the target collection's admin.urlPattern when the frontend needs a resolved URL without another fetch.

export const Posts = defineCollection({
  slug: 'posts',
  admin: { urlPattern: '/blog/{slug}' },
  fields: [
    { name: 'title', type: 'text', label: 'Title' },
    { name: 'slug', type: 'text', label: 'Slug' },
  ],
})

urlPattern is a frontend convenience. It does not change collection API routes.

Numeric and boolean fields

number

{ name: 'price', type: 'number', label: 'Price', defaultValue: 0 }

Use a collection hook when monetary rounding, cross-field totals, or domain-specific ranges must be enforced on every write.

boolean

{
  name: 'featured',
  type: 'boolean',
  label: 'Featured',
  defaultValue: false,
  admin: { layout: 'switch' },
}

Checkbox and switch layouts store the same boolean value.

admin.layout is intentionally scoped here. Only boolean fields support layout: 'checkbox' | 'switch'.

Date and time fields

date

Use date when the calendar day matters but time-of-day does not.

{ name: 'eventDate', type: 'date', label: 'Event date' }

datetime

Use datetime for an instant such as publication or appointment time. API values are ISO-compatible strings; be explicit about timezone presentation in the frontend.

{ name: 'publishedAt', type: 'datetime', label: 'Published at' }

time

Use time for a local time-of-day whose date is modeled elsewhere.

{ name: 'openingTime', type: 'time', label: 'Opening time' }

daterange appeared in older documentation but is not a current FieldType. Model a range with labeled start/end fields and validate their ordering in a collection hook.

Selection fields

select

select stores one option value. Options may be static, resolved on the server, or recalculated in the Admin UI. See Dynamic Options.

{
  name: 'status',
  type: 'select',
  label: 'Status',
  options: [
    { label: 'Draft', value: 'draft' },
    { label: 'Published', value: 'published' },
  ],
}

Set admin.layout: 'radio' when a small option set benefits from being visible at once.

admin.hooks.options is also scoped here. Use it for instant client-side dependent options when the available values depend on other form fields.

radio

radio is also a supported field type. Prefer it when radio-button semantics are intrinsic to the content model; use a select with radio layout when only the presentation should vary.

radio fields support admin.direction and admin.hooks.options.

multiSelect

multiSelect stores an array of option values.

{
  name: 'topics',
  type: 'multiSelect',
  label: 'Topics',
  options: ['engineering', 'design', 'business'],
}

multiSelect also supports admin.hooks.options for dependent option lists.

Relationship and media fields

relationship

A relationship stores the ID of a document in another collection. Set hasMany: true to store multiple IDs.

{
  name: 'author',
  type: 'relationship',
  label: 'Author',
  relationTo: 'users',
  required: true,
}

At depth: 0, responses contain IDs. Higher depth hydrates related documents and increases query and payload cost. Use the lowest depth that satisfies the view.

image

image relates to upload documents and supports hasMany. It does not replace the need for an upload-enabled collection or configured storage adapter.

join

A join is a virtual reverse lookup: it stores nothing on the current document and queries documents whose relationship points back to it.

{
  name: 'posts',
  type: 'join',
  label: 'Posts',
  collection: 'posts',
  on: 'author',
  limit: 20,
}

Use a relationship for the owning side and a join only for reverse navigation. Large joins should be bounded and indexed through the owning relationship.

Structural fields

object

Use object for a nested value with a fixed shape and the same lifecycle as its parent.

{
  name: 'seo',
  type: 'object',
  label: 'Search metadata',
  fields: [
    { name: 'title', type: 'text', label: 'Meta title' },
    { name: 'description', type: 'textarea', label: 'Meta description' },
  ],
}

array

Use array for repeatable items with one shared shape. Use a collection instead if entries need independent IDs, access rules, querying, or reuse.

{
  name: 'questions',
  type: 'array',
  label: 'Questions',
  fields: [
    { name: 'question', type: 'text', label: 'Question', required: true },
    { name: 'answer', type: 'textarea', label: 'Answer', required: true },
  ],
}

blocks

Blocks allow each array entry to choose a different configured shape. Keep block slugs stable and make frontend renderers handle unknown block types safely during rolling deployments.

A block may declare variants: BlockVariant[] — approved layouts that share the block's fields. Each BlockVariant has a required stable slug and optional label, icon (a Lucide name), and description. The selected slug is stored on the item under the reserved variant key and passed to your renderer as a variant prop; switching variant preserves field content, and the first variant is the default. See Presentation variants.

json

Use json for genuinely open-ended structured values. Prefer object, array, or blocks when editors and consumers benefit from an explicit contract.

Layout fields

row

row changes form layout but creates no stored wrapper. Its named children remain at the surrounding document level.

{
  type: 'row',
  fields: [
    { name: 'firstName', type: 'text', label: 'First name', admin: { width: '50%' } },
    { name: 'lastName', type: 'text', label: 'Last name', admin: { width: '50%' } },
  ],
}

Admin field options

Admin options include descriptions, placeholders, conditional visibility, registered components, tabs, widths, read-only state, and filterability. They do not replace server validation or access control.

Use serializable Jexl strings for conditions that must synchronize to Dyrected Cloud:

{
  name: 'scheduledAt',
  type: 'datetime',
  label: 'Scheduled at',
  admin: { condition: "status == 'scheduled'", tab: 'Publishing' },
}

Custom components are registered by string key in the framework integration. Validation, defaults, and access rules still come from the field definition.

Field access

Field read access strips denied values from API responses. Field update access ignores denied incoming changes. Enforce sensitive-data rules here or at collection access—not only with hidden or readOnly.

{
  name: 'internalNotes',
  type: 'textarea',
  label: 'Internal notes',
  access: {
    read: ({ user }) => user?.roles?.includes('admin') ?? false,
    update: ({ user }) => user?.roles?.includes('admin') ?? false,
  },
}

Field hooks

Use field hooks for transformations local to one value, including nested array/object/block values. Use collection hooks for cross-field validation or updates. Server hooks protect all API writes; Admin hooks provide editor feedback only.

See Hooks and Using Hooks.

Generated field and hook contracts

ArrayField

Exported type from @dyrected/core.

export type ArrayField = TypedField<"array", unknown>;

AuthDocFields

Exported type from @dyrected/core.

export type AuthDocFields = {
  email: string;
  password?: string;
  roles?: string[];
};

AuthenticatedUser

Base shape of an authenticated user as decoded from the JWT.

The actual shape will include every field on your auth collection — this interface only guarantees the properties that Dyrected always stamps on the token. Extend it in your own codebase for stronger typing:

export interface AuthenticatedUser {
  /** The user's document ID in the database. */
  sub: string;
  /** The user's email address. */
  email?: string;
  /** Slug of the collection this user was authenticated against. */
  collection: string;
  /** Array of role strings, if your auth collection has a `roles` field. */
  roles?: string[];
  /** Any additional fields from the auth collection document. */
  [key: string]: unknown;
}
MemberSignatureDescription
subsub: stringThe user's document ID in the database.
emailemail?: stringThe user's email address.
collectioncollection: stringSlug of the collection this user was authenticated against.
rolesroles?: string[]Array of role strings, if your auth collection has a `roles` field.

BaseFieldAdmin

Exported interface from @dyrected/core.

export interface BaseFieldAdmin {
  /** Placeholder text shown when the input has no value. */
  placeholder?: string;
  /** Custom component key registered in the Admin UI. */
  component?: string;
  /** Help text rendered below the field. */
  description?: string;
  /** Hides the field from the Admin form without deleting stored data. */
  hidden?: boolean;
  /** Excludes the field from Admin list filtering. */
  filterable?: boolean;
  /** Renders the field as non-editable in the Admin UI. */
  readOnly?: boolean;
  /** Hides the field's label in the Admin form (e.g. single-field array rows where the label is redundant). */
  hideLabel?: boolean;
  /** Reactive condition controlling whether the field is visible in the Admin UI. */
  condition?: ((data: Record<string, unknown>, siblingData: Record<string, unknown>) => boolean) | string;
  /** Tab name used when the edit form is rendered as tabs. */
  tab?: string;
  /** CSS width hint used when the field appears inside a `row`. */
  width?: string;
}
MemberSignatureDescription
placeholderplaceholder?: stringPlaceholder text shown when the input has no value.
componentcomponent?: stringCustom component key registered in the Admin UI.
descriptiondescription?: stringHelp text rendered below the field.
hiddenhidden?: booleanHides the field from the Admin form without deleting stored data.
filterablefilterable?: booleanExcludes the field from Admin list filtering.
readOnlyreadOnly?: booleanRenders the field as non-editable in the Admin UI.
hideLabelhideLabel?: booleanHides the field's label in the Admin form (e.g. single-field array rows where the label is redundant).
conditioncondition?: ((data: Record<string, unknown>, siblingData: Record<string, unknown>) => boolean) | stringReactive condition controlling whether the field is visible in the Admin UI.
tabtab?: stringTab name used when the edit form is rendered as tabs.
widthwidth?: stringCSS width hint used when the field appears inside a `row`.

Block

Exported interface from @dyrected/core.

export interface Block {
  /** Stable identifier stored in each block row as `blockType`. */
  slug: string;
  /** Human-readable labels shown in the Admin block picker. */
  labels?: {
    /** Singular label, for example `Hero`. */
    singular: string;
    /** Plural label, for example `Heroes`. */
    plural: string;
  };
  /**
   * Lucide icon name shown on the block card and in the block library.
   * Falls back to a generic layout icon when omitted.
   */
  icon?: AdminIconName;
  /** Short one-line summary shown under the block name (block card subtitle). */
  description?: string;
  /**
   * Presentation variants for this block. All variants share the same `fields`;
   * only the rendered layout differs. The chosen variant is stored on each block
   * row under the reserved `variant` key and passed to the render component as a
   * `variant` prop. Switching variant preserves the author's content.
   */
  variants?: BlockVariant[];
  /** Fields that make up this block's payload. */
  fields: Field[];
}
MemberSignatureDescription
slugslug: stringStable identifier stored in each block row as `blockType`.
labelslabels?: { /** Singular label, for example `Hero`. / singular: string; /* Plural label, for example `Heroes`. */ plural: string; }Human-readable labels shown in the Admin block picker.
iconicon?: AdminIconNameLucide icon name shown on the block card and in the block library. Falls back to a generic layout icon when omitted.
descriptiondescription?: stringShort one-line summary shown under the block name (block card subtitle).
variantsvariants?: BlockVariant[]Presentation variants for this block. All variants share the same `fields`; only the rendered layout differs. The chosen variant is stored on each block row under the reserved `variant` key and passed to the render component as a `variant` prop. Switching variant preserves the author's content.
fieldsfields: Field[]Fields that make up this block's payload.

BlocksField

Exported type from @dyrected/core.

export type BlocksField = TypedField<"blocks", unknown>;

BlockVariant

Exported interface from @dyrected/core.

export interface BlockVariant {
  /** Stable identifier stored on the block row as `variant`. */
  slug: string;
  /** Human-readable label shown in the variant switcher. Defaults to `slug`. */
  label?: string;
  /** Lucide icon name shown beside the variant label. */
  icon?: AdminIconName;
  /** Short one-line summary of what this variant looks like. */
  description?: string;
}
MemberSignatureDescription
slugslug: stringStable identifier stored on the block row as `variant`.
labellabel?: stringHuman-readable label shown in the variant switcher. Defaults to `slug`.
iconicon?: AdminIconNameLucide icon name shown beside the variant label.
descriptiondescription?: stringShort one-line summary of what this variant looks like.

BooleanField

Exported type from @dyrected/core.

export type BooleanField = TypedField<"boolean", boolean, BooleanFieldAdmin>;

BooleanFieldAdmin

Exported type from @dyrected/core.

export type BooleanFieldAdmin = {
  /** Boolean presentation style. */
  layout?: "checkbox" | "switch";
};

CharacterLimitFieldAdmin

Exported type from @dyrected/core.

export type CharacterLimitFieldAdmin = {
  /** Admin-only compatibility alias for `field.maxLength`. Prefer the top-level field property. */
  maxLength?: number;
};

CharacterLimitFieldConfig

Exported interface from @dyrected/core.

export interface CharacterLimitFieldConfig {
  /** Advisory maximum character count exposed to editors and client tooling. */
  maxLength?: number;
}
MemberSignatureDescription
maxLengthmaxLength?: numberAdvisory maximum character count exposed to editors and client tooling.

CollectionAfterChangeHook

Runs after a document is created or updated in the database.

export type CollectionAfterChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
  doc: TDoc;
  previousDoc?: TDoc;
  req: HookRequestContext;
  user?: AuthenticatedUser;
  operation: "create" | "update";
  db: DatabaseAdapter;
}) => void | Promise<void>;

CollectionAfterDeleteHook

Runs after a document has been deleted from the database.

export type CollectionAfterDeleteHook<TDoc extends object = Record<string, unknown>> = (args: {
  id: string;
  doc: TDoc;
  req: HookRequestContext;
  user?: AuthenticatedUser;
  db: DatabaseAdapter;
}) => void | Promise<void>;

CollectionAfterReadHook

Runs after a document (or list of documents) is fetched from the database, before the response is sent to the client.

export type CollectionAfterReadHook<TDoc extends object = Record<string, unknown>> = (args: {
  doc: TDoc;
  req: HookRequestContext;
  user?: AuthenticatedUser;
  db: ReadonlyDatabaseAdapter;
}) => TDoc | Promise<TDoc>;

CollectionBeforeChangeHook

Runs before a document is created or updated in the database.

export type CollectionBeforeChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
  data: Partial<TDoc>;
  doc?: TDoc;
  req: HookRequestContext;
  user?: AuthenticatedUser;
  operation: "create" | "update";
  db: ReadonlyDatabaseAdapter;
}) => Partial<TDoc> | void | Promise<Partial<TDoc> | void>;

CollectionBeforeDeleteHook

Runs before a document is deleted from the database.

export type CollectionBeforeDeleteHook<TDoc extends object = Record<string, unknown>> = (args: {
  id: string;
  doc: TDoc;
  req: HookRequestContext;
  user?: AuthenticatedUser;
  db: ReadonlyDatabaseAdapter;
}) => void | Promise<void>;

CollectionBeforeReadHook

Runs before Dyrected queries the database for a list or single-document fetch.

Return a new where query object to override or extend the current filter. Return undefined (or nothing) to leave the query unchanged.

export type CollectionBeforeReadHook = (args: {
  req: HookRequestContext;
  query?: Record<string, unknown>;
  user?: AuthenticatedUser;
  db: ReadonlyDatabaseAdapter;
}) => Record<string, unknown> | void | Promise<Record<string, unknown> | void>;

DateField

Exported type from @dyrected/core.

export type DateField = TypedField<"date", string>;

DateTimeField

Exported type from @dyrected/core.

export type DateTimeField = TypedField<"datetime", string>;

DynamicOptionItem

Exported type from @dyrected/core.

export type DynamicOptionItem = string | { label: string; value: unknown };

DynamicOptionsConfig

Exported interface from @dyrected/core.

export interface DynamicOptionsConfig {
  /** Resolver function executed on the server to produce option items. */
  resolve: DynamicOptionsResolver;
  /** Cache duration in seconds for identical resolver calls. */
  cacheTTL?: number;
}
MemberSignatureDescription
resolveresolve: DynamicOptionsResolverResolver function executed on the server to produce option items.
cacheTTLcacheTTL?: numberCache duration in seconds for identical resolver calls.

DynamicOptionsResolver

Exported type from @dyrected/core.

export type DynamicOptionsResolver = (
  args: DynamicOptionsResolverArgs,
) => Promise<DynamicOptionItem[]> | DynamicOptionItem[];

DynamicOptionsResolverArgs

Exported interface from @dyrected/core.

export interface DynamicOptionsResolverArgs {
  /** Database adapter available to server-side option resolvers. */
  db?: DatabaseAdapter;
  /** Authenticated user making the request, if any. */
  user?: AuthenticatedUser;
  /** Current HTTP request context, including query parameters. */
  req: HookRequestContext;
}
MemberSignatureDescription
dbdb?: DatabaseAdapterDatabase adapter available to server-side option resolvers.
useruser?: AuthenticatedUserAuthenticated user making the request, if any.
reqreq: HookRequestContextCurrent HTTP request context, including query parameters.

EmailField

Exported type from @dyrected/core.

export type EmailField = TypedField<"email", string, EmailFieldAdmin> & CharacterLimitFieldConfig;

EmailFieldAdmin

Exported type from @dyrected/core.

export type EmailFieldAdmin = CharacterLimitFieldAdmin;

Field

Exported type from @dyrected/core.

export type Field =
  | TextField
  | TextareaField
  | EmailField
  | UrlField
  | IconField
  | DateField
  | DateTimeField
  | TimeField
  | SelectField
  | RadioField
  | NumberField
  | BooleanField
  | MultiSelectField
  | RelationshipField
  | ImageField
  | RichTextField
  | JsonField
  | ObjectField
  | ArrayField
  | BlocksField
  | JoinField
  | RowField;

FieldAdminHooks

Exported type from @dyrected/core.

export type FieldAdminHooks<TValue> = {
  admin?: {
    hooks?: {
      onChange?: FieldAdminOnChangeHook<TValue>;
    };
  };
};

FieldAdminOnChangeHook

Exported type from @dyrected/core.

export type FieldAdminOnChangeHook<TValue = unknown> = (args: FieldAdminOnChangeHookArgs<TValue>) => unknown;

FieldAdminOnChangeHookArgs

Exported interface from @dyrected/core.

export interface FieldAdminOnChangeHookArgs<TValue = unknown> {
  /** Current field value in the form state. */
  value: TValue;
  /** Current values for sibling fields at the same nesting level. */
  siblingData: Record<string, unknown>;
  /** Current values for the entire form. */
  data: Record<string, unknown>;
  /** Imperative setter for async or derived updates. */
  setValue: (value: unknown) => void;
}
MemberSignatureDescription
valuevalue: TValueCurrent field value in the form state.
siblingDatasiblingData: Record<string, unknown>Current values for sibling fields at the same nesting level.
datadata: Record<string, unknown>Current values for the entire form.
setValuesetValue: (value: unknown) => voidImperative setter for async or derived updates.

FieldAdminOptionsHook

Exported type from @dyrected/core.

export type FieldAdminOptionsHook = (
  args: FieldAdminOptionsHookArgs,
) => FieldAdminOptionsHookResult | Promise<FieldAdminOptionsHookResult>;

FieldAdminOptionsHookArgs

Exported interface from @dyrected/core.

export interface FieldAdminOptionsHookArgs {
  /** Current values for sibling fields at the same nesting level. */
  siblingData: Record<string, unknown>;
  /** Current values for the entire form. */
  data: Record<string, unknown>;
}
MemberSignatureDescription
siblingDatasiblingData: Record<string, unknown>Current values for sibling fields at the same nesting level.
datadata: Record<string, unknown>Current values for the entire form.

FieldAdminOptionsHookResult

Exported type from @dyrected/core.

export type FieldAdminOptionsHookResult = Array<string | { label: string; value: unknown }>;

FieldAfterReadHook

Exported type from @dyrected/core.

export type FieldAfterReadHook<TValue = unknown, TDoc extends object = Record<string, unknown>> = (
  args: FieldAfterReadHookArgs<TValue, TDoc>,
) => unknown;

FieldAfterReadHookArgs

Exported interface from @dyrected/core.

export interface FieldAfterReadHookArgs<TValue = unknown, TDoc extends object = Record<string, unknown>> {
  /** Raw stored field value before this hook transforms it. */
  value: TValue;
  /** Full document currently being returned to the caller. */
  doc: TDoc;
  /** Authenticated user requesting the document, if any. */
  user?: AuthenticatedUser;
  /** Read-only database adapter for related lookups. */
  db: ReadonlyDatabaseAdapter;
}
MemberSignatureDescription
valuevalue: TValueRaw stored field value before this hook transforms it.
docdoc: TDocFull document currently being returned to the caller.
useruser?: AuthenticatedUserAuthenticated user requesting the document, if any.
dbdb: ReadonlyDatabaseAdapterRead-only database adapter for related lookups.

FieldBase

Exported interface from @dyrected/core.

export interface FieldBase {
  /** Stored key for this field. Omit only for layout-only fields such as `row` or `join`. */
  name?: string;
  /** Human-readable label shown in the Admin UI. */
  label?: string;
  /** Whether the field must have a value when saving. */
  required?: boolean;
  /** Whether values for this field must be unique across the collection. */
  unique?: boolean;
  /** Default value used when a new document omits this field. */
  defaultValue?: unknown;
  /** Static or dynamic option source for supported selection fields. */
  options?: string[] | { label: string; value: unknown }[] | DynamicOptionsResolver | DynamicOptionsConfig;
  /** Target collection slug for `relationship` fields. */
  relationTo?: string;
  /** Whether the field stores multiple values instead of one. */
  hasMany?: boolean;
  /** Child fields for `object` and `array` field types. */
  fields?: Field[];
  /** Allowed block definitions for a `blocks` field. */
  blocks?: Block[];
  /** Target collection slug for `join` fields. */
  collection?: string;
  /** Back-reference field name on the joined collection. */
  on?: string;
  /** Maximum number of joined documents returned by a `join` field. */
  limit?: number;
  /** Field-level read and update access rules. */
  access?: {
    /** Controls whether this field is returned in API responses. */
    read?: AccessFunction | string;
    /** Controls whether incoming writes may change this field. */
    update?: AccessFunction | string;
  };
  /** Admin-only presentation options for this field. */
  admin?: BaseFieldAdmin;
  /** Previous storage key to migrate from during schema sync. */
  renameTo?: string;
  /** Whether SQL adapters should promote this field into a first-class column. */
  promoted?: boolean;
}
MemberSignatureDescription
namename?: stringStored key for this field. Omit only for layout-only fields such as `row` or `join`.
labellabel?: stringHuman-readable label shown in the Admin UI.
requiredrequired?: booleanWhether the field must have a value when saving.
uniqueunique?: booleanWhether values for this field must be unique across the collection.
defaultValuedefaultValue?: unknownDefault value used when a new document omits this field.
optionsoptions?: string[] | { label: string; value: unknown }[] | DynamicOptionsResolver | DynamicOptionsConfigStatic or dynamic option source for supported selection fields.
relationTorelationTo?: stringTarget collection slug for `relationship` fields.
hasManyhasMany?: booleanWhether the field stores multiple values instead of one.
fieldsfields?: Field[]Child fields for `object` and `array` field types.
blocksblocks?: Block[]Allowed block definitions for a `blocks` field.
collectioncollection?: stringTarget collection slug for `join` fields.
onon?: stringBack-reference field name on the joined collection.
limitlimit?: numberMaximum number of joined documents returned by a `join` field.
accessaccess?: { /** Controls whether this field is returned in API responses. / read?: AccessFunction | string; /* Controls whether incoming writes may change this field. */ update?: AccessFunction | string; }Field-level read and update access rules.
adminadmin?: BaseFieldAdminAdmin-only presentation options for this field.
renameTorenameTo?: stringPrevious storage key to migrate from during schema sync.
promotedpromoted?: booleanWhether SQL adapters should promote this field into a first-class column.

FieldBeforeChangeHook

Exported type from @dyrected/core.

export type FieldBeforeChangeHook<TValue = unknown, TDoc extends object = Record<string, unknown>> = (
  args: FieldBeforeChangeHookArgs<TValue, TDoc>,
) => unknown;

FieldBeforeChangeHookArgs

Exported interface from @dyrected/core.

export interface FieldBeforeChangeHookArgs<TValue = unknown, TDoc extends object = Record<string, unknown>> {
  /** Current field value after previous hooks in the chain. */
  value: TValue;
  /** Existing stored document before the write, if this is an update. */
  originalDoc?: TDoc;
  /** Full incoming payload being written. */
  data: Record<string, unknown>;
  /** Authenticated user performing the write, if any. */
  user?: AuthenticatedUser;
  /** Read-only database adapter for related lookups. */
  db: ReadonlyDatabaseAdapter;
}
MemberSignatureDescription
valuevalue: TValueCurrent field value after previous hooks in the chain.
originalDocoriginalDoc?: TDocExisting stored document before the write, if this is an update.
datadata: Record<string, unknown>Full incoming payload being written.
useruser?: AuthenticatedUserAuthenticated user performing the write, if any.
dbdb: ReadonlyDatabaseAdapterRead-only database adapter for related lookups.

FieldHook

Exported type from @dyrected/core.

export type FieldHook<TDoc extends object = Record<string, unknown>, TValue = unknown> = FieldBeforeChangeHook<
  TValue,
  TDoc
>;

FieldHooks

Exported type from @dyrected/core.

export type FieldHooks<TValue> = {
  hooks?: {
    beforeChange?: Array<FieldBeforeChangeHook<TValue>>;
    afterRead?: Array<FieldAfterReadHook<TValue>>;
  };
};

FieldType

Exported type from @dyrected/core.

export type FieldType =
  | "text"
  | "textarea"
  | "richText"
  | "number"
  | "boolean"
  | "date"
  | "datetime"
  | "time"
  | "select"
  | "multiSelect"
  | "radio"
  | "relationship"
  | "array"
  | "object"
  | "json"
  | "blocks"
  | "image"
  | "email"
  | "url"
  | "icon"
  | "join"
  | "row";

GlobalAfterChangeHook

Runs after the global document is updated. Side-effects only.

export type GlobalAfterChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
  doc: TDoc;
  previousDoc?: TDoc;
  req: HookRequestContext;
  user?: AuthenticatedUser;
  operation: "update";
  db: DatabaseAdapter;
}) => void | Promise<void>;

GlobalAfterReadHook

Runs after the global document is fetched, before the response is sent.

export type GlobalAfterReadHook<TDoc extends object = Record<string, unknown>> = (args: {
  doc: TDoc;
  req: HookRequestContext;
  user?: AuthenticatedUser;
  db: ReadonlyDatabaseAdapter;
}) => TDoc | Promise<TDoc>;

GlobalBeforeChangeHook

Runs before the global document is updated. Operation is always 'update' (globals cannot be created or deleted).

export type GlobalBeforeChangeHook<TDoc extends object = Record<string, unknown>> = (args: {
  data: Partial<TDoc>;
  doc?: TDoc;
  req: HookRequestContext;
  user?: AuthenticatedUser;
  operation: "update";
  db: ReadonlyDatabaseAdapter;
}) => Partial<TDoc> | void | Promise<Partial<TDoc> | void>;

GlobalBeforeReadHook

Exported type from @dyrected/core.

export type GlobalBeforeReadHook = CollectionBeforeReadHook;

HookFunction

Exported type from @dyrected/core.

export type HookFunction<TDoc extends object = Record<string, unknown>> = (args: {
  data?: Partial<TDoc>;
  doc?: TDoc;
  user?: AuthenticatedUser;
  req?: HookRequestContext;
  operation?: "create" | "update" | "delete";
  db?: DatabaseAdapter;
  [key: string]: unknown;
}) => unknown | Promise<unknown>;

HookRequestContext

Minimum HTTP request context passed to every server-side hook and resolver.

The full Web Standard Request is available as raw when you need it, but most hooks only need query (URL search parameters).

export interface HookRequestContext {
  /** Parsed URL query-string parameters, e.g. `{ page: '2', search: 'hello' }`. */
  query: Record<string, string>;
  /** Incoming HTTP headers, lowercased. */
  headers: Record<string, string>;
  /** The raw Web Standard `Request` object. Useful for streaming or advanced header inspection. */
  raw?: Request;
}
MemberSignatureDescription
queryquery: Record<string, string>Parsed URL query-string parameters, e.g. `{ page: '2', search: 'hello' }`.
headersheaders: Record<string, string>Incoming HTTP headers, lowercased.
rawraw?: RequestThe raw Web Standard `Request` object. Useful for streaming or advanced header inspection.

IconField

Exported type from @dyrected/core.

export type IconField = TypedField<"icon", string, IconFieldAdmin> & CharacterLimitFieldConfig;

IconFieldAdmin

Exported type from @dyrected/core.

export type IconFieldAdmin = CharacterLimitFieldAdmin;

ImageField

Exported type from @dyrected/core.

export type ImageField = TypedField<"image", string | string[]>;

InferDocShape

Exported type from @dyrected/core.

export type InferDocShape<Fields extends readonly Field[]> = Fields extends readonly []
  ? Record<never, never>
  : Fields extends readonly [infer Head extends Field, ...infer Tail extends readonly Field[]]
    ? InferFieldEntry<Head> & InferDocShape<Tail>
    : Record<string, unknown>;

JoinField

Exported type from @dyrected/core.

export type JoinField = TypedField<"join", unknown>;

JsonField

Exported type from @dyrected/core.

export type JsonField = TypedField<"json", Record<string, unknown>>;

MultiSelectField

Exported type from @dyrected/core.

export type MultiSelectField = TypedField<"multiSelect", string[], MultiSelectFieldAdmin>;

MultiSelectFieldAdmin

Exported type from @dyrected/core.

export type MultiSelectFieldAdmin = {
  hooks?: {
    /** Client-side option recalculation for dependent multi-select fields. */
    options?: FieldAdminOptionsHook;
  };
};

NumberField

Exported type from @dyrected/core.

export type NumberField = TypedField<"number", number>;

ObjectField

Exported type from @dyrected/core.

export type ObjectField = TypedField<"object", unknown>;

RadioField

Exported type from @dyrected/core.

export type RadioField = TypedField<"radio", string, RadioFieldAdmin>;

RadioFieldAdmin

Exported type from @dyrected/core.

export type RadioFieldAdmin = {
  /** Radio group orientation. */
  direction?: "horizontal" | "vertical";
  hooks?: {
    /** Client-side option recalculation for dependent radio groups. */
    options?: FieldAdminOptionsHook;
  };
};

RelationshipField

Exported type from @dyrected/core.

export type RelationshipField = TypedField<"relationship", string | string[]>;

RichTextField

Exported type from @dyrected/core.

export type RichTextField = TypedField<"richText", Record<string, unknown>>;

RowField

Exported type from @dyrected/core.

export type RowField = TypedField<"row", unknown>;

SelectField

Exported type from @dyrected/core.

export type SelectField = TypedField<"select", string, SelectFieldAdmin>;

SelectFieldAdmin

Exported type from @dyrected/core.

export type SelectFieldAdmin = {
  /** Select presentation style. */
  layout?: "radio" | "select";
  /** Radio orientation when `layout: 'radio'` is used. */
  direction?: "horizontal" | "vertical";
  hooks?: {
    /** Client-side option recalculation for dependent dropdowns or radios. */
    options?: FieldAdminOptionsHook;
  };
};

SystemDocFields

Exported type from @dyrected/core.

export type SystemDocFields = {
  createdAt?: string;
  updatedAt?: string;
  createdBy?: string;
  updatedBy?: string;
};

TextareaField

Exported type from @dyrected/core.

export type TextareaField = TypedField<"textarea", string, TextareaFieldAdmin> &
  CharacterLimitFieldConfig &
  WordLimitFieldConfig;

TextareaFieldAdmin

Exported type from @dyrected/core.

export type TextareaFieldAdmin = CharacterLimitFieldAdmin & WordLimitFieldAdmin;

TextField

Exported type from @dyrected/core.

export type TextField = TypedField<"text", string, TextFieldAdmin> & CharacterLimitFieldConfig & WordLimitFieldConfig;

TextFieldAdmin

Exported type from @dyrected/core.

export type TextFieldAdmin = CharacterLimitFieldAdmin & WordLimitFieldAdmin;

TimeField

Exported type from @dyrected/core.

export type TimeField = TypedField<"time", string>;

TypedField

Exported type from @dyrected/core.

export type TypedField<TType extends FieldType, TValue, TAdminExtra = Record<never, never>> = Omit<FieldBase, "admin"> & {
  type: TType;
  admin?: BaseFieldAdmin & TAdminExtra;
} & FieldHooks<TValue> &
  FieldAdminHooks<TValue>;

UploadDocFields

Exported type from @dyrected/core.

export type UploadDocFields = {
  filename: string;
  filesize?: number;
  mimeType: string;
  url: string;
  width?: number;
  height?: number;
  focalPoint?: { x: number; y: number };
  blurhash?: string;
  sizes?: Record<string, { filename?: string; url?: string; width?: number; height?: number }>;
};

UrlField

Exported type from @dyrected/core.

export type UrlField = TypedField<"url", string, UrlFieldAdmin> & CharacterLimitFieldConfig;

UrlFieldAdmin

Exported type from @dyrected/core.

export type UrlFieldAdmin = CharacterLimitFieldAdmin;

WordLimitFieldAdmin

Exported type from @dyrected/core.

export type WordLimitFieldAdmin = {
  /** Admin-only compatibility alias for `field.maxWords`. Prefer the top-level field property. */
  maxWords?: number;
};

WordLimitFieldConfig

Exported interface from @dyrected/core.

export interface WordLimitFieldConfig {
  /** Advisory maximum word count exposed to editors and client tooling. */
  maxWords?: number;
}
MemberSignatureDescription
maxWordsmaxWords?: numberAdvisory maximum word count exposed to editors and client tooling.

On this page

Base properties (all fields)Text fieldstextSize and word limitstextarearichTextemailiconurlStored shapeNumeric and boolean fieldsnumberbooleanDate and time fieldsdatedatetimetimeSelection fieldsselectradiomultiSelectRelationship and media fieldsrelationshipimagejoinStructural fieldsobjectarrayblocksjsonLayout fieldsrowAdmin field optionsField accessField hooksGenerated field and hook contractsArrayFieldAuthDocFieldsAuthenticatedUserBaseFieldAdminBlockBlocksFieldBlockVariantBooleanFieldBooleanFieldAdminCharacterLimitFieldAdminCharacterLimitFieldConfigCollectionAfterChangeHookCollectionAfterDeleteHookCollectionAfterReadHookCollectionBeforeChangeHookCollectionBeforeDeleteHookCollectionBeforeReadHookDateFieldDateTimeFieldDynamicOptionItemDynamicOptionsConfigDynamicOptionsResolverDynamicOptionsResolverArgsEmailFieldEmailFieldAdminFieldFieldAdminHooksFieldAdminOnChangeHookFieldAdminOnChangeHookArgsFieldAdminOptionsHookFieldAdminOptionsHookArgsFieldAdminOptionsHookResultFieldAfterReadHookFieldAfterReadHookArgsFieldBaseFieldBeforeChangeHookFieldBeforeChangeHookArgsFieldHookFieldHooksFieldTypeGlobalAfterChangeHookGlobalAfterReadHookGlobalBeforeChangeHookGlobalBeforeReadHookHookFunctionHookRequestContextIconFieldIconFieldAdminImageFieldInferDocShapeJoinFieldJsonFieldMultiSelectFieldMultiSelectFieldAdminNumberFieldObjectFieldRadioFieldRadioFieldAdminRelationshipFieldRichTextFieldRowFieldSelectFieldSelectFieldAdminSystemDocFieldsTextareaFieldTextareaFieldAdminTextFieldTextFieldAdminTimeFieldTypedFieldUploadDocFieldsUrlFieldUrlFieldAdminWordLimitFieldAdminWordLimitFieldConfig