@murumets-ee/entity 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,903 @@
1
+ import * as _$drizzle_orm0 from "drizzle-orm";
2
+ import { SQL } from "drizzle-orm";
3
+ import * as _$drizzle_orm_pg_core0 from "drizzle-orm/pg-core";
4
+ import { PgTableWithColumns } from "drizzle-orm/pg-core";
5
+ import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
6
+
7
+ //#region src/admin-config.d.ts
8
+ /**
9
+ * Optional admin UI configuration for entities.
10
+ * Controls how entities appear in the admin sidebar, list pages, and forms.
11
+ */
12
+ interface EntityAdminConfig {
13
+ /** Sidebar section: 'content' | 'structure' | custom string. Default: 'content' */
14
+ group?: string;
15
+ /** Plural display name for sidebar + list pages. Default: title-cased pluralized entity name */
16
+ label?: string;
17
+ /** Singular label for "New X" button. Default: title-cased entity name */
18
+ labelSingular?: string;
19
+ /** Lucide icon name as string, e.g. 'file-text' */
20
+ icon?: string;
21
+ /** Description shown on list page */
22
+ description?: string;
23
+ /** Form layout. Default: 'single' */
24
+ layout?: 'single' | 'two-column';
25
+ /** Fields to hide in the form */
26
+ hiddenFields?: string[];
27
+ /** Columns to hide in the list */
28
+ hiddenColumns?: string[];
29
+ /** Per-field label/description/placeholder overrides */
30
+ fieldOverrides?: Record<string, {
31
+ label?: string;
32
+ description?: string;
33
+ placeholder?: string;
34
+ }>;
35
+ /** Default list sort field. Default: 'createdAt' */
36
+ defaultSort?: string;
37
+ /** Default list sort direction. Default: 'desc' */
38
+ defaultSortDirection?: 'asc' | 'desc';
39
+ /** List page size. Default: 20 */
40
+ pageSize?: number;
41
+ /** For block editor: fields to show in Puck root config */
42
+ rootFields?: string[];
43
+ /** Suppress "New" button in the list page */
44
+ disableCreate?: boolean;
45
+ /** Order within sidebar group. Default: 0 */
46
+ sortOrder?: number;
47
+ }
48
+ //#endregion
49
+ //#region src/fields/base.d.ts
50
+ /**
51
+ * Field type definitions
52
+ * These define the structure and configuration for all field types
53
+ */
54
+ interface BaseFieldConfig {
55
+ required?: boolean;
56
+ default?: unknown;
57
+ translatable?: boolean;
58
+ indexed?: boolean;
59
+ unique?: boolean;
60
+ access?: {
61
+ view?: string;
62
+ edit?: string;
63
+ };
64
+ }
65
+ interface IdField extends BaseFieldConfig {
66
+ type: 'id';
67
+ }
68
+ interface TextField extends BaseFieldConfig {
69
+ type: 'text';
70
+ maxLength?: number;
71
+ minLength?: number;
72
+ pattern?: RegExp;
73
+ }
74
+ interface NumberField extends BaseFieldConfig {
75
+ type: 'number';
76
+ min?: number;
77
+ max?: number;
78
+ integer?: boolean;
79
+ }
80
+ interface BooleanField extends BaseFieldConfig {
81
+ type: 'boolean';
82
+ }
83
+ interface DateField extends BaseFieldConfig {
84
+ type: 'date';
85
+ minDate?: Date;
86
+ maxDate?: Date;
87
+ }
88
+ interface SelectField extends BaseFieldConfig {
89
+ type: 'select';
90
+ options: readonly string[];
91
+ }
92
+ interface ReferenceField extends BaseFieldConfig {
93
+ type: 'reference';
94
+ entity: string;
95
+ cardinality: 'one' | 'many';
96
+ onDelete?: 'cascade' | 'set-null' | 'restrict';
97
+ }
98
+ interface MediaField extends BaseFieldConfig {
99
+ type: 'media';
100
+ accept?: string[];
101
+ maxSize?: number;
102
+ }
103
+ interface RichTextField extends BaseFieldConfig {
104
+ type: 'richtext';
105
+ blocks?: string[];
106
+ }
107
+ interface SlugField extends BaseFieldConfig {
108
+ type: 'slug';
109
+ from: string;
110
+ unique?: boolean;
111
+ }
112
+ /**
113
+ * Minimal block definition reference — used by BlocksField to type-check allowed blocks.
114
+ * The full BlockDefinition (with label, etc.) lives in @murumets-ee/content.
115
+ */
116
+ interface BlockDefinitionRef {
117
+ slug: string;
118
+ fields: Record<string, FieldConfig>;
119
+ }
120
+ /**
121
+ * Blocks field — ordered array of typed content blocks.
122
+ * Each block instance stores its data in {entity}_layout table.
123
+ *
124
+ * @property blocks - Allowed block definitions
125
+ * @property min/max - Block count constraints
126
+ * @property localized - true = per-locale layouts, false = shared layout with translated content (default)
127
+ */
128
+ interface JsonField extends BaseFieldConfig {
129
+ type: 'json';
130
+ }
131
+ interface BlocksField extends BaseFieldConfig {
132
+ type: 'blocks';
133
+ blocks: readonly BlockDefinitionRef[];
134
+ min?: number;
135
+ max?: number;
136
+ localized?: boolean;
137
+ }
138
+ type FieldConfig = IdField | TextField | NumberField | BooleanField | DateField | SelectField | ReferenceField | MediaField | RichTextField | SlugField | JsonField | BlocksField;
139
+ //#endregion
140
+ //#region src/types/infer.d.ts
141
+ /**
142
+ * Maps a single FieldConfig to its TypeScript output type.
143
+ * Each branch is a shallow comparison — no recursion.
144
+ */
145
+ type FieldToTS<F extends FieldConfig> = F extends IdField ? string : F extends TextField ? string : F extends NumberField ? number : F extends BooleanField ? boolean : F extends DateField ? Date | string : F extends SelectField ? F['options'][number] : F extends ReferenceField ? F['cardinality'] extends 'many' ? string[] : string : F extends MediaField ? string : F extends RichTextField ? Record<string, unknown>[] : F extends SlugField ? string : F extends JsonField ? Record<string, unknown> : F extends BlocksField ? Array<{
146
+ _block: string;
147
+ _id: string;
148
+ [key: string]: unknown;
149
+ }> : never;
150
+ /**
151
+ * Extract keys of fields where `required` is literally `true`.
152
+ * Fields without `required` or with `required?: false` are optional.
153
+ */
154
+ type RequiredFieldKeys<Fields extends Record<string, FieldConfig>> = { [K in keyof Fields]: Fields[K]['required'] extends true ? K : never }[keyof Fields];
155
+ type OptionalFieldKeys<Fields extends Record<string, FieldConfig>> = { [K in keyof Fields]: Fields[K]['required'] extends true ? never : K }[keyof Fields];
156
+ /**
157
+ * Maps a full field record to its TypeScript output type.
158
+ * Required fields are non-nullable; optional fields are `T | null | undefined`.
159
+ *
160
+ * The `id` field is always `string` and always present.
161
+ * The `id` key from Fields is excluded to avoid duplication since
162
+ * we hardcode `{ id: string }` at the front.
163
+ */
164
+ type InferEntityDTO<Fields extends Record<string, FieldConfig>> = {
165
+ id: string;
166
+ } & { [K in Exclude<RequiredFieldKeys<Fields>, 'id'>]: FieldToTS<Fields[K]> } & { [K in OptionalFieldKeys<Fields>]?: FieldToTS<Fields[K]> | null };
167
+ /** Fields that are auto-generated and should not appear in create input. */
168
+ type AutoGeneratedFields = 'id' | 'createdAt' | 'updatedAt' | 'createdBy' | 'updatedBy' | '_version';
169
+ /**
170
+ * The input type for creating an entity.
171
+ * - Omits auto-generated fields (id, timestamps, version)
172
+ * - Required fields stay required; optional fields stay optional
173
+ */
174
+ type InferCreateInput<Fields extends Record<string, FieldConfig>> = Omit<{ [K in Exclude<RequiredFieldKeys<Fields>, 'id'>]: FieldToTS<Fields[K]> } & { [K in OptionalFieldKeys<Fields>]?: FieldToTS<Fields[K]> | null }, AutoGeneratedFields>;
175
+ /** Fields that cannot be changed after creation. */
176
+ type ImmutableFields = 'id' | 'createdAt' | 'createdBy';
177
+ type InferUpdateInput<Fields extends Record<string, FieldConfig>> = Partial<Omit<InferEntityDTO<Fields>, ImmutableFields>>;
178
+ /**
179
+ * Behavior field types use `type` (not `interface`) because interfaces
180
+ * lack implicit index signatures needed for Record<string, FieldConfig>.
181
+ *
182
+ * Types are simplified to match what the field builders actually return,
183
+ * with only the specificity that FieldToTS needs (e.g., options tuple
184
+ * for SelectField, cardinality for ReferenceField).
185
+ */
186
+ /** Fields added by publishable() */
187
+ type PublishableFields = {
188
+ status: SelectField & {
189
+ options: readonly ['draft', 'published'];
190
+ };
191
+ publishedAt: DateField;
192
+ };
193
+ /** Fields added by auditable() */
194
+ type AuditableFields = {
195
+ createdBy: TextField;
196
+ updatedBy: TextField;
197
+ createdAt: DateField;
198
+ updatedAt: DateField;
199
+ };
200
+ /** Fields added by sluggable() */
201
+ type SluggableFields = {
202
+ slug: SlugField;
203
+ };
204
+ /** Fields added by revisionable() */
205
+ type RevisionableFields = {
206
+ _version: NumberField;
207
+ };
208
+ /** Fields added by hierarchical() */
209
+ type HierarchicalFields = {
210
+ parentId: ReferenceField & {
211
+ cardinality: 'one';
212
+ };
213
+ path: TextField;
214
+ depth: NumberField;
215
+ };
216
+ /**
217
+ * Extract the DTO type from an Entity.
218
+ *
219
+ * Usage:
220
+ * const Article = defineEntity({ ... })
221
+ * type ArticleDTO = InferEntity<typeof Article>
222
+ */
223
+ type InferEntity<E> = E extends {
224
+ allFields: infer F extends Record<string, FieldConfig>;
225
+ } ? InferEntityDTO<F> : never;
226
+ //#endregion
227
+ //#region src/behaviors/types.d.ts
228
+ interface Behavior<F extends Record<string, FieldConfig> = Record<string, FieldConfig>> {
229
+ name: string;
230
+ fields?: F;
231
+ hooks?: {
232
+ beforeCreate?: (data: Record<string, unknown>) => Promise<Record<string, unknown>>;
233
+ afterCreate?: (entity: Record<string, unknown>) => Promise<void>;
234
+ beforeUpdate?: (id: string, data: Record<string, unknown>) => Promise<Record<string, unknown>>;
235
+ afterUpdate?: (entity: Record<string, unknown>) => Promise<void>;
236
+ beforeDelete?: (id: string) => Promise<void>;
237
+ afterDelete?: (id: string) => Promise<void>;
238
+ };
239
+ }
240
+ type BehaviorFactory = (...args: unknown[]) => Behavior;
241
+ //#endregion
242
+ //#region src/behaviors/auditable.d.ts
243
+ declare function auditable(): Behavior<AuditableFields>;
244
+ //#endregion
245
+ //#region src/behaviors/hierarchical.d.ts
246
+ interface HierarchicalOptions {
247
+ /**
248
+ * What happens when deleting a node that has children.
249
+ * - 'restrict': Prevent deletion (default)
250
+ * - 'cascade': Delete all descendants
251
+ * - 'reparent': Move children to the deleted node's parent
252
+ */
253
+ onDelete?: 'restrict' | 'cascade' | 'reparent';
254
+ }
255
+ declare function hierarchical(_options?: HierarchicalOptions): Behavior<HierarchicalFields>;
256
+ //#endregion
257
+ //#region src/behaviors/publishable.d.ts
258
+ declare function publishable(): Behavior<PublishableFields>;
259
+ //#endregion
260
+ //#region src/behaviors/revisionable.d.ts
261
+ declare function revisionable(): Behavior<RevisionableFields>;
262
+ //#endregion
263
+ //#region src/behaviors/sluggable.d.ts
264
+ interface SluggableOptions {
265
+ /** Make the slug translatable — each locale gets its own slug. Default: false */
266
+ translatable?: boolean;
267
+ }
268
+ /**
269
+ * Convert text to URL-safe slug
270
+ */
271
+ declare function slugify(text: string): string;
272
+ declare function sluggable(sourceField: string, options?: SluggableOptions): Behavior<SluggableFields>;
273
+ //#endregion
274
+ //#region src/fields/builders.d.ts
275
+ declare const field: {
276
+ /**
277
+ * ID field (auto-added to every entity)
278
+ */
279
+ id: <const C extends Partial<IdField> = {}>(config?: C) => IdField & C;
280
+ /**
281
+ * Text field
282
+ */
283
+ text: <const C extends Partial<TextField> = {}>(config?: C) => TextField & C;
284
+ /**
285
+ * Number field
286
+ */
287
+ number: <const C extends Partial<NumberField> = {}>(config?: C) => NumberField & C;
288
+ /**
289
+ * Boolean field
290
+ */
291
+ boolean: <const C extends Partial<BooleanField> = {}>(config?: C) => BooleanField & C;
292
+ /**
293
+ * Date field
294
+ */
295
+ date: <const C extends Partial<DateField> = {}>(config?: C) => DateField & C;
296
+ /**
297
+ * Select field (enum)
298
+ * Preserves literal option types for type inference.
299
+ * e.g. field.select({ options: ['news', 'tutorial'] }) infers 'news' | 'tutorial'
300
+ */
301
+ select: <const O extends readonly string[], const C extends Omit<Partial<SelectField>, "options"> = {}>(config: {
302
+ options: O;
303
+ } & C) => SelectField & {
304
+ options: O;
305
+ } & C;
306
+ /**
307
+ * Reference field (foreign key to another entity)
308
+ * Preserves literal cardinality to distinguish string vs string[] in inferred types.
309
+ */
310
+ reference: <C extends "one" | "many" = "one", const R extends Partial<Omit<ReferenceField, "entity" | "cardinality">> = {}>(config: {
311
+ entity: string;
312
+ cardinality?: C;
313
+ } & R) => ReferenceField & {
314
+ cardinality: C;
315
+ } & R;
316
+ /**
317
+ * Media field (file upload)
318
+ */
319
+ media: <const C extends Partial<MediaField> = {}>(config?: C) => MediaField & C;
320
+ /**
321
+ * Rich text field (WYSIWYG editor)
322
+ */
323
+ richtext: <const C extends Partial<RichTextField> = {}>(config?: C) => RichTextField & C;
324
+ /**
325
+ * Slug field (URL-safe string, auto-generated from source field)
326
+ */
327
+ slug: <const C extends Partial<SlugField> = {}>(config: Pick<SlugField, "from"> & C) => SlugField & C;
328
+ /**
329
+ * JSON field (arbitrary JSON data, stored as JSONB)
330
+ */
331
+ json: <const C extends Partial<JsonField> = {}>(config?: C) => JsonField & C;
332
+ /**
333
+ * Blocks field — ordered array of typed content blocks
334
+ * Preserves literal block tuple type for discriminated union inference.
335
+ */
336
+ blocks: <const B extends readonly BlockDefinitionRef[]>(config: {
337
+ blocks: B;
338
+ min?: number;
339
+ max?: number;
340
+ localized?: boolean;
341
+ }) => BlocksField & {
342
+ blocks: B;
343
+ };
344
+ };
345
+ //#endregion
346
+ //#region src/behaviors/timestamped.d.ts
347
+ type TimestampedFields = {
348
+ createdAt: ReturnType<typeof field.date>;
349
+ updatedAt: ReturnType<typeof field.date>;
350
+ };
351
+ declare function timestamped(): Behavior<TimestampedFields>;
352
+ //#endregion
353
+ //#region src/behaviors/index.d.ts
354
+ /**
355
+ * Behavior namespace for fluent API
356
+ */
357
+ declare const behavior: {
358
+ publishable: typeof publishable;
359
+ auditable: typeof auditable;
360
+ sluggable: typeof sluggable;
361
+ revisionable: typeof revisionable;
362
+ hierarchical: typeof hierarchical;
363
+ timestamped: typeof timestamped;
364
+ };
365
+ //#endregion
366
+ //#region src/count-cache.d.ts
367
+ /**
368
+ * In-memory TTL cache for COUNT(*) query results.
369
+ *
370
+ * Reduces database load on paginated list pages where the total count
371
+ * is recalculated on every pagination/sort/search interaction. The cache
372
+ * is per-process (not shared across workers) with a short TTL (default 5s)
373
+ * so counts are at most a few seconds stale.
374
+ *
375
+ * Cache keys include the entity name + serialized WHERE clause, so filtered
376
+ * and unfiltered counts are cached independently.
377
+ */
378
+ /**
379
+ * Interface for count cache implementations.
380
+ * Used in client configs to avoid TypeScript private-field structural incompatibility
381
+ * across separate .d.ts files.
382
+ */
383
+ interface CountCacheLike {
384
+ get(key: string): number | undefined;
385
+ set(key: string, count: number): void;
386
+ invalidate(prefix: string): void;
387
+ }
388
+ declare class CountCache implements CountCacheLike {
389
+ private cache;
390
+ private ttlMs;
391
+ constructor(ttlMs?: number);
392
+ /**
393
+ * Get a cached count. Returns undefined on miss or expired entry.
394
+ */
395
+ get(key: string): number | undefined;
396
+ /**
397
+ * Cache a count result with the configured TTL.
398
+ */
399
+ set(key: string, count: number): void;
400
+ /**
401
+ * Invalidate all cache entries whose key starts with the given prefix.
402
+ * Typically called with the entity name after mutations (create/update/delete).
403
+ */
404
+ invalidate(prefix: string): void;
405
+ /**
406
+ * Remove all expired entries. Useful for periodic cleanup in long-running processes.
407
+ */
408
+ prune(): void;
409
+ /**
410
+ * Clear the entire cache.
411
+ */
412
+ clear(): void;
413
+ /**
414
+ * Number of entries currently in the cache (including expired ones not yet pruned).
415
+ */
416
+ get size(): number;
417
+ }
418
+ //#endregion
419
+ //#region src/count-estimate.d.ts
420
+ /**
421
+ * Estimate the total row count for a table using Postgres statistics.
422
+ *
423
+ * Returns the approximate row count from `pg_class.reltuples`, which is
424
+ * updated by VACUUM/ANALYZE. Returns 0 if the table is not found or
425
+ * statistics are not yet available (e.g., freshly created table).
426
+ *
427
+ * @param db - Drizzle Postgres database instance
428
+ * @param tableName - The Postgres table name (without schema prefix)
429
+ * @returns Estimated row count (non-negative integer)
430
+ */
431
+ declare function estimateRowCount(db: PostgresJsDatabase, tableName: string): Promise<number>;
432
+ //#endregion
433
+ //#region src/cursor.d.ts
434
+ /** Cursor input for keyset pagination. */
435
+ interface CursorInput {
436
+ /** Sort field name (e.g. 'createdAt'). Must be a real column on the entity. */
437
+ field: string;
438
+ /** Last seen value of the sort field. */
439
+ value: string | number;
440
+ /** Sort direction — must match the ORDER BY direction. */
441
+ direction: 'asc' | 'desc';
442
+ /** Tie-breaker: last seen entity ID. Required for non-unique sort fields. */
443
+ id?: string;
444
+ }
445
+ /** Decoded cursor (internal, after validation). */
446
+ interface DecodedCursor {
447
+ field: string;
448
+ value: string | number;
449
+ direction: 'asc' | 'desc';
450
+ id?: string;
451
+ }
452
+ /**
453
+ * Encode a cursor for API transport (base64url).
454
+ * Built from the last item in a result set.
455
+ */
456
+ declare function encodeCursor(item: Record<string, unknown>, sortField: string, direction: 'asc' | 'desc'): string;
457
+ /**
458
+ * Decode and validate a cursor string from query params.
459
+ * Returns null if the cursor is malformed, tampered, or invalid.
460
+ *
461
+ * Security: the `field` value is NOT validated here — the caller must
462
+ * whitelist it against the entity's actual columns.
463
+ */
464
+ declare function decodeCursor(encoded: string): DecodedCursor | null;
465
+ /**
466
+ * Build the keyset WHERE condition from a decoded cursor.
467
+ *
468
+ * For DESC: `WHERE (field < value) OR (field = value AND id < cursorId)`
469
+ * For ASC: `WHERE (field > value) OR (field = value AND id > cursorId)`
470
+ *
471
+ * The caller must verify that `cursor.field` exists on the table before calling.
472
+ *
473
+ * @param table - Drizzle table with columns
474
+ * @param cursor - Decoded and validated cursor
475
+ * @returns SQL condition, or null if the field doesn't exist on the table
476
+ */
477
+ declare function buildCursorCondition(table: PgTableWithColumns<any>, cursor: DecodedCursor): SQL | null;
478
+ //#endregion
479
+ //#region src/define-entity.d.ts
480
+ /**
481
+ * Entity definition input (without behaviors — behaviors are typed separately
482
+ * on the `defineEntity` function to enable tuple inference).
483
+ *
484
+ * @typeParam F - The literal field map. Inferred automatically from the call site.
485
+ */
486
+ interface EntityDefinition<F extends Record<string, FieldConfig> = Record<string, FieldConfig>> {
487
+ name: string;
488
+ kind?: 'collection' | 'singleton';
489
+ fields: F;
490
+ scope?: 'global' | 'team' | 'user';
491
+ access?: {
492
+ view?: string;
493
+ create?: string;
494
+ update?: string;
495
+ delete?: string;
496
+ };
497
+ /** Admin UI configuration — controls sidebar, list, and form display */
498
+ admin?: EntityAdminConfig;
499
+ }
500
+ /**
501
+ * Full input for defineEntity (fields + behaviors + other config).
502
+ * Behaviors are typed as a tuple `B` for type extraction.
503
+ */
504
+ type EntityInput<F extends Record<string, FieldConfig> = Record<string, FieldConfig>, B extends Behavior[] = Behavior[]> = EntityDefinition<F> & {
505
+ behaviors?: B;
506
+ };
507
+ /**
508
+ * A fully resolved entity with merged behavior fields.
509
+ * @typeParam AllFields - The complete field map (id + behaviors + user fields).
510
+ */
511
+ interface Entity<AllFields extends Record<string, FieldConfig> = Record<string, FieldConfig>> {
512
+ name: string;
513
+ kind?: 'collection' | 'singleton';
514
+ fields: Record<string, FieldConfig>;
515
+ behaviors?: Behavior[];
516
+ scope?: 'global' | 'team' | 'user';
517
+ access?: {
518
+ view?: string;
519
+ create?: string;
520
+ update?: string;
521
+ delete?: string;
522
+ };
523
+ /** Admin UI configuration — controls sidebar, list, and form display */
524
+ admin?: EntityAdminConfig;
525
+ allFields: AllFields;
526
+ hooks: Behavior['hooks'];
527
+ }
528
+ /**
529
+ * Extract and intersect behavior field types from a behaviors tuple.
530
+ * Walks the tuple recursively (depth bounded by number of behaviors, max ~5).
531
+ */
532
+ type ExtractBehaviorFields<B extends Behavior[]> = B extends [Behavior<infer F1>, ...infer Rest extends Behavior[]] ? F1 & ExtractBehaviorFields<Rest> : {};
533
+ /**
534
+ * Define an entity with full type inference.
535
+ *
536
+ * @example
537
+ * const Article = defineEntity({
538
+ * name: 'article',
539
+ * fields: {
540
+ * title: field.text({ required: true }),
541
+ * featured: field.boolean(),
542
+ * },
543
+ * behaviors: [publishable(), auditable()],
544
+ * })
545
+ *
546
+ * type ArticleDTO = InferEntity<typeof Article>
547
+ * // { id: string; title: string; featured?: boolean | null; status?: ...; createdAt?: ...; }
548
+ */
549
+ declare function defineEntity<F extends Record<string, FieldConfig>, const B extends Behavior[] = []>(definition: EntityDefinition<F> & {
550
+ behaviors?: B;
551
+ }): Entity<{
552
+ id: IdField;
553
+ } & ExtractBehaviorFields<B> & F>;
554
+ //#endregion
555
+ //#region src/refs/find-usages.d.ts
556
+ interface EntityUsage {
557
+ sourceEntity: string;
558
+ sourceId: string;
559
+ sourceField: string;
560
+ }
561
+ //#endregion
562
+ //#region src/refs/errors.d.ts
563
+ declare class ReferencedEntityError extends Error {
564
+ readonly entityName: string;
565
+ readonly entityId: string;
566
+ readonly usages: EntityUsage[];
567
+ constructor(entityName: string, entityId: string, usages: EntityUsage[]);
568
+ }
569
+ //#endregion
570
+ //#region src/schema-generator.d.ts
571
+ /**
572
+ * Generate a runtime Drizzle schema from an entity definition.
573
+ * Every field becomes its own column — no JSONB.
574
+ */
575
+ declare function generateSchema(entity: Entity): _$drizzle_orm_pg_core0.PgTableWithColumns<{
576
+ name: string;
577
+ schema: undefined;
578
+ columns: {
579
+ [x: string]: _$drizzle_orm_pg_core0.PgColumn<{
580
+ name: string;
581
+ tableName: string;
582
+ dataType: _$drizzle_orm0.ColumnDataType;
583
+ columnType: string;
584
+ data: unknown;
585
+ driverParam: unknown;
586
+ notNull: false;
587
+ hasDefault: false;
588
+ isPrimaryKey: false;
589
+ isAutoincrement: false;
590
+ hasRuntimeDefault: false;
591
+ enumValues: string[] | undefined;
592
+ baseColumn: never;
593
+ identity: undefined;
594
+ generated: undefined;
595
+ }, {}, {}>;
596
+ };
597
+ dialect: "pg";
598
+ }>;
599
+ /**
600
+ * Generate TypeScript code string for an entity schema.
601
+ * Every field becomes its own column — no JSONB.
602
+ */
603
+ declare function generateSchemaCode(entity: Entity): string;
604
+ /**
605
+ * Generate runtime translation table schema.
606
+ * Each translatable field gets its own nullable column.
607
+ */
608
+ declare function generateTranslationSchema(entity: Entity): _$drizzle_orm_pg_core0.PgTableWithColumns<{
609
+ name: string;
610
+ schema: undefined;
611
+ columns: {
612
+ [x: string]: _$drizzle_orm_pg_core0.PgColumn<{
613
+ name: string;
614
+ tableName: string;
615
+ dataType: _$drizzle_orm0.ColumnDataType;
616
+ columnType: string;
617
+ data: unknown;
618
+ driverParam: unknown;
619
+ notNull: false;
620
+ hasDefault: false;
621
+ isPrimaryKey: false;
622
+ isAutoincrement: false;
623
+ hasRuntimeDefault: false;
624
+ enumValues: string[] | undefined;
625
+ baseColumn: never;
626
+ identity: undefined;
627
+ generated: undefined;
628
+ }, {}, {}>;
629
+ };
630
+ dialect: "pg";
631
+ }> | null;
632
+ /**
633
+ * Generate TypeScript code string for a translation table.
634
+ * Each translatable field gets its own nullable column.
635
+ */
636
+ declare function generateTranslationSchemaCode(entity: Entity): string | null;
637
+ /**
638
+ * Check if an entity has any blocks fields
639
+ */
640
+ declare function hasBlocksFields(entity: Entity): boolean;
641
+ /**
642
+ * Generate layout table schema for entities with blocks fields.
643
+ * Stores block instances in a separate table with ordering.
644
+ *
645
+ * When blocks field has localized: false (default), locale is NULL (shared layout).
646
+ * When blocks field has localized: true, locale is set per-locale.
647
+ */
648
+ declare function generateLayoutSchema(entity: Entity): _$drizzle_orm_pg_core0.PgTableWithColumns<{
649
+ name: string;
650
+ schema: undefined;
651
+ columns: {
652
+ id: _$drizzle_orm_pg_core0.PgColumn<{
653
+ name: "id";
654
+ tableName: string;
655
+ dataType: "string";
656
+ columnType: "PgUUID";
657
+ data: string;
658
+ driverParam: string;
659
+ notNull: true;
660
+ hasDefault: true;
661
+ isPrimaryKey: true;
662
+ isAutoincrement: false;
663
+ hasRuntimeDefault: false;
664
+ enumValues: undefined;
665
+ baseColumn: never;
666
+ identity: undefined;
667
+ generated: undefined;
668
+ }, {}, {}>;
669
+ entityId: _$drizzle_orm_pg_core0.PgColumn<{
670
+ name: "entity_id";
671
+ tableName: string;
672
+ dataType: "string";
673
+ columnType: "PgUUID";
674
+ data: string;
675
+ driverParam: string;
676
+ notNull: true;
677
+ hasDefault: false;
678
+ isPrimaryKey: false;
679
+ isAutoincrement: false;
680
+ hasRuntimeDefault: false;
681
+ enumValues: undefined;
682
+ baseColumn: never;
683
+ identity: undefined;
684
+ generated: undefined;
685
+ }, {}, {}>;
686
+ fieldName: _$drizzle_orm_pg_core0.PgColumn<{
687
+ name: "field_name";
688
+ tableName: string;
689
+ dataType: "string";
690
+ columnType: "PgVarchar";
691
+ data: string;
692
+ driverParam: string;
693
+ notNull: true;
694
+ hasDefault: false;
695
+ isPrimaryKey: false;
696
+ isAutoincrement: false;
697
+ hasRuntimeDefault: false;
698
+ enumValues: [string, ...string[]];
699
+ baseColumn: never;
700
+ identity: undefined;
701
+ generated: undefined;
702
+ }, {}, {
703
+ length: 100;
704
+ }>;
705
+ blockType: _$drizzle_orm_pg_core0.PgColumn<{
706
+ name: "block_type";
707
+ tableName: string;
708
+ dataType: "string";
709
+ columnType: "PgVarchar";
710
+ data: string;
711
+ driverParam: string;
712
+ notNull: true;
713
+ hasDefault: false;
714
+ isPrimaryKey: false;
715
+ isAutoincrement: false;
716
+ hasRuntimeDefault: false;
717
+ enumValues: [string, ...string[]];
718
+ baseColumn: never;
719
+ identity: undefined;
720
+ generated: undefined;
721
+ }, {}, {
722
+ length: 100;
723
+ }>;
724
+ sortOrder: _$drizzle_orm_pg_core0.PgColumn<{
725
+ name: "sort_order";
726
+ tableName: string;
727
+ dataType: "number";
728
+ columnType: "PgInteger";
729
+ data: number;
730
+ driverParam: string | number;
731
+ notNull: true;
732
+ hasDefault: true;
733
+ isPrimaryKey: false;
734
+ isAutoincrement: false;
735
+ hasRuntimeDefault: false;
736
+ enumValues: undefined;
737
+ baseColumn: never;
738
+ identity: undefined;
739
+ generated: undefined;
740
+ }, {}, {}>;
741
+ data: _$drizzle_orm_pg_core0.PgColumn<{
742
+ name: "data";
743
+ tableName: string;
744
+ dataType: "json";
745
+ columnType: "PgJsonb";
746
+ data: unknown;
747
+ driverParam: unknown;
748
+ notNull: false;
749
+ hasDefault: false;
750
+ isPrimaryKey: false;
751
+ isAutoincrement: false;
752
+ hasRuntimeDefault: false;
753
+ enumValues: undefined;
754
+ baseColumn: never;
755
+ identity: undefined;
756
+ generated: undefined;
757
+ }, {}, {}>;
758
+ locale: _$drizzle_orm_pg_core0.PgColumn<{
759
+ name: "locale";
760
+ tableName: string;
761
+ dataType: "string";
762
+ columnType: "PgVarchar";
763
+ data: string;
764
+ driverParam: string;
765
+ notNull: false;
766
+ hasDefault: false;
767
+ isPrimaryKey: false;
768
+ isAutoincrement: false;
769
+ hasRuntimeDefault: false;
770
+ enumValues: [string, ...string[]];
771
+ baseColumn: never;
772
+ identity: undefined;
773
+ generated: undefined;
774
+ }, {}, {
775
+ length: 10;
776
+ }>;
777
+ };
778
+ dialect: "pg";
779
+ }> | null;
780
+ /**
781
+ * Check if an entity has the versionable behavior
782
+ */
783
+ declare function isVersionable(entity: Entity): boolean;
784
+ /**
785
+ * Check if an entity needs a per-locale publish status table.
786
+ * Requires both publishable() behavior AND at least one translatable field.
787
+ */
788
+ declare function needsLocaleStatus(entity: Entity): boolean;
789
+ /**
790
+ * Generate TypeScript code string for a per-locale publish status table.
791
+ */
792
+ declare function generateLocaleStatusCode(entity: Entity): string;
793
+ /**
794
+ * Check if an entity is publishable (has publishable() behavior).
795
+ */
796
+ declare function isPublishable(entity: Entity): boolean;
797
+ /**
798
+ * Generate TypeScript code string for a drafts overlay table.
799
+ */
800
+ declare function generateDraftsCode(entity: Entity): string;
801
+ /**
802
+ * Generate TypeScript code string for the shared content locks table.
803
+ */
804
+ declare function generateContentLocksCode(): string;
805
+ /**
806
+ * Check if an entity has blocks fields with translatable block content (non-localized mode).
807
+ */
808
+ declare function hasTranslatableBlocks(entity: Entity): boolean;
809
+ /**
810
+ * Generate TypeScript code string for a layout table (blocks storage).
811
+ */
812
+ declare function generateLayoutCode(entity: Entity): string;
813
+ /**
814
+ * Generate TypeScript code string for a layout translation table.
815
+ */
816
+ declare function generateLayoutTranslationCode(entity: Entity): string;
817
+ /**
818
+ * Generate TypeScript code string for a versions table.
819
+ */
820
+ declare function generateVersionsCode(entity: Entity): string;
821
+ /**
822
+ * Generate layout translation table for non-localized blocks with translatable fields.
823
+ */
824
+ declare function generateLayoutTranslationSchema(entity: Entity): _$drizzle_orm_pg_core0.PgTableWithColumns<{
825
+ name: string;
826
+ schema: undefined;
827
+ columns: {
828
+ id: _$drizzle_orm_pg_core0.PgColumn<{
829
+ name: "id";
830
+ tableName: string;
831
+ dataType: "string";
832
+ columnType: "PgUUID";
833
+ data: string;
834
+ driverParam: string;
835
+ notNull: true;
836
+ hasDefault: true;
837
+ isPrimaryKey: true;
838
+ isAutoincrement: false;
839
+ hasRuntimeDefault: false;
840
+ enumValues: undefined;
841
+ baseColumn: never;
842
+ identity: undefined;
843
+ generated: undefined;
844
+ }, {}, {}>;
845
+ layoutId: _$drizzle_orm_pg_core0.PgColumn<{
846
+ name: "layout_id";
847
+ tableName: string;
848
+ dataType: "string";
849
+ columnType: "PgUUID";
850
+ data: string;
851
+ driverParam: string;
852
+ notNull: true;
853
+ hasDefault: false;
854
+ isPrimaryKey: false;
855
+ isAutoincrement: false;
856
+ hasRuntimeDefault: false;
857
+ enumValues: undefined;
858
+ baseColumn: never;
859
+ identity: undefined;
860
+ generated: undefined;
861
+ }, {}, {}>;
862
+ locale: _$drizzle_orm_pg_core0.PgColumn<{
863
+ name: "locale";
864
+ tableName: string;
865
+ dataType: "string";
866
+ columnType: "PgVarchar";
867
+ data: string;
868
+ driverParam: string;
869
+ notNull: true;
870
+ hasDefault: false;
871
+ isPrimaryKey: false;
872
+ isAutoincrement: false;
873
+ hasRuntimeDefault: false;
874
+ enumValues: [string, ...string[]];
875
+ baseColumn: never;
876
+ identity: undefined;
877
+ generated: undefined;
878
+ }, {}, {
879
+ length: 10;
880
+ }>;
881
+ fields: _$drizzle_orm_pg_core0.PgColumn<{
882
+ name: "fields";
883
+ tableName: string;
884
+ dataType: "json";
885
+ columnType: "PgJsonb";
886
+ data: unknown;
887
+ driverParam: unknown;
888
+ notNull: true;
889
+ hasDefault: false;
890
+ isPrimaryKey: false;
891
+ isAutoincrement: false;
892
+ hasRuntimeDefault: false;
893
+ enumValues: undefined;
894
+ baseColumn: never;
895
+ identity: undefined;
896
+ generated: undefined;
897
+ }, {}, {}>;
898
+ };
899
+ dialect: "pg";
900
+ }> | null;
901
+ //#endregion
902
+ export { type AuditableFields, type Behavior, type BehaviorFactory, type BlockDefinitionRef, type BlocksField, type BooleanField, CountCache, type CountCacheLike, type CursorInput, type DateField, type Entity, type EntityAdminConfig, type EntityDefinition, type EntityInput, type EntityUsage, type FieldConfig, type FieldToTS, type HierarchicalFields, type IdField, type InferCreateInput, type InferEntity, type InferEntityDTO, type InferUpdateInput, type JsonField, type MediaField, type NumberField, type PublishableFields, type ReferenceField, ReferencedEntityError, type RevisionableFields, type RichTextField, type SelectField, type SlugField, type SluggableFields, type SluggableOptions, type TextField, auditable, behavior, buildCursorCondition, decodeCursor, defineEntity, encodeCursor, estimateRowCount, field, generateContentLocksCode, generateDraftsCode, generateLayoutCode, generateLayoutSchema, generateLayoutTranslationCode, generateLayoutTranslationSchema, generateLocaleStatusCode, generateSchema, generateSchemaCode, generateTranslationSchema, generateTranslationSchemaCode, generateVersionsCode, hasBlocksFields, hasTranslatableBlocks, hierarchical, isPublishable, isVersionable, needsLocaleStatus, publishable, revisionable, sluggable, slugify, timestamped };
903
+ //# sourceMappingURL=index.d.mts.map