@nicia-ai/typegraph 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/README.md +23 -0
  2. package/dist/{ast-BVyihVbP.d.cts → ast-CXFx6bF6.d.ts} +45 -165
  3. package/dist/{ast-BVyihVbP.d.ts → ast-D-3bOanX.d.cts} +45 -165
  4. package/dist/backend/drizzle/index.cjs +20 -20
  5. package/dist/backend/drizzle/index.d.cts +6 -5
  6. package/dist/backend/drizzle/index.d.ts +6 -5
  7. package/dist/backend/drizzle/index.js +8 -8
  8. package/dist/backend/drizzle/postgres.cjs +9 -9
  9. package/dist/backend/drizzle/postgres.d.cts +9 -11
  10. package/dist/backend/drizzle/postgres.d.ts +9 -11
  11. package/dist/backend/drizzle/postgres.js +6 -6
  12. package/dist/backend/drizzle/schema/postgres.cjs +10 -10
  13. package/dist/backend/drizzle/schema/postgres.d.cts +6 -5
  14. package/dist/backend/drizzle/schema/postgres.d.ts +6 -5
  15. package/dist/backend/drizzle/schema/postgres.js +3 -3
  16. package/dist/backend/drizzle/schema/sqlite.cjs +10 -10
  17. package/dist/backend/drizzle/schema/sqlite.d.cts +6 -5
  18. package/dist/backend/drizzle/schema/sqlite.d.ts +6 -5
  19. package/dist/backend/drizzle/schema/sqlite.js +3 -3
  20. package/dist/backend/drizzle/sqlite.cjs +9 -9
  21. package/dist/backend/drizzle/sqlite.d.cts +17 -18
  22. package/dist/backend/drizzle/sqlite.d.ts +17 -18
  23. package/dist/backend/drizzle/sqlite.js +6 -6
  24. package/dist/backend/postgres/index.cjs +21 -17
  25. package/dist/backend/postgres/index.d.cts +8 -7
  26. package/dist/backend/postgres/index.d.ts +8 -7
  27. package/dist/backend/postgres/index.js +8 -8
  28. package/dist/backend/sqlite/index.cjs +27 -21
  29. package/dist/backend/sqlite/index.cjs.map +1 -1
  30. package/dist/backend/sqlite/index.d.cts +7 -6
  31. package/dist/backend/sqlite/index.d.ts +7 -6
  32. package/dist/backend/sqlite/index.js +18 -12
  33. package/dist/backend/sqlite/index.js.map +1 -1
  34. package/dist/{chunk-YM5AL65Y.cjs → chunk-2WVFEIHR.cjs} +29 -3
  35. package/dist/chunk-2WVFEIHR.cjs.map +1 -0
  36. package/dist/{chunk-4PIEL2VO.js → chunk-3PURVEA4.js} +36 -5
  37. package/dist/chunk-3PURVEA4.js.map +1 -0
  38. package/dist/chunk-4HARSV2G.js +1448 -0
  39. package/dist/chunk-4HARSV2G.js.map +1 -0
  40. package/dist/{chunk-IIAT36MI.js → chunk-54WJF3DW.js} +29 -3
  41. package/dist/chunk-54WJF3DW.js.map +1 -0
  42. package/dist/chunk-CMHFS34N.cjs +390 -0
  43. package/dist/chunk-CMHFS34N.cjs.map +1 -0
  44. package/dist/chunk-DD6ONEBN.cjs +1264 -0
  45. package/dist/chunk-DD6ONEBN.cjs.map +1 -0
  46. package/dist/chunk-F2BZSEFE.js +388 -0
  47. package/dist/chunk-F2BZSEFE.js.map +1 -0
  48. package/dist/{chunk-DDM2FZRJ.cjs → chunk-JQDWEX6V.cjs} +24 -24
  49. package/dist/{chunk-DDM2FZRJ.cjs.map → chunk-JQDWEX6V.cjs.map} +1 -1
  50. package/dist/chunk-NP4G4ZKM.js +1228 -0
  51. package/dist/chunk-NP4G4ZKM.js.map +1 -0
  52. package/dist/{chunk-UJAGXJDG.cjs → chunk-NU2XNMVI.cjs} +38 -7
  53. package/dist/chunk-NU2XNMVI.cjs.map +1 -0
  54. package/dist/{chunk-JKTO7TW3.js → chunk-O5XPCJLF.js} +25 -3
  55. package/dist/chunk-O5XPCJLF.js.map +1 -0
  56. package/dist/{chunk-2QHQ2C4P.js → chunk-OGGLFYFA.js} +36 -5
  57. package/dist/chunk-OGGLFYFA.js.map +1 -0
  58. package/dist/{chunk-SV5H3XM5.cjs → chunk-OYL2SGBD.cjs} +26 -2
  59. package/dist/chunk-OYL2SGBD.cjs.map +1 -0
  60. package/dist/chunk-SFY2PPOY.cjs +1469 -0
  61. package/dist/chunk-SFY2PPOY.cjs.map +1 -0
  62. package/dist/{chunk-JDAET5LO.js → chunk-SMLIWLS7.js} +9 -9
  63. package/dist/chunk-SMLIWLS7.js.map +1 -0
  64. package/dist/{chunk-VXRVGFCI.js → chunk-U3452TEU.js} +17 -17
  65. package/dist/{chunk-VXRVGFCI.js.map → chunk-U3452TEU.js.map} +1 -1
  66. package/dist/{chunk-MNO33ASC.cjs → chunk-UYMT4LO2.cjs} +9 -8
  67. package/dist/chunk-UYMT4LO2.cjs.map +1 -0
  68. package/dist/chunk-V7CS2MDB.cjs +289 -0
  69. package/dist/chunk-V7CS2MDB.cjs.map +1 -0
  70. package/dist/chunk-WE5BKYNB.js +287 -0
  71. package/dist/chunk-WE5BKYNB.js.map +1 -0
  72. package/dist/{chunk-L642L24T.js → chunk-XDTYTNYL.js} +14 -21
  73. package/dist/chunk-XDTYTNYL.js.map +1 -0
  74. package/dist/{chunk-N4AOJ3VF.cjs → chunk-XZL6MCZJ.cjs} +38 -7
  75. package/dist/chunk-XZL6MCZJ.cjs.map +1 -0
  76. package/dist/{chunk-DBFCKELK.cjs → chunk-ZJHQZZT2.cjs} +18 -27
  77. package/dist/chunk-ZJHQZZT2.cjs.map +1 -0
  78. package/dist/index-Dkicw49A.d.cts +373 -0
  79. package/dist/index-Dkicw49A.d.ts +373 -0
  80. package/dist/index.cjs +5915 -3377
  81. package/dist/index.cjs.map +1 -1
  82. package/dist/index.d.cts +24 -664
  83. package/dist/index.d.ts +24 -664
  84. package/dist/index.js +5781 -3223
  85. package/dist/index.js.map +1 -1
  86. package/dist/indexes/index.cjs +16 -16
  87. package/dist/indexes/index.d.cts +5 -4
  88. package/dist/indexes/index.d.ts +5 -4
  89. package/dist/indexes/index.js +2 -2
  90. package/dist/interchange/index.cjs +9 -9
  91. package/dist/interchange/index.cjs.map +1 -1
  92. package/dist/interchange/index.d.cts +5 -3
  93. package/dist/interchange/index.d.ts +5 -3
  94. package/dist/interchange/index.js +8 -8
  95. package/dist/interchange/index.js.map +1 -1
  96. package/dist/manager-Jc5Btay9.d.cts +493 -0
  97. package/dist/manager-e9LXthrx.d.ts +493 -0
  98. package/dist/profiler/index.cjs +2 -8
  99. package/dist/profiler/index.cjs.map +1 -1
  100. package/dist/profiler/index.d.cts +9 -161
  101. package/dist/profiler/index.d.ts +9 -161
  102. package/dist/profiler/index.js +4 -4
  103. package/dist/profiler/index.js.map +1 -1
  104. package/dist/schema/index.cjs +145 -0
  105. package/dist/schema/index.cjs.map +1 -0
  106. package/dist/schema/index.d.cts +237 -0
  107. package/dist/schema/index.d.ts +237 -0
  108. package/dist/schema/index.js +72 -0
  109. package/dist/schema/index.js.map +1 -0
  110. package/dist/{store-BPhjw5S8.d.ts → store-DM3Tk3Pw.d.ts} +874 -1283
  111. package/dist/{store-DNOOQEm8.d.cts → store-nbBybLWP.d.cts} +874 -1283
  112. package/dist/{test-helpers-BjyRYJZX.d.ts → test-helpers-CIq1Hhj1.d.ts} +5 -1
  113. package/dist/{test-helpers-NoQXhleQ.d.cts → test-helpers-DPRFVky4.d.cts} +5 -1
  114. package/dist/{types-D_3mEv2y.d.ts → types-BL1GyVku.d.cts} +2 -2
  115. package/dist/{types-DsRfx0yk.d.ts → types-Cdbi4hcx.d.ts} +228 -4
  116. package/dist/{types-BrSfFSpW.d.cts → types-DCGa53O2.d.ts} +2 -2
  117. package/dist/{types-aapj0GLz.d.cts → types-DDP0MGBF.d.cts} +228 -4
  118. package/dist/{types-CX4cLd7M.d.ts → types-DHRsi6j9.d.cts} +4 -3
  119. package/dist/types-DTJEu_-h.d.cts +158 -0
  120. package/dist/types-DTJEu_-h.d.ts +158 -0
  121. package/dist/{types-a5rAxC92.d.cts → types-ZT5mlism.d.ts} +4 -3
  122. package/package.json +17 -2
  123. package/dist/chunk-2FURVVAX.cjs +0 -350
  124. package/dist/chunk-2FURVVAX.cjs.map +0 -1
  125. package/dist/chunk-2QHQ2C4P.js.map +0 -1
  126. package/dist/chunk-4PIEL2VO.js.map +0 -1
  127. package/dist/chunk-DBFCKELK.cjs.map +0 -1
  128. package/dist/chunk-H7THXVH6.cjs +0 -314
  129. package/dist/chunk-H7THXVH6.cjs.map +0 -1
  130. package/dist/chunk-HXAPXPZH.cjs +0 -680
  131. package/dist/chunk-HXAPXPZH.cjs.map +0 -1
  132. package/dist/chunk-IIAT36MI.js.map +0 -1
  133. package/dist/chunk-JDAET5LO.js.map +0 -1
  134. package/dist/chunk-JKTO7TW3.js.map +0 -1
  135. package/dist/chunk-L642L24T.js.map +0 -1
  136. package/dist/chunk-MNO33ASC.cjs.map +0 -1
  137. package/dist/chunk-N4AOJ3VF.cjs.map +0 -1
  138. package/dist/chunk-QB3WBMDT.js +0 -646
  139. package/dist/chunk-QB3WBMDT.js.map +0 -1
  140. package/dist/chunk-SV5H3XM5.cjs.map +0 -1
  141. package/dist/chunk-UJAGXJDG.cjs.map +0 -1
  142. package/dist/chunk-X4EVMBON.js +0 -312
  143. package/dist/chunk-X4EVMBON.js.map +0 -1
  144. package/dist/chunk-XZL4NLV6.js +0 -348
  145. package/dist/chunk-XZL4NLV6.js.map +0 -1
  146. package/dist/chunk-YM5AL65Y.cjs.map +0 -1
@@ -0,0 +1,1264 @@
1
+ 'use strict';
2
+
3
+ var chunkZJHQZZT2_cjs = require('./chunk-ZJHQZZT2.cjs');
4
+ var chunkOYL2SGBD_cjs = require('./chunk-OYL2SGBD.cjs');
5
+ var zod = require('zod');
6
+
7
+ // src/ontology/types.ts
8
+ var META_EDGE_BRAND = "__metaEdge";
9
+ function isMetaEdge(value) {
10
+ return typeof value === "object" && value !== null && META_EDGE_BRAND in value && value[META_EDGE_BRAND] === true;
11
+ }
12
+ function getTypeName(typeOrIri) {
13
+ if (typeof typeOrIri === "string") {
14
+ return typeOrIri;
15
+ }
16
+ return typeOrIri.kind;
17
+ }
18
+
19
+ // src/errors/validation.ts
20
+ function zodIssuesToValidationIssues(error) {
21
+ return error.issues.map((issue) => ({
22
+ path: issue.path.join("."),
23
+ message: issue.message,
24
+ code: issue.code
25
+ }));
26
+ }
27
+ function buildLocationString(context) {
28
+ if (context.id) {
29
+ return `${context.kind}/${context.id}`;
30
+ }
31
+ return `new ${context.kind}`;
32
+ }
33
+ function validateProps(schema, props, context) {
34
+ const result = schema.safeParse(props);
35
+ if (result.success) {
36
+ return result.data;
37
+ }
38
+ const issues = zodIssuesToValidationIssues(result.error);
39
+ const location = buildLocationString(context);
40
+ throw new chunkOYL2SGBD_cjs.ValidationError(
41
+ `Invalid ${context.entityType} props for ${location}: ${result.error.message}`,
42
+ {
43
+ entityType: context.entityType,
44
+ kind: context.kind,
45
+ operation: context.operation,
46
+ ...context.id !== void 0 && { id: context.id },
47
+ issues
48
+ },
49
+ { cause: result.error }
50
+ );
51
+ }
52
+ function validateNodeProps(schema, props, context) {
53
+ return validateProps(schema, props, {
54
+ entityType: "node",
55
+ ...context
56
+ });
57
+ }
58
+ function validateEdgeProps(schema, props, context) {
59
+ return validateProps(schema, props, {
60
+ entityType: "edge",
61
+ ...context
62
+ });
63
+ }
64
+ function wrapZodError(error, context) {
65
+ const issues = zodIssuesToValidationIssues(error);
66
+ const location = buildLocationString(context);
67
+ return new chunkOYL2SGBD_cjs.ValidationError(
68
+ `Validation failed for ${context.entityType} ${location}: ${error.message}`,
69
+ {
70
+ entityType: context.entityType,
71
+ kind: context.kind,
72
+ operation: context.operation,
73
+ ...context.id !== void 0 && { id: context.id },
74
+ issues
75
+ },
76
+ { cause: error }
77
+ );
78
+ }
79
+ function createValidationError(message, issues, context) {
80
+ return new chunkOYL2SGBD_cjs.ValidationError(message, {
81
+ ...context?.entityType !== void 0 && {
82
+ entityType: context.entityType
83
+ },
84
+ ...context?.kind !== void 0 && { kind: context.kind },
85
+ ...context?.operation !== void 0 && { operation: context.operation },
86
+ ...context?.id !== void 0 && { id: context.id },
87
+ issues
88
+ });
89
+ }
90
+
91
+ // src/schema/migration.ts
92
+ function computeSchemaDiff(before, after) {
93
+ const nodeChanges = diffNodes(before.nodes, after.nodes);
94
+ const edgeChanges = diffEdges(before.edges, after.edges);
95
+ const ontologyChanges = diffOntology(before.ontology, after.ontology);
96
+ const allChanges = [...nodeChanges, ...edgeChanges, ...ontologyChanges];
97
+ const hasBreakingChanges = allChanges.some(
98
+ (change) => change.severity === "breaking"
99
+ );
100
+ const hasChanges = allChanges.length > 0;
101
+ const summary = generateSummary(nodeChanges, edgeChanges, ontologyChanges);
102
+ return {
103
+ fromVersion: before.version,
104
+ toVersion: after.version,
105
+ nodes: nodeChanges,
106
+ edges: edgeChanges,
107
+ ontology: ontologyChanges,
108
+ hasBreakingChanges,
109
+ isBackwardsCompatible: !hasBreakingChanges,
110
+ hasChanges,
111
+ summary
112
+ };
113
+ }
114
+ function diffNodes(before, after) {
115
+ const changes = [];
116
+ const beforeNames = new Set(Object.keys(before));
117
+ const afterNames = new Set(Object.keys(after));
118
+ for (const name of beforeNames) {
119
+ if (!afterNames.has(name)) {
120
+ changes.push({
121
+ type: "removed",
122
+ kind: name,
123
+ severity: "breaking",
124
+ details: `Node kind "${name}" was removed`,
125
+ before: before[name]
126
+ });
127
+ }
128
+ }
129
+ for (const name of afterNames) {
130
+ if (!beforeNames.has(name)) {
131
+ changes.push({
132
+ type: "added",
133
+ kind: name,
134
+ severity: "safe",
135
+ details: `Node kind "${name}" was added`,
136
+ after: after[name]
137
+ });
138
+ }
139
+ }
140
+ for (const name of beforeNames) {
141
+ if (afterNames.has(name)) {
142
+ const nodeBefore = before[name];
143
+ const nodeAfter = after[name];
144
+ const nodeChanges = diffNodeDef(name, nodeBefore, nodeAfter);
145
+ changes.push(...nodeChanges);
146
+ }
147
+ }
148
+ return changes;
149
+ }
150
+ function diffNodeDef(name, before, after) {
151
+ const changes = [];
152
+ const propsBefore = JSON.stringify(before.properties);
153
+ const propsAfter = JSON.stringify(after.properties);
154
+ if (propsBefore !== propsAfter) {
155
+ const beforeProps = before.properties.properties ?? {};
156
+ const afterProps = after.properties.properties ?? {};
157
+ const beforeRequired = new Set(before.properties.required);
158
+ const afterRequired = new Set(after.properties.required);
159
+ const addedProps = Object.keys(afterProps).filter(
160
+ (p) => !(p in beforeProps)
161
+ );
162
+ const removedProps = Object.keys(beforeProps).filter(
163
+ (p) => !(p in afterProps)
164
+ );
165
+ const newRequired = [...afterRequired].filter(
166
+ (p) => !beforeRequired.has(p)
167
+ );
168
+ const { severity, details } = computePropertyChangeSeverity(
169
+ name,
170
+ removedProps,
171
+ addedProps,
172
+ newRequired
173
+ );
174
+ changes.push({
175
+ type: "modified",
176
+ kind: name,
177
+ severity,
178
+ details,
179
+ before,
180
+ after
181
+ });
182
+ }
183
+ if (before.onDelete !== after.onDelete) {
184
+ changes.push({
185
+ type: "modified",
186
+ kind: name,
187
+ severity: "warning",
188
+ details: `onDelete changed from "${before.onDelete}" to "${after.onDelete}" for "${name}"`,
189
+ before,
190
+ after
191
+ });
192
+ }
193
+ const constraintsBefore = JSON.stringify(before.uniqueConstraints);
194
+ const constraintsAfter = JSON.stringify(after.uniqueConstraints);
195
+ if (constraintsBefore !== constraintsAfter) {
196
+ changes.push({
197
+ type: "modified",
198
+ kind: name,
199
+ severity: "warning",
200
+ details: `Unique constraints changed for "${name}"`,
201
+ before,
202
+ after
203
+ });
204
+ }
205
+ return changes;
206
+ }
207
+ function computePropertyChangeSeverity(name, removedProps, addedProps, newRequired) {
208
+ if (removedProps.length > 0) {
209
+ return {
210
+ severity: "breaking",
211
+ details: `Properties removed from "${name}": ${removedProps.join(", ")}`
212
+ };
213
+ }
214
+ if (newRequired.length > 0) {
215
+ return {
216
+ severity: "breaking",
217
+ details: `New required properties in "${name}": ${newRequired.join(", ")}`
218
+ };
219
+ }
220
+ if (addedProps.length > 0) {
221
+ return {
222
+ severity: "safe",
223
+ details: `Properties added to "${name}": ${addedProps.join(", ")}`
224
+ };
225
+ }
226
+ return {
227
+ severity: "safe",
228
+ details: `Properties changed in "${name}"`
229
+ };
230
+ }
231
+ function diffEdges(before, after) {
232
+ const changes = [];
233
+ const beforeNames = new Set(Object.keys(before));
234
+ const afterNames = new Set(Object.keys(after));
235
+ for (const name of beforeNames) {
236
+ if (!afterNames.has(name)) {
237
+ changes.push({
238
+ type: "removed",
239
+ kind: name,
240
+ severity: "breaking",
241
+ details: `Edge kind "${name}" was removed`,
242
+ before: before[name]
243
+ });
244
+ }
245
+ }
246
+ for (const name of afterNames) {
247
+ if (!beforeNames.has(name)) {
248
+ changes.push({
249
+ type: "added",
250
+ kind: name,
251
+ severity: "safe",
252
+ details: `Edge kind "${name}" was added`,
253
+ after: after[name]
254
+ });
255
+ }
256
+ }
257
+ for (const name of beforeNames) {
258
+ if (afterNames.has(name)) {
259
+ const edgeBefore = before[name];
260
+ const edgeAfter = after[name];
261
+ const edgeChanges = diffEdgeDef(name, edgeBefore, edgeAfter);
262
+ changes.push(...edgeChanges);
263
+ }
264
+ }
265
+ return changes;
266
+ }
267
+ function diffEdgeDef(name, before, after) {
268
+ const changes = [];
269
+ const fromBefore = JSON.stringify(before.fromKinds);
270
+ const fromAfter = JSON.stringify(after.fromKinds);
271
+ if (fromBefore !== fromAfter) {
272
+ changes.push({
273
+ type: "modified",
274
+ kind: name,
275
+ severity: "warning",
276
+ details: `fromKinds changed for "${name}"`,
277
+ before,
278
+ after
279
+ });
280
+ }
281
+ const toBefore = JSON.stringify(before.toKinds);
282
+ const toAfter = JSON.stringify(after.toKinds);
283
+ if (toBefore !== toAfter) {
284
+ changes.push({
285
+ type: "modified",
286
+ kind: name,
287
+ severity: "warning",
288
+ details: `toKinds changed for "${name}"`,
289
+ before,
290
+ after
291
+ });
292
+ }
293
+ if (before.cardinality !== after.cardinality) {
294
+ changes.push({
295
+ type: "modified",
296
+ kind: name,
297
+ severity: "warning",
298
+ details: `Cardinality changed from "${before.cardinality}" to "${after.cardinality}" for "${name}"`,
299
+ before,
300
+ after
301
+ });
302
+ }
303
+ const propsBefore = JSON.stringify(before.properties);
304
+ const propsAfter = JSON.stringify(after.properties);
305
+ if (propsBefore !== propsAfter) {
306
+ changes.push({
307
+ type: "modified",
308
+ kind: name,
309
+ severity: "safe",
310
+ details: `Properties changed for "${name}"`,
311
+ before,
312
+ after
313
+ });
314
+ }
315
+ return changes;
316
+ }
317
+ function diffOntology(before, after) {
318
+ const changes = [];
319
+ const metaEdgesBefore = new Set(Object.keys(before.metaEdges));
320
+ const metaEdgesAfter = new Set(Object.keys(after.metaEdges));
321
+ for (const name of metaEdgesBefore) {
322
+ if (!metaEdgesAfter.has(name)) {
323
+ changes.push({
324
+ type: "removed",
325
+ entity: "metaEdge",
326
+ name,
327
+ severity: "breaking",
328
+ details: `Meta-edge "${name}" was removed`
329
+ });
330
+ }
331
+ }
332
+ for (const name of metaEdgesAfter) {
333
+ if (!metaEdgesBefore.has(name)) {
334
+ changes.push({
335
+ type: "added",
336
+ entity: "metaEdge",
337
+ name,
338
+ severity: "safe",
339
+ details: `Meta-edge "${name}" was added`
340
+ });
341
+ }
342
+ }
343
+ const relationsBefore = new Set(
344
+ before.relations.map((r) => `${r.metaEdge}:${r.from}:${r.to}`)
345
+ );
346
+ const relationsAfter = new Set(
347
+ after.relations.map((r) => `${r.metaEdge}:${r.from}:${r.to}`)
348
+ );
349
+ for (const relationKey of relationsBefore) {
350
+ if (!relationsAfter.has(relationKey)) {
351
+ const [metaEdge, from, to] = relationKey.split(":");
352
+ changes.push({
353
+ type: "removed",
354
+ entity: "relation",
355
+ name: relationKey,
356
+ severity: "warning",
357
+ details: `Relation ${metaEdge}(${from}, ${to}) was removed`
358
+ });
359
+ }
360
+ }
361
+ for (const relationKey of relationsAfter) {
362
+ if (!relationsBefore.has(relationKey)) {
363
+ const [metaEdge, from, to] = relationKey.split(":");
364
+ changes.push({
365
+ type: "added",
366
+ entity: "relation",
367
+ name: relationKey,
368
+ severity: "safe",
369
+ details: `Relation ${metaEdge}(${from}, ${to}) was added`
370
+ });
371
+ }
372
+ }
373
+ return changes;
374
+ }
375
+ function generateSummary(nodeChanges, edgeChanges, ontologyChanges) {
376
+ const parts = [];
377
+ const nodeAdded = nodeChanges.filter((c) => c.type === "added").length;
378
+ const nodeRemoved = nodeChanges.filter((c) => c.type === "removed").length;
379
+ const nodeModified = nodeChanges.filter((c) => c.type === "modified").length;
380
+ if (nodeAdded > 0 || nodeRemoved > 0 || nodeModified > 0) {
381
+ parts.push(
382
+ `Nodes: ${nodeAdded} added, ${nodeRemoved} removed, ${nodeModified} modified`
383
+ );
384
+ }
385
+ const edgeAdded = edgeChanges.filter((c) => c.type === "added").length;
386
+ const edgeRemoved = edgeChanges.filter((c) => c.type === "removed").length;
387
+ const edgeModified = edgeChanges.filter((c) => c.type === "modified").length;
388
+ if (edgeAdded > 0 || edgeRemoved > 0 || edgeModified > 0) {
389
+ parts.push(
390
+ `Edges: ${edgeAdded} added, ${edgeRemoved} removed, ${edgeModified} modified`
391
+ );
392
+ }
393
+ const ontologyAdded = ontologyChanges.filter(
394
+ (c) => c.type === "added"
395
+ ).length;
396
+ const ontologyRemoved = ontologyChanges.filter(
397
+ (c) => c.type === "removed"
398
+ ).length;
399
+ if (ontologyAdded > 0 || ontologyRemoved > 0) {
400
+ parts.push(`Ontology: ${ontologyAdded} added, ${ontologyRemoved} removed`);
401
+ }
402
+ if (parts.length === 0) {
403
+ return "No changes";
404
+ }
405
+ return parts.join("; ");
406
+ }
407
+ function isBackwardsCompatible(diff) {
408
+ return !diff.hasBreakingChanges;
409
+ }
410
+ function getMigrationActions(diff) {
411
+ const actions = [];
412
+ for (const change of diff.nodes) {
413
+ if (change.type === "removed") {
414
+ actions.push(`DELETE data for removed node kind "${change.kind}"`);
415
+ }
416
+ if (change.severity === "breaking" && change.type === "modified") {
417
+ actions.push(
418
+ `MIGRATE data for node kind "${change.kind}": ${change.details}`
419
+ );
420
+ }
421
+ }
422
+ for (const change of diff.edges) {
423
+ if (change.type === "removed") {
424
+ actions.push(`DELETE data for removed edge kind "${change.kind}"`);
425
+ }
426
+ }
427
+ return actions;
428
+ }
429
+
430
+ // src/ontology/closures.ts
431
+ function computeTransitiveClosure(relations) {
432
+ const closure = /* @__PURE__ */ new Map();
433
+ const allNodes = /* @__PURE__ */ new Set();
434
+ for (const [from, to] of relations) {
435
+ allNodes.add(from);
436
+ allNodes.add(to);
437
+ }
438
+ for (const node of allNodes) {
439
+ closure.set(node, /* @__PURE__ */ new Set());
440
+ }
441
+ for (const [from, to] of relations) {
442
+ closure.get(from)?.add(to);
443
+ }
444
+ for (const k of allNodes) {
445
+ for (const index of allNodes) {
446
+ const indexReaches = closure.get(index);
447
+ if (!indexReaches?.has(k)) continue;
448
+ const kReaches = closure.get(k);
449
+ if (!kReaches) continue;
450
+ for (const index2 of kReaches) {
451
+ indexReaches.add(index2);
452
+ }
453
+ }
454
+ }
455
+ return closure;
456
+ }
457
+ function invertClosure(closure) {
458
+ const result = /* @__PURE__ */ new Map();
459
+ for (const [from, tos] of closure) {
460
+ for (const to of tos) {
461
+ const existing = result.get(to) ?? /* @__PURE__ */ new Set();
462
+ existing.add(from);
463
+ result.set(to, existing);
464
+ }
465
+ }
466
+ return result;
467
+ }
468
+ function isReachable(closure, source, target) {
469
+ return closure.get(source)?.has(target) ?? false;
470
+ }
471
+
472
+ // src/ontology/constants.ts
473
+ var META_EDGE_SUB_CLASS_OF = "subClassOf";
474
+ var META_EDGE_BROADER = "broader";
475
+ var META_EDGE_NARROWER = "narrower";
476
+ var META_EDGE_RELATED_TO = "relatedTo";
477
+ var META_EDGE_EQUIVALENT_TO = "equivalentTo";
478
+ var META_EDGE_SAME_AS = "sameAs";
479
+ var META_EDGE_DIFFERENT_FROM = "differentFrom";
480
+ var META_EDGE_DISJOINT_WITH = "disjointWith";
481
+ var META_EDGE_PART_OF = "partOf";
482
+ var META_EDGE_HAS_PART = "hasPart";
483
+ var META_EDGE_INVERSE_OF = "inverseOf";
484
+ var META_EDGE_IMPLIES = "implies";
485
+
486
+ // src/registry/kind-registry.ts
487
+ var KindRegistry = class {
488
+ // === Node & Edge Kinds ===
489
+ nodeKinds;
490
+ edgeKinds;
491
+ // === Subsumption (subClassOf) ===
492
+ // Transitive closure for inheritance
493
+ subClassAncestors;
494
+ subClassDescendants;
495
+ // === Hierarchy (broader/narrower) ===
496
+ // Transitive closure for concept hierarchy (separate from subClassOf!)
497
+ broaderClosure;
498
+ narrowerClosure;
499
+ // === Equivalence ===
500
+ equivalenceSets;
501
+ iriToKind;
502
+ // === Constraints ===
503
+ disjointPairs;
504
+ // Normalized pairs: "Organization|Person"
505
+ // === Composition ===
506
+ partOfClosure;
507
+ hasPartClosure;
508
+ // === Edge Relationships ===
509
+ edgeInverses;
510
+ edgeImplicationsClosure;
511
+ edgeImplyingClosure;
512
+ constructor(nodeKinds, edgeKinds, closures) {
513
+ this.nodeKinds = nodeKinds;
514
+ this.edgeKinds = edgeKinds;
515
+ this.subClassAncestors = closures.subClassAncestors;
516
+ this.subClassDescendants = closures.subClassDescendants;
517
+ this.broaderClosure = closures.broaderClosure;
518
+ this.narrowerClosure = closures.narrowerClosure;
519
+ this.equivalenceSets = closures.equivalenceSets;
520
+ this.iriToKind = closures.iriToKind;
521
+ this.disjointPairs = closures.disjointPairs;
522
+ this.partOfClosure = closures.partOfClosure;
523
+ this.hasPartClosure = closures.hasPartClosure;
524
+ this.edgeInverses = closures.edgeInverses;
525
+ this.edgeImplicationsClosure = closures.edgeImplicationsClosure;
526
+ this.edgeImplyingClosure = closures.edgeImplyingClosure;
527
+ }
528
+ // === Subsumption Methods ===
529
+ /**
530
+ * Checks if child is a subclass of parent (directly or transitively).
531
+ */
532
+ isSubClassOf(child, parent) {
533
+ return isReachable(this.subClassAncestors, child, parent);
534
+ }
535
+ /**
536
+ * Expands a kind to include all its subclasses.
537
+ * Returns [kind, ...subclasses].
538
+ */
539
+ expandSubClasses(kind) {
540
+ const descendants = this.subClassDescendants.get(kind) ?? /* @__PURE__ */ new Set();
541
+ return [kind, ...descendants];
542
+ }
543
+ /**
544
+ * Gets all ancestors of a kind (via subClassOf).
545
+ */
546
+ getAncestors(kind) {
547
+ return this.subClassAncestors.get(kind) ?? /* @__PURE__ */ new Set();
548
+ }
549
+ /**
550
+ * Gets all descendants of a kind (via subClassOf).
551
+ */
552
+ getDescendants(kind) {
553
+ return this.subClassDescendants.get(kind) ?? /* @__PURE__ */ new Set();
554
+ }
555
+ // === Hierarchy Methods ===
556
+ /**
557
+ * Checks if narrowerConcept is narrower than broaderConcept.
558
+ */
559
+ isNarrowerThan(narrowerConcept, broaderConcept) {
560
+ return isReachable(this.broaderClosure, narrowerConcept, broaderConcept);
561
+ }
562
+ /**
563
+ * Checks if broaderConcept is broader than narrowerConcept.
564
+ */
565
+ isBroaderThan(broaderConcept, narrowerConcept) {
566
+ return isReachable(this.narrowerClosure, broaderConcept, narrowerConcept);
567
+ }
568
+ /**
569
+ * Expands to include all narrower concepts.
570
+ */
571
+ expandNarrower(kind) {
572
+ const narrower = this.narrowerClosure.get(kind) ?? /* @__PURE__ */ new Set();
573
+ return [kind, ...narrower];
574
+ }
575
+ /**
576
+ * Expands to include all broader concepts.
577
+ */
578
+ expandBroader(kind) {
579
+ const broader = this.broaderClosure.get(kind) ?? /* @__PURE__ */ new Set();
580
+ return [kind, ...broader];
581
+ }
582
+ // === Equivalence Methods ===
583
+ /**
584
+ * Checks if two kinds are equivalent.
585
+ */
586
+ areEquivalent(a, b) {
587
+ const equivalents = this.equivalenceSets.get(a);
588
+ return equivalents?.has(b) ?? false;
589
+ }
590
+ /**
591
+ * Gets all equivalents of a kind (including external IRIs).
592
+ */
593
+ getEquivalents(kind) {
594
+ const equivalents = this.equivalenceSets.get(kind);
595
+ return equivalents ? [...equivalents] : [];
596
+ }
597
+ /**
598
+ * Resolves an external IRI to an internal kind name.
599
+ */
600
+ resolveIri(iri) {
601
+ return this.iriToKind.get(iri);
602
+ }
603
+ // === Constraint Methods ===
604
+ /**
605
+ * Checks if two kinds are disjoint.
606
+ */
607
+ areDisjoint(a, b) {
608
+ const normalizedPair = a < b ? `${a}|${b}` : `${b}|${a}`;
609
+ return this.disjointPairs.has(normalizedPair);
610
+ }
611
+ /**
612
+ * Gets all kinds that are disjoint with the given kind.
613
+ */
614
+ getDisjointKinds(kind) {
615
+ const result = [];
616
+ for (const pair of this.disjointPairs) {
617
+ const parts = pair.split("|");
618
+ const a = parts[0];
619
+ const b = parts[1];
620
+ if (a === kind) result.push(b);
621
+ else if (b === kind) result.push(a);
622
+ }
623
+ return result;
624
+ }
625
+ // === Composition Methods ===
626
+ /**
627
+ * Checks if part is part of whole (directly or transitively).
628
+ */
629
+ isPartOf(part, whole) {
630
+ return isReachable(this.partOfClosure, part, whole);
631
+ }
632
+ /**
633
+ * Gets all wholes that contain this part.
634
+ */
635
+ getWholes(part) {
636
+ const wholes = this.partOfClosure.get(part);
637
+ return wholes ? [...wholes] : [];
638
+ }
639
+ /**
640
+ * Gets all parts of this whole.
641
+ */
642
+ getParts(whole) {
643
+ const parts = this.hasPartClosure.get(whole);
644
+ return parts ? [...parts] : [];
645
+ }
646
+ // === Edge Relationship Methods ===
647
+ /**
648
+ * Gets the inverse edge kind for a given edge kind.
649
+ * If edgeA inverseOf edgeB, then getInverseEdge("edgeA") returns "edgeB".
650
+ */
651
+ getInverseEdge(edgeKind) {
652
+ return this.edgeInverses.get(edgeKind);
653
+ }
654
+ /**
655
+ * Gets all edges implied by a given edge (transitively).
656
+ * If A implies B and B implies C, then getImpliedEdges("A") returns ["B", "C"].
657
+ */
658
+ getImpliedEdges(edgeKind) {
659
+ const implied = this.edgeImplicationsClosure.get(edgeKind);
660
+ return implied ? [...implied] : [];
661
+ }
662
+ /**
663
+ * Gets all edges that imply a given edge (transitively).
664
+ * If A implies B and B implies C, then getImplyingEdges("C") returns ["A", "B"].
665
+ * Used for query-time expansion: when querying for C, also include A and B edges.
666
+ */
667
+ getImplyingEdges(edgeKind) {
668
+ const implying = this.edgeImplyingClosure.get(edgeKind);
669
+ return implying ? [...implying] : [];
670
+ }
671
+ /**
672
+ * Expands an edge kind to include all edges that imply it.
673
+ * Returns [edgeKind, ...implyingEdges].
674
+ */
675
+ expandImplyingEdges(edgeKind) {
676
+ const implying = this.edgeImplyingClosure.get(edgeKind) ?? /* @__PURE__ */ new Set();
677
+ return [edgeKind, ...implying];
678
+ }
679
+ // === Edge Endpoint Validation ===
680
+ /**
681
+ * Checks if a concrete kind is assignable to a target kind.
682
+ * Uses subsumption: Company is assignable to Organization if Company subClassOf Organization.
683
+ */
684
+ isAssignableTo(concreteKind, targetKind) {
685
+ if (concreteKind === targetKind) return true;
686
+ return this.isSubClassOf(concreteKind, targetKind);
687
+ }
688
+ /**
689
+ * Validates that a kind exists in the registry.
690
+ */
691
+ hasNodeType(name) {
692
+ return this.nodeKinds.has(name);
693
+ }
694
+ /**
695
+ * Validates that an edge kind exists in the registry.
696
+ */
697
+ hasEdgeType(name) {
698
+ return this.edgeKinds.has(name);
699
+ }
700
+ /**
701
+ * Gets a node kind by name.
702
+ */
703
+ getNodeType(name) {
704
+ return this.nodeKinds.get(name);
705
+ }
706
+ /**
707
+ * Gets an edge kind by name.
708
+ */
709
+ getEdgeType(name) {
710
+ return this.edgeKinds.get(name);
711
+ }
712
+ };
713
+ function createEmptyClosures() {
714
+ return {
715
+ subClassAncestors: /* @__PURE__ */ new Map(),
716
+ subClassDescendants: /* @__PURE__ */ new Map(),
717
+ broaderClosure: /* @__PURE__ */ new Map(),
718
+ narrowerClosure: /* @__PURE__ */ new Map(),
719
+ equivalenceSets: /* @__PURE__ */ new Map(),
720
+ iriToKind: /* @__PURE__ */ new Map(),
721
+ disjointPairs: /* @__PURE__ */ new Set(),
722
+ partOfClosure: /* @__PURE__ */ new Map(),
723
+ hasPartClosure: /* @__PURE__ */ new Map(),
724
+ edgeInverses: /* @__PURE__ */ new Map(),
725
+ edgeImplicationsClosure: /* @__PURE__ */ new Map(),
726
+ edgeImplyingClosure: /* @__PURE__ */ new Map()
727
+ };
728
+ }
729
+ function computeClosuresFromOntology(ontology) {
730
+ const subClassRelations = [];
731
+ const broaderRelations = [];
732
+ const equivalentRelations = [];
733
+ const disjointRelations = [];
734
+ const partOfRelations = [];
735
+ const inverseOfRelations = [];
736
+ const impliesRelations = [];
737
+ for (const relation of ontology) {
738
+ const fromName = getKindName(relation.from);
739
+ const toName = getKindName(relation.to);
740
+ switch (relation.metaEdge.name) {
741
+ case META_EDGE_SUB_CLASS_OF: {
742
+ subClassRelations.push([fromName, toName]);
743
+ break;
744
+ }
745
+ case META_EDGE_BROADER: {
746
+ broaderRelations.push([fromName, toName]);
747
+ break;
748
+ }
749
+ case META_EDGE_NARROWER: {
750
+ broaderRelations.push([toName, fromName]);
751
+ break;
752
+ }
753
+ case META_EDGE_EQUIVALENT_TO:
754
+ case META_EDGE_SAME_AS: {
755
+ equivalentRelations.push([fromName, toName]);
756
+ break;
757
+ }
758
+ case META_EDGE_DISJOINT_WITH: {
759
+ disjointRelations.push([fromName, toName]);
760
+ break;
761
+ }
762
+ case META_EDGE_PART_OF: {
763
+ partOfRelations.push([fromName, toName]);
764
+ break;
765
+ }
766
+ case META_EDGE_HAS_PART: {
767
+ partOfRelations.push([toName, fromName]);
768
+ break;
769
+ }
770
+ case META_EDGE_INVERSE_OF: {
771
+ inverseOfRelations.push([fromName, toName]);
772
+ break;
773
+ }
774
+ case META_EDGE_IMPLIES: {
775
+ impliesRelations.push([fromName, toName]);
776
+ break;
777
+ }
778
+ }
779
+ }
780
+ const subClassAncestors = computeTransitiveClosure(subClassRelations);
781
+ const subClassDescendants = invertClosure(subClassAncestors);
782
+ const broaderClosure = computeTransitiveClosure(broaderRelations);
783
+ const narrowerClosure = invertClosure(broaderClosure);
784
+ const equivalenceSets = computeEquivalenceSets(equivalentRelations);
785
+ const iriToKind = computeIriMapping(equivalentRelations);
786
+ const disjointPairs = computeDisjointPairs(disjointRelations);
787
+ const partOfClosure = computeTransitiveClosure(partOfRelations);
788
+ const hasPartClosure = invertClosure(partOfClosure);
789
+ const edgeInverses = computeEdgeInverses(inverseOfRelations);
790
+ const edgeImplicationsClosure = computeTransitiveClosure(impliesRelations);
791
+ const edgeImplyingClosure = invertClosure(edgeImplicationsClosure);
792
+ return {
793
+ subClassAncestors,
794
+ subClassDescendants,
795
+ broaderClosure,
796
+ narrowerClosure,
797
+ equivalenceSets,
798
+ iriToKind,
799
+ disjointPairs,
800
+ partOfClosure,
801
+ hasPartClosure,
802
+ edgeInverses,
803
+ edgeImplicationsClosure,
804
+ edgeImplyingClosure
805
+ };
806
+ }
807
+ function getKindName(kindOrIri) {
808
+ if (typeof kindOrIri === "string") {
809
+ return kindOrIri;
810
+ }
811
+ return kindOrIri.kind;
812
+ }
813
+ function isExternalIri(value) {
814
+ return value.startsWith("http://") || value.startsWith("https://");
815
+ }
816
+ function computeEquivalenceSets(relations) {
817
+ const parent = /* @__PURE__ */ new Map();
818
+ function find(x) {
819
+ if (!parent.has(x)) {
820
+ parent.set(x, x);
821
+ return x;
822
+ }
823
+ const p = parent.get(x);
824
+ if (p === x) return x;
825
+ const root = find(p);
826
+ parent.set(x, root);
827
+ return root;
828
+ }
829
+ function union(a, b) {
830
+ const rootA = find(a);
831
+ const rootB = find(b);
832
+ if (rootA !== rootB) {
833
+ parent.set(rootA, rootB);
834
+ }
835
+ }
836
+ for (const [a, b] of relations) {
837
+ union(a, b);
838
+ }
839
+ const classes = /* @__PURE__ */ new Map();
840
+ for (const key of parent.keys()) {
841
+ const root = find(key);
842
+ const existing = classes.get(root) ?? /* @__PURE__ */ new Set();
843
+ existing.add(key);
844
+ classes.set(root, existing);
845
+ }
846
+ const result = /* @__PURE__ */ new Map();
847
+ for (const members of classes.values()) {
848
+ for (const member of members) {
849
+ const others = new Set(members);
850
+ others.delete(member);
851
+ result.set(member, others);
852
+ }
853
+ }
854
+ return result;
855
+ }
856
+ function computeIriMapping(relations) {
857
+ const result = /* @__PURE__ */ new Map();
858
+ for (const [a, b] of relations) {
859
+ if (isExternalIri(a) && !isExternalIri(b)) {
860
+ result.set(a, b);
861
+ } else if (isExternalIri(b) && !isExternalIri(a)) {
862
+ result.set(b, a);
863
+ }
864
+ }
865
+ return result;
866
+ }
867
+ function computeDisjointPairs(relations) {
868
+ const result = /* @__PURE__ */ new Set();
869
+ for (const [a, b] of relations) {
870
+ const normalized = a < b ? `${a}|${b}` : `${b}|${a}`;
871
+ result.add(normalized);
872
+ }
873
+ return result;
874
+ }
875
+ function computeEdgeInverses(relations) {
876
+ const result = /* @__PURE__ */ new Map();
877
+ for (const [a, b] of relations) {
878
+ result.set(a, b);
879
+ result.set(b, a);
880
+ }
881
+ return result;
882
+ }
883
+
884
+ // src/schema/serializer.ts
885
+ function serializeSchema(graph, version) {
886
+ const nodes = serializeNodes(graph);
887
+ const edges = serializeEdges(graph);
888
+ const ontology = serializeOntology(graph.ontology);
889
+ return {
890
+ graphId: graph.id,
891
+ version,
892
+ generatedAt: chunkZJHQZZT2_cjs.nowIso(),
893
+ nodes,
894
+ edges,
895
+ ontology,
896
+ defaults: {
897
+ onNodeDelete: graph.defaults.onNodeDelete,
898
+ temporalMode: graph.defaults.temporalMode
899
+ }
900
+ };
901
+ }
902
+ function serializeNodes(graph) {
903
+ const result = {};
904
+ for (const kindName of chunkZJHQZZT2_cjs.getNodeKinds(graph)) {
905
+ const registration = graph.nodes[kindName];
906
+ if (registration === void 0) continue;
907
+ result[kindName] = serializeNodeDef(registration);
908
+ }
909
+ return result;
910
+ }
911
+ function serializeNodeDef(registration) {
912
+ const node = registration.type;
913
+ return {
914
+ kind: node.kind,
915
+ properties: serializeZodSchema(node.schema),
916
+ uniqueConstraints: serializeUniqueConstraints(registration.unique ?? []),
917
+ onDelete: registration.onDelete ?? "restrict",
918
+ description: node.description
919
+ };
920
+ }
921
+ function serializeUniqueConstraints(constraints) {
922
+ return constraints.map((constraint) => ({
923
+ name: constraint.name,
924
+ fields: [...constraint.fields],
925
+ where: constraint.where ? serializeWherePredicate(constraint.where) : void 0,
926
+ scope: constraint.scope,
927
+ collation: constraint.collation
928
+ }));
929
+ }
930
+ function serializeWherePredicate(whereFunction) {
931
+ const builder = new Proxy({}, {
932
+ get(_target, field) {
933
+ return {
934
+ isNull: () => ({
935
+ __type: "unique_predicate",
936
+ field,
937
+ op: "isNull"
938
+ }),
939
+ isNotNull: () => ({
940
+ __type: "unique_predicate",
941
+ field,
942
+ op: "isNotNull"
943
+ })
944
+ };
945
+ }
946
+ });
947
+ const predicate = whereFunction(builder);
948
+ return JSON.stringify({ field: predicate.field, op: predicate.op });
949
+ }
950
+ function deserializeWherePredicate(serialized) {
951
+ const parsed = JSON.parse(serialized);
952
+ return (builder) => {
953
+ const fieldBuilder = builder[parsed.field];
954
+ if (!fieldBuilder) {
955
+ throw new Error(`Unknown field in where predicate: ${parsed.field}`);
956
+ }
957
+ const result = parsed.op === "isNull" ? fieldBuilder.isNull() : fieldBuilder.isNotNull();
958
+ return {
959
+ __type: "unique_predicate",
960
+ field: result.field,
961
+ op: result.op
962
+ };
963
+ };
964
+ }
965
+ function serializeEdges(graph) {
966
+ const result = {};
967
+ for (const kindName of chunkZJHQZZT2_cjs.getEdgeKinds(graph)) {
968
+ const registration = graph.edges[kindName];
969
+ if (registration === void 0) continue;
970
+ result[kindName] = serializeEdgeDef(registration);
971
+ }
972
+ return result;
973
+ }
974
+ function serializeEdgeDef(registration) {
975
+ const edge = registration.type;
976
+ return {
977
+ kind: edge.kind,
978
+ fromKinds: registration.from.map((node) => node.kind),
979
+ toKinds: registration.to.map((node) => node.kind),
980
+ properties: serializeZodSchema(edge.schema),
981
+ cardinality: registration.cardinality ?? "many",
982
+ endpointExistence: registration.endpointExistence ?? "notDeleted",
983
+ description: edge.description
984
+ };
985
+ }
986
+ function serializeOntology(relations) {
987
+ const metaEdgeMap = /* @__PURE__ */ new Map();
988
+ for (const relation of relations) {
989
+ const metaEdge = relation.metaEdge;
990
+ if (!metaEdgeMap.has(metaEdge.name)) {
991
+ metaEdgeMap.set(metaEdge.name, metaEdge);
992
+ }
993
+ }
994
+ const metaEdges = {};
995
+ for (const [name, metaEdge] of metaEdgeMap) {
996
+ metaEdges[name] = serializeMetaEdge(metaEdge);
997
+ }
998
+ const serializedRelations = relations.map(
999
+ (relation) => serializeOntologyRelation(relation)
1000
+ );
1001
+ const closures = serializeClosures(relations);
1002
+ return {
1003
+ metaEdges,
1004
+ relations: serializedRelations,
1005
+ closures
1006
+ };
1007
+ }
1008
+ function serializeMetaEdge(metaEdge) {
1009
+ return {
1010
+ name: metaEdge.name,
1011
+ transitive: metaEdge.properties.transitive,
1012
+ symmetric: metaEdge.properties.symmetric,
1013
+ reflexive: metaEdge.properties.reflexive,
1014
+ inverse: metaEdge.properties.inverse,
1015
+ inference: metaEdge.properties.inference,
1016
+ description: metaEdge.properties.description
1017
+ };
1018
+ }
1019
+ function serializeOntologyRelation(relation) {
1020
+ return {
1021
+ metaEdge: relation.metaEdge.name,
1022
+ from: getTypeName(relation.from),
1023
+ to: getTypeName(relation.to)
1024
+ };
1025
+ }
1026
+ function serializeClosures(relations) {
1027
+ if (relations.length === 0) {
1028
+ return {
1029
+ subClassAncestors: {},
1030
+ subClassDescendants: {},
1031
+ broaderClosure: {},
1032
+ narrowerClosure: {},
1033
+ equivalenceSets: {},
1034
+ disjointPairs: [],
1035
+ partOfClosure: {},
1036
+ hasPartClosure: {},
1037
+ iriToKind: {},
1038
+ edgeInverses: {},
1039
+ edgeImplicationsClosure: {},
1040
+ edgeImplyingClosure: {}
1041
+ };
1042
+ }
1043
+ const computed = computeClosuresFromOntology(relations);
1044
+ return {
1045
+ subClassAncestors: mapToRecord(computed.subClassAncestors),
1046
+ subClassDescendants: mapToRecord(computed.subClassDescendants),
1047
+ broaderClosure: mapToRecord(computed.broaderClosure),
1048
+ narrowerClosure: mapToRecord(computed.narrowerClosure),
1049
+ equivalenceSets: mapToRecord(computed.equivalenceSets),
1050
+ disjointPairs: [...computed.disjointPairs],
1051
+ partOfClosure: mapToRecord(computed.partOfClosure),
1052
+ hasPartClosure: mapToRecord(computed.hasPartClosure),
1053
+ iriToKind: mapToSimpleRecord(computed.iriToKind),
1054
+ edgeInverses: mapToSimpleRecord(computed.edgeInverses),
1055
+ edgeImplicationsClosure: mapToRecord(computed.edgeImplicationsClosure),
1056
+ edgeImplyingClosure: mapToRecord(computed.edgeImplyingClosure)
1057
+ };
1058
+ }
1059
+ function mapToRecord(map) {
1060
+ const result = {};
1061
+ for (const [key, values] of map) {
1062
+ result[key] = [...values];
1063
+ }
1064
+ return result;
1065
+ }
1066
+ function mapToSimpleRecord(map) {
1067
+ const result = {};
1068
+ for (const [key, value] of map) {
1069
+ result[key] = value;
1070
+ }
1071
+ return result;
1072
+ }
1073
+ function serializeZodSchema(schema) {
1074
+ try {
1075
+ const jsonSchema = zod.z.toJSONSchema(schema);
1076
+ return jsonSchema;
1077
+ } catch {
1078
+ return { type: "object" };
1079
+ }
1080
+ }
1081
+ async function computeSchemaHash(schema) {
1082
+ const hashable = {
1083
+ graphId: schema.graphId,
1084
+ nodes: schema.nodes,
1085
+ edges: schema.edges,
1086
+ ontology: schema.ontology,
1087
+ defaults: schema.defaults
1088
+ };
1089
+ const json = JSON.stringify(hashable, sortedReplacer);
1090
+ return sha256Hash(json);
1091
+ }
1092
+ function sortedReplacer(_key, value) {
1093
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
1094
+ const sorted = {};
1095
+ for (const key of Object.keys(value).toSorted()) {
1096
+ sorted[key] = value[key];
1097
+ }
1098
+ return sorted;
1099
+ }
1100
+ return value;
1101
+ }
1102
+ async function sha256Hash(input) {
1103
+ const encoded = new TextEncoder().encode(input);
1104
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", encoded);
1105
+ const bytes = new Uint8Array(digest);
1106
+ let hex = "";
1107
+ for (let index = 0; index < 8; index++) {
1108
+ const byte = bytes[index];
1109
+ if (byte === void 0) break;
1110
+ hex += byte.toString(16).padStart(2, "0");
1111
+ }
1112
+ return hex;
1113
+ }
1114
+
1115
+ // src/schema/manager.ts
1116
+ async function ensureSchema(backend, graph, options) {
1117
+ const autoMigrate = options?.autoMigrate ?? true;
1118
+ const throwOnBreaking = options?.throwOnBreaking ?? true;
1119
+ const activeSchema = await backend.getActiveSchema(graph.id);
1120
+ if (!activeSchema) {
1121
+ const result = await initializeSchema(backend, graph);
1122
+ return { status: "initialized", version: result.version };
1123
+ }
1124
+ const storedSchema = JSON.parse(activeSchema.schema_doc);
1125
+ const currentSchema = serializeSchema(graph, activeSchema.version + 1);
1126
+ const storedHash = activeSchema.schema_hash;
1127
+ const currentHash = await computeSchemaHash(currentSchema);
1128
+ if (storedHash === currentHash) {
1129
+ return { status: "unchanged", version: activeSchema.version };
1130
+ }
1131
+ const diff = computeSchemaDiff(storedSchema, currentSchema);
1132
+ if (!diff.hasChanges) {
1133
+ return { status: "unchanged", version: activeSchema.version };
1134
+ }
1135
+ if (isBackwardsCompatible(diff)) {
1136
+ if (autoMigrate) {
1137
+ const hookContext = {
1138
+ graphId: graph.id,
1139
+ fromVersion: activeSchema.version,
1140
+ toVersion: activeSchema.version + 1,
1141
+ diff
1142
+ };
1143
+ await options?.onBeforeMigrate?.(hookContext);
1144
+ const newVersion = await migrateSchema(
1145
+ backend,
1146
+ graph,
1147
+ activeSchema.version
1148
+ );
1149
+ await options?.onAfterMigrate?.(hookContext);
1150
+ return {
1151
+ status: "migrated",
1152
+ fromVersion: activeSchema.version,
1153
+ toVersion: newVersion,
1154
+ diff
1155
+ };
1156
+ }
1157
+ return {
1158
+ status: "pending",
1159
+ version: activeSchema.version,
1160
+ diff
1161
+ };
1162
+ }
1163
+ const actions = getMigrationActions(diff);
1164
+ if (throwOnBreaking) {
1165
+ throw new chunkOYL2SGBD_cjs.MigrationError(
1166
+ `Schema migration required: ${diff.summary}. ${actions.length} migration action(s) needed. Use getSchemaChanges() to review, then migrateSchema() to apply.`,
1167
+ {
1168
+ graphId: graph.id,
1169
+ fromVersion: activeSchema.version,
1170
+ toVersion: activeSchema.version + 1
1171
+ }
1172
+ );
1173
+ }
1174
+ return { status: "breaking", diff, actions };
1175
+ }
1176
+ async function initializeSchema(backend, graph) {
1177
+ const schema = serializeSchema(graph, 1);
1178
+ const hash = await computeSchemaHash(schema);
1179
+ return backend.insertSchema({
1180
+ graphId: graph.id,
1181
+ version: 1,
1182
+ schemaHash: hash,
1183
+ schemaDoc: schema,
1184
+ isActive: true
1185
+ });
1186
+ }
1187
+ async function migrateSchema(backend, graph, currentVersion) {
1188
+ const newVersion = currentVersion + 1;
1189
+ const schema = serializeSchema(graph, newVersion);
1190
+ const hash = await computeSchemaHash(schema);
1191
+ await backend.insertSchema({
1192
+ graphId: graph.id,
1193
+ version: newVersion,
1194
+ schemaHash: hash,
1195
+ schemaDoc: schema,
1196
+ isActive: false
1197
+ });
1198
+ await backend.setActiveSchema(graph.id, newVersion);
1199
+ return newVersion;
1200
+ }
1201
+ async function rollbackSchema(backend, graphId, targetVersion) {
1202
+ const row = await backend.getSchemaVersion(graphId, targetVersion);
1203
+ if (!row) {
1204
+ throw new chunkOYL2SGBD_cjs.MigrationError(
1205
+ `Cannot rollback to version ${targetVersion}: version does not exist.`,
1206
+ { graphId, fromVersion: targetVersion, toVersion: targetVersion }
1207
+ );
1208
+ }
1209
+ await backend.setActiveSchema(graphId, targetVersion);
1210
+ }
1211
+ async function getActiveSchema(backend, graphId) {
1212
+ const row = await backend.getActiveSchema(graphId);
1213
+ if (!row) return void 0;
1214
+ return JSON.parse(row.schema_doc);
1215
+ }
1216
+ async function isSchemaInitialized(backend, graphId) {
1217
+ const row = await backend.getActiveSchema(graphId);
1218
+ return row !== void 0;
1219
+ }
1220
+ async function getSchemaChanges(backend, graph) {
1221
+ const activeSchema = await backend.getActiveSchema(graph.id);
1222
+ if (!activeSchema) return void 0;
1223
+ const storedSchema = JSON.parse(activeSchema.schema_doc);
1224
+ const currentSchema = serializeSchema(graph, activeSchema.version + 1);
1225
+ return computeSchemaDiff(storedSchema, currentSchema);
1226
+ }
1227
+
1228
+ exports.KindRegistry = KindRegistry;
1229
+ exports.META_EDGE_BRAND = META_EDGE_BRAND;
1230
+ exports.META_EDGE_BROADER = META_EDGE_BROADER;
1231
+ exports.META_EDGE_DIFFERENT_FROM = META_EDGE_DIFFERENT_FROM;
1232
+ exports.META_EDGE_DISJOINT_WITH = META_EDGE_DISJOINT_WITH;
1233
+ exports.META_EDGE_EQUIVALENT_TO = META_EDGE_EQUIVALENT_TO;
1234
+ exports.META_EDGE_HAS_PART = META_EDGE_HAS_PART;
1235
+ exports.META_EDGE_IMPLIES = META_EDGE_IMPLIES;
1236
+ exports.META_EDGE_INVERSE_OF = META_EDGE_INVERSE_OF;
1237
+ exports.META_EDGE_NARROWER = META_EDGE_NARROWER;
1238
+ exports.META_EDGE_PART_OF = META_EDGE_PART_OF;
1239
+ exports.META_EDGE_RELATED_TO = META_EDGE_RELATED_TO;
1240
+ exports.META_EDGE_SAME_AS = META_EDGE_SAME_AS;
1241
+ exports.META_EDGE_SUB_CLASS_OF = META_EDGE_SUB_CLASS_OF;
1242
+ exports.computeClosuresFromOntology = computeClosuresFromOntology;
1243
+ exports.computeSchemaDiff = computeSchemaDiff;
1244
+ exports.computeSchemaHash = computeSchemaHash;
1245
+ exports.createEmptyClosures = createEmptyClosures;
1246
+ exports.createValidationError = createValidationError;
1247
+ exports.deserializeWherePredicate = deserializeWherePredicate;
1248
+ exports.ensureSchema = ensureSchema;
1249
+ exports.getActiveSchema = getActiveSchema;
1250
+ exports.getMigrationActions = getMigrationActions;
1251
+ exports.getSchemaChanges = getSchemaChanges;
1252
+ exports.initializeSchema = initializeSchema;
1253
+ exports.isBackwardsCompatible = isBackwardsCompatible;
1254
+ exports.isMetaEdge = isMetaEdge;
1255
+ exports.isSchemaInitialized = isSchemaInitialized;
1256
+ exports.migrateSchema = migrateSchema;
1257
+ exports.rollbackSchema = rollbackSchema;
1258
+ exports.serializeSchema = serializeSchema;
1259
+ exports.validateEdgeProps = validateEdgeProps;
1260
+ exports.validateNodeProps = validateNodeProps;
1261
+ exports.validateProps = validateProps;
1262
+ exports.wrapZodError = wrapZodError;
1263
+ //# sourceMappingURL=chunk-DD6ONEBN.cjs.map
1264
+ //# sourceMappingURL=chunk-DD6ONEBN.cjs.map