import type { Field, SchemaBase } from './dsl.js'; import type { FrontAppSchema, ProjectApiSchema } from './project.js'; /** A row object: a set of database columns. Columns may come from one table * (write args of insert/update/upsert) or span tables through the main * table's foreign keys (read results of find/get) — where the columns come * from is the responsibility of the consuming position, not of this schema. * Storage is entity_schema/{api.name}/{app.name}/entity/{table}.entity.ts: * one file per table (the main table), any number of entities per file. * "Row" is only a naming convention for read-shaped entities * (OrderListRow, OrderDetailRow) — they are all defineEntity declarations. */ export interface EntitySchema extends SchemaBase { type: 'entity'; /** The backend api module this entity belongs to (shared instance from * project.config.ts apis). Entities are always backend-side. */ api: ProjectApiSchema; /** The frontend app this entity belongs to (shared instance from project.config). * Unset = api-level common domain entity shared by all modules of the api. */ app?: FrontAppSchema; /** The columns of this row object: main-table columns, external reference * columns, and — for aggregate result entities — aggField columns * (count/sum/avg outputs). */ columns: Field[]; } export function defineEntity(options: { name: string; api: ProjectApiSchema; app?: FrontAppSchema; columns: Field[]; description?: string; }): EntitySchema { if (options.app && !options.api.apps.includes(options.app)) { throw new Error(`entity ${options.name}: api '${options.api.name}' does not serve app '${options.app.name}'`); } return { type: 'entity', name: options.name, description: options.description, api: options.api, app: options.app, columns: options.columns, }; }