@atscript/db 0.1.54 → 0.1.55

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 (42) hide show
  1. package/dist/db-error-Cepx-RsQ.mjs +29 -0
  2. package/dist/db-error-D8tQhNgM.cjs +40 -0
  3. package/dist/{db-readable-ktHqF277.d.cts → db-readable-DtrC0BGF.d.cts} +122 -115
  4. package/dist/{db-readable-GBjlsJXR.d.mts → db-readable-RTtqL7H4.d.mts} +123 -116
  5. package/dist/{db-space-DB0MT6B3.d.cts → db-space-BqVLHVq7.d.cts} +14 -1
  6. package/dist/{db-space-DpaXOdRp.d.mts → db-space-D3QSKx2B.d.mts} +14 -1
  7. package/dist/{db-validator-plugin-Cz4QoDWg.d.cts → db-validator-plugin-DDvYyv5t.d.mts} +10 -0
  8. package/dist/{db-validator-plugin-KC4aNIQq.d.mts → db-validator-plugin-DRGMCEn3.d.cts} +10 -0
  9. package/dist/{db-view-DjDKgytJ.cjs → db-view-DIGN4079.cjs} +81 -19
  10. package/dist/{db-view-B1j_IKSf.mjs → db-view-DNwX6_4x.mjs} +72 -10
  11. package/dist/index.cjs +5 -4
  12. package/dist/index.d.cts +4 -4
  13. package/dist/index.d.mts +6 -6
  14. package/dist/index.mjs +4 -3
  15. package/dist/{nested-writer-CNDyhg2L.mjs → nested-writer-CT2rLURx.mjs} +9 -16
  16. package/dist/{nested-writer-BIQ6EfaR.cjs → nested-writer-v_LPR1yJ.cjs} +14 -27
  17. package/dist/ops.d.mts +1 -1
  18. package/dist/plugin.cjs +99 -9
  19. package/dist/plugin.mjs +99 -9
  20. package/dist/rel.cjs +1 -1
  21. package/dist/rel.d.cts +2 -2
  22. package/dist/rel.d.mts +2 -2
  23. package/dist/rel.mjs +1 -1
  24. package/dist/shared.cjs +1 -1
  25. package/dist/shared.mjs +1 -1
  26. package/dist/sync.cjs +5 -5
  27. package/dist/sync.d.cts +2 -2
  28. package/dist/sync.d.mts +2 -2
  29. package/dist/sync.mjs +5 -5
  30. package/dist/{validator-D_7Fqzs4.mjs → validator-BB5h1Le3.mjs} +42 -0
  31. package/dist/{validator-0iGuvGOD.cjs → validator-BIuw_T0k.cjs} +42 -0
  32. package/dist/validator.cjs +1 -1
  33. package/dist/validator.d.cts +1 -1
  34. package/dist/validator.d.mts +3 -3
  35. package/dist/validator.mjs +1 -1
  36. package/package.json +6 -6
  37. /package/dist/{control-D1QdBO21.cjs → control-CDnwVj4q.cjs} +0 -0
  38. /package/dist/{control-DBd_ff5-.mjs → control-ExEKWYBE.mjs} +0 -0
  39. /package/dist/{ops-DcHDxrjX.d.mts → ops-C61kelof.d.mts} +0 -0
  40. /package/dist/{validation-utils-BiG3pLP0.cjs → validation-utils-B9WJv9aH.cjs} +0 -0
  41. /package/dist/{validation-utils-aNrgK-cj.mjs → validation-utils-Bh7RVrVl.mjs} +0 -0
  42. /package/dist/{validator-BeXlQISk.d.mts → validator-DttN2e5_.d.mts} +0 -0
@@ -0,0 +1,29 @@
1
+ //#region src/db-error.ts
2
+ var DbError = class extends Error {
3
+ name = "DbError";
4
+ constructor(code, errors, message) {
5
+ super(message ?? errors[0]?.message ?? "Database error");
6
+ this.code = code;
7
+ this.errors = errors;
8
+ this.stack = void 0;
9
+ }
10
+ };
11
+ /**
12
+ * Thrown when a write payload nests deeper than the table's
13
+ * declared `@db.depth.limit N`. Surfaced as HTTP 400 in moost-db.
14
+ */
15
+ var DepthLimitExceededError = class extends DbError {
16
+ name = "DepthLimitExceededError";
17
+ constructor(field, declared, actual) {
18
+ const message = `Nested write depth ${actual} exceeds declared @db.depth.limit ${declared} at '${field}'`;
19
+ super("DEPTH_EXCEEDED", [{
20
+ path: field,
21
+ message
22
+ }], message);
23
+ this.field = field;
24
+ this.declared = declared;
25
+ this.actual = actual;
26
+ }
27
+ };
28
+ //#endregion
29
+ export { DepthLimitExceededError as n, DbError as t };
@@ -0,0 +1,40 @@
1
+ //#region src/db-error.ts
2
+ var DbError = class extends Error {
3
+ name = "DbError";
4
+ constructor(code, errors, message) {
5
+ super(message ?? errors[0]?.message ?? "Database error");
6
+ this.code = code;
7
+ this.errors = errors;
8
+ this.stack = void 0;
9
+ }
10
+ };
11
+ /**
12
+ * Thrown when a write payload nests deeper than the table's
13
+ * declared `@db.depth.limit N`. Surfaced as HTTP 400 in moost-db.
14
+ */
15
+ var DepthLimitExceededError = class extends DbError {
16
+ name = "DepthLimitExceededError";
17
+ constructor(field, declared, actual) {
18
+ const message = `Nested write depth ${actual} exceeds declared @db.depth.limit ${declared} at '${field}'`;
19
+ super("DEPTH_EXCEEDED", [{
20
+ path: field,
21
+ message
22
+ }], message);
23
+ this.field = field;
24
+ this.declared = declared;
25
+ this.actual = actual;
26
+ }
27
+ };
28
+ //#endregion
29
+ Object.defineProperty(exports, "DbError", {
30
+ enumerable: true,
31
+ get: function() {
32
+ return DbError;
33
+ }
34
+ });
35
+ Object.defineProperty(exports, "DepthLimitExceededError", {
36
+ enumerable: true,
37
+ get: function() {
38
+ return DepthLimitExceededError;
39
+ }
40
+ });
@@ -44,6 +44,120 @@ declare class UniquSelect {
44
44
  get hasAggregates(): boolean;
45
45
  }
46
46
  //#endregion
47
+ //#region src/logger.d.ts
48
+ interface TGenericLogger {
49
+ error(...messages: any[]): void;
50
+ warn(...messages: any[]): void;
51
+ log(...messages: any[]): void;
52
+ info(...messages: any[]): void;
53
+ debug(...messages: any[]): void;
54
+ }
55
+ declare const NoopLogger: TGenericLogger;
56
+ //#endregion
57
+ //#region src/table/table-metadata.d.ts
58
+ /**
59
+ * Computed metadata for a database table or view.
60
+ *
61
+ * Contains all field metadata, physical mapping indexes, relation definitions,
62
+ * and constraint information derived from Atscript annotations. Built lazily
63
+ * on first access via {@link build}, then immutable.
64
+ *
65
+ * This class owns the build pipeline that was previously part of
66
+ * `AtscriptDbReadable._flatten()`. The Readable delegates all metadata
67
+ * access to this class.
68
+ */
69
+ declare class TableMetadata {
70
+ readonly nestedObjects: boolean;
71
+ flatMap: Map<string, TAtscriptAnnotatedType>;
72
+ fieldDescriptors: readonly TDbFieldMeta[];
73
+ primaryKeys: string[];
74
+ originalMetaIdFields: string[];
75
+ indexes: Map<string, TDbIndex>;
76
+ foreignKeys: Map<string, TDbForeignKey>;
77
+ relations: Map<string, TDbRelation>;
78
+ navFields: Set<string>;
79
+ ignoredFields: Set<string>;
80
+ uniqueProps: Set<string>;
81
+ defaults: Map<string, TDbDefaultValue>;
82
+ columnMap: Map<string, string>;
83
+ dimensions: string[];
84
+ measures: string[];
85
+ pathToPhysical: Map<string, string>;
86
+ physicalToPath: Map<string, string>;
87
+ flattenedParents: Set<string>;
88
+ jsonFields: Set<string>;
89
+ selectExpansion: Map<string, string[]>;
90
+ booleanFields: Set<string>;
91
+ decimalFields: Set<string>;
92
+ allPhysicalFields: string[];
93
+ /** Precomputed parent path → child physical column names for fast null-setting. */
94
+ childrenByParent: Map<string, string[]>;
95
+ requiresMappings: boolean;
96
+ /** True when the only mappings needed are simple `@db.column` renames (no nesting/JSON). */
97
+ onlyColumnRenames: boolean;
98
+ toStorageFormatters?: Map<string, (value: unknown) => unknown>;
99
+ fromStorageFormatters?: Map<string, (value: unknown) => unknown>;
100
+ /** Leaf field descriptors indexed by physical column name (read path). */
101
+ leafByPhysical: Map<string, TDbFieldMeta>;
102
+ /** Leaf field descriptors indexed by logical path (write/patch/filter paths). */
103
+ leafByLogical: Map<string, TDbFieldMeta>;
104
+ private _built;
105
+ private _collateMap;
106
+ private _columnFromMap;
107
+ constructor(nestedObjects: boolean);
108
+ get isBuilt(): boolean;
109
+ /**
110
+ * Runs the full metadata compilation pipeline. Called once by
111
+ * `AtscriptDbReadable._ensureBuilt()` on first metadata access.
112
+ *
113
+ * Pipeline steps:
114
+ * 1. `adapter.onBeforeFlatten(type)` — adapter hook
115
+ * 2. `flattenAnnotatedType()` — collect field tuples, detect nav fields eagerly
116
+ * 3. Replay non-nav-descendant tuples through annotation scanning + adapter.onFieldScanned
117
+ * 4. Classify fields and build path maps (skipped for nested-objects adapters)
118
+ * 5. `adapter.getMetadataOverrides()` → `_applyOverrides()` (PK/unique/inject adjustments)
119
+ * 6. Build field descriptors (TDbFieldMeta[])
120
+ * 7. Build leaf field indexes (skipped for nested-objects adapters)
121
+ * 8. Finalize indexes (resolve field names to physical)
122
+ * 9. `adapter.onAfterFlatten()` — adapter hook (read-only bookkeeping)
123
+ * 10. Build allPhysicalFields list
124
+ */
125
+ build(type: TAtscriptAnnotatedType<TAtscriptTypeObject>, adapter: BaseDbAdapter, logger: TGenericLogger): void;
126
+ /**
127
+ * Applies adapter-provided metadata overrides atomically.
128
+ * Processing order: injectFields → removePrimaryKeys → addPrimaryKeys → addUniqueFields.
129
+ */
130
+ private _applyOverrides;
131
+ /**
132
+ * Scans `@db.*` and `@meta.id` annotations on a field during flattening.
133
+ */
134
+ private _scanGenericAnnotations;
135
+ private _addIndexField;
136
+ /**
137
+ * Classifies each field as column, flattened, json, or parent-object.
138
+ * Builds the bidirectional pathToPhysical / physicalToPath maps.
139
+ */
140
+ private _classifyFields;
141
+ /** Returns the `__`-separated parent prefix for a dot-separated path, or empty string for top-level paths. */
142
+ private _flattenedPrefix;
143
+ /**
144
+ * Indexes `fieldDescriptors` into two lookup maps for unified
145
+ * read/write field classification in the RelationalFieldMapper.
146
+ */
147
+ private _buildLeafIndexes;
148
+ /**
149
+ * Builds field descriptors, physical-name lookup, and value formatters.
150
+ * Called once during build() — everything it needs
151
+ * (flatMap, indexes, columnMap, etc.) is already populated.
152
+ */
153
+ private _buildFieldDescriptors;
154
+ /**
155
+ * Resolves `fkTargetField` for FK fields in field descriptors.
156
+ */
157
+ private _resolveFkTargetFields;
158
+ private _finalizeIndexes;
159
+ }
160
+ //#endregion
47
161
  //#region src/types.d.ts
48
162
  /** Controls with resolved projection. Used in the adapter interface. */
49
163
  interface DbControls extends Omit<UniqueryControls, "$select"> {
@@ -290,6 +404,7 @@ interface AtscriptDbTableLike {
290
404
  primaryKeys: readonly string[];
291
405
  relations: ReadonlyMap<string, TDbRelation>;
292
406
  foreignKeys: ReadonlyMap<string, TDbForeignKey>;
407
+ getMetadata(): TableMetadata;
293
408
  }
294
409
  /** Minimal writable table interface for nested creation/update. */
295
410
  interface AtscriptDbWritable {
@@ -375,120 +490,6 @@ interface TDbRelation {
375
490
  viaType?: () => TAtscriptAnnotatedType;
376
491
  }
377
492
  //#endregion
378
- //#region src/logger.d.ts
379
- interface TGenericLogger {
380
- error(...messages: any[]): void;
381
- warn(...messages: any[]): void;
382
- log(...messages: any[]): void;
383
- info(...messages: any[]): void;
384
- debug(...messages: any[]): void;
385
- }
386
- declare const NoopLogger: TGenericLogger;
387
- //#endregion
388
- //#region src/table/table-metadata.d.ts
389
- /**
390
- * Computed metadata for a database table or view.
391
- *
392
- * Contains all field metadata, physical mapping indexes, relation definitions,
393
- * and constraint information derived from Atscript annotations. Built lazily
394
- * on first access via {@link build}, then immutable.
395
- *
396
- * This class owns the build pipeline that was previously part of
397
- * `AtscriptDbReadable._flatten()`. The Readable delegates all metadata
398
- * access to this class.
399
- */
400
- declare class TableMetadata {
401
- readonly nestedObjects: boolean;
402
- flatMap: Map<string, TAtscriptAnnotatedType>;
403
- fieldDescriptors: readonly TDbFieldMeta[];
404
- primaryKeys: string[];
405
- originalMetaIdFields: string[];
406
- indexes: Map<string, TDbIndex>;
407
- foreignKeys: Map<string, TDbForeignKey>;
408
- relations: Map<string, TDbRelation>;
409
- navFields: Set<string>;
410
- ignoredFields: Set<string>;
411
- uniqueProps: Set<string>;
412
- defaults: Map<string, TDbDefaultValue>;
413
- columnMap: Map<string, string>;
414
- dimensions: string[];
415
- measures: string[];
416
- pathToPhysical: Map<string, string>;
417
- physicalToPath: Map<string, string>;
418
- flattenedParents: Set<string>;
419
- jsonFields: Set<string>;
420
- selectExpansion: Map<string, string[]>;
421
- booleanFields: Set<string>;
422
- decimalFields: Set<string>;
423
- allPhysicalFields: string[];
424
- /** Precomputed parent path → child physical column names for fast null-setting. */
425
- childrenByParent: Map<string, string[]>;
426
- requiresMappings: boolean;
427
- /** True when the only mappings needed are simple `@db.column` renames (no nesting/JSON). */
428
- onlyColumnRenames: boolean;
429
- toStorageFormatters?: Map<string, (value: unknown) => unknown>;
430
- fromStorageFormatters?: Map<string, (value: unknown) => unknown>;
431
- /** Leaf field descriptors indexed by physical column name (read path). */
432
- leafByPhysical: Map<string, TDbFieldMeta>;
433
- /** Leaf field descriptors indexed by logical path (write/patch/filter paths). */
434
- leafByLogical: Map<string, TDbFieldMeta>;
435
- private _built;
436
- private _collateMap;
437
- private _columnFromMap;
438
- constructor(nestedObjects: boolean);
439
- get isBuilt(): boolean;
440
- /**
441
- * Runs the full metadata compilation pipeline. Called once by
442
- * `AtscriptDbReadable._ensureBuilt()` on first metadata access.
443
- *
444
- * Pipeline steps:
445
- * 1. `adapter.onBeforeFlatten(type)` — adapter hook
446
- * 2. `flattenAnnotatedType()` — collect field tuples, detect nav fields eagerly
447
- * 3. Replay non-nav-descendant tuples through annotation scanning + adapter.onFieldScanned
448
- * 4. Classify fields and build path maps (skipped for nested-objects adapters)
449
- * 5. `adapter.getMetadataOverrides()` → `_applyOverrides()` (PK/unique/inject adjustments)
450
- * 6. Build field descriptors (TDbFieldMeta[])
451
- * 7. Build leaf field indexes (skipped for nested-objects adapters)
452
- * 8. Finalize indexes (resolve field names to physical)
453
- * 9. `adapter.onAfterFlatten()` — adapter hook (read-only bookkeeping)
454
- * 10. Build allPhysicalFields list
455
- */
456
- build(type: TAtscriptAnnotatedType<TAtscriptTypeObject>, adapter: BaseDbAdapter, logger: TGenericLogger): void;
457
- /**
458
- * Applies adapter-provided metadata overrides atomically.
459
- * Processing order: injectFields → removePrimaryKeys → addPrimaryKeys → addUniqueFields.
460
- */
461
- private _applyOverrides;
462
- /**
463
- * Scans `@db.*` and `@meta.id` annotations on a field during flattening.
464
- */
465
- private _scanGenericAnnotations;
466
- private _addIndexField;
467
- /**
468
- * Classifies each field as column, flattened, json, or parent-object.
469
- * Builds the bidirectional pathToPhysical / physicalToPath maps.
470
- */
471
- private _classifyFields;
472
- /** Returns the `__`-separated parent prefix for a dot-separated path, or empty string for top-level paths. */
473
- private _flattenedPrefix;
474
- /**
475
- * Indexes `fieldDescriptors` into two lookup maps for unified
476
- * read/write field classification in the RelationalFieldMapper.
477
- */
478
- private _buildLeafIndexes;
479
- /**
480
- * Builds field descriptors, physical-name lookup, and value formatters.
481
- * Called once during build() — everything it needs
482
- * (flatMap, indexes, columnMap, etc.) is already populated.
483
- */
484
- private _buildFieldDescriptors;
485
- /**
486
- * Resolves `fkTargetField` for FK fields in field descriptors.
487
- */
488
- private _resolveFkTargetFields;
489
- private _finalizeIndexes;
490
- }
491
- //#endregion
492
493
  //#region src/base-adapter.d.ts
493
494
  /**
494
495
  * Abstract base class for database adapters.
@@ -1106,6 +1107,12 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
1106
1107
  constructor(_type: T, adapter: A, logger?: TGenericLogger, _tableResolver?: TTableResolver | undefined);
1107
1108
  /** Ensures metadata is built. Called before any metadata access. */
1108
1109
  protected _ensureBuilt(): void;
1110
+ /**
1111
+ * Built table metadata. Triggers a lazy build on first access — safe to call
1112
+ * from peer tables that need this one's relations / nav fields before any
1113
+ * operation has run against it directly.
1114
+ */
1115
+ getMetadata(): TableMetadata;
1109
1116
  protected _ensureSearchable(): void;
1110
1117
  /** Whether this readable is a view (overridden in AtscriptDbView). */
1111
1118
  get isView(): boolean;
@@ -1280,4 +1287,4 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
1280
1287
  }, thisTableName: string, alias?: string): TDbForeignKey | undefined;
1281
1288
  }
1282
1289
  //#endregion
1283
- export { TValueFormatterPair as $, TDbForeignKey as A, TExistingColumn as B, TCascadeTarget as C, TDbDefaultValue as D, TDbDefaultFn as E, TDbInsertResult as F, TIdDescriptor as G, TFieldMeta as H, TDbReferentialAction as I, TRelationInfo as J, TMetaResponse as K, TDbRelation as L, TDbIndexField as M, TDbIndexType as N, TDbDeleteResult as O, TDbInsertManyResult as P, TTableResolver as Q, TDbStorageType as R, TCascadeResolver as S, TDbCollation as T, TFkLookupResolver as U, TExistingTableOption as V, TFkLookupTarget as W, TSyncColumnResult as X, TSearchIndexInfo as Y, TTableOptionDiff as Z, DbQuery as _, FieldMappingStrategy as a, UniquSelect as at, NavPropsOf$1 as b, NoopLogger as c, AggregateExpr$1 as d, TWriteTableResolver as et, AggregateFn as f, DbControls as g, AtscriptDbWritable as h, DocumentFieldMapper as i, WithRelation$1 as it, TDbIndex as j, TDbFieldMeta as k, TGenericLogger as l, AggregateResult as m, DbResponse as n, Uniquery$1 as nt, BaseDbAdapter as o, AggregateQuery$1 as p, TMetadataOverrides as q, resolveDesignType as r, UniqueryControls$1 as rt, TableMetadata as s, AtscriptDbReadable as t, TypedWithRelation as tt, AggregateControls as u, FieldOpsFor as v, TColumnDiff as w, OwnPropsOf$1 as x, FilterExpr$1 as y, TDbUpdateResult as z };
1290
+ export { Uniquery$1 as $, TDbIndexType as A, TFkLookupResolver as B, TDbDefaultFn as C, TDbForeignKey as D, TDbFieldMeta as E, TDbStorageType as F, TRelationInfo as G, TIdDescriptor as H, TDbUpdateResult as I, TTableOptionDiff as J, TSearchIndexInfo as K, TExistingColumn as L, TDbInsertResult as M, TDbReferentialAction as N, TDbIndex as O, TDbRelation as P, TypedWithRelation as Q, TExistingTableOption as R, TDbCollation as S, TDbDeleteResult as T, TMetaResponse as U, TFkLookupTarget as V, TMetadataOverrides as W, TValueFormatterPair as X, TTableResolver as Y, TWriteTableResolver as Z, NavPropsOf$1 as _, FieldMappingStrategy as a, UniquSelect as at, TCascadeTarget as b, AggregateExpr$1 as c, AggregateResult as d, UniqueryControls$1 as et, AtscriptDbWritable as f, FilterExpr$1 as g, FieldOpsFor as h, DocumentFieldMapper as i, TGenericLogger as it, TDbInsertManyResult as j, TDbIndexField as k, AggregateFn as l, DbQuery as m, DbResponse as n, TableMetadata as nt, BaseDbAdapter as o, DbControls as p, TSyncColumnResult as q, resolveDesignType as r, NoopLogger as rt, AggregateControls as s, AtscriptDbReadable as t, WithRelation$1 as tt, AggregateQuery$1 as u, OwnPropsOf$1 as v, TDbDefaultValue as w, TColumnDiff as x, TCascadeResolver as y, TFieldMeta as z };
@@ -1,4 +1,4 @@
1
- import { u as TFieldOps } from "./ops-DcHDxrjX.mjs";
1
+ import { u as TFieldOps } from "./ops-C61kelof.mjs";
2
2
  import { FlatOf, NavPropsOf, NavPropsOf as NavPropsOf$1, OwnPropsOf, OwnPropsOf as OwnPropsOf$1, PrimaryKeyOf, TAtscriptAnnotatedType, TAtscriptDataType, TAtscriptTypeObject, TMetadataMap, TSerializedAnnotatedType, TValidatorOptions, TValidatorPlugin, Validator } from "@atscript/typescript/utils";
3
3
  import { AggregateControls, AggregateExpr, AggregateExpr as AggregateExpr$1, AggregateFn, AggregateQuery, AggregateQuery as AggregateQuery$1, AggregateResult, FieldOpsFor, FilterExpr, FilterExpr as FilterExpr$1, TypedWithRelation, Uniquery, Uniquery as Uniquery$1, UniqueryControls, UniqueryControls as UniqueryControls$1, UniqueryInsights, WithRelation, WithRelation as WithRelation$1 } from "@uniqu/core";
4
4
 
@@ -44,6 +44,120 @@ declare class UniquSelect {
44
44
  get hasAggregates(): boolean;
45
45
  }
46
46
  //#endregion
47
+ //#region src/logger.d.ts
48
+ interface TGenericLogger {
49
+ error(...messages: any[]): void;
50
+ warn(...messages: any[]): void;
51
+ log(...messages: any[]): void;
52
+ info(...messages: any[]): void;
53
+ debug(...messages: any[]): void;
54
+ }
55
+ declare const NoopLogger: TGenericLogger;
56
+ //#endregion
57
+ //#region src/table/table-metadata.d.ts
58
+ /**
59
+ * Computed metadata for a database table or view.
60
+ *
61
+ * Contains all field metadata, physical mapping indexes, relation definitions,
62
+ * and constraint information derived from Atscript annotations. Built lazily
63
+ * on first access via {@link build}, then immutable.
64
+ *
65
+ * This class owns the build pipeline that was previously part of
66
+ * `AtscriptDbReadable._flatten()`. The Readable delegates all metadata
67
+ * access to this class.
68
+ */
69
+ declare class TableMetadata {
70
+ readonly nestedObjects: boolean;
71
+ flatMap: Map<string, TAtscriptAnnotatedType>;
72
+ fieldDescriptors: readonly TDbFieldMeta[];
73
+ primaryKeys: string[];
74
+ originalMetaIdFields: string[];
75
+ indexes: Map<string, TDbIndex>;
76
+ foreignKeys: Map<string, TDbForeignKey>;
77
+ relations: Map<string, TDbRelation>;
78
+ navFields: Set<string>;
79
+ ignoredFields: Set<string>;
80
+ uniqueProps: Set<string>;
81
+ defaults: Map<string, TDbDefaultValue>;
82
+ columnMap: Map<string, string>;
83
+ dimensions: string[];
84
+ measures: string[];
85
+ pathToPhysical: Map<string, string>;
86
+ physicalToPath: Map<string, string>;
87
+ flattenedParents: Set<string>;
88
+ jsonFields: Set<string>;
89
+ selectExpansion: Map<string, string[]>;
90
+ booleanFields: Set<string>;
91
+ decimalFields: Set<string>;
92
+ allPhysicalFields: string[];
93
+ /** Precomputed parent path → child physical column names for fast null-setting. */
94
+ childrenByParent: Map<string, string[]>;
95
+ requiresMappings: boolean;
96
+ /** True when the only mappings needed are simple `@db.column` renames (no nesting/JSON). */
97
+ onlyColumnRenames: boolean;
98
+ toStorageFormatters?: Map<string, (value: unknown) => unknown>;
99
+ fromStorageFormatters?: Map<string, (value: unknown) => unknown>;
100
+ /** Leaf field descriptors indexed by physical column name (read path). */
101
+ leafByPhysical: Map<string, TDbFieldMeta>;
102
+ /** Leaf field descriptors indexed by logical path (write/patch/filter paths). */
103
+ leafByLogical: Map<string, TDbFieldMeta>;
104
+ private _built;
105
+ private _collateMap;
106
+ private _columnFromMap;
107
+ constructor(nestedObjects: boolean);
108
+ get isBuilt(): boolean;
109
+ /**
110
+ * Runs the full metadata compilation pipeline. Called once by
111
+ * `AtscriptDbReadable._ensureBuilt()` on first metadata access.
112
+ *
113
+ * Pipeline steps:
114
+ * 1. `adapter.onBeforeFlatten(type)` — adapter hook
115
+ * 2. `flattenAnnotatedType()` — collect field tuples, detect nav fields eagerly
116
+ * 3. Replay non-nav-descendant tuples through annotation scanning + adapter.onFieldScanned
117
+ * 4. Classify fields and build path maps (skipped for nested-objects adapters)
118
+ * 5. `adapter.getMetadataOverrides()` → `_applyOverrides()` (PK/unique/inject adjustments)
119
+ * 6. Build field descriptors (TDbFieldMeta[])
120
+ * 7. Build leaf field indexes (skipped for nested-objects adapters)
121
+ * 8. Finalize indexes (resolve field names to physical)
122
+ * 9. `adapter.onAfterFlatten()` — adapter hook (read-only bookkeeping)
123
+ * 10. Build allPhysicalFields list
124
+ */
125
+ build(type: TAtscriptAnnotatedType<TAtscriptTypeObject>, adapter: BaseDbAdapter, logger: TGenericLogger): void;
126
+ /**
127
+ * Applies adapter-provided metadata overrides atomically.
128
+ * Processing order: injectFields → removePrimaryKeys → addPrimaryKeys → addUniqueFields.
129
+ */
130
+ private _applyOverrides;
131
+ /**
132
+ * Scans `@db.*` and `@meta.id` annotations on a field during flattening.
133
+ */
134
+ private _scanGenericAnnotations;
135
+ private _addIndexField;
136
+ /**
137
+ * Classifies each field as column, flattened, json, or parent-object.
138
+ * Builds the bidirectional pathToPhysical / physicalToPath maps.
139
+ */
140
+ private _classifyFields;
141
+ /** Returns the `__`-separated parent prefix for a dot-separated path, or empty string for top-level paths. */
142
+ private _flattenedPrefix;
143
+ /**
144
+ * Indexes `fieldDescriptors` into two lookup maps for unified
145
+ * read/write field classification in the RelationalFieldMapper.
146
+ */
147
+ private _buildLeafIndexes;
148
+ /**
149
+ * Builds field descriptors, physical-name lookup, and value formatters.
150
+ * Called once during build() — everything it needs
151
+ * (flatMap, indexes, columnMap, etc.) is already populated.
152
+ */
153
+ private _buildFieldDescriptors;
154
+ /**
155
+ * Resolves `fkTargetField` for FK fields in field descriptors.
156
+ */
157
+ private _resolveFkTargetFields;
158
+ private _finalizeIndexes;
159
+ }
160
+ //#endregion
47
161
  //#region src/types.d.ts
48
162
  /** Controls with resolved projection. Used in the adapter interface. */
49
163
  interface DbControls extends Omit<UniqueryControls, "$select"> {
@@ -290,6 +404,7 @@ interface AtscriptDbTableLike {
290
404
  primaryKeys: readonly string[];
291
405
  relations: ReadonlyMap<string, TDbRelation>;
292
406
  foreignKeys: ReadonlyMap<string, TDbForeignKey>;
407
+ getMetadata(): TableMetadata;
293
408
  }
294
409
  /** Minimal writable table interface for nested creation/update. */
295
410
  interface AtscriptDbWritable {
@@ -375,120 +490,6 @@ interface TDbRelation {
375
490
  viaType?: () => TAtscriptAnnotatedType;
376
491
  }
377
492
  //#endregion
378
- //#region src/logger.d.ts
379
- interface TGenericLogger {
380
- error(...messages: any[]): void;
381
- warn(...messages: any[]): void;
382
- log(...messages: any[]): void;
383
- info(...messages: any[]): void;
384
- debug(...messages: any[]): void;
385
- }
386
- declare const NoopLogger: TGenericLogger;
387
- //#endregion
388
- //#region src/table/table-metadata.d.ts
389
- /**
390
- * Computed metadata for a database table or view.
391
- *
392
- * Contains all field metadata, physical mapping indexes, relation definitions,
393
- * and constraint information derived from Atscript annotations. Built lazily
394
- * on first access via {@link build}, then immutable.
395
- *
396
- * This class owns the build pipeline that was previously part of
397
- * `AtscriptDbReadable._flatten()`. The Readable delegates all metadata
398
- * access to this class.
399
- */
400
- declare class TableMetadata {
401
- readonly nestedObjects: boolean;
402
- flatMap: Map<string, TAtscriptAnnotatedType>;
403
- fieldDescriptors: readonly TDbFieldMeta[];
404
- primaryKeys: string[];
405
- originalMetaIdFields: string[];
406
- indexes: Map<string, TDbIndex>;
407
- foreignKeys: Map<string, TDbForeignKey>;
408
- relations: Map<string, TDbRelation>;
409
- navFields: Set<string>;
410
- ignoredFields: Set<string>;
411
- uniqueProps: Set<string>;
412
- defaults: Map<string, TDbDefaultValue>;
413
- columnMap: Map<string, string>;
414
- dimensions: string[];
415
- measures: string[];
416
- pathToPhysical: Map<string, string>;
417
- physicalToPath: Map<string, string>;
418
- flattenedParents: Set<string>;
419
- jsonFields: Set<string>;
420
- selectExpansion: Map<string, string[]>;
421
- booleanFields: Set<string>;
422
- decimalFields: Set<string>;
423
- allPhysicalFields: string[];
424
- /** Precomputed parent path → child physical column names for fast null-setting. */
425
- childrenByParent: Map<string, string[]>;
426
- requiresMappings: boolean;
427
- /** True when the only mappings needed are simple `@db.column` renames (no nesting/JSON). */
428
- onlyColumnRenames: boolean;
429
- toStorageFormatters?: Map<string, (value: unknown) => unknown>;
430
- fromStorageFormatters?: Map<string, (value: unknown) => unknown>;
431
- /** Leaf field descriptors indexed by physical column name (read path). */
432
- leafByPhysical: Map<string, TDbFieldMeta>;
433
- /** Leaf field descriptors indexed by logical path (write/patch/filter paths). */
434
- leafByLogical: Map<string, TDbFieldMeta>;
435
- private _built;
436
- private _collateMap;
437
- private _columnFromMap;
438
- constructor(nestedObjects: boolean);
439
- get isBuilt(): boolean;
440
- /**
441
- * Runs the full metadata compilation pipeline. Called once by
442
- * `AtscriptDbReadable._ensureBuilt()` on first metadata access.
443
- *
444
- * Pipeline steps:
445
- * 1. `adapter.onBeforeFlatten(type)` — adapter hook
446
- * 2. `flattenAnnotatedType()` — collect field tuples, detect nav fields eagerly
447
- * 3. Replay non-nav-descendant tuples through annotation scanning + adapter.onFieldScanned
448
- * 4. Classify fields and build path maps (skipped for nested-objects adapters)
449
- * 5. `adapter.getMetadataOverrides()` → `_applyOverrides()` (PK/unique/inject adjustments)
450
- * 6. Build field descriptors (TDbFieldMeta[])
451
- * 7. Build leaf field indexes (skipped for nested-objects adapters)
452
- * 8. Finalize indexes (resolve field names to physical)
453
- * 9. `adapter.onAfterFlatten()` — adapter hook (read-only bookkeeping)
454
- * 10. Build allPhysicalFields list
455
- */
456
- build(type: TAtscriptAnnotatedType<TAtscriptTypeObject>, adapter: BaseDbAdapter, logger: TGenericLogger): void;
457
- /**
458
- * Applies adapter-provided metadata overrides atomically.
459
- * Processing order: injectFields → removePrimaryKeys → addPrimaryKeys → addUniqueFields.
460
- */
461
- private _applyOverrides;
462
- /**
463
- * Scans `@db.*` and `@meta.id` annotations on a field during flattening.
464
- */
465
- private _scanGenericAnnotations;
466
- private _addIndexField;
467
- /**
468
- * Classifies each field as column, flattened, json, or parent-object.
469
- * Builds the bidirectional pathToPhysical / physicalToPath maps.
470
- */
471
- private _classifyFields;
472
- /** Returns the `__`-separated parent prefix for a dot-separated path, or empty string for top-level paths. */
473
- private _flattenedPrefix;
474
- /**
475
- * Indexes `fieldDescriptors` into two lookup maps for unified
476
- * read/write field classification in the RelationalFieldMapper.
477
- */
478
- private _buildLeafIndexes;
479
- /**
480
- * Builds field descriptors, physical-name lookup, and value formatters.
481
- * Called once during build() — everything it needs
482
- * (flatMap, indexes, columnMap, etc.) is already populated.
483
- */
484
- private _buildFieldDescriptors;
485
- /**
486
- * Resolves `fkTargetField` for FK fields in field descriptors.
487
- */
488
- private _resolveFkTargetFields;
489
- private _finalizeIndexes;
490
- }
491
- //#endregion
492
493
  //#region src/base-adapter.d.ts
493
494
  /**
494
495
  * Abstract base class for database adapters.
@@ -1106,6 +1107,12 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
1106
1107
  constructor(_type: T, adapter: A, logger?: TGenericLogger, _tableResolver?: TTableResolver | undefined);
1107
1108
  /** Ensures metadata is built. Called before any metadata access. */
1108
1109
  protected _ensureBuilt(): void;
1110
+ /**
1111
+ * Built table metadata. Triggers a lazy build on first access — safe to call
1112
+ * from peer tables that need this one's relations / nav fields before any
1113
+ * operation has run against it directly.
1114
+ */
1115
+ getMetadata(): TableMetadata;
1109
1116
  protected _ensureSearchable(): void;
1110
1117
  /** Whether this readable is a view (overridden in AtscriptDbView). */
1111
1118
  get isView(): boolean;
@@ -1280,4 +1287,4 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
1280
1287
  }, thisTableName: string, alias?: string): TDbForeignKey | undefined;
1281
1288
  }
1282
1289
  //#endregion
1283
- export { TValueFormatterPair as $, TDbForeignKey as A, TExistingColumn as B, TCascadeTarget as C, TDbDefaultValue as D, TDbDefaultFn as E, TDbInsertResult as F, TIdDescriptor as G, TFieldMeta as H, TDbReferentialAction as I, TRelationInfo as J, TMetaResponse as K, TDbRelation as L, TDbIndexField as M, TDbIndexType as N, TDbDeleteResult as O, TDbInsertManyResult as P, TTableResolver as Q, TDbStorageType as R, TCascadeResolver as S, TDbCollation as T, TFkLookupResolver as U, TExistingTableOption as V, TFkLookupTarget as W, TSyncColumnResult as X, TSearchIndexInfo as Y, TTableOptionDiff as Z, DbQuery as _, FieldMappingStrategy as a, UniquSelect as at, NavPropsOf$1 as b, NoopLogger as c, AggregateExpr$1 as d, TWriteTableResolver as et, AggregateFn as f, DbControls as g, AtscriptDbWritable as h, DocumentFieldMapper as i, WithRelation$1 as it, TDbIndex as j, TDbFieldMeta as k, TGenericLogger as l, AggregateResult as m, DbResponse as n, Uniquery$1 as nt, BaseDbAdapter as o, AggregateQuery$1 as p, TMetadataOverrides as q, resolveDesignType as r, UniqueryControls$1 as rt, TableMetadata as s, AtscriptDbReadable as t, TypedWithRelation as tt, AggregateControls as u, FieldOpsFor as v, TColumnDiff as w, OwnPropsOf$1 as x, FilterExpr$1 as y, TDbUpdateResult as z };
1290
+ export { Uniquery$1 as $, TDbIndexType as A, TFkLookupResolver as B, TDbDefaultFn as C, TDbForeignKey as D, TDbFieldMeta as E, TDbStorageType as F, TRelationInfo as G, TIdDescriptor as H, TDbUpdateResult as I, TTableOptionDiff as J, TSearchIndexInfo as K, TExistingColumn as L, TDbInsertResult as M, TDbReferentialAction as N, TDbIndex as O, TDbRelation as P, TypedWithRelation as Q, TExistingTableOption as R, TDbCollation as S, TDbDeleteResult as T, TMetaResponse as U, TFkLookupTarget as V, TMetadataOverrides as W, TValueFormatterPair as X, TTableResolver as Y, TWriteTableResolver as Z, NavPropsOf$1 as _, FieldMappingStrategy as a, UniquSelect as at, TCascadeTarget as b, AggregateExpr$1 as c, AggregateResult as d, UniqueryControls$1 as et, AtscriptDbWritable as f, FilterExpr$1 as g, FieldOpsFor as h, DocumentFieldMapper as i, TGenericLogger as it, TDbInsertManyResult as j, TDbIndexField as k, AggregateFn as l, DbQuery as m, DbResponse as n, TableMetadata as nt, BaseDbAdapter as o, DbControls as p, TSyncColumnResult as q, resolveDesignType as r, NoopLogger as rt, AggregateControls as s, AtscriptDbReadable as t, WithRelation$1 as tt, AggregateQuery$1 as u, OwnPropsOf$1 as v, TDbDefaultValue as w, TColumnDiff as x, TCascadeResolver as y, TFieldMeta as z };
@@ -1,4 +1,4 @@
1
- import { F as TDbInsertResult, O as TDbDeleteResult, P as TDbInsertManyResult, Q as TTableResolver, S as TCascadeResolver, U as TFkLookupResolver, et as TWriteTableResolver, l as TGenericLogger, o as BaseDbAdapter, s as TableMetadata, t as AtscriptDbReadable, z as TDbUpdateResult } from "./db-readable-ktHqF277.cjs";
1
+ import { B as TFkLookupResolver, I as TDbUpdateResult, M as TDbInsertResult, T as TDbDeleteResult, Y as TTableResolver, Z as TWriteTableResolver, it as TGenericLogger, j as TDbInsertManyResult, nt as TableMetadata, o as BaseDbAdapter, t as AtscriptDbReadable, y as TCascadeResolver } from "./db-readable-DtrC0BGF.cjs";
2
2
  import { FilterExpr } from "@uniqu/core";
3
3
  import { AtscriptQueryComparison, AtscriptQueryFieldRef, AtscriptQueryFieldRef as AtscriptQueryFieldRef$1, AtscriptQueryNode, AtscriptQueryNode as AtscriptQueryNode$1, AtscriptRef, FlatOf, NavPropsOf, OwnPropsOf, PrimaryKeyOf, TAtscriptAnnotatedType, TAtscriptDataType, Validator } from "@atscript/typescript/utils";
4
4
 
@@ -29,6 +29,7 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
29
29
  protected _fkLookupResolver?: TFkLookupResolver;
30
30
  protected readonly _integrity: IntegrityStrategy;
31
31
  protected readonly validators: Map<string, Validator<T, DataType>>;
32
+ private _fromDepthMap?;
32
33
  constructor(_type: T, adapter: A, logger?: TGenericLogger, _tableResolver?: TTableResolver, _writeTableResolver?: TWriteTableResolver);
33
34
  /**
34
35
  * Sets the cascade resolver for application-level cascade deletes.
@@ -141,6 +142,18 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
141
142
  */
142
143
  protected _extractRecordFilter(payload: Record<string, unknown>): FilterExpr;
143
144
  private _prepareFilterValue;
145
+ /**
146
+ * Lazy — builds a `normalized-path → from-depth` map from `this._meta.flatMap`
147
+ * on first use. Only paths reachable through an unbroken chain of `db.rel.from`
148
+ * nav fields from the root are included (chains crossing `to`/`via` are excluded).
149
+ */
150
+ private _getFromDepthMap;
151
+ /**
152
+ * Populate the depth-limit bundle on a `DbValidationContext`. Only the root
153
+ * write call (`depth === 0`) enforces — nested re-entries leave `depthCheck`
154
+ * unset so the full tree is validated once at the root.
155
+ */
156
+ private _applyDepthCtx;
144
157
  /**
145
158
  * Pre-validate items (type validation + FK constraints) without inserting them.
146
159
  * Used by parent tables to validate FROM children before the main insert,