@danceroutine/tango-schema 0.1.0 → 1.0.0

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.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +122 -0
  3. package/dist/domain/DeleteReferentialAction.d.ts +1 -2
  4. package/dist/domain/Model.d.ts +17 -1
  5. package/dist/domain/ModelMetadata.d.ts +7 -0
  6. package/dist/domain/ModelWriteHooks.d.ts +82 -0
  7. package/dist/domain/UpdateReferentialAction.d.ts +1 -2
  8. package/dist/domain/index.d.ts +2 -1
  9. package/dist/domain-Cufz6y1q.js.map +1 -1
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.js +2 -2
  12. package/dist/model/ModelAugmentorRegistry.d.ts +11 -0
  13. package/dist/model/ModelDefinition.d.ts +12 -1
  14. package/dist/model/RelationBuilder.d.ts +6 -0
  15. package/dist/model/constraints/Constraints.d.ts +19 -0
  16. package/dist/model/constraints/Indexes.d.ts +4 -0
  17. package/dist/model/constraints/index.d.ts +6 -0
  18. package/dist/model/decorators/Decorators.d.ts +35 -0
  19. package/dist/model/decorators/index.d.ts +6 -0
  20. package/dist/model/decorators/types.d.ts +29 -0
  21. package/dist/model/index.d.ts +8 -0
  22. package/dist/model/index.js +2 -2
  23. package/dist/model/inferFields.d.ts +8 -1
  24. package/dist/model/internal/FieldMetadataStore.d.ts +3 -0
  25. package/dist/model/meta/Meta.d.ts +22 -0
  26. package/dist/model/meta/index.d.ts +5 -0
  27. package/dist/model/registry/ModelRegistry.d.ts +68 -0
  28. package/dist/model-DI8lQH1W.js +585 -0
  29. package/dist/model-DI8lQH1W.js.map +1 -0
  30. package/package.json +52 -50
  31. package/dist/domain/DeleteReferentialAction.js +0 -1
  32. package/dist/domain/Model.js +0 -1
  33. package/dist/domain/UpdateReferentialAction.js +0 -1
  34. package/dist/domain/internal/InternalFieldType.js +0 -10
  35. package/dist/domain/internal/InternalReferentialAction.d.ts +0 -6
  36. package/dist/domain/internal/InternalReferentialAction.js +0 -6
  37. package/dist/domain/internal/InternalRelationType.js +0 -5
  38. package/dist/domain/internal/ZodGuards.d.ts +0 -13
  39. package/dist/domain/internal/ZodGuards.js +0 -39
  40. package/dist/domain/internal/zod/hasConstructorName.js +0 -5
  41. package/dist/domain/internal/zod/index.js +0 -13
  42. package/dist/domain/internal/zod/isDate.js +0 -3
  43. package/dist/domain/internal/zod/isZodArray.js +0 -5
  44. package/dist/domain/internal/zod/isZodBoolean.js +0 -5
  45. package/dist/domain/internal/zod/isZodDate.js +0 -5
  46. package/dist/domain/internal/zod/isZodDefault.js +0 -5
  47. package/dist/domain/internal/zod/isZodNullable.js +0 -5
  48. package/dist/domain/internal/zod/isZodNumber.js +0 -5
  49. package/dist/domain/internal/zod/isZodObject.js +0 -5
  50. package/dist/domain/internal/zod/isZodOptional.js +0 -5
  51. package/dist/domain/internal/zod/isZodString.js +0 -5
  52. package/dist/model/Model.js +0 -22
  53. package/dist/model/ModelDefinition.js +0 -1
  54. package/dist/model/inferFields.js +0 -64
  55. package/dist/model-DE1qDItF.js +0 -174
  56. package/dist/model-DE1qDItF.js.map +0 -1
@@ -0,0 +1,585 @@
1
+ import { z } from "zod";
2
+
3
+ //#region rolldown:runtime
4
+ var __defProp = Object.defineProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all) __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ };
11
+
12
+ //#endregion
13
+ //#region src/domain/internal/InternalRelationType.ts
14
+ const InternalRelationType = {
15
+ HAS_MANY: "hasMany",
16
+ BELONGS_TO: "belongsTo",
17
+ HAS_ONE: "hasOne"
18
+ };
19
+
20
+ //#endregion
21
+ //#region src/model/RelationBuilder.ts
22
+ var RelationBuilder = class {
23
+ /** Declare a one-to-many relation from this model to `target`. */
24
+ hasMany(target, foreignKey$1) {
25
+ return {
26
+ type: InternalRelationType.HAS_MANY,
27
+ target,
28
+ foreignKey: foreignKey$1
29
+ };
30
+ }
31
+ /** Declare an owning relation to a parent model. */
32
+ belongsTo(target, foreignKey$1, localKey) {
33
+ return {
34
+ type: InternalRelationType.BELONGS_TO,
35
+ target,
36
+ foreignKey: foreignKey$1,
37
+ localKey
38
+ };
39
+ }
40
+ /** Declare a one-to-one relation from this model to `target`. */
41
+ hasOne(target, foreignKey$1) {
42
+ return {
43
+ type: InternalRelationType.HAS_ONE,
44
+ target,
45
+ foreignKey: foreignKey$1
46
+ };
47
+ }
48
+ };
49
+
50
+ //#endregion
51
+ //#region src/model/registry/ModelRegistry.ts
52
+ var ModelRegistry = class ModelRegistry {
53
+ static globalRegistry;
54
+ models = new Map();
55
+ /**
56
+ * Return the shared process-wide registry used by `Model(...)`.
57
+ */
58
+ static global() {
59
+ if (!ModelRegistry.globalRegistry) ModelRegistry.globalRegistry = new ModelRegistry();
60
+ return ModelRegistry.globalRegistry;
61
+ }
62
+ /**
63
+ * Register a model on the shared global registry.
64
+ */
65
+ static register(model) {
66
+ ModelRegistry.global().register(model);
67
+ }
68
+ /**
69
+ * Register several models on the shared global registry.
70
+ */
71
+ static registerMany(models) {
72
+ ModelRegistry.global().registerMany(models);
73
+ }
74
+ /**
75
+ * Resolve a model from the shared registry by namespace and name.
76
+ */
77
+ static get(namespace, name) {
78
+ return ModelRegistry.global().get(namespace, name);
79
+ }
80
+ /**
81
+ * Resolve a model from the shared registry by its `namespace/name` key.
82
+ */
83
+ static getByKey(key) {
84
+ return ModelRegistry.global().getByKey(key);
85
+ }
86
+ /**
87
+ * Resolve any supported model reference form against the shared registry.
88
+ */
89
+ static resolveRef(ref) {
90
+ return ModelRegistry.global().resolveRef(ref);
91
+ }
92
+ /**
93
+ * Clear the shared registry, which is mainly useful in tests.
94
+ */
95
+ static clear() {
96
+ ModelRegistry.global().clear();
97
+ }
98
+ /**
99
+ * Register a model on this registry instance.
100
+ */
101
+ register(model) {
102
+ this.models.set(model.metadata.key, model);
103
+ }
104
+ /**
105
+ * Register several models on this registry instance.
106
+ */
107
+ registerMany(models) {
108
+ for (const model of models) this.register(model);
109
+ }
110
+ /**
111
+ * Resolve a model from this registry instance by namespace and name.
112
+ */
113
+ get(namespace, name) {
114
+ return this.getByKey(`${namespace}/${name}`);
115
+ }
116
+ /**
117
+ * Resolve a model from this registry instance by its `namespace/name` key.
118
+ */
119
+ getByKey(key) {
120
+ return this.models.get(key);
121
+ }
122
+ /**
123
+ * Resolve a string, callback, or direct model reference into a model object.
124
+ */
125
+ resolveRef(ref) {
126
+ if (typeof ref === "string") {
127
+ const model = this.getByKey(ref);
128
+ if (!model) throw new Error(`Unable to resolve model reference '${ref}'. Ensure it is registered in ModelRegistry.`);
129
+ return model;
130
+ }
131
+ if (typeof ref === "function") return ref();
132
+ return ref;
133
+ }
134
+ /**
135
+ * Remove all registered models from this registry instance.
136
+ */
137
+ clear() {
138
+ this.models.clear();
139
+ }
140
+ /**
141
+ * Return all registered models in insertion order.
142
+ */
143
+ values() {
144
+ return Array.from(this.models.values());
145
+ }
146
+ };
147
+
148
+ //#endregion
149
+ //#region src/model/ModelAugmentorRegistry.ts
150
+ const modelAugmentors = new Set();
151
+ function registerModelAugmentor(augmentor) {
152
+ modelAugmentors.add(augmentor);
153
+ for (const model of ModelRegistry.global().values()) augmentor(model);
154
+ return () => {
155
+ modelAugmentors.delete(augmentor);
156
+ };
157
+ }
158
+ function applyModelAugmentors(model) {
159
+ for (const augmentor of modelAugmentors) augmentor(model);
160
+ return model;
161
+ }
162
+
163
+ //#endregion
164
+ //#region src/domain/internal/InternalFieldType.ts
165
+ const InternalFieldType = {
166
+ SERIAL: "serial",
167
+ INT: "int",
168
+ BIGINT: "bigint",
169
+ TEXT: "text",
170
+ BOOL: "bool",
171
+ TIMESTAMPTZ: "timestamptz",
172
+ JSONB: "jsonb",
173
+ UUID: "uuid"
174
+ };
175
+
176
+ //#endregion
177
+ //#region src/model/internal/FieldMetadataStore.ts
178
+ const fieldMetadataStore = new WeakMap();
179
+ function getFieldMetadata(schema) {
180
+ return fieldMetadataStore.get(schema);
181
+ }
182
+ function setFieldMetadata(schema, meta) {
183
+ const existing = fieldMetadataStore.get(schema);
184
+ fieldMetadataStore.set(schema, {
185
+ ...existing,
186
+ ...meta
187
+ });
188
+ }
189
+
190
+ //#endregion
191
+ //#region src/domain/internal/zod/isDate.ts
192
+ function isDate(value) {
193
+ return value !== null && value !== undefined && Object.prototype.toString.call(value) === "[object Date]";
194
+ }
195
+
196
+ //#endregion
197
+ //#region src/domain/internal/zod/hasConstructorName.ts
198
+ function hasConstructorName(value, name) {
199
+ return !!value && typeof value === "object" && value.constructor?.name === name;
200
+ }
201
+
202
+ //#endregion
203
+ //#region src/domain/internal/zod/isZodArray.ts
204
+ function isZodArray(value) {
205
+ return hasConstructorName(value, "ZodArray");
206
+ }
207
+
208
+ //#endregion
209
+ //#region src/domain/internal/zod/isZodBoolean.ts
210
+ function isZodBoolean(value) {
211
+ return hasConstructorName(value, "ZodBoolean");
212
+ }
213
+
214
+ //#endregion
215
+ //#region src/domain/internal/zod/isZodDate.ts
216
+ function isZodDate(value) {
217
+ return hasConstructorName(value, "ZodDate");
218
+ }
219
+
220
+ //#endregion
221
+ //#region src/domain/internal/zod/isZodDefault.ts
222
+ function isZodDefault(value) {
223
+ return hasConstructorName(value, "ZodDefault");
224
+ }
225
+
226
+ //#endregion
227
+ //#region src/domain/internal/zod/isZodNullable.ts
228
+ function isZodNullable(value) {
229
+ return hasConstructorName(value, "ZodNullable");
230
+ }
231
+
232
+ //#endregion
233
+ //#region src/domain/internal/zod/isZodNumber.ts
234
+ function isZodNumber(value) {
235
+ return hasConstructorName(value, "ZodNumber");
236
+ }
237
+
238
+ //#endregion
239
+ //#region src/domain/internal/zod/isZodObject.ts
240
+ function isZodObject(value) {
241
+ return hasConstructorName(value, "ZodObject");
242
+ }
243
+
244
+ //#endregion
245
+ //#region src/domain/internal/zod/isZodOptional.ts
246
+ function isZodOptional(value) {
247
+ return hasConstructorName(value, "ZodOptional");
248
+ }
249
+
250
+ //#endregion
251
+ //#region src/domain/internal/zod/isZodString.ts
252
+ function isZodString(value) {
253
+ return hasConstructorName(value, "ZodString");
254
+ }
255
+
256
+ //#endregion
257
+ //#region src/model/inferFields.ts
258
+ function inferField(name, zodType, meta, registry) {
259
+ let type;
260
+ let notNull$1 = true;
261
+ let defaultValue$1 = undefined;
262
+ let unwrapped = zodType;
263
+ if (isZodOptional(unwrapped)) {
264
+ notNull$1 = false;
265
+ unwrapped = unwrapped.unwrap();
266
+ }
267
+ if (isZodNullable(unwrapped)) {
268
+ notNull$1 = false;
269
+ unwrapped = unwrapped.unwrap();
270
+ }
271
+ if (isZodDefault(unwrapped)) {
272
+ const def = unwrapped._zod.def.defaultValue;
273
+ if (isDate(def)) defaultValue$1 = { now: true };
274
+ else if (typeof def === "string" || typeof def === "number") defaultValue$1 = String(def);
275
+ unwrapped = unwrapped.removeDefault();
276
+ }
277
+ if (isZodString(unwrapped)) type = InternalFieldType.TEXT;
278
+ else if (isZodNumber(unwrapped)) {
279
+ const checks = unwrapped._zod.def.checks ?? [];
280
+ const isInt = checks.some((c) => "format" in c._zod.def && c._zod.def.format === "safeint");
281
+ type = isInt ? InternalFieldType.INT : InternalFieldType.BIGINT;
282
+ } else if (isZodBoolean(unwrapped)) type = InternalFieldType.BOOL;
283
+ else if (isZodDate(unwrapped)) type = InternalFieldType.TIMESTAMPTZ;
284
+ else if (isZodObject(unwrapped) || isZodArray(unwrapped)) type = InternalFieldType.JSONB;
285
+ else return null;
286
+ const field = {
287
+ name,
288
+ type,
289
+ notNull: notNull$1,
290
+ default: defaultValue$1
291
+ };
292
+ if (!meta) return field;
293
+ if (meta.dbColumn) field.name = meta.dbColumn;
294
+ if (typeof meta.notNull === "boolean") field.notNull = meta.notNull;
295
+ if (meta.default !== undefined) field.default = meta.default;
296
+ if (meta.primaryKey) field.primaryKey = true;
297
+ if (meta.unique) field.unique = true;
298
+ if (meta.references && meta.relationKind !== "manyToMany") {
299
+ const targetModel = registry.resolveRef(meta.references.target);
300
+ const referencedColumn = meta.references.options?.column ?? targetModel.metadata.fields.find((candidate) => candidate.primaryKey)?.name ?? "id";
301
+ field.references = {
302
+ table: targetModel.metadata.table,
303
+ column: referencedColumn,
304
+ onDelete: meta.references.options?.onDelete,
305
+ onUpdate: meta.references.options?.onUpdate
306
+ };
307
+ }
308
+ return field;
309
+ }
310
+ function inferFieldsFromSchema(schema, options) {
311
+ const registry = options?.registry ?? ModelRegistry.global();
312
+ const shape = schema.shape;
313
+ const fields = [];
314
+ for (const [name, zodType] of Object.entries(shape)) {
315
+ const field = inferField(name, zodType, getFieldMetadata(zodType), registry);
316
+ if (field) fields.push(field);
317
+ }
318
+ return fields;
319
+ }
320
+
321
+ //#endregion
322
+ //#region src/model/Model.ts
323
+ function deriveTableName(name) {
324
+ const snake = toSnakeCase(name);
325
+ return pluralize(snake);
326
+ }
327
+ function toSnakeCase(value) {
328
+ return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toLowerCase();
329
+ }
330
+ function pluralize(value) {
331
+ if (/(s|x|z|ch|sh)$/.test(value)) return `${value}es`;
332
+ if (/[^aeiou]y$/.test(value)) return `${value.slice(0, -1)}ies`;
333
+ return `${value}s`;
334
+ }
335
+ function Model(definition) {
336
+ if (!definition.namespace.trim()) throw new Error("Model.namespace is required and cannot be empty.");
337
+ if (!definition.name.trim()) throw new Error("Model.name is required and cannot be empty.");
338
+ if (definition.table !== undefined && !definition.table.trim()) throw new Error("Model.table cannot be empty when provided.");
339
+ const builder = new RelationBuilder();
340
+ const relations = definition.relations ? definition.relations(builder) : undefined;
341
+ const registry = ModelRegistry.global();
342
+ const fields = definition.fields || inferFieldsFromSchema(definition.schema, { registry });
343
+ const key = `${definition.namespace}/${definition.name}`;
344
+ const table = definition.table?.trim() || deriveTableName(definition.name);
345
+ const metadata = {
346
+ namespace: definition.namespace,
347
+ name: definition.name,
348
+ key,
349
+ table,
350
+ fields,
351
+ indexes: definition.indexes,
352
+ relations,
353
+ ordering: definition.ordering,
354
+ managed: definition.managed,
355
+ defaultRelatedName: definition.defaultRelatedName,
356
+ constraints: definition.constraints
357
+ };
358
+ const baseModel = {
359
+ metadata,
360
+ schema: definition.schema,
361
+ hooks: definition.hooks
362
+ };
363
+ const model = applyModelAugmentors(baseModel);
364
+ registry.register(model);
365
+ return model;
366
+ }
367
+
368
+ //#endregion
369
+ //#region src/model/decorators/Decorators.ts
370
+ function isZodType(value) {
371
+ return !!value && typeof value === "object" && "safeParse" in value && typeof value.safeParse === "function";
372
+ }
373
+ function decorate(schema, meta) {
374
+ setFieldMetadata(schema, meta);
375
+ return schema;
376
+ }
377
+ function maybeDecorator(schemaOrUndefined, meta) {
378
+ if (schemaOrUndefined) return decorate(schemaOrUndefined, meta);
379
+ return (schema) => decorate(schema, meta);
380
+ }
381
+ function primaryKey(schema) {
382
+ return maybeDecorator(schema, {
383
+ primaryKey: true,
384
+ notNull: true
385
+ });
386
+ }
387
+ function unique(schema) {
388
+ return maybeDecorator(schema, { unique: true });
389
+ }
390
+ function nullValue(schema) {
391
+ return maybeDecorator(schema, { notNull: false });
392
+ }
393
+ function notNull(schema) {
394
+ return maybeDecorator(schema, { notNull: true });
395
+ }
396
+ function defaultValue(schema, value) {
397
+ return decorate(schema, { default: value });
398
+ }
399
+ function dbDefault(schema, value) {
400
+ return decorate(schema, { dbDefault: value });
401
+ }
402
+ function dbColumn(schema, name) {
403
+ return decorate(schema, { dbColumn: name });
404
+ }
405
+ function dbIndex(schema) {
406
+ return decorate(schema, { dbIndex: true });
407
+ }
408
+ function choices(schema, values) {
409
+ return decorate(schema, { choices: values });
410
+ }
411
+ function validators(schema, ...values) {
412
+ return decorate(schema, { validators: values });
413
+ }
414
+ function helpText(schema, text) {
415
+ return decorate(schema, { helpText: text });
416
+ }
417
+ function errorMessages(schema, map) {
418
+ return decorate(schema, { errorMessages: map });
419
+ }
420
+ function foreignKey(target, schemaOrOptions, maybeOptions) {
421
+ if (isZodType(schemaOrOptions)) return decorate(schemaOrOptions, {
422
+ relationKind: "foreignKey",
423
+ references: {
424
+ target,
425
+ options: maybeOptions
426
+ }
427
+ });
428
+ const defaultSchema = z.number().int();
429
+ return decorate(defaultSchema, {
430
+ relationKind: "foreignKey",
431
+ references: {
432
+ target,
433
+ options: schemaOrOptions
434
+ },
435
+ notNull: true
436
+ });
437
+ }
438
+ function oneToOne(target, schemaOrOptions, maybeOptions) {
439
+ if (isZodType(schemaOrOptions)) return decorate(schemaOrOptions, {
440
+ relationKind: "oneToOne",
441
+ unique: true,
442
+ references: {
443
+ target,
444
+ options: maybeOptions
445
+ }
446
+ });
447
+ const defaultSchema = z.number().int();
448
+ return decorate(defaultSchema, {
449
+ relationKind: "oneToOne",
450
+ unique: true,
451
+ references: {
452
+ target,
453
+ options: schemaOrOptions
454
+ },
455
+ notNull: true
456
+ });
457
+ }
458
+ function manyToMany(target, schema) {
459
+ if (schema) return decorate(schema, {
460
+ relationKind: "manyToMany",
461
+ references: { target }
462
+ });
463
+ const defaultSchema = z.array(z.number().int());
464
+ return decorate(defaultSchema, {
465
+ relationKind: "manyToMany",
466
+ references: { target }
467
+ });
468
+ }
469
+ const Decorators = {
470
+ primaryKey,
471
+ unique,
472
+ null: nullValue,
473
+ notNull,
474
+ default: defaultValue,
475
+ dbDefault,
476
+ dbColumn,
477
+ dbIndex,
478
+ choices,
479
+ validators,
480
+ helpText,
481
+ errorMessages,
482
+ foreignKey,
483
+ oneToOne,
484
+ manyToMany
485
+ };
486
+
487
+ //#endregion
488
+ //#region src/model/meta/Meta.ts
489
+ const Meta = {
490
+ ordering(...fields) {
491
+ return { ordering: fields };
492
+ },
493
+ managed(value) {
494
+ return { managed: value };
495
+ },
496
+ defaultRelatedName(value) {
497
+ return { defaultRelatedName: value };
498
+ },
499
+ indexes(...indexes) {
500
+ return { indexes };
501
+ },
502
+ constraints(...constraints) {
503
+ return { constraints };
504
+ },
505
+ uniqueTogether(...sets) {
506
+ return { constraints: sets.map((fields) => ({
507
+ kind: "uniqueTogether",
508
+ fields
509
+ })) };
510
+ },
511
+ indexTogether(...sets) {
512
+ return { indexes: sets.map((on, index) => ({
513
+ name: `idx_${on.join("_")}_${index}`,
514
+ on
515
+ })) };
516
+ },
517
+ merge(...fragments) {
518
+ return fragments.reduce((acc, fragment) => ({
519
+ ordering: fragment.ordering ?? acc.ordering,
520
+ managed: fragment.managed ?? acc.managed,
521
+ defaultRelatedName: fragment.defaultRelatedName ?? acc.defaultRelatedName,
522
+ indexes: [...acc.indexes ?? [], ...fragment.indexes ?? []],
523
+ constraints: [...acc.constraints ?? [], ...fragment.constraints ?? []]
524
+ }), {});
525
+ }
526
+ };
527
+
528
+ //#endregion
529
+ //#region src/model/constraints/Constraints.ts
530
+ const Constraints = {
531
+ unique(fields, options) {
532
+ return {
533
+ kind: "unique",
534
+ fields,
535
+ ...options
536
+ };
537
+ },
538
+ check(condition, options) {
539
+ return {
540
+ kind: "check",
541
+ condition,
542
+ ...options
543
+ };
544
+ },
545
+ exclusion(definition) {
546
+ return {
547
+ kind: "exclusion",
548
+ ...definition
549
+ };
550
+ }
551
+ };
552
+
553
+ //#endregion
554
+ //#region src/model/constraints/Indexes.ts
555
+ const Indexes = { index(on, options) {
556
+ const suffix = on.join("_");
557
+ return {
558
+ name: options?.name ?? `idx_${suffix}`,
559
+ on,
560
+ unique: options?.unique,
561
+ where: options?.where
562
+ };
563
+ } };
564
+
565
+ //#endregion
566
+ //#region src/model/index.ts
567
+ var model_exports = {};
568
+ __export(model_exports, {
569
+ Constraints: () => Constraints,
570
+ Decorators: () => Decorators,
571
+ Indexes: () => Indexes,
572
+ Meta: () => Meta,
573
+ Model: () => Model,
574
+ ModelRegistry: () => ModelRegistry,
575
+ RelationBuilder: () => RelationBuilder,
576
+ c: () => Constraints,
577
+ i: () => Indexes,
578
+ m: () => Meta,
579
+ registerModelAugmentor: () => registerModelAugmentor,
580
+ t: () => Decorators
581
+ });
582
+
583
+ //#endregion
584
+ export { Constraints, Decorators, Indexes, Meta, Model, ModelRegistry, RelationBuilder, model_exports, registerModelAugmentor };
585
+ //# sourceMappingURL=model-DI8lQH1W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-DI8lQH1W.js","names":["target: string","foreignKey: string","localKey?: string","model: Model","models: readonly Model[]","namespace: string","name: string","key: string","ref: ModelRef","augmentor: ModelAugmentor","model: Model<TSchema>","schema: ZodTypeAny","meta: TangoFieldMeta","value: unknown","value: unknown","name: string","value: unknown","value: unknown","value: unknown","value: unknown","value: unknown","value: unknown","value: unknown","value: unknown","value: unknown","name: string","zodType: z.ZodType","meta: TangoFieldMeta | undefined","registry: ModelRegistry","type: FieldType","defaultValue: Field['default']","unwrapped: z.ZodType","field: Field","schema: z.ZodObject<z.ZodRawShape>","options?: InferFieldsOptions","fields: Field[]","name: string","value: string","definition: ModelDefinition<TSchema>","metadata: ModelMetadata","value: unknown","schema: T","meta: TangoFieldMeta","schemaOrUndefined: T | undefined","schema?: T","value: string | { now: true } | null","value: string","name: string","values: readonly unknown[]","text: string","map: Record<string, string>","target: ModelRef","schemaOrOptions?: T | ReferentialOptions","maybeOptions?: ReferentialOptions","Decorators: TangoDecorators","value: boolean","value: string","fields: string[]","options?: { name?: string; where?: string }","condition: string","options?: { name?: string }","definition: { using?: string; elements: string[]; where?: string; name?: string }","on: string[]","options?: Omit<IndexDef, 'on'>"],"sources":["../src/domain/internal/InternalRelationType.ts","../src/model/RelationBuilder.ts","../src/model/registry/ModelRegistry.ts","../src/model/ModelAugmentorRegistry.ts","../src/domain/internal/InternalFieldType.ts","../src/model/internal/FieldMetadataStore.ts","../src/domain/internal/zod/isDate.ts","../src/domain/internal/zod/hasConstructorName.ts","../src/domain/internal/zod/isZodArray.ts","../src/domain/internal/zod/isZodBoolean.ts","../src/domain/internal/zod/isZodDate.ts","../src/domain/internal/zod/isZodDefault.ts","../src/domain/internal/zod/isZodNullable.ts","../src/domain/internal/zod/isZodNumber.ts","../src/domain/internal/zod/isZodObject.ts","../src/domain/internal/zod/isZodOptional.ts","../src/domain/internal/zod/isZodString.ts","../src/model/inferFields.ts","../src/model/Model.ts","../src/model/decorators/Decorators.ts","../src/model/meta/Meta.ts","../src/model/constraints/Constraints.ts","../src/model/constraints/Indexes.ts","../src/model/index.ts"],"sourcesContent":["export const InternalRelationType = {\n HAS_MANY: 'hasMany',\n BELONGS_TO: 'belongsTo',\n HAS_ONE: 'hasOne',\n} as const;\n","import type { RelationDef } from '../domain/index';\nimport { InternalRelationType } from '../domain/internal/InternalRelationType';\n\n/**\n * Fluent helper for declaring model relation metadata.\n */\nexport class RelationBuilder {\n /** Declare a one-to-many relation from this model to `target`. */\n hasMany(target: string, foreignKey: string): RelationDef {\n return {\n type: InternalRelationType.HAS_MANY,\n target,\n foreignKey,\n };\n }\n\n /** Declare an owning relation to a parent model. */\n belongsTo(target: string, foreignKey: string, localKey?: string): RelationDef {\n return {\n type: InternalRelationType.BELONGS_TO,\n target,\n foreignKey,\n localKey,\n };\n }\n\n /** Declare a one-to-one relation from this model to `target`. */\n hasOne(target: string, foreignKey: string): RelationDef {\n return {\n type: InternalRelationType.HAS_ONE,\n target,\n foreignKey,\n };\n }\n}\n","import type { Model } from '../../domain/index';\nimport type { ModelRef } from '../decorators/types';\n\n/**\n * Registry that resolves Tango models by stable identity.\n *\n * The global registry is convenient for application bootstrapping, while\n * dedicated instances are useful in tests and tooling.\n */\nexport class ModelRegistry {\n private static globalRegistry?: ModelRegistry;\n private readonly models = new Map<string, Model>();\n\n /**\n * Return the shared process-wide registry used by `Model(...)`.\n */\n static global(): ModelRegistry {\n if (!ModelRegistry.globalRegistry) {\n ModelRegistry.globalRegistry = new ModelRegistry();\n }\n return ModelRegistry.globalRegistry;\n }\n\n /**\n * Register a model on the shared global registry.\n */\n static register(model: Model): void {\n ModelRegistry.global().register(model);\n }\n\n /**\n * Register several models on the shared global registry.\n */\n static registerMany(models: readonly Model[]): void {\n ModelRegistry.global().registerMany(models);\n }\n\n /**\n * Resolve a model from the shared registry by namespace and name.\n */\n static get(namespace: string, name: string): Model | undefined {\n return ModelRegistry.global().get(namespace, name);\n }\n\n /**\n * Resolve a model from the shared registry by its `namespace/name` key.\n */\n static getByKey(key: string): Model | undefined {\n return ModelRegistry.global().getByKey(key);\n }\n\n /**\n * Resolve any supported model reference form against the shared registry.\n */\n static resolveRef(ref: ModelRef): Model {\n return ModelRegistry.global().resolveRef(ref);\n }\n\n /**\n * Clear the shared registry, which is mainly useful in tests.\n */\n static clear(): void {\n ModelRegistry.global().clear();\n }\n\n /**\n * Register a model on this registry instance.\n */\n register(model: Model): void {\n this.models.set(model.metadata.key, model);\n }\n\n /**\n * Register several models on this registry instance.\n */\n registerMany(models: readonly Model[]): void {\n for (const model of models) {\n this.register(model);\n }\n }\n\n /**\n * Resolve a model from this registry instance by namespace and name.\n */\n get(namespace: string, name: string): Model | undefined {\n return this.getByKey(`${namespace}/${name}`);\n }\n\n /**\n * Resolve a model from this registry instance by its `namespace/name` key.\n */\n getByKey(key: string): Model | undefined {\n return this.models.get(key);\n }\n\n /**\n * Resolve a string, callback, or direct model reference into a model object.\n */\n resolveRef(ref: ModelRef): Model {\n if (typeof ref === 'string') {\n const model = this.getByKey(ref);\n if (!model) {\n throw new Error(\n `Unable to resolve model reference '${ref}'. Ensure it is registered in ModelRegistry.`\n );\n }\n return model;\n }\n\n if (typeof ref === 'function') {\n return ref();\n }\n\n return ref;\n }\n\n /**\n * Remove all registered models from this registry instance.\n */\n clear(): void {\n this.models.clear();\n }\n\n /**\n * Return all registered models in insertion order.\n */\n values(): readonly Model[] {\n return Array.from(this.models.values());\n }\n}\n","import type { z } from 'zod';\nimport type { Model } from '../domain/Model';\nimport { ModelRegistry } from './registry/ModelRegistry';\n\nexport type ModelAugmentor = <TSchema extends z.ZodObject<z.ZodRawShape>>(model: Model<TSchema>) => void;\n\nconst modelAugmentors = new Set<ModelAugmentor>();\n\n/**\n * Register a model augmentor that runs for existing and future models.\n */\nexport function registerModelAugmentor(augmentor: ModelAugmentor): () => void {\n modelAugmentors.add(augmentor);\n\n for (const model of ModelRegistry.global().values()) {\n augmentor(model);\n }\n\n return () => {\n modelAugmentors.delete(augmentor);\n };\n}\n\n/**\n * Apply all registered augmentors to a model before it is returned publicly.\n */\nexport function applyModelAugmentors<TSchema extends z.ZodObject<z.ZodRawShape>>(\n model: Model<TSchema>\n): Model<TSchema> {\n for (const augmentor of modelAugmentors) {\n augmentor(model);\n }\n\n return model;\n}\n","export const InternalFieldType = {\n SERIAL: 'serial',\n INT: 'int',\n BIGINT: 'bigint',\n TEXT: 'text',\n BOOL: 'bool',\n TIMESTAMPTZ: 'timestamptz',\n JSONB: 'jsonb',\n UUID: 'uuid',\n} as const;\n","import type { TangoFieldMeta, ZodTypeAny } from '../decorators/types';\n\nconst fieldMetadataStore = new WeakMap<ZodTypeAny, TangoFieldMeta>();\n\nexport function getFieldMetadata(schema: ZodTypeAny): TangoFieldMeta | undefined {\n return fieldMetadataStore.get(schema);\n}\n\nexport function setFieldMetadata(schema: ZodTypeAny, meta: TangoFieldMeta): void {\n const existing = fieldMetadataStore.get(schema);\n fieldMetadataStore.set(schema, {\n ...existing,\n ...meta,\n });\n}\n","export function isDate(value: unknown): value is Date {\n return value !== null && value !== undefined && Object.prototype.toString.call(value) === '[object Date]';\n}\n","export function hasConstructorName(value: unknown, name: string): boolean {\n return (\n !!value &&\n typeof value === 'object' &&\n (value as { constructor?: { name?: unknown } }).constructor?.name === name\n );\n}\n","import { z } from 'zod';\nimport { hasConstructorName } from './hasConstructorName';\n\nexport function isZodArray(value: unknown): value is z.ZodArray<z.ZodTypeAny> {\n return hasConstructorName(value, 'ZodArray');\n}\n","import { z } from 'zod';\nimport { hasConstructorName } from './hasConstructorName';\n\nexport function isZodBoolean(value: unknown): value is z.ZodBoolean {\n return hasConstructorName(value, 'ZodBoolean');\n}\n","import { z } from 'zod';\nimport { hasConstructorName } from './hasConstructorName';\n\nexport function isZodDate(value: unknown): value is z.ZodDate {\n return hasConstructorName(value, 'ZodDate');\n}\n","import { z } from 'zod';\nimport { hasConstructorName } from './hasConstructorName';\n\nexport function isZodDefault(value: unknown): value is z.ZodDefault<z.ZodTypeAny> {\n return hasConstructorName(value, 'ZodDefault');\n}\n","import { z } from 'zod';\nimport { hasConstructorName } from './hasConstructorName';\n\nexport function isZodNullable(value: unknown): value is z.ZodNullable<z.ZodTypeAny> {\n return hasConstructorName(value, 'ZodNullable');\n}\n","import { z } from 'zod';\nimport { hasConstructorName } from './hasConstructorName';\n\nexport function isZodNumber(value: unknown): value is z.ZodNumber {\n return hasConstructorName(value, 'ZodNumber');\n}\n","import { z } from 'zod';\nimport { hasConstructorName } from './hasConstructorName';\n\nexport function isZodObject(value: unknown): value is z.ZodObject<z.ZodRawShape> {\n return hasConstructorName(value, 'ZodObject');\n}\n","import { z } from 'zod';\nimport { hasConstructorName } from './hasConstructorName';\n\nexport function isZodOptional(value: unknown): value is z.ZodOptional<z.ZodTypeAny> {\n return hasConstructorName(value, 'ZodOptional');\n}\n","import { z } from 'zod';\nimport { hasConstructorName } from './hasConstructorName';\n\nexport function isZodString(value: unknown): value is z.ZodString {\n return hasConstructorName(value, 'ZodString');\n}\n","import { z } from 'zod';\nimport type { Field, FieldType } from '../domain/index';\nimport { InternalFieldType } from '../domain/internal/InternalFieldType';\nimport { getFieldMetadata } from './internal/FieldMetadataStore';\nimport type { TangoFieldMeta, ZodTypeAny } from './decorators/types';\nimport { ModelRegistry } from './registry/ModelRegistry';\nimport {\n isDate,\n isZodArray,\n isZodBoolean,\n isZodDate,\n isZodDefault,\n isZodNullable,\n isZodNumber,\n isZodObject,\n isZodOptional,\n isZodString,\n} from '../domain/internal/zod/index';\n\nexport type InferFieldsOptions = {\n registry?: ModelRegistry;\n};\n\nfunction inferField(\n name: string,\n zodType: z.ZodType,\n meta: TangoFieldMeta | undefined,\n registry: ModelRegistry\n): Field | null {\n let type: FieldType;\n let notNull = true;\n let defaultValue: Field['default'] = undefined;\n\n let unwrapped: z.ZodType = zodType;\n\n if (isZodOptional(unwrapped)) {\n notNull = false;\n unwrapped = unwrapped.unwrap() as z.ZodType;\n }\n\n if (isZodNullable(unwrapped)) {\n notNull = false;\n unwrapped = unwrapped.unwrap() as z.ZodType;\n }\n\n if (isZodDefault(unwrapped)) {\n const def = unwrapped._zod.def.defaultValue;\n if (isDate(def)) {\n defaultValue = { now: true };\n } else if (typeof def === 'string' || typeof def === 'number') {\n defaultValue = String(def);\n }\n unwrapped = unwrapped.removeDefault() as z.ZodType;\n }\n\n if (isZodString(unwrapped)) {\n type = InternalFieldType.TEXT;\n } else if (isZodNumber(unwrapped)) {\n const checks = unwrapped._zod.def.checks ?? [];\n const isInt = checks.some((c) => 'format' in c._zod.def && c._zod.def.format === 'safeint');\n type = isInt ? InternalFieldType.INT : InternalFieldType.BIGINT;\n } else if (isZodBoolean(unwrapped)) {\n type = InternalFieldType.BOOL;\n } else if (isZodDate(unwrapped)) {\n type = InternalFieldType.TIMESTAMPTZ;\n } else if (isZodObject(unwrapped) || isZodArray(unwrapped)) {\n type = InternalFieldType.JSONB;\n } else {\n return null;\n }\n\n const field: Field = {\n name,\n type,\n notNull,\n default: defaultValue,\n };\n\n if (!meta) {\n return field;\n }\n\n if (meta.dbColumn) {\n field.name = meta.dbColumn;\n }\n\n if (typeof meta.notNull === 'boolean') {\n field.notNull = meta.notNull;\n }\n\n if (meta.default !== undefined) {\n field.default = meta.default;\n }\n\n if (meta.primaryKey) {\n field.primaryKey = true;\n }\n\n if (meta.unique) {\n field.unique = true;\n }\n\n if (meta.references && meta.relationKind !== 'manyToMany') {\n const targetModel = registry.resolveRef(meta.references.target);\n const referencedColumn =\n meta.references.options?.column ??\n targetModel.metadata.fields.find((candidate) => candidate.primaryKey)?.name ??\n 'id';\n\n field.references = {\n table: targetModel.metadata.table,\n column: referencedColumn,\n onDelete: meta.references.options?.onDelete,\n onUpdate: meta.references.options?.onUpdate,\n };\n }\n\n return field;\n}\n\n/**\n * Infer Tango field metadata from a Zod object schema and any attached field decorators.\n */\nexport function inferFieldsFromSchema(schema: z.ZodObject<z.ZodRawShape>, options?: InferFieldsOptions): Field[] {\n const registry = options?.registry ?? ModelRegistry.global();\n const shape = schema.shape;\n const fields: Field[] = [];\n\n for (const [name, zodType] of Object.entries(shape)) {\n const field = inferField(name, zodType as z.ZodType, getFieldMetadata(zodType as ZodTypeAny), registry);\n if (field) {\n fields.push(field);\n }\n }\n\n return fields;\n}\n","import { z } from 'zod';\nimport type { Model as SchemaModel } from '../domain/Model';\nimport type { ModelMetadata } from '../domain/index';\nimport type { ModelDefinition } from './ModelDefinition';\nimport { applyModelAugmentors } from './ModelAugmentorRegistry';\nimport { RelationBuilder } from './RelationBuilder';\nimport { inferFieldsFromSchema } from './inferFields';\nimport { ModelRegistry } from './registry/ModelRegistry';\n\nfunction deriveTableName(name: string): string {\n const snake = toSnakeCase(name);\n return pluralize(snake);\n}\n\nfunction toSnakeCase(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, '$1_$2')\n .replace(/[\\s-]+/g, '_')\n .toLowerCase();\n}\n\nfunction pluralize(value: string): string {\n if (/(s|x|z|ch|sh)$/.test(value)) {\n return `${value}es`;\n }\n\n if (/[^aeiou]y$/.test(value)) {\n return `${value.slice(0, -1)}ies`;\n }\n\n return `${value}s`;\n}\n\n/**\n * Creates a model definition with metadata and schema validation.\n * Automatically infers field types from Zod schema if fields are not explicitly provided.\n */\nexport function Model<TSchema extends z.ZodObject<z.ZodRawShape>>(\n definition: ModelDefinition<TSchema>\n): SchemaModel<TSchema> {\n if (!definition.namespace.trim()) {\n throw new Error('Model.namespace is required and cannot be empty.');\n }\n if (!definition.name.trim()) {\n throw new Error('Model.name is required and cannot be empty.');\n }\n if (definition.table !== undefined && !definition.table.trim()) {\n throw new Error('Model.table cannot be empty when provided.');\n }\n\n const builder = new RelationBuilder();\n const relations = definition.relations ? definition.relations(builder) : undefined;\n\n const registry = ModelRegistry.global();\n const fields = definition.fields || inferFieldsFromSchema(definition.schema, { registry });\n const key = `${definition.namespace}/${definition.name}`;\n const table = definition.table?.trim() || deriveTableName(definition.name);\n\n const metadata: ModelMetadata = {\n namespace: definition.namespace,\n name: definition.name,\n key,\n table,\n fields,\n indexes: definition.indexes,\n relations,\n ordering: definition.ordering,\n managed: definition.managed,\n defaultRelatedName: definition.defaultRelatedName,\n constraints: definition.constraints,\n };\n\n const baseModel = {\n metadata,\n schema: definition.schema,\n hooks: definition.hooks,\n } satisfies Pick<SchemaModel<TSchema>, 'metadata' | 'schema' | 'hooks'>;\n\n const model = applyModelAugmentors(baseModel as SchemaModel<TSchema>);\n\n registry.register(model);\n return model;\n}\n","import { z } from 'zod';\nimport { setFieldMetadata } from '../internal/FieldMetadataStore';\nimport type { ModelRef, ReferentialOptions, TangoFieldMeta, ZodTypeAny } from './types';\n\nfunction isZodType(value: unknown): value is ZodTypeAny {\n return (\n !!value &&\n typeof value === 'object' &&\n 'safeParse' in value &&\n typeof (value as { safeParse?: unknown }).safeParse === 'function'\n );\n}\n\nfunction decorate<T extends ZodTypeAny>(schema: T, meta: TangoFieldMeta): T {\n setFieldMetadata(schema, meta);\n return schema;\n}\n\nfunction maybeDecorator<T extends ZodTypeAny>(\n schemaOrUndefined: T | undefined,\n meta: TangoFieldMeta\n): T | ((schema: T) => T) {\n if (schemaOrUndefined) {\n return decorate(schemaOrUndefined, meta);\n }\n\n return (schema: T) => decorate(schema, meta);\n}\n\nfunction primaryKey<T extends ZodTypeAny>(schema: T): T;\nfunction primaryKey<T extends ZodTypeAny>(): (input: T) => T;\nfunction primaryKey<T extends ZodTypeAny>(schema?: T): T | ((input: T) => T) {\n return maybeDecorator(schema, { primaryKey: true, notNull: true });\n}\n\nfunction unique<T extends ZodTypeAny>(schema: T): T;\nfunction unique<T extends ZodTypeAny>(): (input: T) => T;\nfunction unique<T extends ZodTypeAny>(schema?: T): T | ((input: T) => T) {\n return maybeDecorator(schema, { unique: true });\n}\n\nfunction nullValue<T extends ZodTypeAny>(schema: T): T;\nfunction nullValue<T extends ZodTypeAny>(): (input: T) => T;\nfunction nullValue<T extends ZodTypeAny>(schema?: T): T | ((input: T) => T) {\n return maybeDecorator(schema, { notNull: false });\n}\n\nfunction notNull<T extends ZodTypeAny>(schema: T): T;\nfunction notNull<T extends ZodTypeAny>(): (input: T) => T;\nfunction notNull<T extends ZodTypeAny>(schema?: T): T | ((input: T) => T) {\n return maybeDecorator(schema, { notNull: true });\n}\n\nfunction defaultValue<T extends ZodTypeAny>(schema: T, value: string | { now: true } | null): T {\n return decorate(schema, { default: value });\n}\n\nfunction dbDefault<T extends ZodTypeAny>(schema: T, value: string): T {\n return decorate(schema, { dbDefault: value });\n}\n\nfunction dbColumn<T extends ZodTypeAny>(schema: T, name: string): T {\n return decorate(schema, { dbColumn: name });\n}\n\nfunction dbIndex<T extends ZodTypeAny>(schema: T): T {\n return decorate(schema, { dbIndex: true });\n}\n\nfunction choices<T extends ZodTypeAny>(schema: T, values: readonly unknown[]): T {\n return decorate(schema, { choices: values });\n}\n\nfunction validators<T extends ZodTypeAny>(schema: T, ...values: readonly ((value: unknown) => unknown)[]): T {\n return decorate(schema, { validators: values });\n}\n\nfunction helpText<T extends ZodTypeAny>(schema: T, text: string): T {\n return decorate(schema, { helpText: text });\n}\n\nfunction errorMessages<T extends ZodTypeAny>(schema: T, map: Record<string, string>): T {\n return decorate(schema, { errorMessages: map });\n}\n\nfunction foreignKey<T extends ZodTypeAny>(target: ModelRef, schema: T, options?: ReferentialOptions): T;\nfunction foreignKey(target: ModelRef, options?: ReferentialOptions): z.ZodNumber;\nfunction foreignKey<T extends ZodTypeAny>(\n target: ModelRef,\n schemaOrOptions?: T | ReferentialOptions,\n maybeOptions?: ReferentialOptions\n): T | z.ZodNumber {\n if (isZodType(schemaOrOptions)) {\n return decorate(schemaOrOptions, {\n relationKind: 'foreignKey',\n references: {\n target,\n options: maybeOptions,\n },\n });\n }\n\n const defaultSchema = z.number().int();\n return decorate(defaultSchema, {\n relationKind: 'foreignKey',\n references: {\n target,\n options: schemaOrOptions,\n },\n notNull: true,\n });\n}\n\nfunction oneToOne<T extends ZodTypeAny>(target: ModelRef, schema: T, options?: ReferentialOptions): T;\nfunction oneToOne(target: ModelRef, options?: ReferentialOptions): z.ZodNumber;\nfunction oneToOne<T extends ZodTypeAny>(\n target: ModelRef,\n schemaOrOptions?: T | ReferentialOptions,\n maybeOptions?: ReferentialOptions\n): T | z.ZodNumber {\n if (isZodType(schemaOrOptions)) {\n return decorate(schemaOrOptions, {\n relationKind: 'oneToOne',\n unique: true,\n references: {\n target,\n options: maybeOptions,\n },\n });\n }\n\n const defaultSchema = z.number().int();\n return decorate(defaultSchema, {\n relationKind: 'oneToOne',\n unique: true,\n references: {\n target,\n options: schemaOrOptions,\n },\n notNull: true,\n });\n}\n\nfunction manyToMany<T extends ZodTypeAny>(target: ModelRef, schema: T): T;\nfunction manyToMany(target: ModelRef): z.ZodArray<z.ZodNumber>;\nfunction manyToMany<T extends ZodTypeAny>(target: ModelRef, schema?: T): T | z.ZodArray<z.ZodNumber> {\n if (schema) {\n return decorate(schema, {\n relationKind: 'manyToMany',\n references: {\n target,\n },\n });\n }\n\n const defaultSchema = z.array(z.number().int());\n return decorate(defaultSchema, {\n relationKind: 'manyToMany',\n references: {\n target,\n },\n });\n}\n\ntype UnaryFieldDecorator = {\n <T extends ZodTypeAny>(schema: T): T;\n <T extends ZodTypeAny>(): (input: T) => T;\n};\n\ntype RelationshipDecorator = {\n <T extends ZodTypeAny>(target: ModelRef, schema: T, options?: ReferentialOptions): T;\n (target: ModelRef, options?: ReferentialOptions): z.ZodNumber;\n};\n\ntype ManyToManyDecorator = {\n <T extends ZodTypeAny>(target: ModelRef, schema: T): T;\n (target: ModelRef): z.ZodArray<z.ZodNumber>;\n};\n\nexport interface TangoDecorators {\n primaryKey: UnaryFieldDecorator;\n unique: UnaryFieldDecorator;\n null: UnaryFieldDecorator;\n notNull: UnaryFieldDecorator;\n default: <T extends ZodTypeAny>(schema: T, value: string | { now: true } | null) => T;\n dbDefault: <T extends ZodTypeAny>(schema: T, value: string) => T;\n dbColumn: <T extends ZodTypeAny>(schema: T, name: string) => T;\n dbIndex: <T extends ZodTypeAny>(schema: T) => T;\n choices: <T extends ZodTypeAny>(schema: T, values: readonly unknown[]) => T;\n validators: <T extends ZodTypeAny>(schema: T, ...values: readonly ((value: unknown) => unknown)[]) => T;\n helpText: <T extends ZodTypeAny>(schema: T, text: string) => T;\n errorMessages: <T extends ZodTypeAny>(schema: T, map: Record<string, string>) => T;\n foreignKey: RelationshipDecorator;\n oneToOne: RelationshipDecorator;\n manyToMany: ManyToManyDecorator;\n}\n\nexport const Decorators: TangoDecorators = {\n primaryKey: primaryKey as UnaryFieldDecorator,\n unique: unique as UnaryFieldDecorator,\n null: nullValue as UnaryFieldDecorator,\n notNull: notNull as UnaryFieldDecorator,\n default: defaultValue,\n dbDefault: dbDefault,\n dbColumn: dbColumn,\n dbIndex: dbIndex,\n choices: choices,\n validators: validators,\n helpText: helpText,\n errorMessages: errorMessages,\n foreignKey: foreignKey as RelationshipDecorator,\n oneToOne: oneToOne as RelationshipDecorator,\n manyToMany: manyToMany as ManyToManyDecorator,\n};\n","import type { IndexDef } from '../../domain/index';\n\nexport type ModelConstraint = {\n kind: string;\n [key: string]: unknown;\n};\n\nexport type ModelMetaFragment = {\n ordering?: string[];\n managed?: boolean;\n defaultRelatedName?: string;\n indexes?: IndexDef[];\n constraints?: ModelConstraint[];\n};\n\nexport const Meta = {\n ordering(...fields: string[]): ModelMetaFragment {\n return { ordering: fields };\n },\n\n managed(value: boolean): ModelMetaFragment {\n return { managed: value };\n },\n\n defaultRelatedName(value: string): ModelMetaFragment {\n return { defaultRelatedName: value };\n },\n\n indexes(...indexes: IndexDef[]): ModelMetaFragment {\n return { indexes };\n },\n\n constraints(...constraints: ModelConstraint[]): ModelMetaFragment {\n return { constraints };\n },\n\n uniqueTogether(...sets: string[][]): ModelMetaFragment {\n return {\n constraints: sets.map((fields) => ({ kind: 'uniqueTogether', fields })),\n };\n },\n\n indexTogether(...sets: string[][]): ModelMetaFragment {\n return {\n indexes: sets.map((on, index) => ({\n name: `idx_${on.join('_')}_${index}`,\n on,\n })),\n };\n },\n\n merge(...fragments: readonly ModelMetaFragment[]): ModelMetaFragment {\n return fragments.reduce<ModelMetaFragment>(\n (acc, fragment) => ({\n ordering: fragment.ordering ?? acc.ordering,\n managed: fragment.managed ?? acc.managed,\n defaultRelatedName: fragment.defaultRelatedName ?? acc.defaultRelatedName,\n indexes: [...(acc.indexes ?? []), ...(fragment.indexes ?? [])],\n constraints: [...(acc.constraints ?? []), ...(fragment.constraints ?? [])],\n }),\n {}\n );\n },\n};\n","export type ConstraintDefinition = {\n kind: string;\n [key: string]: unknown;\n};\n\nexport const Constraints = {\n unique(fields: string[], options?: { name?: string; where?: string }): ConstraintDefinition {\n return {\n kind: 'unique',\n fields,\n ...options,\n };\n },\n\n check(condition: string, options?: { name?: string }): ConstraintDefinition {\n return {\n kind: 'check',\n condition,\n ...options,\n };\n },\n\n exclusion(definition: { using?: string; elements: string[]; where?: string; name?: string }): ConstraintDefinition {\n return {\n kind: 'exclusion',\n ...definition,\n };\n },\n};\n","import type { IndexDef } from '../../domain/index';\n\nexport const Indexes = {\n index(on: string[], options?: Omit<IndexDef, 'on'>): IndexDef {\n const suffix = on.join('_');\n return {\n name: options?.name ?? `idx_${suffix}`,\n on,\n unique: options?.unique,\n where: options?.where,\n };\n },\n};\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport type { ModelDefinition } from './ModelDefinition';\nexport { RelationBuilder } from './RelationBuilder';\nexport { Model } from './Model';\nexport { registerModelAugmentor } from './ModelAugmentorRegistry';\nexport { Decorators, t } from './decorators/index';\nexport type { TangoDecorators } from './decorators/index';\nexport { Meta, m } from './meta/index';\nexport type { ModelConstraint, ModelMetaFragment } from './meta/index';\nexport { Constraints, Indexes, c, i } from './constraints/index';\nexport type { ConstraintDefinition } from './constraints/index';\nexport { ModelRegistry } from './registry/ModelRegistry';\n"],"mappings":"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"}