@atscript/db 0.1.39 → 0.1.41

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 (64) hide show
  1. package/README.md +18 -18
  2. package/dist/agg.cjs +8 -3
  3. package/dist/agg.d.cts +7 -0
  4. package/dist/agg.d.mts +7 -0
  5. package/dist/agg.mjs +7 -3
  6. package/dist/control-DRgryKeg.cjs +14 -0
  7. package/dist/{control_as-bjmwe24C.mjs → control-IANbnfjG.mjs} +6 -18
  8. package/dist/db-readable-BQQzfguJ.d.cts +1249 -0
  9. package/dist/db-readable-Bbr4CjMb.d.mts +1249 -0
  10. package/dist/db-space-BUrQ5BFm.d.mts +309 -0
  11. package/dist/db-space-Vxpcnyt5.d.cts +309 -0
  12. package/dist/db-validator-plugin-07kDiis2.d.cts +22 -0
  13. package/dist/db-validator-plugin-CiqsHTI_.d.mts +22 -0
  14. package/dist/db-view-CMI9TOo1.cjs +3096 -0
  15. package/dist/db-view-Esy2fDxw.mjs +2995 -0
  16. package/dist/index.cjs +95 -2801
  17. package/dist/index.d.cts +137 -0
  18. package/dist/index.d.mts +137 -0
  19. package/dist/index.mjs +55 -2761
  20. package/dist/{nested-writer-BkqL7cp3.cjs → nested-writer-BDXsDMPP.cjs} +196 -150
  21. package/dist/{nested-writer-NEN51mnR.mjs → nested-writer-Dmm1gbZV.mjs} +118 -70
  22. package/dist/ops-BdRAFLKY.d.mts +67 -0
  23. package/dist/ops-DXJ4Zw0P.d.cts +67 -0
  24. package/dist/ops.cjs +123 -0
  25. package/dist/ops.d.cts +2 -0
  26. package/dist/ops.d.mts +2 -0
  27. package/dist/ops.mjs +112 -0
  28. package/dist/plugin.cjs +90 -109
  29. package/dist/plugin.d.cts +6 -0
  30. package/dist/plugin.d.mts +6 -0
  31. package/dist/plugin.mjs +29 -49
  32. package/dist/rel.cjs +20 -20
  33. package/dist/rel.d.cts +119 -0
  34. package/dist/rel.d.mts +119 -0
  35. package/dist/rel.mjs +4 -5
  36. package/dist/{relation-helpers-guFL_oRf.cjs → relation-helpers-BYvsE1tR.cjs} +26 -22
  37. package/dist/{relation-helpers-DyBIlQnB.mjs → relation-helpers-CLasawQq.mjs} +11 -6
  38. package/dist/{relation-loader-Dv7qXYq7.mjs → relation-loader-BEOTXNcq.mjs} +63 -43
  39. package/dist/{relation-loader-CpnDRf9k.cjs → relation-loader-CRC5LcqM.cjs} +74 -49
  40. package/dist/shared.cjs +13 -13
  41. package/dist/{shared.d.ts → shared.d.cts} +14 -13
  42. package/dist/shared.d.mts +71 -0
  43. package/dist/shared.mjs +2 -3
  44. package/dist/sync.cjs +300 -252
  45. package/dist/sync.d.cts +369 -0
  46. package/dist/sync.d.mts +369 -0
  47. package/dist/sync.mjs +284 -233
  48. package/dist/{validation-utils-DEoCMmEb.cjs → validation-utils-DVJDijnB.cjs} +141 -109
  49. package/dist/{validation-utils-DhR_mtKa.mjs → validation-utils-DhjIjP1-.mjs} +71 -37
  50. package/package.json +30 -29
  51. package/LICENSE +0 -21
  52. package/dist/agg-BJFJ3dFQ.mjs +0 -8
  53. package/dist/agg-DnUWAOK8.cjs +0 -14
  54. package/dist/agg.d.ts +0 -13
  55. package/dist/chunk-CrpGerW8.cjs +0 -31
  56. package/dist/control_as-BFPERAF_.cjs +0 -28
  57. package/dist/index.d.ts +0 -1706
  58. package/dist/logger-B7oxCfLQ.mjs +0 -12
  59. package/dist/logger-Dt2v_-wb.cjs +0 -18
  60. package/dist/plugin.d.ts +0 -5
  61. package/dist/rel.d.ts +0 -1305
  62. package/dist/relation-loader-D4mTw6yH.cjs +0 -4
  63. package/dist/relation-loader-Ggy1ujwR.mjs +0 -4
  64. package/dist/sync.d.ts +0 -1878
package/dist/plugin.mjs CHANGED
@@ -1,7 +1,6 @@
1
- import { findFKFieldsPointingTo, getAnnotationAlias, getDbTableOwner, getNavTargetTypeName, getParentStruct, getParentTypeName, hasAnyViewAnnotation, refActionAnnotation, validateFieldBaseType, validateQueryScope, validateRefArgument } from "./validation-utils-DhR_mtKa.mjs";
1
+ import { a as getAnnotationAlias, c as getParentStruct, d as validateFieldBaseType, i as validateRefArgument, l as getParentTypeName, n as hasAnyViewAnnotation, o as getDbTableOwner, r as validateQueryScope, s as getNavTargetTypeName, t as findFKFieldsPointingTo, u as refActionAnnotation } from "./validation-utils-DhjIjP1-.mjs";
2
2
  import { AnnotationSpec, isArray, isInterface, isPrimitive, isRef, isStructure } from "@atscript/core";
3
-
4
- //#region packages/db/src/plugin/annotations/agg.ts
3
+ //#region src/plugin/annotations/agg.ts
5
4
  const dbAggAnnotations = { agg: {
6
5
  sum: new AnnotationSpec({
7
6
  description: "Declares a view field as SUM of a source column.",
@@ -59,9 +58,8 @@ const dbAggAnnotations = { agg: {
59
58
  }
60
59
  })
61
60
  } };
62
-
63
61
  //#endregion
64
- //#region packages/db/src/plugin/annotations/column.ts
62
+ //#region src/plugin/annotations/column.ts
65
63
  const dbColumnAnnotations = {
66
64
  patch: { strategy: new AnnotationSpec({
67
65
  description: "Defines the **patching strategy** for updating nested objects.\n\n- **\"replace\"** → The field or object will be **fully replaced**.\n- **\"merge\"** → The field or object will be **merged recursively** (applies only to objects, not arrays).\n\n**Example:**\n```atscript\n@db.patch.strategy \"merge\"\nsettings: {\n notifications: boolean\n preferences: {\n theme: string\n }\n}\n```\n",
@@ -198,8 +196,7 @@ const dbColumnAnnotations = {
198
196
  nodeType: ["prop"],
199
197
  validate(token, _args, doc) {
200
198
  const errors = [];
201
- const field = token.parentNode;
202
- const definition = field.getDefinition();
199
+ const definition = token.parentNode.getDefinition();
203
200
  if (definition && isRef(definition)) {
204
201
  const unwound = doc.unwindType(definition.id, definition.chain);
205
202
  if (unwound && isPrimitive(unwound.def)) errors.push({
@@ -214,10 +211,9 @@ const dbColumnAnnotations = {
214
211
  ignore: new AnnotationSpec({
215
212
  description: "Excludes a field from the database schema. The field exists in the Atscript type but has no column in the DB.\n\n**Example:**\n```atscript\n@db.ignore\ndisplayName: string\n```\n",
216
213
  nodeType: ["prop"],
217
- validate(token, args, doc) {
214
+ validate(token, _args, _doc) {
218
215
  const errors = [];
219
- const field = token.parentNode;
220
- if (field.countAnnotations("meta.id") > 0) errors.push({
216
+ if (token.parentNode.countAnnotations("meta.id") > 0) errors.push({
221
217
  message: `@db.ignore cannot coexist with @meta.id — a field cannot be both a primary key and excluded from the database`,
222
218
  severity: 1,
223
219
  range: token.range
@@ -226,9 +222,8 @@ const dbColumnAnnotations = {
226
222
  }
227
223
  })
228
224
  };
229
-
230
225
  //#endregion
231
- //#region packages/db/src/plugin/annotations/index-ann.ts
226
+ //#region src/plugin/annotations/index-ann.ts
232
227
  const dbIndexAnnotations = { index: {
233
228
  plain: new AnnotationSpec({
234
229
  description: "Standard (non-unique) index for query performance. Fields sharing the same index name form a composite index.\n\n**Example:**\n```atscript\n@db.index.plain \"idx_timeline\", \"desc\"\ncreatedAt: number.timestamp\n```\n",
@@ -278,9 +273,8 @@ const dbIndexAnnotations = { index: {
278
273
  }]
279
274
  })
280
275
  } };
281
-
282
276
  //#endregion
283
- //#region packages/db/src/plugin/annotations/rel.ts
277
+ //#region src/plugin/annotations/rel.ts
284
278
  const dbRelAnnotations = { rel: {
285
279
  FK: new AnnotationSpec({
286
280
  description: "Declares a foreign key constraint on this field. The field must use a chain reference type (e.g., `User.id`) to specify the FK target.\n\n**Example:**\n```atscript\n@db.rel.FK\nauthorId: User.id\n\n// With alias (required when multiple FKs point to the same type)\n@db.rel.FK \"author\"\nauthorId: User.id\n```\n",
@@ -401,7 +395,7 @@ const dbRelAnnotations = { rel: {
401
395
  const unwound = doc.unwindType(targetTypeName);
402
396
  if (unwound) {
403
397
  const targetDef = unwound.def;
404
- const targetNode = isInterface(targetDef) ? targetDef : undefined;
398
+ const targetNode = isInterface(targetDef) ? targetDef : void 0;
405
399
  if (!targetNode || targetNode.countAnnotations("db.table") === 0) errors.push({
406
400
  message: `@db.rel.to target '${targetTypeName}' is not a @db.table entity`,
407
401
  severity: 1,
@@ -421,9 +415,8 @@ const dbRelAnnotations = { rel: {
421
415
  if (name === fieldName) continue;
422
416
  if (prop.countAnnotations("db.rel.to") === 0) continue;
423
417
  const propAlias = getAnnotationAlias(prop, "db.rel.to");
424
- if ((alias || undefined) === (propAlias || undefined)) {
425
- const otherTarget = getNavTargetTypeName(prop);
426
- if (otherTarget === targetTypeName) {
418
+ if ((alias || void 0) === (propAlias || void 0)) {
419
+ if (getNavTargetTypeName(prop) === targetTypeName) {
427
420
  errors.push({
428
421
  message: `Duplicate @db.rel.to '${alias || targetTypeName}' — only one forward navigational property per alias`,
429
422
  severity: 1,
@@ -434,8 +427,7 @@ const dbRelAnnotations = { rel: {
434
427
  }
435
428
  }
436
429
  if (alias) {
437
- const matches = findFKFieldsPointingTo(doc, struct, targetTypeName, alias);
438
- if (matches.length === 0) errors.push({
430
+ if (findFKFieldsPointingTo(doc, struct, targetTypeName, alias).length === 0) errors.push({
439
431
  message: `No @db.rel.FK '${alias}' found on this interface`,
440
432
  severity: 1,
441
433
  range: token.range
@@ -447,7 +439,7 @@ const dbRelAnnotations = { rel: {
447
439
  severity: 1,
448
440
  range: token.range
449
441
  });
450
- else if (matches.length > 1) errors.push({
442
+ else if (matches.length > 1) errors.push({
451
443
  message: `Multiple @db.rel.FK fields point to '${targetTypeName}' — add alias to disambiguate`,
452
444
  severity: 1,
453
445
  range: token.range
@@ -502,9 +494,8 @@ else if (matches.length > 1) errors.push({
502
494
  if (name === fieldName) continue;
503
495
  if (prop.countAnnotations("db.rel.from") === 0) continue;
504
496
  const propAlias = getAnnotationAlias(prop, "db.rel.from");
505
- if ((alias || undefined) === (propAlias || undefined)) {
506
- const otherTarget = getNavTargetTypeName(prop);
507
- if (otherTarget === targetTypeName) {
497
+ if ((alias || void 0) === (propAlias || void 0)) {
498
+ if (getNavTargetTypeName(prop) === targetTypeName) {
508
499
  errors.push({
509
500
  message: `Duplicate @db.rel.from '${alias || targetTypeName}' — only one inverse navigational property per alias`,
510
501
  severity: 1,
@@ -529,15 +520,13 @@ else if (matches.length > 1) errors.push({
529
520
  severity: 1,
530
521
  range: token.range
531
522
  });
532
- else if (matches.length > 1) errors.push({
523
+ else if (matches.length > 1) errors.push({
533
524
  message: `'${targetTypeName}' has multiple @db.rel.FK fields pointing to '${thisTypeName}' — add alias`,
534
525
  severity: 1,
535
526
  range: token.range
536
527
  });
537
- const fieldDef = field.getDefinition();
538
- if (!isArray(fieldDef) && matches.length === 1) {
539
- const fkProp = matches[0].prop;
540
- if (fkProp.countAnnotations("db.index.unique") === 0) errors.push({
528
+ if (!isArray(field.getDefinition()) && matches.length === 1) {
529
+ if (matches[0].prop.countAnnotations("db.index.unique") === 0) errors.push({
541
530
  message: `@db.rel.from '${field.id}' has singular type '${targetTypeName}' (1:1) but the FK on '${targetTypeName}' is not @db.index.unique — did you mean '${targetTypeName}[]' (1:N)?`,
542
531
  severity: 2,
543
532
  range: token.range
@@ -564,8 +553,7 @@ else if (matches.length > 1) errors.push({
564
553
  severity: 1,
565
554
  range: token.range
566
555
  });
567
- const definition = field.getDefinition();
568
- if (!isArray(definition)) errors.push({
556
+ if (!isArray(field.getDefinition())) errors.push({
569
557
  message: "@db.rel.via requires an array type (e.g. Tag[])",
570
558
  severity: 1,
571
559
  range: token.range
@@ -587,7 +575,7 @@ else if (matches.length > 1) errors.push({
587
575
  severity: 1,
588
576
  range: args[0].range
589
577
  });
590
- else if (fksToThis.length > 1) errors.push({
578
+ else if (fksToThis.length > 1) errors.push({
591
579
  message: `Junction '${junctionName}' has multiple @db.rel.FK pointing to '${thisTypeName}' — not supported`,
592
580
  severity: 1,
593
581
  range: args[0].range
@@ -599,7 +587,7 @@ else if (fksToThis.length > 1) errors.push({
599
587
  severity: 1,
600
588
  range: args[0].range
601
589
  });
602
- else if (fksToTarget.length > 1) errors.push({
590
+ else if (fksToTarget.length > 1) errors.push({
603
591
  message: `Junction '${junctionName}' has multiple @db.rel.FK pointing to '${targetTypeName}' — not supported`,
604
592
  severity: 1,
605
593
  range: args[0].range
@@ -643,9 +631,8 @@ else if (fksToTarget.length > 1) errors.push({
643
631
  }
644
632
  })
645
633
  } };
646
-
647
634
  //#endregion
648
- //#region packages/db/src/plugin/annotations/search.ts
635
+ //#region src/plugin/annotations/search.ts
649
636
  const dbSearchAnnotations = { search: {
650
637
  vector: {
651
638
  $self: new AnnotationSpec({
@@ -710,9 +697,8 @@ const dbSearchAnnotations = { search: {
710
697
  }
711
698
  })
712
699
  } };
713
-
714
700
  //#endregion
715
- //#region packages/db/src/plugin/annotations/table.ts
701
+ //#region src/plugin/annotations/table.ts
716
702
  const dbTableAnnotations = {
717
703
  table: {
718
704
  $self: new AnnotationSpec({
@@ -745,8 +731,7 @@ const dbTableAnnotations = {
745
731
  },
746
732
  validate(token, _args, _doc) {
747
733
  const errors = [];
748
- const owner = token.parentNode;
749
- if (owner.countAnnotations("db.table") === 0) errors.push({
734
+ if (token.parentNode.countAnnotations("db.table") === 0) errors.push({
750
735
  message: "@db.table.renamed requires @db.table on the same interface",
751
736
  severity: 1,
752
737
  range: token.range
@@ -775,9 +760,8 @@ const dbTableAnnotations = {
775
760
  }
776
761
  }) }
777
762
  };
778
-
779
763
  //#endregion
780
- //#region packages/db/src/plugin/annotations/view.ts
764
+ //#region src/plugin/annotations/view.ts
781
765
  const dbViewAnnotations = { view: {
782
766
  $self: new AnnotationSpec({
783
767
  description: "Marks an interface as a **database view**. Optionally takes a view name argument.\n\n**Example:**\n```atscript\n@db.view \"active_premium_users\"\n@db.view.for User\nexport interface ActivePremiumUser { ... }\n```\n",
@@ -790,8 +774,7 @@ const dbViewAnnotations = { view: {
790
774
  },
791
775
  validate(token, _args, _doc) {
792
776
  const errors = [];
793
- const owner = token.parentNode;
794
- if (owner.countAnnotations("db.table") > 0) errors.push({
777
+ if (token.parentNode.countAnnotations("db.table") > 0) errors.push({
795
778
  message: "An interface cannot be both a @db.table and a @db.view",
796
779
  severity: 1,
797
780
  range: token.range
@@ -809,8 +792,7 @@ const dbViewAnnotations = { view: {
809
792
  },
810
793
  validate(token, args, doc) {
811
794
  const errors = [];
812
- const owner = token.parentNode;
813
- if (owner.countAnnotations("db.table") > 0) errors.push({
795
+ if (token.parentNode.countAnnotations("db.table") > 0) errors.push({
814
796
  message: "An interface cannot be both a @db.table and a @db.view",
815
797
  severity: 1,
816
798
  range: token.range
@@ -952,9 +934,8 @@ const dbViewAnnotations = { view: {
952
934
  }
953
935
  })
954
936
  } };
955
-
956
937
  //#endregion
957
- //#region packages/db/src/plugin/index.ts
938
+ //#region src/plugin/index.ts
958
939
  const dbPlugin = () => ({
959
940
  name: "db",
960
941
  config() {
@@ -984,6 +965,5 @@ const dbPlugin = () => ({
984
965
  };
985
966
  }
986
967
  });
987
-
988
968
  //#endregion
989
- export { dbPlugin, dbPlugin as default };
969
+ export { dbPlugin, dbPlugin as default };
package/dist/rel.cjs CHANGED
@@ -1,20 +1,20 @@
1
- const require_nested_writer = require('./nested-writer-BkqL7cp3.cjs');
2
- const require_relation_helpers = require('./relation-helpers-guFL_oRf.cjs');
3
- const require_relation_loader = require('./relation-loader-CpnDRf9k.cjs');
4
-
5
- exports.batchInsertNestedFrom = require_nested_writer.batchInsertNestedFrom
6
- exports.batchInsertNestedTo = require_nested_writer.batchInsertNestedTo
7
- exports.batchInsertNestedVia = require_nested_writer.batchInsertNestedVia
8
- exports.batchPatchNestedFrom = require_nested_writer.batchPatchNestedFrom
9
- exports.batchPatchNestedTo = require_nested_writer.batchPatchNestedTo
10
- exports.batchPatchNestedVia = require_nested_writer.batchPatchNestedVia
11
- exports.batchReplaceNestedFrom = require_nested_writer.batchReplaceNestedFrom
12
- exports.batchReplaceNestedTo = require_nested_writer.batchReplaceNestedTo
13
- exports.batchReplaceNestedVia = require_nested_writer.batchReplaceNestedVia
14
- exports.checkDepthOverflow = require_nested_writer.checkDepthOverflow
15
- exports.findFKForRelation = require_relation_helpers.findFKForRelation
16
- exports.findRemoteFK = require_relation_helpers.findRemoteFK
17
- exports.loadRelationsImpl = require_relation_loader.loadRelationsImpl
18
- exports.preValidateNestedFrom = require_nested_writer.preValidateNestedFrom
19
- exports.resolveRelationTargetTable = require_relation_helpers.resolveRelationTargetTable
20
- exports.validateBatch = require_nested_writer.validateBatch
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_relation_loader = require("./relation-loader-CRC5LcqM.cjs");
3
+ const require_nested_writer = require("./nested-writer-BDXsDMPP.cjs");
4
+ const require_relation_helpers = require("./relation-helpers-BYvsE1tR.cjs");
5
+ exports.batchInsertNestedFrom = require_nested_writer.batchInsertNestedFrom;
6
+ exports.batchInsertNestedTo = require_nested_writer.batchInsertNestedTo;
7
+ exports.batchInsertNestedVia = require_nested_writer.batchInsertNestedVia;
8
+ exports.batchPatchNestedFrom = require_nested_writer.batchPatchNestedFrom;
9
+ exports.batchPatchNestedTo = require_nested_writer.batchPatchNestedTo;
10
+ exports.batchPatchNestedVia = require_nested_writer.batchPatchNestedVia;
11
+ exports.batchReplaceNestedFrom = require_nested_writer.batchReplaceNestedFrom;
12
+ exports.batchReplaceNestedTo = require_nested_writer.batchReplaceNestedTo;
13
+ exports.batchReplaceNestedVia = require_nested_writer.batchReplaceNestedVia;
14
+ exports.checkDepthOverflow = require_nested_writer.checkDepthOverflow;
15
+ exports.findFKForRelation = require_relation_helpers.findFKForRelation;
16
+ exports.findRemoteFK = require_relation_helpers.findRemoteFK;
17
+ exports.loadRelationsImpl = require_relation_loader.loadRelationsImpl;
18
+ exports.preValidateNestedFrom = require_nested_writer.preValidateNestedFrom;
19
+ exports.resolveRelationTargetTable = require_relation_helpers.resolveRelationTargetTable;
20
+ exports.validateBatch = require_nested_writer.validateBatch;
package/dist/rel.d.cts ADDED
@@ -0,0 +1,119 @@
1
+ import { A as TDbForeignKey, L as TDbRelation, Y as TTableResolver, Z as TWriteTableResolver, l as TGenericLogger, o as BaseDbAdapter, s as TableMetadata } from "./db-readable-BQQzfguJ.cjs";
2
+ import { t as DbValidationContext } from "./db-validator-plugin-07kDiis2.cjs";
3
+ import { FilterExpr, WithRelation } from "@uniqu/core";
4
+ import { Validator } from "@atscript/typescript/utils";
5
+
6
+ //#region src/rel/relation-loader.d.ts
7
+ /** Host interface for the relation loader — matches AtscriptDbReadable property names. */
8
+ interface TRelationLoaderHost {
9
+ readonly tableName: string;
10
+ readonly _meta: {
11
+ readonly relations: ReadonlyMap<string, TDbRelation>;
12
+ readonly foreignKeys: ReadonlyMap<string, TDbForeignKey>;
13
+ };
14
+ readonly _tableResolver?: TTableResolver;
15
+ readonly adapter: BaseDbAdapter;
16
+ readonly logger: TGenericLogger;
17
+ }
18
+ /**
19
+ * Loads related data for `$with` relations and attaches them to result rows.
20
+ */
21
+ declare function loadRelationsImpl(rows: Array<Record<string, unknown>>, withRelations: WithRelation[], host: TRelationLoaderHost): Promise<void>;
22
+ //#endregion
23
+ //#region src/rel/relation-helpers.d.ts
24
+ /**
25
+ * Finds the FK entry that connects a `@db.rel.to` relation to its target.
26
+ */
27
+ declare function findFKForRelation(relation: TDbRelation, foreignKeys: ReadonlyMap<string, TDbForeignKey>): {
28
+ localFields: string[];
29
+ targetFields: string[];
30
+ } | undefined;
31
+ /**
32
+ * Finds a FK on a remote table that points back to a given table name.
33
+ */
34
+ declare function findRemoteFK(targetTable: {
35
+ foreignKeys: ReadonlyMap<string, TDbForeignKey>;
36
+ }, thisTableName: string, alias?: string): TDbForeignKey | undefined;
37
+ /**
38
+ * Resolves the target table name from a relation's target type metadata.
39
+ */
40
+ declare function resolveRelationTargetTable(relation: TDbRelation): string;
41
+ //#endregion
42
+ //#region src/rel/nested-writer.d.ts
43
+ /**
44
+ * Properties the nested writer functions need from the table instance.
45
+ * AtscriptDbTable satisfies this structurally — pass `this` with a cast.
46
+ */
47
+ interface TNestedWriterHost {
48
+ readonly tableName: string;
49
+ readonly _meta: TableMetadata;
50
+ readonly _writeTableResolver?: TWriteTableResolver;
51
+ _findFKForRelation(relation: TDbRelation): {
52
+ localFields: string[];
53
+ targetFields: string[];
54
+ } | undefined;
55
+ _findRemoteFK(targetTable: {
56
+ foreignKeys: ReadonlyMap<string, TDbForeignKey>;
57
+ }, thisTableName: string, alias?: string): TDbForeignKey | undefined;
58
+ _extractPrimaryKeyFilter(payload: Record<string, unknown>): FilterExpr;
59
+ findOne(query: {
60
+ filter: FilterExpr;
61
+ controls: Record<string, never>;
62
+ }): Promise<Record<string, unknown> | null>;
63
+ }
64
+ /**
65
+ * Checks if any payload contains navigational data that would be silently
66
+ * dropped because maxDepth is 0.
67
+ */
68
+ declare function checkDepthOverflow(payloads: Array<Record<string, unknown>>, maxDepth: number, meta: TableMetadata): void;
69
+ /**
70
+ * Validates a batch of items using the given validator and context.
71
+ * Wraps per-item validation errors with array index paths for batch operations.
72
+ */
73
+ declare function validateBatch(validator: Validator<any, any>, items: Array<Record<string, unknown>>, ctx: DbValidationContext): void;
74
+ /**
75
+ * Pre-validates FROM children (type + FK constraints) before the main insert.
76
+ * Catches errors early before the parent record is committed.
77
+ */
78
+ declare function preValidateNestedFrom(host: TNestedWriterHost, originals: Array<Record<string, unknown>>): Promise<void>;
79
+ /**
80
+ * Batch-creates TO dependencies before the main insert.
81
+ */
82
+ declare function batchInsertNestedTo(host: TNestedWriterHost, items: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
83
+ /**
84
+ * Batch-creates FROM dependents after the main insert.
85
+ */
86
+ declare function batchInsertNestedFrom(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, parentIds: unknown[], maxDepth: number, depth: number): Promise<void>;
87
+ /**
88
+ * Batch-creates VIA (M:N) targets and junction entries after the main insert.
89
+ */
90
+ declare function batchInsertNestedVia(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, parentIds: unknown[], maxDepth: number, depth: number): Promise<void>;
91
+ /**
92
+ * Batch-replaces TO dependencies before the main replace.
93
+ */
94
+ declare function batchReplaceNestedTo(host: TNestedWriterHost, items: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
95
+ /**
96
+ * Batch-replaces FROM dependents after the main replace.
97
+ */
98
+ declare function batchReplaceNestedFrom(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
99
+ /**
100
+ * Handles VIA (M:N) relations during replace.
101
+ */
102
+ declare function batchReplaceNestedVia(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
103
+ /**
104
+ * Batch-patches TO dependencies before the main patch.
105
+ * Reads FK values from DB if not present in the payload.
106
+ */
107
+ declare function batchPatchNestedTo(host: TNestedWriterHost, items: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
108
+ /**
109
+ * Batch-patches FROM (1:N) dependencies after the main patch.
110
+ * Supports patch operators: $replace, $insert, $remove, $update, $upsert.
111
+ */
112
+ declare function batchPatchNestedFrom(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
113
+ /**
114
+ * Batch-patches VIA (M:N) dependencies after the main patch.
115
+ * Supports patch operators: $replace, $insert, $remove, $update, $upsert.
116
+ */
117
+ declare function batchPatchNestedVia(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
118
+ //#endregion
119
+ export { TNestedWriterHost, TRelationLoaderHost, batchInsertNestedFrom, batchInsertNestedTo, batchInsertNestedVia, batchPatchNestedFrom, batchPatchNestedTo, batchPatchNestedVia, batchReplaceNestedFrom, batchReplaceNestedTo, batchReplaceNestedVia, checkDepthOverflow, findFKForRelation, findRemoteFK, loadRelationsImpl, preValidateNestedFrom, resolveRelationTargetTable, validateBatch };
package/dist/rel.d.mts ADDED
@@ -0,0 +1,119 @@
1
+ import { A as TDbForeignKey, L as TDbRelation, Y as TTableResolver, Z as TWriteTableResolver, l as TGenericLogger, o as BaseDbAdapter, s as TableMetadata } from "./db-readable-Bbr4CjMb.mjs";
2
+ import { t as DbValidationContext } from "./db-validator-plugin-CiqsHTI_.mjs";
3
+ import { Validator } from "@atscript/typescript/utils";
4
+ import { FilterExpr, WithRelation } from "@uniqu/core";
5
+
6
+ //#region src/rel/relation-loader.d.ts
7
+ /** Host interface for the relation loader — matches AtscriptDbReadable property names. */
8
+ interface TRelationLoaderHost {
9
+ readonly tableName: string;
10
+ readonly _meta: {
11
+ readonly relations: ReadonlyMap<string, TDbRelation>;
12
+ readonly foreignKeys: ReadonlyMap<string, TDbForeignKey>;
13
+ };
14
+ readonly _tableResolver?: TTableResolver;
15
+ readonly adapter: BaseDbAdapter;
16
+ readonly logger: TGenericLogger;
17
+ }
18
+ /**
19
+ * Loads related data for `$with` relations and attaches them to result rows.
20
+ */
21
+ declare function loadRelationsImpl(rows: Array<Record<string, unknown>>, withRelations: WithRelation[], host: TRelationLoaderHost): Promise<void>;
22
+ //#endregion
23
+ //#region src/rel/relation-helpers.d.ts
24
+ /**
25
+ * Finds the FK entry that connects a `@db.rel.to` relation to its target.
26
+ */
27
+ declare function findFKForRelation(relation: TDbRelation, foreignKeys: ReadonlyMap<string, TDbForeignKey>): {
28
+ localFields: string[];
29
+ targetFields: string[];
30
+ } | undefined;
31
+ /**
32
+ * Finds a FK on a remote table that points back to a given table name.
33
+ */
34
+ declare function findRemoteFK(targetTable: {
35
+ foreignKeys: ReadonlyMap<string, TDbForeignKey>;
36
+ }, thisTableName: string, alias?: string): TDbForeignKey | undefined;
37
+ /**
38
+ * Resolves the target table name from a relation's target type metadata.
39
+ */
40
+ declare function resolveRelationTargetTable(relation: TDbRelation): string;
41
+ //#endregion
42
+ //#region src/rel/nested-writer.d.ts
43
+ /**
44
+ * Properties the nested writer functions need from the table instance.
45
+ * AtscriptDbTable satisfies this structurally — pass `this` with a cast.
46
+ */
47
+ interface TNestedWriterHost {
48
+ readonly tableName: string;
49
+ readonly _meta: TableMetadata;
50
+ readonly _writeTableResolver?: TWriteTableResolver;
51
+ _findFKForRelation(relation: TDbRelation): {
52
+ localFields: string[];
53
+ targetFields: string[];
54
+ } | undefined;
55
+ _findRemoteFK(targetTable: {
56
+ foreignKeys: ReadonlyMap<string, TDbForeignKey>;
57
+ }, thisTableName: string, alias?: string): TDbForeignKey | undefined;
58
+ _extractPrimaryKeyFilter(payload: Record<string, unknown>): FilterExpr;
59
+ findOne(query: {
60
+ filter: FilterExpr;
61
+ controls: Record<string, never>;
62
+ }): Promise<Record<string, unknown> | null>;
63
+ }
64
+ /**
65
+ * Checks if any payload contains navigational data that would be silently
66
+ * dropped because maxDepth is 0.
67
+ */
68
+ declare function checkDepthOverflow(payloads: Array<Record<string, unknown>>, maxDepth: number, meta: TableMetadata): void;
69
+ /**
70
+ * Validates a batch of items using the given validator and context.
71
+ * Wraps per-item validation errors with array index paths for batch operations.
72
+ */
73
+ declare function validateBatch(validator: Validator<any, any>, items: Array<Record<string, unknown>>, ctx: DbValidationContext): void;
74
+ /**
75
+ * Pre-validates FROM children (type + FK constraints) before the main insert.
76
+ * Catches errors early before the parent record is committed.
77
+ */
78
+ declare function preValidateNestedFrom(host: TNestedWriterHost, originals: Array<Record<string, unknown>>): Promise<void>;
79
+ /**
80
+ * Batch-creates TO dependencies before the main insert.
81
+ */
82
+ declare function batchInsertNestedTo(host: TNestedWriterHost, items: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
83
+ /**
84
+ * Batch-creates FROM dependents after the main insert.
85
+ */
86
+ declare function batchInsertNestedFrom(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, parentIds: unknown[], maxDepth: number, depth: number): Promise<void>;
87
+ /**
88
+ * Batch-creates VIA (M:N) targets and junction entries after the main insert.
89
+ */
90
+ declare function batchInsertNestedVia(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, parentIds: unknown[], maxDepth: number, depth: number): Promise<void>;
91
+ /**
92
+ * Batch-replaces TO dependencies before the main replace.
93
+ */
94
+ declare function batchReplaceNestedTo(host: TNestedWriterHost, items: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
95
+ /**
96
+ * Batch-replaces FROM dependents after the main replace.
97
+ */
98
+ declare function batchReplaceNestedFrom(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
99
+ /**
100
+ * Handles VIA (M:N) relations during replace.
101
+ */
102
+ declare function batchReplaceNestedVia(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
103
+ /**
104
+ * Batch-patches TO dependencies before the main patch.
105
+ * Reads FK values from DB if not present in the payload.
106
+ */
107
+ declare function batchPatchNestedTo(host: TNestedWriterHost, items: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
108
+ /**
109
+ * Batch-patches FROM (1:N) dependencies after the main patch.
110
+ * Supports patch operators: $replace, $insert, $remove, $update, $upsert.
111
+ */
112
+ declare function batchPatchNestedFrom(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
113
+ /**
114
+ * Batch-patches VIA (M:N) dependencies after the main patch.
115
+ * Supports patch operators: $replace, $insert, $remove, $update, $upsert.
116
+ */
117
+ declare function batchPatchNestedVia(host: TNestedWriterHost, originals: Array<Record<string, unknown>>, maxDepth: number, depth: number): Promise<void>;
118
+ //#endregion
119
+ export { type TNestedWriterHost, type TRelationLoaderHost, batchInsertNestedFrom, batchInsertNestedTo, batchInsertNestedVia, batchPatchNestedFrom, batchPatchNestedTo, batchPatchNestedVia, batchReplaceNestedFrom, batchReplaceNestedTo, batchReplaceNestedVia, checkDepthOverflow, findFKForRelation, findRemoteFK, loadRelationsImpl, preValidateNestedFrom, resolveRelationTargetTable, validateBatch };
package/dist/rel.mjs CHANGED
@@ -1,5 +1,4 @@
1
- import { batchInsertNestedFrom, batchInsertNestedTo, batchInsertNestedVia, batchPatchNestedFrom, batchPatchNestedTo, batchPatchNestedVia, batchReplaceNestedFrom, batchReplaceNestedTo, batchReplaceNestedVia, checkDepthOverflow, preValidateNestedFrom, validateBatch } from "./nested-writer-NEN51mnR.mjs";
2
- import { findFKForRelation, findRemoteFK, resolveRelationTargetTable } from "./relation-helpers-DyBIlQnB.mjs";
3
- import { loadRelationsImpl } from "./relation-loader-Dv7qXYq7.mjs";
4
-
5
- export { batchInsertNestedFrom, batchInsertNestedTo, batchInsertNestedVia, batchPatchNestedFrom, batchPatchNestedTo, batchPatchNestedVia, batchReplaceNestedFrom, batchReplaceNestedTo, batchReplaceNestedVia, checkDepthOverflow, findFKForRelation, findRemoteFK, loadRelationsImpl, preValidateNestedFrom, resolveRelationTargetTable, validateBatch };
1
+ import { t as loadRelationsImpl } from "./relation-loader-BEOTXNcq.mjs";
2
+ import { a as batchPatchNestedTo, c as batchReplaceNestedTo, d as preValidateNestedFrom, f as validateBatch, i as batchPatchNestedFrom, l as batchReplaceNestedVia, n as batchInsertNestedTo, o as batchPatchNestedVia, r as batchInsertNestedVia, s as batchReplaceNestedFrom, t as batchInsertNestedFrom, u as checkDepthOverflow } from "./nested-writer-Dmm1gbZV.mjs";
3
+ import { n as findRemoteFK, r as resolveRelationTargetTable, t as findFKForRelation } from "./relation-helpers-CLasawQq.mjs";
4
+ export { batchInsertNestedFrom, batchInsertNestedTo, batchInsertNestedVia, batchPatchNestedFrom, batchPatchNestedTo, batchPatchNestedVia, batchReplaceNestedFrom, batchReplaceNestedTo, batchReplaceNestedVia, checkDepthOverflow, findFKForRelation, findRemoteFK, loadRelationsImpl, preValidateNestedFrom, resolveRelationTargetTable, validateBatch };
@@ -1,6 +1,7 @@
1
- "use strict";
2
-
3
- //#region packages/db/src/rel/relation-helpers.ts
1
+ //#region src/rel/relation-helpers.ts
2
+ /**
3
+ * Finds the FK entry that connects a `@db.rel.to` relation to its target.
4
+ */
4
5
  function findFKForRelation(relation, foreignKeys) {
5
6
  const targetTable = resolveRelationTargetTable(relation);
6
7
  for (const fk of foreignKeys.values()) if (relation.alias) {
@@ -12,36 +13,39 @@ function findFKForRelation(relation, foreignKeys) {
12
13
  localFields: fk.fields,
13
14
  targetFields: fk.targetFields
14
15
  };
15
- return undefined;
16
16
  }
17
+ /**
18
+ * Finds a FK on a remote table that points back to a given table name.
19
+ */
17
20
  function findRemoteFK(targetTable, thisTableName, alias) {
18
21
  for (const fk of targetTable.foreignKeys.values()) {
19
22
  if (alias && fk.alias === alias && fk.targetTable === thisTableName) return fk;
20
23
  if (!alias && fk.targetTable === thisTableName) return fk;
21
24
  }
22
- return undefined;
23
25
  }
26
+ /**
27
+ * Resolves the target table name from a relation's target type metadata.
28
+ */
24
29
  function resolveRelationTargetTable(relation) {
25
30
  const targetType = relation.targetType();
26
31
  return targetType?.metadata?.get("db.table") || targetType?.id || "";
27
32
  }
28
-
29
33
  //#endregion
30
- Object.defineProperty(exports, 'findFKForRelation', {
31
- enumerable: true,
32
- get: function () {
33
- return findFKForRelation;
34
- }
34
+ Object.defineProperty(exports, "findFKForRelation", {
35
+ enumerable: true,
36
+ get: function() {
37
+ return findFKForRelation;
38
+ }
39
+ });
40
+ Object.defineProperty(exports, "findRemoteFK", {
41
+ enumerable: true,
42
+ get: function() {
43
+ return findRemoteFK;
44
+ }
35
45
  });
36
- Object.defineProperty(exports, 'findRemoteFK', {
37
- enumerable: true,
38
- get: function () {
39
- return findRemoteFK;
40
- }
46
+ Object.defineProperty(exports, "resolveRelationTargetTable", {
47
+ enumerable: true,
48
+ get: function() {
49
+ return resolveRelationTargetTable;
50
+ }
41
51
  });
42
- Object.defineProperty(exports, 'resolveRelationTargetTable', {
43
- enumerable: true,
44
- get: function () {
45
- return resolveRelationTargetTable;
46
- }
47
- });
@@ -1,5 +1,7 @@
1
-
2
- //#region packages/db/src/rel/relation-helpers.ts
1
+ //#region src/rel/relation-helpers.ts
2
+ /**
3
+ * Finds the FK entry that connects a `@db.rel.to` relation to its target.
4
+ */
3
5
  function findFKForRelation(relation, foreignKeys) {
4
6
  const targetTable = resolveRelationTargetTable(relation);
5
7
  for (const fk of foreignKeys.values()) if (relation.alias) {
@@ -11,19 +13,22 @@ function findFKForRelation(relation, foreignKeys) {
11
13
  localFields: fk.fields,
12
14
  targetFields: fk.targetFields
13
15
  };
14
- return undefined;
15
16
  }
17
+ /**
18
+ * Finds a FK on a remote table that points back to a given table name.
19
+ */
16
20
  function findRemoteFK(targetTable, thisTableName, alias) {
17
21
  for (const fk of targetTable.foreignKeys.values()) {
18
22
  if (alias && fk.alias === alias && fk.targetTable === thisTableName) return fk;
19
23
  if (!alias && fk.targetTable === thisTableName) return fk;
20
24
  }
21
- return undefined;
22
25
  }
26
+ /**
27
+ * Resolves the target table name from a relation's target type metadata.
28
+ */
23
29
  function resolveRelationTargetTable(relation) {
24
30
  const targetType = relation.targetType();
25
31
  return targetType?.metadata?.get("db.table") || targetType?.id || "";
26
32
  }
27
-
28
33
  //#endregion
29
- export { findFKForRelation, findRemoteFK, resolveRelationTargetTable };
34
+ export { findRemoteFK as n, resolveRelationTargetTable as r, findFKForRelation as t };