@nicia-ai/typegraph 0.65.0 → 0.66.1

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 (196) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/{atomic-mutation-program-BznZQ06C.d.ts → atomic-mutation-program-BhP75Qn0.d.ts} +1 -1
  3. package/dist/{atomic-mutation-program-Bfu5z-je.d.cts → atomic-mutation-program-DMdmc4s0.d.cts} +1 -1
  4. package/dist/backend/drizzle/engine/index.cjs +13 -13
  5. package/dist/backend/drizzle/engine/index.d.cts +9 -9
  6. package/dist/backend/drizzle/engine/index.d.ts +9 -9
  7. package/dist/backend/drizzle/engine/index.js +8 -8
  8. package/dist/backend/drizzle/indexes.d.cts +1 -1
  9. package/dist/backend/drizzle/indexes.d.ts +1 -1
  10. package/dist/backend/index.cjs +91 -91
  11. package/dist/backend/index.d.cts +7 -7
  12. package/dist/backend/index.d.ts +7 -7
  13. package/dist/backend/index.js +8 -8
  14. package/dist/backend/postgres/index.cjs +23 -23
  15. package/dist/backend/postgres/index.d.cts +8 -8
  16. package/dist/backend/postgres/index.d.ts +8 -8
  17. package/dist/backend/postgres/index.js +8 -8
  18. package/dist/backend/postgres/pglite-store.cjs +1 -1
  19. package/dist/backend/postgres/pglite-store.d.cts +6 -6
  20. package/dist/backend/postgres/pglite-store.d.ts +6 -6
  21. package/dist/backend/postgres/pglite-store.js +1 -1
  22. package/dist/backend/postgres/pglite.cjs +10 -10
  23. package/dist/backend/postgres/pglite.d.cts +3 -3
  24. package/dist/backend/postgres/pglite.d.ts +3 -3
  25. package/dist/backend/postgres/pglite.js +9 -9
  26. package/dist/backend/sqlite/index.cjs +21 -21
  27. package/dist/backend/sqlite/index.d.cts +7 -7
  28. package/dist/backend/sqlite/index.d.ts +7 -7
  29. package/dist/backend/sqlite/index.js +8 -8
  30. package/dist/backend/sqlite/libsql.cjs +14 -14
  31. package/dist/backend/sqlite/libsql.d.cts +3 -3
  32. package/dist/backend/sqlite/libsql.d.ts +3 -3
  33. package/dist/backend/sqlite/libsql.js +8 -8
  34. package/dist/backend/sqlite/local-store.cjs +1 -1
  35. package/dist/backend/sqlite/local-store.d.cts +6 -6
  36. package/dist/backend/sqlite/local-store.d.ts +6 -6
  37. package/dist/backend/sqlite/local-store.js +1 -1
  38. package/dist/backend/sqlite/local.cjs +10 -10
  39. package/dist/backend/sqlite/local.d.cts +3 -3
  40. package/dist/backend/sqlite/local.d.ts +3 -3
  41. package/dist/backend/sqlite/local.js +9 -9
  42. package/dist/{chunk-PFXNQFFY.js → chunk-2DJKHZQ4.js} +75 -8
  43. package/dist/chunk-2DJKHZQ4.js.map +1 -0
  44. package/dist/{chunk-337ONI2I.js → chunk-3SUZXB5X.js} +146 -80
  45. package/dist/chunk-3SUZXB5X.js.map +1 -0
  46. package/dist/{chunk-4VTCIEK3.js → chunk-4TQOIBWH.js} +3 -3
  47. package/dist/{chunk-4VTCIEK3.js.map → chunk-4TQOIBWH.js.map} +1 -1
  48. package/dist/{chunk-JRWKRBI5.cjs → chunk-5JOCIMQ3.cjs} +6 -6
  49. package/dist/{chunk-JRWKRBI5.cjs.map → chunk-5JOCIMQ3.cjs.map} +1 -1
  50. package/dist/{chunk-BWQA3POT.cjs → chunk-6B3LQUYG.cjs} +206 -138
  51. package/dist/chunk-6B3LQUYG.cjs.map +1 -0
  52. package/dist/{chunk-RQPCUHIH.js → chunk-6ECNYQDW.js} +3 -3
  53. package/dist/{chunk-RQPCUHIH.js.map → chunk-6ECNYQDW.js.map} +1 -1
  54. package/dist/{chunk-OLB75LRQ.js → chunk-6GKKAQMW.js} +5 -5
  55. package/dist/{chunk-OLB75LRQ.js.map → chunk-6GKKAQMW.js.map} +1 -1
  56. package/dist/{chunk-OC5ROP7V.cjs → chunk-6JRVV2SS.cjs} +8 -2
  57. package/dist/chunk-6JRVV2SS.cjs.map +1 -0
  58. package/dist/{chunk-DSX3P4S5.cjs → chunk-76OB5RSH.cjs} +6 -6
  59. package/dist/{chunk-DSX3P4S5.cjs.map → chunk-76OB5RSH.cjs.map} +1 -1
  60. package/dist/{chunk-DHRLOQLQ.cjs → chunk-7LQTDGV5.cjs} +11 -11
  61. package/dist/{chunk-DHRLOQLQ.cjs.map → chunk-7LQTDGV5.cjs.map} +1 -1
  62. package/dist/{chunk-Q25QYSOH.js → chunk-7YJHUY4T.js} +9 -9
  63. package/dist/{chunk-Q25QYSOH.js.map → chunk-7YJHUY4T.js.map} +1 -1
  64. package/dist/{chunk-JERQGJKG.cjs → chunk-ANMCKLZQ.cjs} +18 -18
  65. package/dist/{chunk-JERQGJKG.cjs.map → chunk-ANMCKLZQ.cjs.map} +1 -1
  66. package/dist/{chunk-BBOMNH44.js → chunk-BABP4D5B.js} +3 -3
  67. package/dist/{chunk-BBOMNH44.js.map → chunk-BABP4D5B.js.map} +1 -1
  68. package/dist/{chunk-EVGZ2TRQ.js → chunk-BE75G3M5.js} +3 -3
  69. package/dist/{chunk-EVGZ2TRQ.js.map → chunk-BE75G3M5.js.map} +1 -1
  70. package/dist/{chunk-FXGZT3WO.cjs → chunk-BX42F7IJ.cjs} +41 -41
  71. package/dist/{chunk-FXGZT3WO.cjs.map → chunk-BX42F7IJ.cjs.map} +1 -1
  72. package/dist/{chunk-G6T23JU7.js → chunk-CDKNGCE7.js} +3 -3
  73. package/dist/{chunk-G6T23JU7.js.map → chunk-CDKNGCE7.js.map} +1 -1
  74. package/dist/{chunk-BNTJ5YFO.cjs → chunk-EACDHXJL.cjs} +4 -4
  75. package/dist/{chunk-BNTJ5YFO.cjs.map → chunk-EACDHXJL.cjs.map} +1 -1
  76. package/dist/{chunk-SNDJUTMB.cjs → chunk-EBQX7MYL.cjs} +72 -72
  77. package/dist/{chunk-SNDJUTMB.cjs.map → chunk-EBQX7MYL.cjs.map} +1 -1
  78. package/dist/{chunk-GKSAEUX6.js → chunk-FXOFJ4FS.js} +7 -7
  79. package/dist/{chunk-GKSAEUX6.js.map → chunk-FXOFJ4FS.js.map} +1 -1
  80. package/dist/{chunk-ZOWRACZQ.cjs → chunk-G7OKJDMG.cjs} +5 -5
  81. package/dist/{chunk-ZOWRACZQ.cjs.map → chunk-G7OKJDMG.cjs.map} +1 -1
  82. package/dist/{chunk-MKJPBSID.cjs → chunk-I7SBZJI2.cjs} +4 -4
  83. package/dist/{chunk-MKJPBSID.cjs.map → chunk-I7SBZJI2.cjs.map} +1 -1
  84. package/dist/{chunk-H346QK3V.cjs → chunk-K7YACILO.cjs} +9 -9
  85. package/dist/{chunk-H346QK3V.cjs.map → chunk-K7YACILO.cjs.map} +1 -1
  86. package/dist/{chunk-3KWF25MF.cjs → chunk-MN325MG4.cjs} +313 -246
  87. package/dist/chunk-MN325MG4.cjs.map +1 -0
  88. package/dist/{chunk-KDNRACRG.cjs → chunk-MRUOOAIQ.cjs} +4 -4
  89. package/dist/{chunk-KDNRACRG.cjs.map → chunk-MRUOOAIQ.cjs.map} +1 -1
  90. package/dist/{chunk-HTSJTWUT.js → chunk-OF63ZHSD.js} +4 -4
  91. package/dist/{chunk-HTSJTWUT.js.map → chunk-OF63ZHSD.js.map} +1 -1
  92. package/dist/{chunk-NGA3THGU.cjs → chunk-QR7W37HG.cjs} +14 -14
  93. package/dist/{chunk-NGA3THGU.cjs.map → chunk-QR7W37HG.cjs.map} +1 -1
  94. package/dist/{chunk-QFEO4M5W.js → chunk-RTPMG6LQ.js} +11 -11
  95. package/dist/{chunk-QFEO4M5W.js.map → chunk-RTPMG6LQ.js.map} +1 -1
  96. package/dist/{chunk-PFD4NUYV.js → chunk-SSDHR2C2.js} +3 -3
  97. package/dist/{chunk-PFD4NUYV.js.map → chunk-SSDHR2C2.js.map} +1 -1
  98. package/dist/{chunk-THK3SCQA.js → chunk-SYXTWPX6.js} +5 -5
  99. package/dist/{chunk-THK3SCQA.js.map → chunk-SYXTWPX6.js.map} +1 -1
  100. package/dist/{chunk-XSLQYGNR.cjs → chunk-T3VU3YRQ.cjs} +69 -69
  101. package/dist/{chunk-XSLQYGNR.cjs.map → chunk-T3VU3YRQ.cjs.map} +1 -1
  102. package/dist/{chunk-MIBWA6HX.js → chunk-TR7QTODF.js} +213 -33
  103. package/dist/chunk-TR7QTODF.js.map +1 -0
  104. package/dist/{chunk-AD3NLSV5.js → chunk-TU22BFMP.js} +8 -2
  105. package/dist/chunk-TU22BFMP.js.map +1 -0
  106. package/dist/{chunk-WTMSUIRO.js → chunk-UFKYMQJ5.js} +3 -3
  107. package/dist/{chunk-WTMSUIRO.js.map → chunk-UFKYMQJ5.js.map} +1 -1
  108. package/dist/{chunk-35LDKSMM.cjs → chunk-VNJMM2QQ.cjs} +30 -30
  109. package/dist/{chunk-35LDKSMM.cjs.map → chunk-VNJMM2QQ.cjs.map} +1 -1
  110. package/dist/{chunk-53ZEBIMD.js → chunk-WB55URNM.js} +6 -6
  111. package/dist/{chunk-53ZEBIMD.js.map → chunk-WB55URNM.js.map} +1 -1
  112. package/dist/{chunk-L2GBVYRU.cjs → chunk-WWSYGZED.cjs} +11 -11
  113. package/dist/{chunk-L2GBVYRU.cjs.map → chunk-WWSYGZED.cjs.map} +1 -1
  114. package/dist/{chunk-D2JPOFRZ.cjs → chunk-WY3IFEKV.cjs} +191 -191
  115. package/dist/{chunk-D2JPOFRZ.cjs.map → chunk-WY3IFEKV.cjs.map} +1 -1
  116. package/dist/{chunk-3RSFLZ7A.cjs → chunk-Y4X6ODVY.cjs} +943 -763
  117. package/dist/chunk-Y4X6ODVY.cjs.map +1 -0
  118. package/dist/{chunk-VZRXXABW.js → chunk-YHMXF7OZ.js} +5 -5
  119. package/dist/{chunk-VZRXXABW.js.map → chunk-YHMXF7OZ.js.map} +1 -1
  120. package/dist/{chunk-VROJKWZ7.js → chunk-ZONDBN6H.js} +5 -5
  121. package/dist/{chunk-VROJKWZ7.js.map → chunk-ZONDBN6H.js.map} +1 -1
  122. package/dist/core/index.d.cts +3 -3
  123. package/dist/core/index.d.ts +3 -3
  124. package/dist/{ddl-DvW9aobX.d.ts → ddl-2q7xLM1X.d.ts} +3 -3
  125. package/dist/{ddl-BjuXbPfw.d.cts → ddl-D_09BfbN.d.cts} +3 -3
  126. package/dist/graph-extension/index.d.cts +2 -2
  127. package/dist/graph-extension/index.d.ts +2 -2
  128. package/dist/graph-merge/index.cjs +156 -156
  129. package/dist/graph-merge/index.d.cts +7 -7
  130. package/dist/graph-merge/index.d.ts +7 -7
  131. package/dist/graph-merge/index.js +14 -14
  132. package/dist/{graph-templates-1vMqlPsu.d.cts → graph-templates-B5Q7oYAA.d.cts} +2 -2
  133. package/dist/{graph-templates-Y52w16dH.d.ts → graph-templates-D9N-Z9kw.d.ts} +2 -2
  134. package/dist/index.cjs +99 -99
  135. package/dist/index.d.cts +10 -10
  136. package/dist/index.d.ts +10 -10
  137. package/dist/index.js +18 -18
  138. package/dist/indexes/index.d.cts +4 -4
  139. package/dist/indexes/index.d.ts +4 -4
  140. package/dist/{ingestion-import-target-CCKeXZbW.d.ts → ingestion-import-target-B8EU6ug2.d.ts} +1 -1
  141. package/dist/{ingestion-import-target-774QRgkF.d.cts → ingestion-import-target-C5sHNFJF.d.cts} +1 -1
  142. package/dist/interchange/index.cjs +34 -34
  143. package/dist/interchange/index.d.cts +7 -7
  144. package/dist/interchange/index.d.ts +7 -7
  145. package/dist/interchange/index.js +11 -11
  146. package/dist/{local-store-impl-DFKS7QTV.js → local-store-impl-ERPNYOCL.js} +18 -18
  147. package/dist/{local-store-impl-DFKS7QTV.js.map → local-store-impl-ERPNYOCL.js.map} +1 -1
  148. package/dist/{local-store-impl-3E4VLFCI.cjs → local-store-impl-OUINMCYI.cjs} +22 -22
  149. package/dist/{local-store-impl-3E4VLFCI.cjs.map → local-store-impl-OUINMCYI.cjs.map} +1 -1
  150. package/dist/{pglite-store-impl-N63GGBU2.js → pglite-store-impl-DUJBQZS5.js} +18 -18
  151. package/dist/{pglite-store-impl-N63GGBU2.js.map → pglite-store-impl-DUJBQZS5.js.map} +1 -1
  152. package/dist/{pglite-store-impl-T75O3LVQ.cjs → pglite-store-impl-Z3SOOP75.cjs} +22 -22
  153. package/dist/{pglite-store-impl-T75O3LVQ.cjs.map → pglite-store-impl-Z3SOOP75.cjs.map} +1 -1
  154. package/dist/{postgres-C9gitL71.d.ts → postgres-BbTYW3b_.d.ts} +3 -3
  155. package/dist/{postgres-BONrXHb4.d.cts → postgres-DOBXcZVg.d.cts} +1 -1
  156. package/dist/{postgres-DAFRdnTr.d.ts → postgres-DhZixg92.d.ts} +1 -1
  157. package/dist/{postgres-2FYdVYCm.d.cts → postgres-Dp3MpyJt.d.cts} +3 -3
  158. package/dist/{profile-CAD65CqS.d.ts → profile-Ch5SSewK.d.ts} +8 -8
  159. package/dist/{profile-Bmcg07Ki.d.cts → profile-DppApFgt.d.cts} +8 -8
  160. package/dist/profiler/index.d.cts +8 -8
  161. package/dist/profiler/index.d.ts +8 -8
  162. package/dist/provenance/index.cjs +22 -22
  163. package/dist/provenance/index.d.cts +6 -6
  164. package/dist/provenance/index.d.ts +6 -6
  165. package/dist/provenance/index.js +6 -6
  166. package/dist/{repair-validity-windows-CinP91t7.d.cts → repair-validity-windows-CpP_GpIx.d.cts} +1 -1
  167. package/dist/{repair-validity-windows-BJz4nffP.d.ts → repair-validity-windows-lfe275bY.d.ts} +1 -1
  168. package/dist/{resolve-DgOSlXx_.d.ts → resolve-CoYqHqno.d.cts} +7 -2
  169. package/dist/{resolve-DQXSEN_A.d.cts → resolve-DV0Iposp.d.ts} +7 -2
  170. package/dist/schema/index.cjs +37 -37
  171. package/dist/schema/index.d.cts +7 -7
  172. package/dist/schema/index.d.ts +7 -7
  173. package/dist/schema/index.js +7 -7
  174. package/dist/{searchable-DMdCwkXO.d.cts → searchable-C7Xt6g45.d.cts} +1 -1
  175. package/dist/{searchable-BPRF0Bah.d.ts → searchable-KKXrPet3.d.ts} +1 -1
  176. package/dist/{sqlite-DgbYa-1Y.d.cts → sqlite-BkQM9ZeI.d.cts} +1 -1
  177. package/dist/{sqlite-Co_uIpfs.d.cts → sqlite-BpRtjC36.d.cts} +3 -3
  178. package/dist/{sqlite-DcDAAYow.d.ts → sqlite-CH0Zq0Qv.d.ts} +3 -3
  179. package/dist/{sqlite-UlG5prJQ.d.ts → sqlite-CcCSeXGg.d.ts} +1 -1
  180. package/dist/{store-HxoFyQMu.d.cts → store-3nfPQK5j.d.cts} +30 -7
  181. package/dist/{store-C9T1c9Az.d.ts → store-C8ZPl7OW.d.ts} +30 -7
  182. package/dist/{types-CRCyg1fJ.d.cts → types-BynPp5kU.d.cts} +18 -2
  183. package/dist/{types-CRCyg1fJ.d.ts → types-BynPp5kU.d.ts} +18 -2
  184. package/dist/{types-Dg_prBqC.d.ts → types-C9YwrkSe.d.ts} +1 -1
  185. package/dist/{types-B5AUesS1.d.cts → types-JG-4CG6P.d.cts} +1 -1
  186. package/dist/{where-gRyc3jj_.d.cts → where-D1gBDqQ_.d.cts} +1 -1
  187. package/dist/{where-D-NDKMPw.d.ts → where-D2GqMFp-.d.ts} +1 -1
  188. package/package.json +1 -1
  189. package/dist/chunk-337ONI2I.js.map +0 -1
  190. package/dist/chunk-3KWF25MF.cjs.map +0 -1
  191. package/dist/chunk-3RSFLZ7A.cjs.map +0 -1
  192. package/dist/chunk-AD3NLSV5.js.map +0 -1
  193. package/dist/chunk-BWQA3POT.cjs.map +0 -1
  194. package/dist/chunk-MIBWA6HX.js.map +0 -1
  195. package/dist/chunk-OC5ROP7V.cjs.map +0 -1
  196. package/dist/chunk-PFXNQFFY.js.map +0 -1
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunkOC5ROP7V_cjs = require('./chunk-OC5ROP7V.cjs');
3
+ var chunk6JRVV2SS_cjs = require('./chunk-6JRVV2SS.cjs');
4
4
  var chunk5ICDVLI3_cjs = require('./chunk-5ICDVLI3.cjs');
5
5
  var chunk7XYPLAPL_cjs = require('./chunk-7XYPLAPL.cjs');
6
6
 
7
7
  // src/store/claims/backing.ts
8
8
  function claimSupport(target, verdict) {
9
9
  if (!verdict.supported) return { supported: false };
10
- return { supported: true, claims: chunkOC5ROP7V_cjs.claimsMembers(target, verdict) };
10
+ return { supported: true, claims: chunk6JRVV2SS_cjs.claimsMembers(target, verdict) };
11
11
  }
12
12
 
13
13
  // src/store/claims/edge-claims.ts
@@ -97,7 +97,7 @@ async function withEdgeClaimRelationPrecondition(graphId, issue) {
97
97
  try {
98
98
  return await issue();
99
99
  } catch (error) {
100
- if (!chunkOC5ROP7V_cjs.isMissingTableError(error)) throw error;
100
+ if (!chunk6JRVV2SS_cjs.isMissingTableError(error)) throw error;
101
101
  throw edgeClaimRelationMissing(graphId, error);
102
102
  }
103
103
  }
@@ -165,5 +165,5 @@ exports.edgeCardinalityClaimRefusal = edgeCardinalityClaimRefusal;
165
165
  exports.edgeCardinalityClaimTarget = edgeCardinalityClaimTarget;
166
166
  exports.edgeClaimRelationMissing = edgeClaimRelationMissing;
167
167
  exports.purgeEdgeClaims = purgeEdgeClaims;
168
- //# sourceMappingURL=chunk-ZOWRACZQ.cjs.map
169
- //# sourceMappingURL=chunk-ZOWRACZQ.cjs.map
168
+ //# sourceMappingURL=chunk-G7OKJDMG.cjs.map
169
+ //# sourceMappingURL=chunk-G7OKJDMG.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/claims/backing.ts","../src/store/claims/edge-claims.ts"],"names":["claimsMembers","edgeCardinalityAxis","encodeTupleKey","checkUniqueEdge","checkCardinality","CardinalityError","ConfigurationError","isMissingTableError","outcome","compareClaimTargets"],"mappings":"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","file":"chunk-ZOWRACZQ.cjs","sourcesContent":["/**\n * What backs each constraint fence class.\n *\n * A constrained write is fenced by one of two things: a per-graph lock that\n * serializes the probe with the write it guards, or a CLAIM row whose primary\n * key refuses a second claimant outright. The second is strictly stronger — it\n * holds without a lock, which is what an import needs — and this module records\n * which class has reached it, so \"is this fence a lock or a key?\" is answered\n * from one table rather than inferred from whichever module a reader lands in.\n *\n * It also owns the runtime half of the same question — {@link claimSupport},\n * the one reader of \"can THIS object hold a claim?\" — so the declaration and\n * the surface are reconciled in one place rather than at each claim site.\n * `claimSupport` is now a thin binder over the `claims` capability bundle\n * (`backend/capabilities`): the bidirectional declaration/surface cross-check\n * lives once in `resolve.ts`'s `assertClaimsBidirectionalAgreement`, reached\n * through the verdict every caller threads in, and this module owns only the\n * per-write port bind (`claimsMembers`) and this decision's shape.\n */\nimport {\n type BundleBinding,\n claimsMembers,\n} from \"../../backend/capabilities/bind\";\nimport type { CLAIMS } from \"../../backend/capabilities/bundle-registry\";\nimport { type BundleVerdictOf } from \"../../backend/capabilities/resolve\";\nimport { type GraphBackend } from \"../../backend/types\";\n\n/**\n * The runtime extent of the fence classes. {@link ConstraintFenceReason} is\n * DERIVED from it rather than declared beside it: a union type has no runtime\n * extent, so a totality test over a map keyed by the union could only iterate\n * that map's own keys and would be trivially true.\n */\nexport const CONSTRAINT_FENCE_REASONS = [\n \"edgeCardinality\",\n \"edgeMatchKeyConvergence\",\n \"nodeDisjointness\",\n \"nodeUniquenessClaim\",\n \"nodeUniquenessScope\",\n] as const;\n\n/**\n * WHICH declared constraint makes a write constrained.\n *\n * The classification names the reason rather than answering yes/no, because\n * the reason is load-bearing twice over: it is what the fence is taken FOR, and\n * — on a backend that cannot hold the fence — it is what the refusal has to\n * tell the caller. \"This backend cannot fence constrained writes\" is unusable\n * advice; \"your `cardinality: 'one'` edge cannot be enforced here\" is\n * actionable, and only the classifier knows which it was.\n */\nexport type ConstraintFenceReason = (typeof CONSTRAINT_FENCE_REASONS)[number];\n\n/** The relation whose key fences a class, or `lockOnly` when nothing does yet. */\ntype ConstraintFenceBacking = \"uniques\" | \"edgeClaims\" | \"lockOnly\";\n\n/**\n * Which claim relation backs each fence class. The `satisfies` forces totality:\n * a new reason cannot be added without stating what backs it.\n *\n * `nodeUniquenessScope` is `\"uniques\"` because a shared-scope claim is now\n * written at the scope's axis, so two writers of two kinds in one hierarchy\n * contend for one row. `nodeUniquenessClaim` is the same relation seen from the\n * other side: the claim row is the fence, and the class exists because a write\n * that must issue it BEFORE the row it gates needs a transaction to undo the\n * pair together — which is what its refusal names. `nodeDisjointness` is the\n * same relation again, at a third kind of axis: a claim keyed on the declared\n * PAIR and on the node's id, which is the axis disjointness actually declares\n * and the one the nodes primary key `(graph_id, kind, id)` cannot fence.\n * `edgeCardinality` is the other relation: a claim keyed on\n * `(<cardinality>:<edgeKind>, endpoint identity)`, which is the axis the\n * declaration actually spans and the one the edges primary key `(graph_id, id)`\n * cannot fence. The classes still marked `lockOnly` are fenced by the per-graph\n * write lock alone, which is why they are also the classes a non-transactional\n * backend refuses.\n */\nexport const CONSTRAINT_FENCE_BACKING = {\n edgeCardinality: \"edgeClaims\",\n edgeMatchKeyConvergence: \"lockOnly\",\n nodeDisjointness: \"uniques\",\n nodeUniquenessClaim: \"uniques\",\n nodeUniquenessScope: \"uniques\",\n} as const satisfies Record<ConstraintFenceReason, ConstraintFenceBacking>;\n\n/** The decision {@link claimSupport} returns — never a flag a caller re-derives. */\nexport type ClaimSupport =\n /** Capability declared AND every claim member present: the members, bound off the port. */\n | Readonly<{\n supported: true;\n claims: BundleBinding<(typeof CLAIMS)[\"core\"][number]>;\n }>\n /** Capability absent or false AND no claim member present: the declared gap. */\n | Readonly<{ supported: false }>;\n\n/**\n * THE one reader of \"can this object hold a claim?\", asked about the object the\n * claim is about to be written to.\n *\n * Takes the bundle's VERDICT — resolved once, against `GraphBackend`, by the\n * caller's `ClaimsVerdictThunk` (ruling B1/B7) — rather than resolving it\n * itself: the declaration/surface cross-check\n * (`resolve.ts`'s `assertClaimsBidirectionalAgreement`) runs exactly once,\n * inside that resolution, and this function never re-derives it. What this\n * function still owns is the PER-WRITE bind: `claimsMembers` (`bind.ts`) binds\n * the verdict's named members off `target` — the object the write actually\n * executes on, which may be a `TransactionBackend` the verdict was never\n * resolved against — and throws the bundle's port-surface code\n * (`CONSTRAINT_CLAIM_SURFACE_MISMATCH`) if `target` disagrees with what the\n * verdict says is present.\n *\n * @throws ConfigurationError (`CONSTRAINT_CLAIM_SURFACE_MISMATCH`) when\n * `target` is missing a member the verdict says is present.\n */\nexport function claimSupport(\n target: Readonly<\n Partial<Pick<GraphBackend, (typeof CLAIMS)[\"core\"][number]>>\n >,\n verdict: BundleVerdictOf<typeof CLAIMS>,\n): ClaimSupport {\n if (!verdict.supported) return { supported: false };\n return { supported: true, claims: claimsMembers(target, verdict) };\n}\n","/**\n * Edge claims — what an edge write reserves on a declared cardinality axis.\n *\n * A declared cardinality is a predicate over `(kind, from)` or\n * `(kind, from, to)`, and the edges relation's only uniqueness is its\n * `(graph_id, id)` primary key, so nothing in the schema re-decides at write\n * time what the probe decided at read time. This module is the reservation that\n * does: one row per `(graph_id, axis, key)` in `typegraph_edge_claims`, whose\n * primary key refuses a second concurrent claimant.\n *\n * The claim needs no release path. A claim whose holder is no longer live (or,\n * for `oneActive`, no longer active) fails the liveness predicate the takeover\n * statement carries and is taken over in place, so the fence never depends on\n * any delete path having run. `purgeEdgeClaims` exists to bound table growth,\n * not to make the fence correct.\n */\nimport type { CLAIMS } from \"../../backend/capabilities/bundle-registry\";\nimport { type BundleVerdictOf } from \"../../backend/capabilities/resolve\";\nimport {\n type ClaimEdgeCardinalityParams,\n type GraphBackend,\n type InsertEdgeParams,\n} from \"../../backend/types\";\nimport { checkCardinality, checkUniqueEdge } from \"../../constraints\";\nimport { type Cardinality } from \"../../core/types\";\nimport { CardinalityError, ConfigurationError } from \"../../errors\";\nimport { isMissingTableError } from \"../../utils/sql-errors\";\nimport { encodeTupleKey } from \"../../utils/tuple-key\";\nimport {\n type ClaimTarget,\n compareClaimTargets,\n edgeCardinalityAxis,\n} from \"./axis\";\nimport { claimSupport } from \"./backing\";\n\n/** A cardinality that declares something — `many` declares nothing. */\nexport type ConstrainedCardinality = Exclude<Cardinality, \"many\">;\n\n/**\n * What one declared cardinality means to every layer that has to agree about\n * it: which endpoints its axis key covers, whether an edge born already ended\n * claims at all, and what a holder must still BE for its claim to stand.\n */\nexport type EdgeCardinalitySpec = Readonly<{\n /** Which endpoints the axis key covers. */\n keyShape: \"from\" | \"fromAndTo\";\n /** Whether a new edge that is born ENDED makes a claim at all. */\n claimsWhenBornEnded: boolean;\n /** What a holder must still be for its claim to stand. */\n holderLiveness: \"live\" | \"liveAndActive\";\n}>;\n\n/**\n * THE table both renderers of the cardinality predicate read: the TypeScript\n * probe ({@link file://../constraints.ts checkCardinalityConstraint}) and the\n * SQL takeover statement\n * ({@link file://../../backend/drizzle/operations/edge-claims.ts}).\n *\n * Two renderers, one table, exhaustive by type: a new cardinality cannot be\n * added without stating all three facts, and the probe and the fence cannot\n * disagree about any of them — a disagreement is exactly the shape where the\n * probe accepts a write the fence then refuses forever (or the reverse).\n */\nexport const EDGE_CARDINALITY_SPECS = {\n one: { keyShape: \"from\", claimsWhenBornEnded: true, holderLiveness: \"live\" },\n unique: {\n keyShape: \"fromAndTo\",\n claimsWhenBornEnded: true,\n holderLiveness: \"live\",\n },\n oneActive: {\n keyShape: \"from\",\n claimsWhenBornEnded: false,\n holderLiveness: \"liveAndActive\",\n },\n} as const satisfies Record<ConstrainedCardinality, EdgeCardinalitySpec>;\n\n/** Every axis an edge kind's claims can sit on, for housekeeping reaps. */\nexport function edgeCardinalityAxesForKind(\n edgeKind: string,\n): readonly string[] {\n return Object.keys(EDGE_CARDINALITY_SPECS).map((cardinality) =>\n edgeCardinalityAxis(cardinality, edgeKind),\n );\n}\n\n/**\n * THE claim row one edge write reserves: its axis, and the endpoint identity\n * the axis is keyed by.\n *\n * The key is {@link encodeTupleKey}, not a delimiter join: node ids are\n * arbitrary caller data (only kind names pass `assertClaimAxisSafe`), and a\n * delimiter that a value may contain makes two different endpoint tuples\n * collapse onto one key — which would refuse a write no constraint forbids.\n */\nexport function edgeCardinalityClaimTarget(\n params: ClaimEdgeCardinalityParams,\n): ClaimTarget {\n const spec = EDGE_CARDINALITY_SPECS[params.cardinality];\n return {\n relation: \"edgeClaims\",\n graphId: params.graphId,\n axis: edgeCardinalityAxis(params.cardinality, params.edgeKind),\n key:\n spec.keyShape === \"from\" ?\n encodeTupleKey([params.fromKind, params.fromId])\n : encodeTupleKey([\n params.fromKind,\n params.fromId,\n params.toKind,\n params.toId,\n ]),\n };\n}\n\n/**\n * The fields a claim is decided from: the row's identity and the upper bound\n * that decides whether it joins an active-only population. Narrower than\n * {@link InsertEdgeParams} on purpose — a resurrect has no insert params to\n * hand over, and passing an invented `props` to satisfy a type would be a\n * fabricated value a reader has to check is unread.\n */\nexport type EdgeClaimSubject = Pick<\n InsertEdgeParams,\n \"graphId\" | \"id\" | \"kind\" | \"fromKind\" | \"fromId\" | \"toKind\" | \"toId\"\n> &\n Readonly<{ validTo?: string }>;\n\n/**\n * THE claim an edge insert owes, or `undefined` when it owes none.\n *\n * `many` declares no constraint, and an `oneActive` edge born already ended\n * joins no active population — `claimsWhenBornEnded` is the one place that\n * second exemption is written down, and the probe reads the same field, so the\n * two cannot drift into \"probed but unclaimed\" (a silent hole) or \"claimed but\n * unprobed\" (a refusal with no matching error).\n */\nexport function edgeCardinalityClaim(\n cardinality: Cardinality,\n subject: EdgeClaimSubject,\n): ClaimEdgeCardinalityParams | undefined {\n if (cardinality === \"many\") return undefined;\n if (\n !EDGE_CARDINALITY_SPECS[cardinality].claimsWhenBornEnded &&\n subject.validTo !== undefined\n ) {\n return undefined;\n }\n return {\n graphId: subject.graphId,\n cardinality,\n edgeKind: subject.kind,\n edgeId: subject.id,\n fromKind: subject.fromKind,\n fromId: subject.fromId,\n toKind: subject.toKind,\n toId: subject.toId,\n };\n}\n\n/**\n * The refusal a lost claim raises — built by the SAME owners the probe calls,\n * so the fence's error is `instanceof` the same class and carries the same\n * payload as the probe's for the same violation (I3).\n */\n/**\n * Builds the public cardinality refusal for a claim decision.\n *\n * Both the ordinary claim path and the fused claim-plus-edge path call this\n * owner. Keeping the translation here prevents a backend result discriminator\n * from growing a second spelling of the same typed error.\n */\nexport function edgeCardinalityClaimRefusal(\n params: ClaimEdgeCardinalityParams,\n): CardinalityError {\n const error =\n params.cardinality === \"unique\" ?\n checkUniqueEdge(\n params.edgeKind,\n params.fromKind,\n params.fromId,\n params.toKind,\n params.toId,\n 1,\n )\n : checkCardinality(\n params.edgeKind,\n params.fromKind,\n params.fromId,\n params.cardinality,\n 1,\n true,\n );\n // Both owners refuse for an incumbent count of one on every constrained\n // cardinality; the fallback keeps the return type honest without inventing a\n // second spelling of the message.\n return (\n error ??\n new CardinalityError({\n edgeKind: params.edgeKind,\n fromKind: params.fromKind,\n fromId: params.fromId,\n cardinality: params.cardinality,\n existingCount: 1,\n })\n );\n}\n\n/**\n * Converts the engine's \"relation does not exist\" into a typed precondition\n * error naming the relation and the way to create it.\n *\n * Checked at FIRST USE rather than at store construction: a graph with no\n * constrained edge kind never issues a claim and must not pay a catalog read\n * for a relation it will never touch. A database bootstrapped before this\n * relation existed reaches it here, on the first constrained edge write, with\n * an error that says what to run instead of an opaque driver failure.\n */\nexport function edgeClaimRelationMissing(\n graphId: string,\n cause: unknown,\n): ConfigurationError {\n return new ConfigurationError(\n \"Enforcing a declared edge cardinality needs the edge claim relation \" +\n \"(typegraph_edge_claims), and this database does not have it. \" +\n \"Databases initialized before this relation existed were never sent \" +\n \"its CREATE TABLE, because the bootstrap DDL runs only on first boot.\",\n { code: \"EDGE_CLAIM_RELATION_MISSING\", graphId },\n {\n cause,\n suggestion:\n \"Run the generated migration SQL (generatePostgresMigrationSQL / \" +\n \"generateSqliteMigrationSQL) against this database, or declare the \" +\n 'edge kind `cardinality: \"many\"` and enforce the limit in ' +\n \"application code.\",\n },\n );\n}\n\nasync function withEdgeClaimRelationPrecondition<T>(\n graphId: string,\n issue: () => Promise<T>,\n): Promise<T> {\n try {\n return await issue();\n } catch (error) {\n if (!isMissingTableError(error)) throw error;\n throw edgeClaimRelationMissing(graphId, error);\n }\n}\n\ntype ClaimModeTarget = Readonly<\n Partial<\n Pick<\n GraphBackend,\n (typeof CLAIMS)[\"core\"][number] | \"claimEdgeCardinalityGuarded\"\n >\n >\n>;\n\n/** The narrow backend facet an edge claim is written through. */\ntype ClaimTargetMembers = ClaimModeTarget;\n\n/**\n * The one owner of whether a single write may replace its entity probe with a\n * guarded claim. Both claim-bundle support and the optional strong member are\n * required: the member is the backend's explicit opt-in contract, while the\n * bundle verdict proves the target can actually persist claims. Either absence\n * deliberately preserves the legacy probe-then-claim protocol.\n */\nexport function edgeCardinalityClaimMode(\n backend: ClaimModeTarget,\n verdict: BundleVerdictOf<typeof CLAIMS>,\n):\n | Readonly<{\n kind: \"guarded\";\n claim: NonNullable<GraphBackend[\"claimEdgeCardinalityGuarded\"]>;\n }>\n | Readonly<{\n kind: \"probeThenClaim\";\n support: ReturnType<typeof claimSupport>;\n }> {\n const support = claimSupport(backend, verdict);\n const guardedClaim = backend.claimEdgeCardinalityGuarded;\n return !support.supported || guardedClaim === undefined ?\n { kind: \"probeThenClaim\", support }\n : { kind: \"guarded\", claim: guardedClaim };\n}\n\n/**\n * Issues ONE edge cardinality claim against the object the row write goes to,\n * refusing with the declared error when a live incumbent holds the axis.\n *\n * A backend that declares no claim support writes no claim and keeps exactly\n * the fence it has today (the per-graph write lock around the probe) — a\n * declared gap with a parity-matrix row, never a silent unfencing and never a\n * new refusal.\n */\nexport async function claimEdgeCardinality(\n backend: ClaimTargetMembers,\n verdict: BundleVerdictOf<typeof CLAIMS>,\n claim: ClaimEdgeCardinalityParams,\n): Promise<void> {\n const mode = edgeCardinalityClaimMode(backend, verdict);\n if (mode.kind === \"guarded\") {\n const outcome = await withEdgeClaimRelationPrecondition(claim.graphId, () =>\n mode.claim(claim),\n );\n if (outcome.status === \"refused\") {\n throw edgeCardinalityClaimRefusal(claim);\n }\n return;\n }\n const support = mode.support;\n if (!support.supported) return;\n const outcome = await withEdgeClaimRelationPrecondition(claim.graphId, () =>\n support.claims.claimEdgeCardinality(claim),\n );\n if (outcome.status === \"refused\") throw edgeCardinalityClaimRefusal(claim);\n}\n\n/**\n * Issues a batch's claims as ONE statement, entries sorted by\n * {@link compareClaimTargets}.\n *\n * One statement takes its row locks in a fixed order, so a batch cannot\n * deadlock against itself; sorting is what stops two writers of the same two\n * axes from taking them in opposite orders. In-batch duplicates are refused\n * before this by the batch validation wrapper's pending-cardinality state, so\n * the backend's duplicate-conflict-target guard stays a defensive invariant.\n */\nexport async function claimEdgeCardinalityBatch(\n backend: ClaimTargetMembers,\n verdict: BundleVerdictOf<typeof CLAIMS>,\n claims: readonly ClaimEdgeCardinalityParams[],\n): Promise<void> {\n if (claims.length === 0) return;\n const support = claimSupport(backend, verdict);\n if (!support.supported) return;\n const ordered = claims\n .map((claim) => ({ claim, target: edgeCardinalityClaimTarget(claim) }))\n .toSorted((left, right) => compareClaimTargets(left.target, right.target));\n const graphId = ordered[0]?.claim.graphId ?? \"\";\n const outcomes = await withEdgeClaimRelationPrecondition(graphId, () =>\n support.claims.claimEdgeCardinalityBatch(\n ordered.map((entry) => entry.claim),\n ),\n );\n for (const [index, outcome] of outcomes.entries()) {\n const entry = ordered[index];\n if (entry !== undefined && outcome.status === \"refused\") {\n throw edgeCardinalityClaimRefusal(entry.claim);\n }\n }\n}\n\n/**\n * Housekeeping: drops the claim rows named edges held.\n *\n * Never a fence and never load-bearing — a claim whose holder is gone already\n * fails the takeover statement's liveness predicate, so the axis is reusable\n * whether or not this ran. It exists so a hard delete does not leave a row\n * behind forever. A backend without claim support has nothing to purge.\n */\nexport async function purgeEdgeClaims(\n backend: ClaimTargetMembers,\n verdict: BundleVerdictOf<typeof CLAIMS>,\n graphId: string,\n edgeIds: readonly string[],\n): Promise<void> {\n if (edgeIds.length === 0) return;\n const support = claimSupport(backend, verdict);\n if (!support.supported) return;\n await withEdgeClaimRelationPrecondition(graphId, () =>\n support.claims.purgeEdgeClaims({ graphId, edgeIds }),\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/store/claims/backing.ts","../src/store/claims/edge-claims.ts"],"names":["claimsMembers","edgeCardinalityAxis","encodeTupleKey","checkUniqueEdge","checkCardinality","CardinalityError","ConfigurationError","isMissingTableError","outcome","compareClaimTargets"],"mappings":"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","file":"chunk-G7OKJDMG.cjs","sourcesContent":["/**\n * What backs each constraint fence class.\n *\n * A constrained write is fenced by one of two things: a per-graph lock that\n * serializes the probe with the write it guards, or a CLAIM row whose primary\n * key refuses a second claimant outright. The second is strictly stronger — it\n * holds without a lock, which is what an import needs — and this module records\n * which class has reached it, so \"is this fence a lock or a key?\" is answered\n * from one table rather than inferred from whichever module a reader lands in.\n *\n * It also owns the runtime half of the same question — {@link claimSupport},\n * the one reader of \"can THIS object hold a claim?\" — so the declaration and\n * the surface are reconciled in one place rather than at each claim site.\n * `claimSupport` is now a thin binder over the `claims` capability bundle\n * (`backend/capabilities`): the bidirectional declaration/surface cross-check\n * lives once in `resolve.ts`'s `assertClaimsBidirectionalAgreement`, reached\n * through the verdict every caller threads in, and this module owns only the\n * per-write port bind (`claimsMembers`) and this decision's shape.\n */\nimport {\n type BundleBinding,\n claimsMembers,\n} from \"../../backend/capabilities/bind\";\nimport type { CLAIMS } from \"../../backend/capabilities/bundle-registry\";\nimport { type BundleVerdictOf } from \"../../backend/capabilities/resolve\";\nimport { type GraphBackend } from \"../../backend/types\";\n\n/**\n * The runtime extent of the fence classes. {@link ConstraintFenceReason} is\n * DERIVED from it rather than declared beside it: a union type has no runtime\n * extent, so a totality test over a map keyed by the union could only iterate\n * that map's own keys and would be trivially true.\n */\nexport const CONSTRAINT_FENCE_REASONS = [\n \"edgeCardinality\",\n \"edgeMatchKeyConvergence\",\n \"nodeDisjointness\",\n \"nodeUniquenessClaim\",\n \"nodeUniquenessScope\",\n] as const;\n\n/**\n * WHICH declared constraint makes a write constrained.\n *\n * The classification names the reason rather than answering yes/no, because\n * the reason is load-bearing twice over: it is what the fence is taken FOR, and\n * — on a backend that cannot hold the fence — it is what the refusal has to\n * tell the caller. \"This backend cannot fence constrained writes\" is unusable\n * advice; \"your `cardinality: 'one'` edge cannot be enforced here\" is\n * actionable, and only the classifier knows which it was.\n */\nexport type ConstraintFenceReason = (typeof CONSTRAINT_FENCE_REASONS)[number];\n\n/** The relation whose key fences a class, or `lockOnly` when nothing does yet. */\ntype ConstraintFenceBacking = \"uniques\" | \"edgeClaims\" | \"lockOnly\";\n\n/**\n * Which claim relation backs each fence class. The `satisfies` forces totality:\n * a new reason cannot be added without stating what backs it.\n *\n * `nodeUniquenessScope` is `\"uniques\"` because a shared-scope claim is now\n * written at the scope's axis, so two writers of two kinds in one hierarchy\n * contend for one row. `nodeUniquenessClaim` is the same relation seen from the\n * other side: the claim row is the fence, and the class exists because a write\n * that must issue it BEFORE the row it gates needs a transaction to undo the\n * pair together — which is what its refusal names. `nodeDisjointness` is the\n * same relation again, at a third kind of axis: a claim keyed on the declared\n * PAIR and on the node's id, which is the axis disjointness actually declares\n * and the one the nodes primary key `(graph_id, kind, id)` cannot fence.\n * `edgeCardinality` is the other relation: a claim keyed on\n * `(<cardinality>:<edgeKind>, endpoint identity)`, which is the axis the\n * declaration actually spans and the one the edges primary key `(graph_id, id)`\n * cannot fence. The classes still marked `lockOnly` are fenced by the per-graph\n * write lock alone, which is why they are also the classes a non-transactional\n * backend refuses.\n */\nexport const CONSTRAINT_FENCE_BACKING = {\n edgeCardinality: \"edgeClaims\",\n edgeMatchKeyConvergence: \"lockOnly\",\n nodeDisjointness: \"uniques\",\n nodeUniquenessClaim: \"uniques\",\n nodeUniquenessScope: \"uniques\",\n} as const satisfies Record<ConstraintFenceReason, ConstraintFenceBacking>;\n\n/** The decision {@link claimSupport} returns — never a flag a caller re-derives. */\nexport type ClaimSupport =\n /** Capability declared AND every claim member present: the members, bound off the port. */\n | Readonly<{\n supported: true;\n claims: BundleBinding<(typeof CLAIMS)[\"core\"][number]>;\n }>\n /** Capability absent or false AND no claim member present: the declared gap. */\n | Readonly<{ supported: false }>;\n\n/**\n * THE one reader of \"can this object hold a claim?\", asked about the object the\n * claim is about to be written to.\n *\n * Takes the bundle's VERDICT — resolved once, against `GraphBackend`, by the\n * caller's `ClaimsVerdictThunk` (ruling B1/B7) — rather than resolving it\n * itself: the declaration/surface cross-check\n * (`resolve.ts`'s `assertClaimsBidirectionalAgreement`) runs exactly once,\n * inside that resolution, and this function never re-derives it. What this\n * function still owns is the PER-WRITE bind: `claimsMembers` (`bind.ts`) binds\n * the verdict's named members off `target` — the object the write actually\n * executes on, which may be a `TransactionBackend` the verdict was never\n * resolved against — and throws the bundle's port-surface code\n * (`CONSTRAINT_CLAIM_SURFACE_MISMATCH`) if `target` disagrees with what the\n * verdict says is present.\n *\n * @throws ConfigurationError (`CONSTRAINT_CLAIM_SURFACE_MISMATCH`) when\n * `target` is missing a member the verdict says is present.\n */\nexport function claimSupport(\n target: Readonly<\n Partial<Pick<GraphBackend, (typeof CLAIMS)[\"core\"][number]>>\n >,\n verdict: BundleVerdictOf<typeof CLAIMS>,\n): ClaimSupport {\n if (!verdict.supported) return { supported: false };\n return { supported: true, claims: claimsMembers(target, verdict) };\n}\n","/**\n * Edge claims — what an edge write reserves on a declared cardinality axis.\n *\n * A declared cardinality is a predicate over `(kind, from)` or\n * `(kind, from, to)`, and the edges relation's only uniqueness is its\n * `(graph_id, id)` primary key, so nothing in the schema re-decides at write\n * time what the probe decided at read time. This module is the reservation that\n * does: one row per `(graph_id, axis, key)` in `typegraph_edge_claims`, whose\n * primary key refuses a second concurrent claimant.\n *\n * The claim needs no release path. A claim whose holder is no longer live (or,\n * for `oneActive`, no longer active) fails the liveness predicate the takeover\n * statement carries and is taken over in place, so the fence never depends on\n * any delete path having run. `purgeEdgeClaims` exists to bound table growth,\n * not to make the fence correct.\n */\nimport type { CLAIMS } from \"../../backend/capabilities/bundle-registry\";\nimport { type BundleVerdictOf } from \"../../backend/capabilities/resolve\";\nimport {\n type ClaimEdgeCardinalityParams,\n type GraphBackend,\n type InsertEdgeParams,\n} from \"../../backend/types\";\nimport { checkCardinality, checkUniqueEdge } from \"../../constraints\";\nimport { type Cardinality } from \"../../core/types\";\nimport { CardinalityError, ConfigurationError } from \"../../errors\";\nimport { isMissingTableError } from \"../../utils/sql-errors\";\nimport { encodeTupleKey } from \"../../utils/tuple-key\";\nimport {\n type ClaimTarget,\n compareClaimTargets,\n edgeCardinalityAxis,\n} from \"./axis\";\nimport { claimSupport } from \"./backing\";\n\n/** A cardinality that declares something — `many` declares nothing. */\nexport type ConstrainedCardinality = Exclude<Cardinality, \"many\">;\n\n/**\n * What one declared cardinality means to every layer that has to agree about\n * it: which endpoints its axis key covers, whether an edge born already ended\n * claims at all, and what a holder must still BE for its claim to stand.\n */\nexport type EdgeCardinalitySpec = Readonly<{\n /** Which endpoints the axis key covers. */\n keyShape: \"from\" | \"fromAndTo\";\n /** Whether a new edge that is born ENDED makes a claim at all. */\n claimsWhenBornEnded: boolean;\n /** What a holder must still be for its claim to stand. */\n holderLiveness: \"live\" | \"liveAndActive\";\n}>;\n\n/**\n * THE table both renderers of the cardinality predicate read: the TypeScript\n * probe ({@link file://../constraints.ts checkCardinalityConstraint}) and the\n * SQL takeover statement\n * ({@link file://../../backend/drizzle/operations/edge-claims.ts}).\n *\n * Two renderers, one table, exhaustive by type: a new cardinality cannot be\n * added without stating all three facts, and the probe and the fence cannot\n * disagree about any of them — a disagreement is exactly the shape where the\n * probe accepts a write the fence then refuses forever (or the reverse).\n */\nexport const EDGE_CARDINALITY_SPECS = {\n one: { keyShape: \"from\", claimsWhenBornEnded: true, holderLiveness: \"live\" },\n unique: {\n keyShape: \"fromAndTo\",\n claimsWhenBornEnded: true,\n holderLiveness: \"live\",\n },\n oneActive: {\n keyShape: \"from\",\n claimsWhenBornEnded: false,\n holderLiveness: \"liveAndActive\",\n },\n} as const satisfies Record<ConstrainedCardinality, EdgeCardinalitySpec>;\n\n/** Every axis an edge kind's claims can sit on, for housekeeping reaps. */\nexport function edgeCardinalityAxesForKind(\n edgeKind: string,\n): readonly string[] {\n return Object.keys(EDGE_CARDINALITY_SPECS).map((cardinality) =>\n edgeCardinalityAxis(cardinality, edgeKind),\n );\n}\n\n/**\n * THE claim row one edge write reserves: its axis, and the endpoint identity\n * the axis is keyed by.\n *\n * The key is {@link encodeTupleKey}, not a delimiter join: node ids are\n * arbitrary caller data (only kind names pass `assertClaimAxisSafe`), and a\n * delimiter that a value may contain makes two different endpoint tuples\n * collapse onto one key — which would refuse a write no constraint forbids.\n */\nexport function edgeCardinalityClaimTarget(\n params: ClaimEdgeCardinalityParams,\n): ClaimTarget {\n const spec = EDGE_CARDINALITY_SPECS[params.cardinality];\n return {\n relation: \"edgeClaims\",\n graphId: params.graphId,\n axis: edgeCardinalityAxis(params.cardinality, params.edgeKind),\n key:\n spec.keyShape === \"from\" ?\n encodeTupleKey([params.fromKind, params.fromId])\n : encodeTupleKey([\n params.fromKind,\n params.fromId,\n params.toKind,\n params.toId,\n ]),\n };\n}\n\n/**\n * The fields a claim is decided from: the row's identity and the upper bound\n * that decides whether it joins an active-only population. Narrower than\n * {@link InsertEdgeParams} on purpose — a resurrect has no insert params to\n * hand over, and passing an invented `props` to satisfy a type would be a\n * fabricated value a reader has to check is unread.\n */\nexport type EdgeClaimSubject = Pick<\n InsertEdgeParams,\n \"graphId\" | \"id\" | \"kind\" | \"fromKind\" | \"fromId\" | \"toKind\" | \"toId\"\n> &\n Readonly<{ validTo?: string }>;\n\n/**\n * THE claim an edge insert owes, or `undefined` when it owes none.\n *\n * `many` declares no constraint, and an `oneActive` edge born already ended\n * joins no active population — `claimsWhenBornEnded` is the one place that\n * second exemption is written down, and the probe reads the same field, so the\n * two cannot drift into \"probed but unclaimed\" (a silent hole) or \"claimed but\n * unprobed\" (a refusal with no matching error).\n */\nexport function edgeCardinalityClaim(\n cardinality: Cardinality,\n subject: EdgeClaimSubject,\n): ClaimEdgeCardinalityParams | undefined {\n if (cardinality === \"many\") return undefined;\n if (\n !EDGE_CARDINALITY_SPECS[cardinality].claimsWhenBornEnded &&\n subject.validTo !== undefined\n ) {\n return undefined;\n }\n return {\n graphId: subject.graphId,\n cardinality,\n edgeKind: subject.kind,\n edgeId: subject.id,\n fromKind: subject.fromKind,\n fromId: subject.fromId,\n toKind: subject.toKind,\n toId: subject.toId,\n };\n}\n\n/**\n * The refusal a lost claim raises — built by the SAME owners the probe calls,\n * so the fence's error is `instanceof` the same class and carries the same\n * payload as the probe's for the same violation (I3).\n */\n/**\n * Builds the public cardinality refusal for a claim decision.\n *\n * Both the ordinary claim path and the fused claim-plus-edge path call this\n * owner. Keeping the translation here prevents a backend result discriminator\n * from growing a second spelling of the same typed error.\n */\nexport function edgeCardinalityClaimRefusal(\n params: ClaimEdgeCardinalityParams,\n): CardinalityError {\n const error =\n params.cardinality === \"unique\" ?\n checkUniqueEdge(\n params.edgeKind,\n params.fromKind,\n params.fromId,\n params.toKind,\n params.toId,\n 1,\n )\n : checkCardinality(\n params.edgeKind,\n params.fromKind,\n params.fromId,\n params.cardinality,\n 1,\n true,\n );\n // Both owners refuse for an incumbent count of one on every constrained\n // cardinality; the fallback keeps the return type honest without inventing a\n // second spelling of the message.\n return (\n error ??\n new CardinalityError({\n edgeKind: params.edgeKind,\n fromKind: params.fromKind,\n fromId: params.fromId,\n cardinality: params.cardinality,\n existingCount: 1,\n })\n );\n}\n\n/**\n * Converts the engine's \"relation does not exist\" into a typed precondition\n * error naming the relation and the way to create it.\n *\n * Checked at FIRST USE rather than at store construction: a graph with no\n * constrained edge kind never issues a claim and must not pay a catalog read\n * for a relation it will never touch. A database bootstrapped before this\n * relation existed reaches it here, on the first constrained edge write, with\n * an error that says what to run instead of an opaque driver failure.\n */\nexport function edgeClaimRelationMissing(\n graphId: string,\n cause: unknown,\n): ConfigurationError {\n return new ConfigurationError(\n \"Enforcing a declared edge cardinality needs the edge claim relation \" +\n \"(typegraph_edge_claims), and this database does not have it. \" +\n \"Databases initialized before this relation existed were never sent \" +\n \"its CREATE TABLE, because the bootstrap DDL runs only on first boot.\",\n { code: \"EDGE_CLAIM_RELATION_MISSING\", graphId },\n {\n cause,\n suggestion:\n \"Run the generated migration SQL (generatePostgresMigrationSQL / \" +\n \"generateSqliteMigrationSQL) against this database, or declare the \" +\n 'edge kind `cardinality: \"many\"` and enforce the limit in ' +\n \"application code.\",\n },\n );\n}\n\nasync function withEdgeClaimRelationPrecondition<T>(\n graphId: string,\n issue: () => Promise<T>,\n): Promise<T> {\n try {\n return await issue();\n } catch (error) {\n if (!isMissingTableError(error)) throw error;\n throw edgeClaimRelationMissing(graphId, error);\n }\n}\n\ntype ClaimModeTarget = Readonly<\n Partial<\n Pick<\n GraphBackend,\n (typeof CLAIMS)[\"core\"][number] | \"claimEdgeCardinalityGuarded\"\n >\n >\n>;\n\n/** The narrow backend facet an edge claim is written through. */\ntype ClaimTargetMembers = ClaimModeTarget;\n\n/**\n * The one owner of whether a single write may replace its entity probe with a\n * guarded claim. Both claim-bundle support and the optional strong member are\n * required: the member is the backend's explicit opt-in contract, while the\n * bundle verdict proves the target can actually persist claims. Either absence\n * deliberately preserves the legacy probe-then-claim protocol.\n */\nexport function edgeCardinalityClaimMode(\n backend: ClaimModeTarget,\n verdict: BundleVerdictOf<typeof CLAIMS>,\n):\n | Readonly<{\n kind: \"guarded\";\n claim: NonNullable<GraphBackend[\"claimEdgeCardinalityGuarded\"]>;\n }>\n | Readonly<{\n kind: \"probeThenClaim\";\n support: ReturnType<typeof claimSupport>;\n }> {\n const support = claimSupport(backend, verdict);\n const guardedClaim = backend.claimEdgeCardinalityGuarded;\n return !support.supported || guardedClaim === undefined ?\n { kind: \"probeThenClaim\", support }\n : { kind: \"guarded\", claim: guardedClaim };\n}\n\n/**\n * Issues ONE edge cardinality claim against the object the row write goes to,\n * refusing with the declared error when a live incumbent holds the axis.\n *\n * A backend that declares no claim support writes no claim and keeps exactly\n * the fence it has today (the per-graph write lock around the probe) — a\n * declared gap with a parity-matrix row, never a silent unfencing and never a\n * new refusal.\n */\nexport async function claimEdgeCardinality(\n backend: ClaimTargetMembers,\n verdict: BundleVerdictOf<typeof CLAIMS>,\n claim: ClaimEdgeCardinalityParams,\n): Promise<void> {\n const mode = edgeCardinalityClaimMode(backend, verdict);\n if (mode.kind === \"guarded\") {\n const outcome = await withEdgeClaimRelationPrecondition(claim.graphId, () =>\n mode.claim(claim),\n );\n if (outcome.status === \"refused\") {\n throw edgeCardinalityClaimRefusal(claim);\n }\n return;\n }\n const support = mode.support;\n if (!support.supported) return;\n const outcome = await withEdgeClaimRelationPrecondition(claim.graphId, () =>\n support.claims.claimEdgeCardinality(claim),\n );\n if (outcome.status === \"refused\") throw edgeCardinalityClaimRefusal(claim);\n}\n\n/**\n * Issues a batch's claims as ONE statement, entries sorted by\n * {@link compareClaimTargets}.\n *\n * One statement takes its row locks in a fixed order, so a batch cannot\n * deadlock against itself; sorting is what stops two writers of the same two\n * axes from taking them in opposite orders. In-batch duplicates are refused\n * before this by the batch validation wrapper's pending-cardinality state, so\n * the backend's duplicate-conflict-target guard stays a defensive invariant.\n */\nexport async function claimEdgeCardinalityBatch(\n backend: ClaimTargetMembers,\n verdict: BundleVerdictOf<typeof CLAIMS>,\n claims: readonly ClaimEdgeCardinalityParams[],\n): Promise<void> {\n if (claims.length === 0) return;\n const support = claimSupport(backend, verdict);\n if (!support.supported) return;\n const ordered = claims\n .map((claim) => ({ claim, target: edgeCardinalityClaimTarget(claim) }))\n .toSorted((left, right) => compareClaimTargets(left.target, right.target));\n const graphId = ordered[0]?.claim.graphId ?? \"\";\n const outcomes = await withEdgeClaimRelationPrecondition(graphId, () =>\n support.claims.claimEdgeCardinalityBatch(\n ordered.map((entry) => entry.claim),\n ),\n );\n for (const [index, outcome] of outcomes.entries()) {\n const entry = ordered[index];\n if (entry !== undefined && outcome.status === \"refused\") {\n throw edgeCardinalityClaimRefusal(entry.claim);\n }\n }\n}\n\n/**\n * Housekeeping: drops the claim rows named edges held.\n *\n * Never a fence and never load-bearing — a claim whose holder is gone already\n * fails the takeover statement's liveness predicate, so the axis is reusable\n * whether or not this ran. It exists so a hard delete does not leave a row\n * behind forever. A backend without claim support has nothing to purge.\n */\nexport async function purgeEdgeClaims(\n backend: ClaimTargetMembers,\n verdict: BundleVerdictOf<typeof CLAIMS>,\n graphId: string,\n edgeIds: readonly string[],\n): Promise<void> {\n if (edgeIds.length === 0) return;\n const support = claimSupport(backend, verdict);\n if (!support.supported) return;\n await withEdgeClaimRelationPrecondition(graphId, () =>\n support.claims.purgeEdgeClaims({ graphId, edgeIds }),\n );\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkKDNRACRG_cjs = require('./chunk-KDNRACRG.cjs');
3
+ var chunkMRUOOAIQ_cjs = require('./chunk-MRUOOAIQ.cjs');
4
4
 
5
5
  // src/backend/capabilities/autocommit-single-statement.ts
6
6
  var BUNDLED_ROOT_AUTOCOMMIT_BACKENDS = /* @__PURE__ */ new WeakSet();
@@ -44,7 +44,7 @@ function rephaseNonTransactionalNodeClaimPlan(plan) {
44
44
  };
45
45
  }
46
46
  function rephaseAtomicNodeClaimPlan(plan, support) {
47
- if (plan.mode.kind !== "ordinary" || plan.claims.length === 0 || !chunkKDNRACRG_cjs.supportsAtomicNodeClaims(support, plan.claims)) {
47
+ if (plan.mode.kind !== "ordinary" || plan.claims.length === 0 || !chunkMRUOOAIQ_cjs.supportsAtomicNodeClaims(support, plan.claims)) {
48
48
  return;
49
49
  }
50
50
  const supported = plan.claims.every((claim) => {
@@ -101,5 +101,5 @@ exports.resolvedNodeUpdateBatchFitsBindBudget = resolvedNodeUpdateBatchFitsBindB
101
101
  exports.supportsNodeCreatePlan = supportsNodeCreatePlan;
102
102
  exports.supportsNodeInsertProjectionRequirements = supportsNodeInsertProjectionRequirements;
103
103
  exports.supportsNodeInsertProjections = supportsNodeInsertProjections;
104
- //# sourceMappingURL=chunk-MKJPBSID.cjs.map
105
- //# sourceMappingURL=chunk-MKJPBSID.cjs.map
104
+ //# sourceMappingURL=chunk-I7SBZJI2.cjs.map
105
+ //# sourceMappingURL=chunk-I7SBZJI2.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/backend/capabilities/autocommit-single-statement.ts","../src/backend/capabilities/node-insert-projections.ts","../src/backend/resolved-node-update-batch.ts"],"names":["supportsAtomicNodeClaims"],"mappings":"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","file":"chunk-MKJPBSID.cjs","sourcesContent":["/**\n * Origin evidence for the managed single-statement autocommit fast path.\n *\n * This is intentionally narrower than schema-fenced-insert eligibility. The\n * latter follows bundled transaction targets and derived wrappers because its\n * statement still runs inside an explicit transaction. Here, omitting that\n * transaction is the optimization, so only the literal root objects produced\n * by the bundled factories may opt in. In particular, this evidence is never\n * carried through `deriveBackend`, an owned transaction, or adoption of a\n * caller-owned transaction.\n */\nimport type { GraphBackend, TransactionBackend } from \"../types\";\n\nconst BUNDLED_ROOT_AUTOCOMMIT_BACKENDS = new WeakSet<object>();\n\n/** @internal Called only by bundled factories after their root backend exists. */\nexport function markBundledRootAutocommitEligible<T extends object>(\n target: T,\n): T {\n BUNDLED_ROOT_AUTOCOMMIT_BACKENDS.add(target);\n return target;\n}\n\n/** Whether this is the exact root backend a bundled factory created. */\nexport function isBundledRootAutocommitEligible(\n target: GraphBackend | TransactionBackend,\n): target is GraphBackend {\n return BUNDLED_ROOT_AUTOCOMMIT_BACKENDS.has(target);\n}\n","import type {\n BackendIdentity,\n GraphBackend,\n ManagedNodeCreatePlan,\n NodeInsertClaim,\n NodeInsertProjection,\n} from \"../types\";\nimport {\n type AtomicNodeClaimSupport,\n supportsAtomicNodeClaims,\n} from \"./atomic-mutation-program\";\n\nexport type NodeProjectionInsertTarget = BackendIdentity &\n Pick<GraphBackend, \"commands\">;\n\nexport type NodeInsertProjectionRequirements = Readonly<{\n fulltext: boolean;\n embedding: boolean;\n}>;\n\nexport function supportsNodeInsertProjectionRequirements(\n target: NodeProjectionInsertTarget,\n requirements: NodeInsertProjectionRequirements,\n): boolean {\n return (\n (!requirements.fulltext ||\n target.fulltextStrategy?.buildSyncFromInsertedNode !== undefined) &&\n (!requirements.embedding ||\n target.vectorStrategy?.buildUpsertFromInsertedNode !== undefined)\n );\n}\n\n/**\n * The single owner of projection-fusion eligibility.\n *\n * A projection plan is all-or-nothing: every requested projection must have\n * an inserted-node builder on the active strategy, and the receiver must\n * expose the atomic executor. Callers use this same predicate before choosing\n * root autocommit and again on the actual transaction callback target.\n */\nexport function supportsNodeInsertProjections(\n target: NodeProjectionInsertTarget,\n projections: readonly NodeInsertProjection[],\n): boolean {\n if (projections.length === 0) return false;\n return supportsNodeInsertProjectionRequirements(target, {\n fulltext: projections.some((projection) => projection.kind === \"fulltext\"),\n embedding: projections.some(\n (projection) => projection.kind === \"embedding\",\n ),\n });\n}\n\n/**\n * Whether the receiver can make uniqueness/disjointness claims authoritative\n * inside the planned node statement.\n *\n * Claims are reported by the statement as a verdict, so the caller must have a\n * transaction boundary around the statement before it can safely defer the\n * application probes. A root backend is deliberately excluded: its\n * command port is also used for projection-only\n * autocommit writes, but a claim refusal must roll back the node and any\n * claims it touched together.\n */\nfunction supportsNodeInsertClaims(target: NodeProjectionInsertTarget): boolean {\n return (\n !(\"transaction\" in target) &&\n target.capabilities.atomicNodeInsertClaims === true\n );\n}\n\n/**\n * The only claim shape that is safe to execute on a root backend without a\n * rollback boundary. A generated id cannot collide with a different node, so\n * the claim is the sole conflict source; same-kind uniqueness has no legacy\n * axis or cross-kind/disjoint probe to consult. Rephasing it before the node\n * insert makes a conflict prevent the node row from being written at all.\n */\nfunction supportsNonTransactionalNodeClaimPlan(\n plan: Pick<\n ManagedNodeCreatePlan,\n \"idGenerated\" | \"mode\" | \"params\" | \"claims\" | \"projections\"\n >,\n): boolean {\n return (\n plan.idGenerated &&\n plan.mode.kind === \"ordinary\" &&\n plan.projections.length === 0 &&\n plan.claims.length === 1 &&\n plan.claims.every(\n (claim) =>\n claim.verdict.kind === \"uniqueness\" &&\n claim.axis === plan.params.kind &&\n claim.verdict.probeAxes.length === 1 &&\n claim.verdict.probeAxes[0] === claim.axis,\n )\n );\n}\n\n/** Rephases the safe root claim shape so a conflict gates the node insert. */\nexport function rephaseNonTransactionalNodeClaimPlan(\n plan: ManagedNodeCreatePlan,\n): ManagedNodeCreatePlan | undefined {\n if (!supportsNonTransactionalNodeClaimPlan(plan)) return;\n return {\n ...plan,\n claims: plan.claims.map((claim) => ({\n ...claim,\n placement: \"pre-insert\",\n })),\n };\n}\n\n/**\n * Normalizes the complete claim envelope accepted by an atomic node program.\n *\n * Unlike the ordinary root insert seam, a closed program can also prove a\n * disjoint claim because it carries the legacy live-node probe and cleanup in\n * the same atomic transport submission. The executor's advertised support is\n * authoritative; an omitted family remains on the portable path.\n */\nexport function rephaseAtomicNodeClaimPlan(\n plan: ManagedNodeCreatePlan,\n support: AtomicNodeClaimSupport | undefined,\n): ManagedNodeCreatePlan | undefined {\n if (\n plan.mode.kind !== \"ordinary\" ||\n plan.claims.length === 0 ||\n !supportsAtomicNodeClaims(support, plan.claims)\n ) {\n return;\n }\n const supported = plan.claims.every((claim) => {\n if (claim.verdict.kind === \"uniqueness\") {\n return (\n claim.verdict.probeAxes.length > 0 &&\n claim.verdict.probeAxes[0] === claim.axis &&\n new Set(claim.verdict.probeAxes).size === claim.verdict.probeAxes.length\n );\n }\n return (\n claim.key === plan.params.id &&\n claim.verdict.conflictingKinds.length > 0 &&\n new Set(claim.verdict.conflictingKinds).size ===\n claim.verdict.conflictingKinds.length\n );\n });\n if (!supported) return;\n return {\n ...plan,\n claims: plan.claims.map((claim) => ({\n ...claim,\n placement: \"pre-insert\",\n })),\n };\n}\n\n/** Whether the receiver can lower this complete insert plan atomically. */\nexport function supportsNodeCreatePlan(\n target: NodeProjectionInsertTarget,\n input: Readonly<{\n params?: ManagedNodeCreatePlan[\"params\"];\n idGenerated?: ManagedNodeCreatePlan[\"idGenerated\"];\n mode?: ManagedNodeCreatePlan[\"mode\"];\n claims: readonly NodeInsertClaim[];\n projections: readonly NodeInsertProjection[];\n /** Store-side proof that no identity/history/revision side effect exists. */\n allowNonTransactionalClaims?: boolean | undefined;\n }>,\n): boolean {\n if (input.claims.length === 0) {\n return supportsNodeInsertProjections(target, input.projections);\n }\n // A claim refusal is discovered from the data-modifying statement's result,\n // so the caller-owned transaction is the rollback boundary. Root graph\n // backends expose `transaction`; transaction-scoped operation backends do\n // not. Keep this exported predicate aligned with the execution contract.\n const ordinaryPlan =\n (\n input.params === undefined ||\n input.mode === undefined ||\n input.idGenerated === undefined\n ) ?\n undefined\n : {\n entity: \"node\" as const,\n params: input.params,\n idGenerated: input.idGenerated,\n mode: input.mode,\n claims: input.claims,\n projections: input.projections,\n };\n const rootClaimFusion =\n input.allowNonTransactionalClaims === true &&\n target.capabilities.atomicNodeInsertClaims === true &&\n ordinaryPlan !== undefined &&\n supportsNonTransactionalNodeClaimPlan(ordinaryPlan);\n return (\n (supportsNodeInsertClaims(target) ||\n (\"transaction\" in target && rootClaimFusion)) &&\n supportsNodeInsertProjectionRequirements(target, {\n fulltext: input.projections.some(\n (projection) => projection.kind === \"fulltext\",\n ),\n embedding: input.projections.some(\n (projection) => projection.kind === \"embedding\",\n ),\n })\n );\n}\n","/**\n * Bind parameters in one resolved node replacement statement, excluding its\n * entries: two graph/kind predicates, the update timestamp, and the count gate.\n */\nconst RESOLVED_NODE_UPDATE_BATCH_FIXED_BIND_COUNT = 6;\n\n/** Each entry contributes one relational id/props/version row. */\nconst RESOLVED_NODE_UPDATE_BATCH_ENTRY_BIND_COUNT = 3;\n\n/**\n * The one owner of whether the portable resolved-update statement fits the\n * target's advertised bind budget. An absent budget is an explicit admission\n * that this backend has no known ceiling.\n */\nexport function resolvedNodeUpdateBatchFitsBindBudget(\n entryCount: number,\n maxBindParameters: number | undefined,\n): boolean {\n if (!Number.isSafeInteger(entryCount) || entryCount < 1) return false;\n if (maxBindParameters === undefined) return true;\n return (\n RESOLVED_NODE_UPDATE_BATCH_FIXED_BIND_COUNT +\n entryCount * RESOLVED_NODE_UPDATE_BATCH_ENTRY_BIND_COUNT <=\n maxBindParameters\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/backend/capabilities/autocommit-single-statement.ts","../src/backend/capabilities/node-insert-projections.ts","../src/backend/resolved-node-update-batch.ts"],"names":["supportsAtomicNodeClaims"],"mappings":"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","file":"chunk-I7SBZJI2.cjs","sourcesContent":["/**\n * Origin evidence for the managed single-statement autocommit fast path.\n *\n * This is intentionally narrower than schema-fenced-insert eligibility. The\n * latter follows bundled transaction targets and derived wrappers because its\n * statement still runs inside an explicit transaction. Here, omitting that\n * transaction is the optimization, so only the literal root objects produced\n * by the bundled factories may opt in. In particular, this evidence is never\n * carried through `deriveBackend`, an owned transaction, or adoption of a\n * caller-owned transaction.\n */\nimport type { GraphBackend, TransactionBackend } from \"../types\";\n\nconst BUNDLED_ROOT_AUTOCOMMIT_BACKENDS = new WeakSet<object>();\n\n/** @internal Called only by bundled factories after their root backend exists. */\nexport function markBundledRootAutocommitEligible<T extends object>(\n target: T,\n): T {\n BUNDLED_ROOT_AUTOCOMMIT_BACKENDS.add(target);\n return target;\n}\n\n/** Whether this is the exact root backend a bundled factory created. */\nexport function isBundledRootAutocommitEligible(\n target: GraphBackend | TransactionBackend,\n): target is GraphBackend {\n return BUNDLED_ROOT_AUTOCOMMIT_BACKENDS.has(target);\n}\n","import type {\n BackendIdentity,\n GraphBackend,\n ManagedNodeCreatePlan,\n NodeInsertClaim,\n NodeInsertProjection,\n} from \"../types\";\nimport {\n type AtomicNodeClaimSupport,\n supportsAtomicNodeClaims,\n} from \"./atomic-mutation-program\";\n\nexport type NodeProjectionInsertTarget = BackendIdentity &\n Pick<GraphBackend, \"commands\">;\n\nexport type NodeInsertProjectionRequirements = Readonly<{\n fulltext: boolean;\n embedding: boolean;\n}>;\n\nexport function supportsNodeInsertProjectionRequirements(\n target: NodeProjectionInsertTarget,\n requirements: NodeInsertProjectionRequirements,\n): boolean {\n return (\n (!requirements.fulltext ||\n target.fulltextStrategy?.buildSyncFromInsertedNode !== undefined) &&\n (!requirements.embedding ||\n target.vectorStrategy?.buildUpsertFromInsertedNode !== undefined)\n );\n}\n\n/**\n * The single owner of projection-fusion eligibility.\n *\n * A projection plan is all-or-nothing: every requested projection must have\n * an inserted-node builder on the active strategy, and the receiver must\n * expose the atomic executor. Callers use this same predicate before choosing\n * root autocommit and again on the actual transaction callback target.\n */\nexport function supportsNodeInsertProjections(\n target: NodeProjectionInsertTarget,\n projections: readonly NodeInsertProjection[],\n): boolean {\n if (projections.length === 0) return false;\n return supportsNodeInsertProjectionRequirements(target, {\n fulltext: projections.some((projection) => projection.kind === \"fulltext\"),\n embedding: projections.some(\n (projection) => projection.kind === \"embedding\",\n ),\n });\n}\n\n/**\n * Whether the receiver can make uniqueness/disjointness claims authoritative\n * inside the planned node statement.\n *\n * Claims are reported by the statement as a verdict, so the caller must have a\n * transaction boundary around the statement before it can safely defer the\n * application probes. A root backend is deliberately excluded: its\n * command port is also used for projection-only\n * autocommit writes, but a claim refusal must roll back the node and any\n * claims it touched together.\n */\nfunction supportsNodeInsertClaims(target: NodeProjectionInsertTarget): boolean {\n return (\n !(\"transaction\" in target) &&\n target.capabilities.atomicNodeInsertClaims === true\n );\n}\n\n/**\n * The only claim shape that is safe to execute on a root backend without a\n * rollback boundary. A generated id cannot collide with a different node, so\n * the claim is the sole conflict source; same-kind uniqueness has no legacy\n * axis or cross-kind/disjoint probe to consult. Rephasing it before the node\n * insert makes a conflict prevent the node row from being written at all.\n */\nfunction supportsNonTransactionalNodeClaimPlan(\n plan: Pick<\n ManagedNodeCreatePlan,\n \"idGenerated\" | \"mode\" | \"params\" | \"claims\" | \"projections\"\n >,\n): boolean {\n return (\n plan.idGenerated &&\n plan.mode.kind === \"ordinary\" &&\n plan.projections.length === 0 &&\n plan.claims.length === 1 &&\n plan.claims.every(\n (claim) =>\n claim.verdict.kind === \"uniqueness\" &&\n claim.axis === plan.params.kind &&\n claim.verdict.probeAxes.length === 1 &&\n claim.verdict.probeAxes[0] === claim.axis,\n )\n );\n}\n\n/** Rephases the safe root claim shape so a conflict gates the node insert. */\nexport function rephaseNonTransactionalNodeClaimPlan(\n plan: ManagedNodeCreatePlan,\n): ManagedNodeCreatePlan | undefined {\n if (!supportsNonTransactionalNodeClaimPlan(plan)) return;\n return {\n ...plan,\n claims: plan.claims.map((claim) => ({\n ...claim,\n placement: \"pre-insert\",\n })),\n };\n}\n\n/**\n * Normalizes the complete claim envelope accepted by an atomic node program.\n *\n * Unlike the ordinary root insert seam, a closed program can also prove a\n * disjoint claim because it carries the legacy live-node probe and cleanup in\n * the same atomic transport submission. The executor's advertised support is\n * authoritative; an omitted family remains on the portable path.\n */\nexport function rephaseAtomicNodeClaimPlan(\n plan: ManagedNodeCreatePlan,\n support: AtomicNodeClaimSupport | undefined,\n): ManagedNodeCreatePlan | undefined {\n if (\n plan.mode.kind !== \"ordinary\" ||\n plan.claims.length === 0 ||\n !supportsAtomicNodeClaims(support, plan.claims)\n ) {\n return;\n }\n const supported = plan.claims.every((claim) => {\n if (claim.verdict.kind === \"uniqueness\") {\n return (\n claim.verdict.probeAxes.length > 0 &&\n claim.verdict.probeAxes[0] === claim.axis &&\n new Set(claim.verdict.probeAxes).size === claim.verdict.probeAxes.length\n );\n }\n return (\n claim.key === plan.params.id &&\n claim.verdict.conflictingKinds.length > 0 &&\n new Set(claim.verdict.conflictingKinds).size ===\n claim.verdict.conflictingKinds.length\n );\n });\n if (!supported) return;\n return {\n ...plan,\n claims: plan.claims.map((claim) => ({\n ...claim,\n placement: \"pre-insert\",\n })),\n };\n}\n\n/** Whether the receiver can lower this complete insert plan atomically. */\nexport function supportsNodeCreatePlan(\n target: NodeProjectionInsertTarget,\n input: Readonly<{\n params?: ManagedNodeCreatePlan[\"params\"];\n idGenerated?: ManagedNodeCreatePlan[\"idGenerated\"];\n mode?: ManagedNodeCreatePlan[\"mode\"];\n claims: readonly NodeInsertClaim[];\n projections: readonly NodeInsertProjection[];\n /** Store-side proof that no identity/history/revision side effect exists. */\n allowNonTransactionalClaims?: boolean | undefined;\n }>,\n): boolean {\n if (input.claims.length === 0) {\n return supportsNodeInsertProjections(target, input.projections);\n }\n // A claim refusal is discovered from the data-modifying statement's result,\n // so the caller-owned transaction is the rollback boundary. Root graph\n // backends expose `transaction`; transaction-scoped operation backends do\n // not. Keep this exported predicate aligned with the execution contract.\n const ordinaryPlan =\n (\n input.params === undefined ||\n input.mode === undefined ||\n input.idGenerated === undefined\n ) ?\n undefined\n : {\n entity: \"node\" as const,\n params: input.params,\n idGenerated: input.idGenerated,\n mode: input.mode,\n claims: input.claims,\n projections: input.projections,\n };\n const rootClaimFusion =\n input.allowNonTransactionalClaims === true &&\n target.capabilities.atomicNodeInsertClaims === true &&\n ordinaryPlan !== undefined &&\n supportsNonTransactionalNodeClaimPlan(ordinaryPlan);\n return (\n (supportsNodeInsertClaims(target) ||\n (\"transaction\" in target && rootClaimFusion)) &&\n supportsNodeInsertProjectionRequirements(target, {\n fulltext: input.projections.some(\n (projection) => projection.kind === \"fulltext\",\n ),\n embedding: input.projections.some(\n (projection) => projection.kind === \"embedding\",\n ),\n })\n );\n}\n","/**\n * Bind parameters in one resolved node replacement statement, excluding its\n * entries: two graph/kind predicates, the update timestamp, and the count gate.\n */\nconst RESOLVED_NODE_UPDATE_BATCH_FIXED_BIND_COUNT = 6;\n\n/** Each entry contributes one relational id/props/version row. */\nconst RESOLVED_NODE_UPDATE_BATCH_ENTRY_BIND_COUNT = 3;\n\n/**\n * The one owner of whether the portable resolved-update statement fits the\n * target's advertised bind budget. An absent budget is an explicit admission\n * that this backend has no known ceiling.\n */\nexport function resolvedNodeUpdateBatchFitsBindBudget(\n entryCount: number,\n maxBindParameters: number | undefined,\n): boolean {\n if (!Number.isSafeInteger(entryCount) || entryCount < 1) return false;\n if (maxBindParameters === undefined) return true;\n return (\n RESOLVED_NODE_UPDATE_BATCH_FIXED_BIND_COUNT +\n entryCount * RESOLVED_NODE_UPDATE_BATCH_ENTRY_BIND_COUNT <=\n maxBindParameters\n );\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkFXGZT3WO_cjs = require('./chunk-FXGZT3WO.cjs');
3
+ var chunkBX42F7IJ_cjs = require('./chunk-BX42F7IJ.cjs');
4
4
  var chunkHAHNRASW_cjs = require('./chunk-HAHNRASW.cjs');
5
5
  var chunkBXHAPCQG_cjs = require('./chunk-BXHAPCQG.cjs');
6
6
  var chunk7XYPLAPL_cjs = require('./chunk-7XYPLAPL.cjs');
@@ -35,7 +35,7 @@ function deserializeSchema(schema) {
35
35
  function buildRegistryFromRelations(schema) {
36
36
  const nodeKinds = /* @__PURE__ */ new Map();
37
37
  const edgeKinds = /* @__PURE__ */ new Map();
38
- return chunkFXGZT3WO_cjs.buildValidatedKindRegistry({
38
+ return chunkBX42F7IJ_cjs.buildValidatedKindRegistry({
39
39
  nodeKinds,
40
40
  edgeKinds,
41
41
  ontology: schema.ontology.relations.map(
@@ -101,8 +101,8 @@ async function registerGraphTemplate(backend, params) {
101
101
  }
102
102
  );
103
103
  }
104
- const schemaDocument = chunkFXGZT3WO_cjs.serializeSchema(reconciled.graph, reconciled.version);
105
- const schemaHash = await chunkFXGZT3WO_cjs.computeSchemaHash(schemaDocument);
104
+ const schemaDocument = chunkBX42F7IJ_cjs.serializeSchema(reconciled.graph, reconciled.version);
105
+ const schemaHash = await chunkBX42F7IJ_cjs.computeSchemaHash(schemaDocument);
106
106
  if (schemaHash !== reconciled.hash) {
107
107
  throw new chunk7XYPLAPL_cjs.ConfigurationError(
108
108
  "Reconciled schema hash does not match its graph snapshot.",
@@ -129,8 +129,8 @@ async function instantiateGraphTemplate(backend, params) {
129
129
  if (sourceVersion === void 0 || reconciledHash === void 0) {
130
130
  throw graphTemplateHandleMismatchError(params.template.id);
131
131
  }
132
- const sourceHash = await chunkFXGZT3WO_cjs.computeSchemaHash(
133
- chunkFXGZT3WO_cjs.serializeSchema(params.template.reconciled.graph, sourceVersion)
132
+ const sourceHash = await chunkBX42F7IJ_cjs.computeSchemaHash(
133
+ chunkBX42F7IJ_cjs.serializeSchema(params.template.reconciled.graph, sourceVersion)
134
134
  );
135
135
  if (sourceHash !== params.template.schemaHash || reconciledHash !== params.template.schemaHash) {
136
136
  throw graphTemplateHandleMismatchError(params.template.id);
@@ -139,7 +139,7 @@ async function instantiateGraphTemplate(backend, params) {
139
139
  ...params.template.reconciled.graph,
140
140
  id: params.graphId
141
141
  });
142
- const targetHash = await chunkFXGZT3WO_cjs.computeSchemaHash(chunkFXGZT3WO_cjs.serializeSchema(targetGraph, 1));
142
+ const targetHash = await chunkBX42F7IJ_cjs.computeSchemaHash(chunkBX42F7IJ_cjs.serializeSchema(targetGraph, 1));
143
143
  const result = await instantiate({
144
144
  templateId: params.template.id,
145
145
  templateSchemaHash: params.template.schemaHash,
@@ -192,5 +192,5 @@ exports.deserializeSchema = deserializeSchema;
192
192
  exports.instantiateGraph = instantiateGraph;
193
193
  exports.instantiateGraphTemplate = instantiateGraphTemplate;
194
194
  exports.registerGraphTemplate = registerGraphTemplate;
195
- //# sourceMappingURL=chunk-H346QK3V.cjs.map
196
- //# sourceMappingURL=chunk-H346QK3V.cjs.map
195
+ //# sourceMappingURL=chunk-K7YACILO.cjs.map
196
+ //# sourceMappingURL=chunk-K7YACILO.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/schema/deserializer.ts","../src/schema/graph-templates.ts"],"names":["hasOwnKey","buildValidatedKindRegistry","ConfigurationError","resolveGraphVectorSlots","serializeSchema","computeSchemaHash"],"mappings":"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","file":"chunk-H346QK3V.cjs","sourcesContent":["/**\n * Schema deserializer for loading stored schemas.\n *\n * Reconstructs runtime objects from SerializedSchema.\n * Note: Zod schemas cannot be fully reconstructed from JSON Schema,\n * so this provides access to the serialized data for introspection.\n */\nimport { type AnyEdgeType, type NodeType } from \"../core/types\";\nimport { type NamedOntologyRelation } from \"../ontology/validation\";\nimport { buildValidatedKindRegistry } from \"../registry/build-validated\";\nimport type { KindRegistry } from \"../registry/kind-registry\";\nimport { type EdgeEndpointKinds } from \"../registry/validate-implies\";\nimport { hasOwnKey } from \"../utils/object\";\nimport {\n type SerializedClosures,\n type SerializedEdgeDef,\n type SerializedMetaEdge,\n type SerializedNodeDef,\n type SerializedOntologyRelation,\n type SerializedSchema,\n} from \"./types\";\n\n// ============================================================\n// Deserialized Schema\n// ============================================================\n\n/**\n * A deserialized schema provides read-only access to schema metadata.\n *\n * Note: Unlike the original GraphDef, this does not include Zod schemas\n * since those cannot be reconstructed from JSON Schema. Use this for\n * introspection and metadata access only.\n */\nexport type DeserializedSchema = Readonly<{\n graphId: string;\n version: number;\n generatedAt: string;\n\n /** Get node definition by name */\n getNode: (name: string) => SerializedNodeDef | undefined;\n\n /** Get all node names */\n getNodeNames: () => readonly string[];\n\n /** Get edge definition by name */\n getEdge: (name: string) => SerializedEdgeDef | undefined;\n\n /** Get all edge names */\n getEdgeNames: () => readonly string[];\n\n /** Get meta-edge definition by name */\n getMetaEdge: (name: string) => SerializedMetaEdge | undefined;\n\n /** Get all meta-edge names */\n getMetaEdgeNames: () => readonly string[];\n\n /** Get all ontology relations */\n getRelations: () => readonly SerializedOntologyRelation[];\n\n /** Get precomputed closures */\n getClosures: () => SerializedClosures;\n\n /** Get graph defaults */\n getDefaults: () => SerializedSchema[\"defaults\"];\n\n /** Get the durable TypeGraph Identity Profile configuration. */\n getIdentity: () => SerializedSchema[\"identity\"];\n\n /** Get the raw serialized schema */\n getRaw: () => SerializedSchema;\n\n /** Build a validated KindRegistry by recomputing closures from relations */\n buildRegistry: () => KindRegistry;\n}>;\n\n// ============================================================\n// Deserialization\n// ============================================================\n\n/**\n * Deserializes a SerializedSchema into a DeserializedSchema.\n *\n * @param schema - The serialized schema to deserialize\n * @returns A deserialized schema with accessor methods\n */\nexport function deserializeSchema(\n schema: SerializedSchema,\n): DeserializedSchema {\n const nodeNames = Object.keys(schema.nodes);\n const edgeNames = Object.keys(schema.edges);\n const metaEdgeNames = Object.keys(schema.ontology.metaEdges);\n\n return {\n graphId: schema.graphId,\n version: schema.version,\n generatedAt: schema.generatedAt,\n\n // Own-key reads, for the same reason {@link buildEdgeEndpointKinds} below\n // uses a `Map`: `schema` is parsed out of a stored JSON document and the\n // caller supplies the name, so a raw read hands back an `Object.prototype`\n // member typed as a definition for any name no kind is registered under.\n getNode: (name) =>\n hasOwnKey(schema.nodes, name) ? schema.nodes[name] : undefined,\n getNodeNames: () => nodeNames,\n\n getEdge: (name) =>\n hasOwnKey(schema.edges, name) ? schema.edges[name] : undefined,\n getEdgeNames: () => edgeNames,\n\n getMetaEdge: (name) =>\n hasOwnKey(schema.ontology.metaEdges, name) ?\n schema.ontology.metaEdges[name]\n : undefined,\n getMetaEdgeNames: () => metaEdgeNames,\n\n getRelations: () => schema.ontology.relations,\n getClosures: () => schema.ontology.closures,\n\n getDefaults: () => schema.defaults,\n getIdentity: () => schema.identity,\n getRaw: () => schema,\n\n buildRegistry: () => buildRegistryFromRelations(schema),\n };\n}\n\n// ============================================================\n// Registry Building\n// ============================================================\n\n/**\n * Builds a KindRegistry from serialized relations.\n *\n * Persisted closures are a legacy inspection artifact. Relations are validated\n * and closures are recomputed so old schemas gain current hardening rules.\n */\nfunction buildRegistryFromRelations(schema: SerializedSchema): KindRegistry {\n // Build empty node/edge kind maps (we don't have the actual Zod schemas)\n const nodeKinds = new Map<string, NodeType>();\n const edgeKinds = new Map<string, AnyEdgeType>();\n return buildValidatedKindRegistry({\n nodeKinds,\n edgeKinds,\n ontology: schema.ontology.relations.map(\n (relation): NamedOntologyRelation => ({\n metaEdge: relation.metaEdge,\n from: relation.from,\n to: relation.to,\n }),\n ),\n edgeEndpoints: buildEdgeEndpointKinds(schema.edges),\n ...(schema.identity === undefined ? {} : { identity: schema.identity }),\n });\n}\n\n/**\n * Maps each edge kind's serialized definition to its domain/range kind\n * names, for `validateImpliesEndpointCompatibility`. A `Map` (rather than\n * the plain `schema.edges` object) so a lookup for an edge kind literally\n * named \"toString\" or another `Object.prototype` member can't resolve to\n * an inherited member instead of `undefined`.\n */\nfunction buildEdgeEndpointKinds(\n edges: Record<string, SerializedEdgeDef>,\n): ReadonlyMap<string, EdgeEndpointKinds> {\n const result = new Map<string, EdgeEndpointKinds>();\n for (const [kind, def] of Object.entries(edges)) {\n const pairs: { from: string; to: string }[] = [];\n if (def.targetKindsBySource === undefined) {\n for (const fromKind of def.fromKinds) {\n for (const toKind of def.toKinds) {\n pairs.push({ from: fromKind, to: toKind });\n }\n }\n } else {\n for (const [sourceKind, targetKinds] of Object.entries(\n def.targetKindsBySource,\n )) {\n for (const targetKind of targetKinds) {\n pairs.push({ from: sourceKind, to: targetKind });\n }\n }\n }\n result.set(kind, {\n from: def.fromKinds,\n to: def.toKinds,\n pairs,\n });\n }\n return result;\n}\n","import type { GraphBackend, SchemaVersionRow } from \"../backend/types\";\nimport { type GraphDef } from \"../core/define-graph\";\nimport { resolveGraphVectorSlots } from \"../core/embedding\";\nimport { ConfigurationError } from \"../errors\";\nimport { type ReconciledSchema } from \"../store/store\";\nimport { computeSchemaHash, serializeSchema } from \"./serializer\";\n\n/** A locally held handle for a durable server-side graph template. */\nexport type GraphTemplate<G extends GraphDef> = Readonly<{\n id: string;\n reconciled: ReconciledSchema<G>;\n schemaHash: string;\n}>;\n\nexport type InstantiateGraphTemplateResult<G extends GraphDef> = Readonly<{\n status: \"ready\";\n reconciled: ReconciledSchema<G>;\n schema: SchemaVersionRow;\n}>;\n\n/**\n * Registers the fully materialized shape of a verified store as a durable\n * template. The original schema version is retained only as snapshot\n * provenance: every instantiated graph starts at v1 with that final shape.\n */\nexport async function registerGraphTemplate<G extends GraphDef>(\n backend: GraphBackend,\n params: Readonly<{ templateId: string; reconciled: ReconciledSchema<G> }>,\n): Promise<GraphTemplate<G>> {\n const register = backend.registerGraphTemplate;\n if (register === undefined) throw graphTemplatesUnsupportedError(backend);\n await backend.assertBaseSchemaCurrent?.();\n const { reconciled } = params;\n if (reconciled.version === undefined || reconciled.hash === undefined) {\n throw new ConfigurationError(\n \"A graph template requires a reconciled schema from a managed or verified Store.\",\n { code: \"GRAPH_TEMPLATE_REQUIRES_RECONCILED_SCHEMA\" },\n );\n }\n if (\n resolveGraphVectorSlots(reconciled.graph).length > 0 &&\n backend.capabilities.vector?.supported === true\n ) {\n throw new ConfigurationError(\n \"Graph templates do not support embedding fields because vector storage is graph-scoped and cannot be instantiated schema-only.\",\n {\n code: \"GRAPH_TEMPLATE_VECTOR_UNSUPPORTED\",\n graphId: reconciled.graph.id,\n },\n {\n suggestion:\n \"Provision the graph through createStoreWithSchema until template instantiation can atomically materialize vector contributions.\",\n },\n );\n }\n const schemaDocument = serializeSchema(reconciled.graph, reconciled.version);\n const schemaHash = await computeSchemaHash(schemaDocument);\n if (schemaHash !== reconciled.hash) {\n throw new ConfigurationError(\n \"Reconciled schema hash does not match its graph snapshot.\",\n { code: \"GRAPH_TEMPLATE_RECONCILED_HASH_MISMATCH\" },\n );\n }\n await register({\n templateId: params.templateId,\n schemaHash,\n schemaDoc: schemaDocument,\n });\n return Object.freeze({\n id: params.templateId,\n reconciled,\n schemaHash,\n });\n}\n\n/**\n * Instantiates the template's final graph shape as target schema v1. Only the\n * target hash crosses the wire; the durable source document stays in the\n * backend template registry and is rebound to `graphId` by one SQL statement.\n */\nexport async function instantiateGraphTemplate<G extends GraphDef>(\n backend: GraphBackend,\n params: Readonly<{ template: GraphTemplate<G>; graphId: string }>,\n): Promise<InstantiateGraphTemplateResult<G>> {\n const instantiate = backend.instantiateGraphTemplate;\n if (instantiate === undefined) throw graphTemplatesUnsupportedError(backend);\n await backend.assertBaseSchemaCurrent?.();\n const sourceVersion = params.template.reconciled.version;\n const reconciledHash = params.template.reconciled.hash;\n if (sourceVersion === undefined || reconciledHash === undefined) {\n throw graphTemplateHandleMismatchError(params.template.id);\n }\n const sourceHash = await computeSchemaHash(\n serializeSchema(params.template.reconciled.graph, sourceVersion),\n );\n if (\n sourceHash !== params.template.schemaHash ||\n reconciledHash !== params.template.schemaHash\n ) {\n throw graphTemplateHandleMismatchError(params.template.id);\n }\n const targetGraph: G = Object.freeze({\n ...params.template.reconciled.graph,\n id: params.graphId,\n });\n const targetHash = await computeSchemaHash(serializeSchema(targetGraph, 1));\n const result = await instantiate({\n templateId: params.template.id,\n templateSchemaHash: params.template.schemaHash,\n graphId: params.graphId,\n schemaHash: targetHash,\n });\n if (result.status === \"refused\") {\n throw new ConfigurationError(\n `Graph template instantiation was refused for graph \"${params.graphId}\". The template may be absent, or the graph already has a different schema.`,\n {\n code: \"GRAPH_TEMPLATE_INSTANTIATION_REFUSED\",\n graphId: params.graphId,\n templateId: params.template.id,\n },\n );\n }\n if (\n result.row.graph_id !== params.graphId ||\n result.row.version !== 1 ||\n result.row.schema_hash !== targetHash\n ) {\n throw new ConfigurationError(\n \"Graph template backend returned a schema row that does not match the requested target.\",\n { code: \"GRAPH_TEMPLATE_INVALID_RESULT\", graphId: params.graphId },\n );\n }\n return Object.freeze({\n status: \"ready\",\n reconciled: Object.freeze({\n graph: targetGraph,\n version: result.row.version,\n hash: result.row.schema_hash,\n }),\n schema: result.row,\n });\n}\n\nfunction graphTemplateHandleMismatchError(\n templateId: string,\n): ConfigurationError {\n return new ConfigurationError(\n `Graph template handle \"${templateId}\" does not match its reconciled schema snapshot.`,\n { code: \"GRAPH_TEMPLATE_HANDLE_MISMATCH\", templateId },\n );\n}\n\n/** Short public name for {@link instantiateGraphTemplate}. */\nexport function instantiateGraph<G extends GraphDef>(\n backend: GraphBackend,\n params: Readonly<{ template: GraphTemplate<G>; graphId: string }>,\n): Promise<InstantiateGraphTemplateResult<G>> {\n return instantiateGraphTemplate(backend, params);\n}\n\nfunction graphTemplatesUnsupportedError(\n backend: GraphBackend,\n): ConfigurationError {\n return new ConfigurationError(\n `The ${backend.dialect} backend does not support durable graph templates.`,\n { code: \"GRAPH_TEMPLATES_UNSUPPORTED\", dialect: backend.dialect },\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/schema/deserializer.ts","../src/schema/graph-templates.ts"],"names":["hasOwnKey","buildValidatedKindRegistry","ConfigurationError","resolveGraphVectorSlots","serializeSchema","computeSchemaHash"],"mappings":"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","file":"chunk-K7YACILO.cjs","sourcesContent":["/**\n * Schema deserializer for loading stored schemas.\n *\n * Reconstructs runtime objects from SerializedSchema.\n * Note: Zod schemas cannot be fully reconstructed from JSON Schema,\n * so this provides access to the serialized data for introspection.\n */\nimport { type AnyEdgeType, type NodeType } from \"../core/types\";\nimport { type NamedOntologyRelation } from \"../ontology/validation\";\nimport { buildValidatedKindRegistry } from \"../registry/build-validated\";\nimport type { KindRegistry } from \"../registry/kind-registry\";\nimport { type EdgeEndpointKinds } from \"../registry/validate-implies\";\nimport { hasOwnKey } from \"../utils/object\";\nimport {\n type SerializedClosures,\n type SerializedEdgeDef,\n type SerializedMetaEdge,\n type SerializedNodeDef,\n type SerializedOntologyRelation,\n type SerializedSchema,\n} from \"./types\";\n\n// ============================================================\n// Deserialized Schema\n// ============================================================\n\n/**\n * A deserialized schema provides read-only access to schema metadata.\n *\n * Note: Unlike the original GraphDef, this does not include Zod schemas\n * since those cannot be reconstructed from JSON Schema. Use this for\n * introspection and metadata access only.\n */\nexport type DeserializedSchema = Readonly<{\n graphId: string;\n version: number;\n generatedAt: string;\n\n /** Get node definition by name */\n getNode: (name: string) => SerializedNodeDef | undefined;\n\n /** Get all node names */\n getNodeNames: () => readonly string[];\n\n /** Get edge definition by name */\n getEdge: (name: string) => SerializedEdgeDef | undefined;\n\n /** Get all edge names */\n getEdgeNames: () => readonly string[];\n\n /** Get meta-edge definition by name */\n getMetaEdge: (name: string) => SerializedMetaEdge | undefined;\n\n /** Get all meta-edge names */\n getMetaEdgeNames: () => readonly string[];\n\n /** Get all ontology relations */\n getRelations: () => readonly SerializedOntologyRelation[];\n\n /** Get precomputed closures */\n getClosures: () => SerializedClosures;\n\n /** Get graph defaults */\n getDefaults: () => SerializedSchema[\"defaults\"];\n\n /** Get the durable TypeGraph Identity Profile configuration. */\n getIdentity: () => SerializedSchema[\"identity\"];\n\n /** Get the raw serialized schema */\n getRaw: () => SerializedSchema;\n\n /** Build a validated KindRegistry by recomputing closures from relations */\n buildRegistry: () => KindRegistry;\n}>;\n\n// ============================================================\n// Deserialization\n// ============================================================\n\n/**\n * Deserializes a SerializedSchema into a DeserializedSchema.\n *\n * @param schema - The serialized schema to deserialize\n * @returns A deserialized schema with accessor methods\n */\nexport function deserializeSchema(\n schema: SerializedSchema,\n): DeserializedSchema {\n const nodeNames = Object.keys(schema.nodes);\n const edgeNames = Object.keys(schema.edges);\n const metaEdgeNames = Object.keys(schema.ontology.metaEdges);\n\n return {\n graphId: schema.graphId,\n version: schema.version,\n generatedAt: schema.generatedAt,\n\n // Own-key reads, for the same reason {@link buildEdgeEndpointKinds} below\n // uses a `Map`: `schema` is parsed out of a stored JSON document and the\n // caller supplies the name, so a raw read hands back an `Object.prototype`\n // member typed as a definition for any name no kind is registered under.\n getNode: (name) =>\n hasOwnKey(schema.nodes, name) ? schema.nodes[name] : undefined,\n getNodeNames: () => nodeNames,\n\n getEdge: (name) =>\n hasOwnKey(schema.edges, name) ? schema.edges[name] : undefined,\n getEdgeNames: () => edgeNames,\n\n getMetaEdge: (name) =>\n hasOwnKey(schema.ontology.metaEdges, name) ?\n schema.ontology.metaEdges[name]\n : undefined,\n getMetaEdgeNames: () => metaEdgeNames,\n\n getRelations: () => schema.ontology.relations,\n getClosures: () => schema.ontology.closures,\n\n getDefaults: () => schema.defaults,\n getIdentity: () => schema.identity,\n getRaw: () => schema,\n\n buildRegistry: () => buildRegistryFromRelations(schema),\n };\n}\n\n// ============================================================\n// Registry Building\n// ============================================================\n\n/**\n * Builds a KindRegistry from serialized relations.\n *\n * Persisted closures are a legacy inspection artifact. Relations are validated\n * and closures are recomputed so old schemas gain current hardening rules.\n */\nfunction buildRegistryFromRelations(schema: SerializedSchema): KindRegistry {\n // Build empty node/edge kind maps (we don't have the actual Zod schemas)\n const nodeKinds = new Map<string, NodeType>();\n const edgeKinds = new Map<string, AnyEdgeType>();\n return buildValidatedKindRegistry({\n nodeKinds,\n edgeKinds,\n ontology: schema.ontology.relations.map(\n (relation): NamedOntologyRelation => ({\n metaEdge: relation.metaEdge,\n from: relation.from,\n to: relation.to,\n }),\n ),\n edgeEndpoints: buildEdgeEndpointKinds(schema.edges),\n ...(schema.identity === undefined ? {} : { identity: schema.identity }),\n });\n}\n\n/**\n * Maps each edge kind's serialized definition to its domain/range kind\n * names, for `validateImpliesEndpointCompatibility`. A `Map` (rather than\n * the plain `schema.edges` object) so a lookup for an edge kind literally\n * named \"toString\" or another `Object.prototype` member can't resolve to\n * an inherited member instead of `undefined`.\n */\nfunction buildEdgeEndpointKinds(\n edges: Record<string, SerializedEdgeDef>,\n): ReadonlyMap<string, EdgeEndpointKinds> {\n const result = new Map<string, EdgeEndpointKinds>();\n for (const [kind, def] of Object.entries(edges)) {\n const pairs: { from: string; to: string }[] = [];\n if (def.targetKindsBySource === undefined) {\n for (const fromKind of def.fromKinds) {\n for (const toKind of def.toKinds) {\n pairs.push({ from: fromKind, to: toKind });\n }\n }\n } else {\n for (const [sourceKind, targetKinds] of Object.entries(\n def.targetKindsBySource,\n )) {\n for (const targetKind of targetKinds) {\n pairs.push({ from: sourceKind, to: targetKind });\n }\n }\n }\n result.set(kind, {\n from: def.fromKinds,\n to: def.toKinds,\n pairs,\n });\n }\n return result;\n}\n","import type { GraphBackend, SchemaVersionRow } from \"../backend/types\";\nimport { type GraphDef } from \"../core/define-graph\";\nimport { resolveGraphVectorSlots } from \"../core/embedding\";\nimport { ConfigurationError } from \"../errors\";\nimport { type ReconciledSchema } from \"../store/store\";\nimport { computeSchemaHash, serializeSchema } from \"./serializer\";\n\n/** A locally held handle for a durable server-side graph template. */\nexport type GraphTemplate<G extends GraphDef> = Readonly<{\n id: string;\n reconciled: ReconciledSchema<G>;\n schemaHash: string;\n}>;\n\nexport type InstantiateGraphTemplateResult<G extends GraphDef> = Readonly<{\n status: \"ready\";\n reconciled: ReconciledSchema<G>;\n schema: SchemaVersionRow;\n}>;\n\n/**\n * Registers the fully materialized shape of a verified store as a durable\n * template. The original schema version is retained only as snapshot\n * provenance: every instantiated graph starts at v1 with that final shape.\n */\nexport async function registerGraphTemplate<G extends GraphDef>(\n backend: GraphBackend,\n params: Readonly<{ templateId: string; reconciled: ReconciledSchema<G> }>,\n): Promise<GraphTemplate<G>> {\n const register = backend.registerGraphTemplate;\n if (register === undefined) throw graphTemplatesUnsupportedError(backend);\n await backend.assertBaseSchemaCurrent?.();\n const { reconciled } = params;\n if (reconciled.version === undefined || reconciled.hash === undefined) {\n throw new ConfigurationError(\n \"A graph template requires a reconciled schema from a managed or verified Store.\",\n { code: \"GRAPH_TEMPLATE_REQUIRES_RECONCILED_SCHEMA\" },\n );\n }\n if (\n resolveGraphVectorSlots(reconciled.graph).length > 0 &&\n backend.capabilities.vector?.supported === true\n ) {\n throw new ConfigurationError(\n \"Graph templates do not support embedding fields because vector storage is graph-scoped and cannot be instantiated schema-only.\",\n {\n code: \"GRAPH_TEMPLATE_VECTOR_UNSUPPORTED\",\n graphId: reconciled.graph.id,\n },\n {\n suggestion:\n \"Provision the graph through createStoreWithSchema until template instantiation can atomically materialize vector contributions.\",\n },\n );\n }\n const schemaDocument = serializeSchema(reconciled.graph, reconciled.version);\n const schemaHash = await computeSchemaHash(schemaDocument);\n if (schemaHash !== reconciled.hash) {\n throw new ConfigurationError(\n \"Reconciled schema hash does not match its graph snapshot.\",\n { code: \"GRAPH_TEMPLATE_RECONCILED_HASH_MISMATCH\" },\n );\n }\n await register({\n templateId: params.templateId,\n schemaHash,\n schemaDoc: schemaDocument,\n });\n return Object.freeze({\n id: params.templateId,\n reconciled,\n schemaHash,\n });\n}\n\n/**\n * Instantiates the template's final graph shape as target schema v1. Only the\n * target hash crosses the wire; the durable source document stays in the\n * backend template registry and is rebound to `graphId` by one SQL statement.\n */\nexport async function instantiateGraphTemplate<G extends GraphDef>(\n backend: GraphBackend,\n params: Readonly<{ template: GraphTemplate<G>; graphId: string }>,\n): Promise<InstantiateGraphTemplateResult<G>> {\n const instantiate = backend.instantiateGraphTemplate;\n if (instantiate === undefined) throw graphTemplatesUnsupportedError(backend);\n await backend.assertBaseSchemaCurrent?.();\n const sourceVersion = params.template.reconciled.version;\n const reconciledHash = params.template.reconciled.hash;\n if (sourceVersion === undefined || reconciledHash === undefined) {\n throw graphTemplateHandleMismatchError(params.template.id);\n }\n const sourceHash = await computeSchemaHash(\n serializeSchema(params.template.reconciled.graph, sourceVersion),\n );\n if (\n sourceHash !== params.template.schemaHash ||\n reconciledHash !== params.template.schemaHash\n ) {\n throw graphTemplateHandleMismatchError(params.template.id);\n }\n const targetGraph: G = Object.freeze({\n ...params.template.reconciled.graph,\n id: params.graphId,\n });\n const targetHash = await computeSchemaHash(serializeSchema(targetGraph, 1));\n const result = await instantiate({\n templateId: params.template.id,\n templateSchemaHash: params.template.schemaHash,\n graphId: params.graphId,\n schemaHash: targetHash,\n });\n if (result.status === \"refused\") {\n throw new ConfigurationError(\n `Graph template instantiation was refused for graph \"${params.graphId}\". The template may be absent, or the graph already has a different schema.`,\n {\n code: \"GRAPH_TEMPLATE_INSTANTIATION_REFUSED\",\n graphId: params.graphId,\n templateId: params.template.id,\n },\n );\n }\n if (\n result.row.graph_id !== params.graphId ||\n result.row.version !== 1 ||\n result.row.schema_hash !== targetHash\n ) {\n throw new ConfigurationError(\n \"Graph template backend returned a schema row that does not match the requested target.\",\n { code: \"GRAPH_TEMPLATE_INVALID_RESULT\", graphId: params.graphId },\n );\n }\n return Object.freeze({\n status: \"ready\",\n reconciled: Object.freeze({\n graph: targetGraph,\n version: result.row.version,\n hash: result.row.schema_hash,\n }),\n schema: result.row,\n });\n}\n\nfunction graphTemplateHandleMismatchError(\n templateId: string,\n): ConfigurationError {\n return new ConfigurationError(\n `Graph template handle \"${templateId}\" does not match its reconciled schema snapshot.`,\n { code: \"GRAPH_TEMPLATE_HANDLE_MISMATCH\", templateId },\n );\n}\n\n/** Short public name for {@link instantiateGraphTemplate}. */\nexport function instantiateGraph<G extends GraphDef>(\n backend: GraphBackend,\n params: Readonly<{ template: GraphTemplate<G>; graphId: string }>,\n): Promise<InstantiateGraphTemplateResult<G>> {\n return instantiateGraphTemplate(backend, params);\n}\n\nfunction graphTemplatesUnsupportedError(\n backend: GraphBackend,\n): ConfigurationError {\n return new ConfigurationError(\n `The ${backend.dialect} backend does not support durable graph templates.`,\n { code: \"GRAPH_TEMPLATES_UNSUPPORTED\", dialect: backend.dialect },\n );\n}\n"]}