Selegic CRM Docs
ServerMetadata

Metadata Hooks

EntityHook and FieldHook logic, execution patterns, and type mapping.

The metadata hooks connect logical model changes to physical database operations.

EntityHook

Located in features/metadata-admin/, manages table lifecycle.

after:create

When a new Entity is created:

  1. Extract orgSlug from HandlerContext
  2. Invoke createModel with default fields:
FieldTypePurpose
idUUIDPrimary key
created_atDateTimeCreation timestamp
updated_atDateTimeLast update timestamp
created_by_idUUIDCreator user ID
updated_by_idUUIDLast updater user ID
org_idUUIDTenant identifier

after:delete

When an Entity is deleted:

  1. Invoke dropModel to remove physical table
  2. Warning: Destructive, cannot be undone
// Entity hook
after: {
  create: async (ctx) => {
    await createModel(ctx.org, ctx.result);
  },
  delete: async (ctx) => {
    await dropModel(ctx.org, ctx.params.where.id);
  },
}

FieldHook

Located in features/metadata-admin/, manages column lifecycle.

The dropColumn Flag

By default, deleting a Field does not drop the database column. To force drop, pass dropColumn: true:

// Client request to delete and drop column
await client.field.deleteOne.$post({
  json: {
    where: { id: "field_123" },
    meta: { dropColumn: true },
  },
});

Type Mapping

CRM types mapped to database types:

CRM TypeDB TypeNotes
TEXTVARCHAR(255)Short text
EMAILVARCHAR(255)With validation
URLVARCHAR(500)
LONG_TEXTTEXT
NUMBERDECIMAL(18,2)
CHECKBOXBOOLEAN
PICKLISTVARCHAR(100)
LOOKUPUUIDForeign key

LOOKUP Relationships

For LOOKUP fields, the hook configures foreign key:

fieldSpec.references = {
  schema: org,
  table: targetEntityName,
  column: "id",
  onDelete: "SET NULL",
};

Error Handling

Hooks use Effect.tryPromise. If DDL fails, the hook returns CrudError. Depending on CrudPolicy, this may roll back the metadata transaction.

On this page