@nicia-ai/typegraph 0.12.0 → 0.14.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 (67) hide show
  1. package/dist/backend/postgres/index.cjs +28 -28
  2. package/dist/backend/postgres/index.d.cts +1 -1
  3. package/dist/backend/postgres/index.d.ts +1 -1
  4. package/dist/backend/postgres/index.js +4 -4
  5. package/dist/backend/sqlite/index.cjs +14 -14
  6. package/dist/backend/sqlite/index.d.cts +1 -1
  7. package/dist/backend/sqlite/index.d.ts +1 -1
  8. package/dist/backend/sqlite/index.js +4 -4
  9. package/dist/backend/sqlite/local.cjs +7 -7
  10. package/dist/backend/sqlite/local.d.cts +1 -1
  11. package/dist/backend/sqlite/local.d.ts +1 -1
  12. package/dist/backend/sqlite/local.js +4 -4
  13. package/dist/{chunk-U3452TEU.js → chunk-6GWJH6AR.js} +15 -27
  14. package/dist/chunk-6GWJH6AR.js.map +1 -0
  15. package/dist/{chunk-52WSY6G5.js → chunk-BNIBR5U2.js} +70 -31
  16. package/dist/chunk-BNIBR5U2.js.map +1 -0
  17. package/dist/{chunk-54WJF3DW.js → chunk-GNIYZKBI.js} +29 -3
  18. package/dist/chunk-GNIYZKBI.js.map +1 -0
  19. package/dist/{chunk-2XPKLHHH.cjs → chunk-KE2BL3JZ.cjs} +74 -35
  20. package/dist/chunk-KE2BL3JZ.cjs.map +1 -0
  21. package/dist/{chunk-PYV4ADC6.js → chunk-KLOSTZDQ.js} +141 -13
  22. package/dist/chunk-KLOSTZDQ.js.map +1 -0
  23. package/dist/{chunk-JQDWEX6V.cjs → chunk-LELLOHJK.cjs} +22 -34
  24. package/dist/chunk-LELLOHJK.cjs.map +1 -0
  25. package/dist/{chunk-2WVFEIHR.cjs → chunk-MME3H4ZF.cjs} +40 -2
  26. package/dist/chunk-MME3H4ZF.cjs.map +1 -0
  27. package/dist/{chunk-NZMKJHE2.cjs → chunk-OEKH5PWL.cjs} +15 -15
  28. package/dist/{chunk-NZMKJHE2.cjs.map → chunk-OEKH5PWL.cjs.map} +1 -1
  29. package/dist/{chunk-7VITUTRA.cjs → chunk-QFZ5QB2J.cjs} +140 -12
  30. package/dist/chunk-QFZ5QB2J.cjs.map +1 -0
  31. package/dist/{chunk-J4SICP3X.js → chunk-RVUEBUBH.js} +3 -3
  32. package/dist/{chunk-J4SICP3X.js.map → chunk-RVUEBUBH.js.map} +1 -1
  33. package/dist/index.cjs +483 -597
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +12 -9
  36. package/dist/index.d.ts +12 -9
  37. package/dist/index.js +445 -559
  38. package/dist/index.js.map +1 -1
  39. package/dist/indexes/index.cjs +16 -16
  40. package/dist/indexes/index.js +2 -2
  41. package/dist/interchange/index.d.cts +3 -3
  42. package/dist/interchange/index.d.ts +3 -3
  43. package/dist/{manager-DGSnJa1v.d.cts → manager-oh2mTMvy.d.cts} +1 -1
  44. package/dist/{manager-BCLhWysp.d.ts → manager-qRSdnKEO.d.ts} +1 -1
  45. package/dist/profiler/index.cjs +6 -6
  46. package/dist/profiler/index.cjs.map +1 -1
  47. package/dist/profiler/index.d.cts +3 -3
  48. package/dist/profiler/index.d.ts +3 -3
  49. package/dist/profiler/index.js +6 -6
  50. package/dist/profiler/index.js.map +1 -1
  51. package/dist/schema/index.cjs +20 -20
  52. package/dist/schema/index.d.cts +4 -4
  53. package/dist/schema/index.d.ts +4 -4
  54. package/dist/schema/index.js +2 -2
  55. package/dist/{store-BcnA11lH.d.ts → store-B9ItxA-Q.d.ts} +56 -17
  56. package/dist/{store-NEa4EFFD.d.cts → store-BJPIoe8u.d.cts} +56 -17
  57. package/dist/{types-1YJKodRv.d.ts → types-5t_MIcvv.d.ts} +12 -6
  58. package/dist/{types-GLkwvQvS.d.cts → types-Ckfwgv9l.d.cts} +12 -6
  59. package/package.json +1 -1
  60. package/dist/chunk-2WVFEIHR.cjs.map +0 -1
  61. package/dist/chunk-2XPKLHHH.cjs.map +0 -1
  62. package/dist/chunk-52WSY6G5.js.map +0 -1
  63. package/dist/chunk-54WJF3DW.js.map +0 -1
  64. package/dist/chunk-7VITUTRA.cjs.map +0 -1
  65. package/dist/chunk-JQDWEX6V.cjs.map +0 -1
  66. package/dist/chunk-PYV4ADC6.js.map +0 -1
  67. package/dist/chunk-U3452TEU.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,18 +1,68 @@
1
- import { META_EDGE_BRAND, META_EDGE_SUB_CLASS_OF, META_EDGE_NARROWER, META_EDGE_BROADER, META_EDGE_RELATED_TO, META_EDGE_EQUIVALENT_TO, META_EDGE_SAME_AS, META_EDGE_DIFFERENT_FROM, META_EDGE_DISJOINT_WITH, META_EDGE_HAS_PART, META_EDGE_PART_OF, META_EDGE_INVERSE_OF, META_EDGE_IMPLIES, ensureSchema, computeClosuresFromOntology, createEmptyClosures, KindRegistry, validateNodeProps, validateEdgeProps } from './chunk-PYV4ADC6.js';
2
- export { isMetaEdge } from './chunk-PYV4ADC6.js';
1
+ import { META_EDGE_BRAND, META_EDGE_SUB_CLASS_OF, META_EDGE_NARROWER, META_EDGE_BROADER, META_EDGE_RELATED_TO, META_EDGE_EQUIVALENT_TO, META_EDGE_SAME_AS, META_EDGE_DIFFERENT_FROM, META_EDGE_DISJOINT_WITH, META_EDGE_HAS_PART, META_EDGE_PART_OF, META_EDGE_INVERSE_OF, META_EDGE_IMPLIES, ensureSchema, computeClosuresFromOntology, createEmptyClosures, KindRegistry, validateNodeProps, validateEdgeProps } from './chunk-KLOSTZDQ.js';
2
+ export { isMetaEdge } from './chunk-KLOSTZDQ.js';
3
3
  import { NODE_TYPE_BRAND, EDGE_TYPE_BRAND, nowIso, validateOptionalIsoDate, getNodeKinds, getEdgeKinds } from './chunk-IRFD3MEU.js';
4
4
  export { defineGraph, getEdgeKinds, getNodeKinds, isEdgeType, isEdgeTypeWithEndpoints, isGraphDef, isNodeType } from './chunk-IRFD3MEU.js';
5
- import { ConfigurationError, UnsupportedPredicateError, ValidationError, CompilerInvariantError, KindNotFoundError, RestrictedDeleteError, NodeNotFoundError, DatabaseOperationError, EdgeNotFoundError, NodeConstraintNotFoundError, UniquenessError, EndpointNotFoundError, CardinalityError, EndpointError, DisjointError } from './chunk-SJ2QMDXY.js';
5
+ import { ConfigurationError, UnsupportedPredicateError, ValidationError, CompilerInvariantError, KindNotFoundError, DatabaseOperationError, EdgeNotFoundError, NodeConstraintNotFoundError, RestrictedDeleteError, NodeNotFoundError, EndpointNotFoundError, UniquenessError, CardinalityError, EndpointError, DisjointError } from './chunk-SJ2QMDXY.js';
6
6
  export { CardinalityError, CompilerInvariantError, ConfigurationError, DatabaseOperationError, DisjointError, EdgeNotFoundError, EndpointError, EndpointNotFoundError, KindNotFoundError, MigrationError, NodeConstraintNotFoundError, NodeNotFoundError, RestrictedDeleteError, SchemaMismatchError, TypeGraphError, UniquenessError, UnsupportedPredicateError, ValidationError, VersionConflictError, getErrorSuggestion, isConstraintError, isSystemError, isTypeGraphError, isUserRecoverable } from './chunk-SJ2QMDXY.js';
7
- import { getDialect, NODE_META_KEYS, EDGE_META_KEYS } from './chunk-54WJF3DW.js';
7
+ import { MAX_PG_IDENTIFIER_LENGTH, DEFAULT_PAGINATION_LIMIT, getDialect, DEFAULT_STREAM_BATCH_SIZE, NODE_META_KEYS, EDGE_META_KEYS, SQLITE_PATH_DELIMITER, PG_ARRAY_START, PG_ARRAY_END, PG_PATH_ELEMENT_SEPARATOR, fnv1aBase36 } from './chunk-GNIYZKBI.js';
8
8
  import { jsonPointer, parseJsonPointer, createSchemaIntrospector, normalizeJsonPointer, joinJsonPointers, resolveFieldTypeInfoAtJsonPointer, getEmbeddingDimensions, isEmbeddingSchema } from './chunk-K7SQ3SWP.js';
9
9
  export { MAX_JSON_POINTER_DEPTH, embedding, getEmbeddingDimensions, isEmbeddingSchema, joinJsonPointers, jsonPointer, normalizeJsonPointer, parseJsonPointer } from './chunk-K7SQ3SWP.js';
10
10
  import { z } from 'zod';
11
11
  import { sql, Placeholder } from 'drizzle-orm';
12
12
  import { nanoid } from 'nanoid';
13
13
 
14
+ // src/store/reserved-keys.ts
15
+ var RESERVED_NODE_KEYS = /* @__PURE__ */ new Set([
16
+ "id",
17
+ "kind",
18
+ "meta"
19
+ ]);
20
+ var RESERVED_EDGE_KEYS = /* @__PURE__ */ new Set([
21
+ "id",
22
+ "kind",
23
+ "meta",
24
+ "fromKind",
25
+ "fromId",
26
+ "toKind",
27
+ "toId"
28
+ ]);
29
+ var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set([
30
+ "__proto__",
31
+ "constructor",
32
+ "prototype"
33
+ ]);
34
+ function validateProjectionField(field2, entityType, kind) {
35
+ const reserved = entityType === "node" ? RESERVED_NODE_KEYS : RESERVED_EDGE_KEYS;
36
+ if (reserved.has(field2)) {
37
+ throw new ConfigurationError(
38
+ `Projection field "${field2}" on ${entityType} kind "${kind}" conflicts with a reserved structural key`,
39
+ { field: field2, kind, entityType, reservedKeys: [...reserved] },
40
+ {
41
+ suggestion: `Remove "${field2}" from the projection. Structural fields (${[...reserved].join(", ")}) are included automatically when relevant.`
42
+ }
43
+ );
44
+ }
45
+ if (PROTOTYPE_POLLUTION_KEYS.has(field2)) {
46
+ throw new ConfigurationError(
47
+ `Projection field "${field2}" on ${entityType} kind "${kind}" is not allowed`,
48
+ { field: field2, kind, entityType },
49
+ {
50
+ suggestion: `"${field2}" cannot be used as a projection field name.`
51
+ }
52
+ );
53
+ }
54
+ }
55
+ function filterReservedKeys(props, reservedKeys) {
56
+ const filtered = {};
57
+ for (const [key, value] of Object.entries(props)) {
58
+ if (!reservedKeys.has(key)) {
59
+ filtered[key] = value;
60
+ }
61
+ }
62
+ return filtered;
63
+ }
64
+
14
65
  // src/core/node.ts
15
- var RESERVED_NODE_KEYS = /* @__PURE__ */ new Set(["id", "kind", "meta"]);
16
66
  function validateSchemaKeys(schema, name) {
17
67
  const shape = schema.shape;
18
68
  const conflicts = Object.keys(shape).filter(
@@ -37,15 +87,6 @@ function defineNode(name, options) {
37
87
  description: options.description
38
88
  });
39
89
  }
40
- var RESERVED_EDGE_KEYS = /* @__PURE__ */ new Set([
41
- "id",
42
- "kind",
43
- "meta",
44
- "fromKind",
45
- "fromId",
46
- "toKind",
47
- "toId"
48
- ]);
49
90
  var EMPTY_SCHEMA = z.object({});
50
91
  function validateSchemaKeys2(schema, name) {
51
92
  const shape = schema.shape;
@@ -1376,14 +1417,14 @@ function extractVectorSimilarityPredicates(predicates) {
1376
1417
  break;
1377
1418
  }
1378
1419
  case "and": {
1379
- for (const p of expr.predicates) {
1380
- visit(p, inDisallowedBranch);
1420
+ for (const predicate2 of expr.predicates) {
1421
+ visit(predicate2, inDisallowedBranch);
1381
1422
  }
1382
1423
  break;
1383
1424
  }
1384
1425
  case "or": {
1385
- for (const p of expr.predicates) {
1386
- visit(p, true);
1426
+ for (const predicate2 of expr.predicates) {
1427
+ visit(predicate2, true);
1387
1428
  }
1388
1429
  break;
1389
1430
  }
@@ -2406,6 +2447,9 @@ function compileTemporalFilter(options) {
2406
2447
  return sql`${deletedAt} IS NULL AND (${validFrom} IS NULL OR ${validFrom} <= ${now}) AND (${validTo} IS NULL OR ${validTo} > ${now})`;
2407
2448
  }
2408
2449
  case "asOf": {
2450
+ if (asOf === void 0) {
2451
+ throw new Error(`asOf timestamp is required for temporal mode "asOf"`);
2452
+ }
2409
2453
  const timestamp = asOf;
2410
2454
  return sql`${deletedAt} IS NULL AND (${validFrom} IS NULL OR ${validFrom} <= ${timestamp}) AND (${validTo} IS NULL OR ${validTo} > ${timestamp})`;
2411
2455
  }
@@ -2813,7 +2857,7 @@ function lowerSetOperationToLogicalPlan(input) {
2813
2857
  }
2814
2858
 
2815
2859
  // src/query/compiler/recursive.ts
2816
- var MAX_RECURSIVE_DEPTH = 100;
2860
+ var MAX_RECURSIVE_DEPTH = 10;
2817
2861
  var MAX_EXPLICIT_RECURSIVE_DEPTH = 1e3;
2818
2862
  var NO_ALWAYS_REQUIRED_COLUMNS = /* @__PURE__ */ new Set();
2819
2863
  function runRecursiveQueryPassPipeline(ast, graphId, ctx) {
@@ -3306,15 +3350,14 @@ var DEFAULT_TABLE_NAMES = {
3306
3350
  edges: "typegraph_edges",
3307
3351
  embeddings: "typegraph_node_embeddings"
3308
3352
  };
3309
- var MAX_IDENTIFIER_LENGTH = 63;
3310
3353
  var VALID_IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_$]*$/i;
3311
3354
  function validateTableName(name, label) {
3312
3355
  if (!name || name.length === 0) {
3313
3356
  throw new ConfigurationError(`${label} table name cannot be empty`);
3314
3357
  }
3315
- if (name.length > MAX_IDENTIFIER_LENGTH) {
3358
+ if (name.length > MAX_PG_IDENTIFIER_LENGTH) {
3316
3359
  throw new ConfigurationError(
3317
- `${label} table name exceeds maximum length of ${MAX_IDENTIFIER_LENGTH} characters`
3360
+ `${label} table name exceeds maximum length of ${MAX_PG_IDENTIFIER_LENGTH} characters`
3318
3361
  );
3319
3362
  }
3320
3363
  if (!VALID_IDENTIFIER_PATTERN.test(name)) {
@@ -3397,64 +3440,13 @@ function decodeByValueType(value, valueType) {
3397
3440
  }
3398
3441
  }
3399
3442
 
3400
- // src/store/reserved-keys.ts
3401
- var RESERVED_NODE_KEYS2 = /* @__PURE__ */ new Set([
3402
- "id",
3403
- "kind",
3404
- "meta"
3405
- ]);
3406
- var RESERVED_EDGE_KEYS2 = /* @__PURE__ */ new Set([
3407
- "id",
3408
- "kind",
3409
- "meta",
3410
- "fromKind",
3411
- "fromId",
3412
- "toKind",
3413
- "toId"
3414
- ]);
3415
- var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set([
3416
- "__proto__",
3417
- "constructor",
3418
- "prototype"
3419
- ]);
3420
- function validateProjectionField(field2, entityType, kind) {
3421
- const reserved = entityType === "node" ? RESERVED_NODE_KEYS2 : RESERVED_EDGE_KEYS2;
3422
- if (reserved.has(field2)) {
3423
- throw new ConfigurationError(
3424
- `Projection field "${field2}" on ${entityType} kind "${kind}" conflicts with a reserved structural key`,
3425
- { field: field2, kind, entityType, reservedKeys: [...reserved] },
3426
- {
3427
- suggestion: `Remove "${field2}" from the projection. Structural fields (${[...reserved].join(", ")}) are included automatically when relevant.`
3428
- }
3429
- );
3430
- }
3431
- if (PROTOTYPE_POLLUTION_KEYS.has(field2)) {
3432
- throw new ConfigurationError(
3433
- `Projection field "${field2}" on ${entityType} kind "${kind}" is not allowed`,
3434
- { field: field2, kind, entityType },
3435
- {
3436
- suggestion: `"${field2}" cannot be used as a projection field name.`
3437
- }
3438
- );
3439
- }
3440
- }
3441
- function filterReservedKeys(props, reservedKeys) {
3442
- const filtered = {};
3443
- for (const [key, value] of Object.entries(props)) {
3444
- if (!reservedKeys.has(key)) {
3445
- filtered[key] = value;
3446
- }
3447
- }
3448
- return filtered;
3449
- }
3450
-
3451
3443
  // src/store/row-mappers.ts
3452
3444
  function nullToUndefined2(value) {
3453
3445
  return value === null ? void 0 : value;
3454
3446
  }
3455
3447
  function rowToNode(row) {
3456
3448
  const rawProps = JSON.parse(row.props);
3457
- const props = filterReservedKeys(rawProps, RESERVED_NODE_KEYS2);
3449
+ const props = filterReservedKeys(rawProps, RESERVED_NODE_KEYS);
3458
3450
  return {
3459
3451
  kind: row.kind,
3460
3452
  id: row.id,
@@ -3474,7 +3466,7 @@ function rowToNodeMeta(row) {
3474
3466
  }
3475
3467
  function rowToEdge(row) {
3476
3468
  const rawProps = JSON.parse(row.props);
3477
- const props = filterReservedKeys(rawProps, RESERVED_EDGE_KEYS2);
3469
+ const props = filterReservedKeys(rawProps, RESERVED_EDGE_KEYS);
3478
3470
  return {
3479
3471
  id: row.id,
3480
3472
  kind: row.kind,
@@ -3498,17 +3490,6 @@ function rowToEdgeMeta(row) {
3498
3490
 
3499
3491
  // src/store/subgraph.ts
3500
3492
  var DEFAULT_SUBGRAPH_MAX_DEPTH = 10;
3501
- var MAX_PG_IDENTIFIER_LENGTH = 63;
3502
- function fnv1aBase36(input) {
3503
- let hash = 2166136261;
3504
- for (const character of input) {
3505
- const codePoint = character.codePointAt(0);
3506
- if (codePoint === void 0) continue;
3507
- hash ^= codePoint;
3508
- hash = Math.imul(hash, 16777619);
3509
- }
3510
- return (hash >>> 0).toString(36);
3511
- }
3512
3493
  var TEXT_ENCODER = new TextEncoder();
3513
3494
  function truncateToBytes(value, maxBytes) {
3514
3495
  const encoded = TEXT_ENCODER.encode(value);
@@ -3540,7 +3521,7 @@ async function executeSubgraph(params) {
3540
3521
  }
3541
3522
  const maxDepth = Math.min(
3542
3523
  options.maxDepth ?? DEFAULT_SUBGRAPH_MAX_DEPTH,
3543
- MAX_RECURSIVE_DEPTH
3524
+ MAX_EXPLICIT_RECURSIVE_DEPTH
3544
3525
  );
3545
3526
  const ctx = {
3546
3527
  graphId: params.graphId,
@@ -4224,6 +4205,7 @@ function compileFieldColumnForSetOp(field2, prefix, dialect) {
4224
4205
  updated_at: "_updated_at",
4225
4206
  deleted_at: "_deleted_at"
4226
4207
  };
4208
+ if (columnName === void 0) return sql.raw(`${cteName}.${alias}_props`);
4227
4209
  const suffix = columnMap[columnName];
4228
4210
  if (suffix) {
4229
4211
  return sql.raw(`${cteName}.${alias}${suffix}`);
@@ -4302,18 +4284,18 @@ function buildSetOperationSuffixClauses(op, dialect) {
4302
4284
  );
4303
4285
  }
4304
4286
  const orderParts = [];
4305
- for (const o of op.orderBy) {
4306
- const projected = matchFieldToProjection(o.field, projection);
4287
+ for (const orderSpec of op.orderBy) {
4288
+ const projected = matchFieldToProjection(orderSpec.field, projection);
4307
4289
  if (!projected) {
4308
- const fieldDesc = o.field.jsonPointer ? `${o.field.alias}.props${o.field.jsonPointer}` : `${o.field.alias}.${o.field.path.join(".")}`;
4290
+ const fieldDesc = orderSpec.field.jsonPointer ? `${orderSpec.field.alias}.props${orderSpec.field.jsonPointer}` : `${orderSpec.field.alias}.${orderSpec.field.path.join(".")}`;
4309
4291
  const availableFields = projection.fields.map((f) => f.outputName).join(", ");
4310
4292
  throw new UnsupportedPredicateError(
4311
4293
  `Set operation ORDER BY field "${fieldDesc}" is not in the projection. ORDER BY for UNION/INTERSECT/EXCEPT must reference projected columns. Available columns: ${availableFields}`
4312
4294
  );
4313
4295
  }
4314
4296
  const columnRef = sql.raw(dialect.quoteIdentifier(projected.outputName));
4315
- const dir = sql.raw(o.direction.toUpperCase());
4316
- const nulls = o.nulls ?? (o.direction === "asc" ? "last" : "first");
4297
+ const dir = sql.raw(orderSpec.direction.toUpperCase());
4298
+ const nulls = orderSpec.nulls ?? (orderSpec.direction === "asc" ? "last" : "first");
4317
4299
  const nullsDir = sql.raw(nulls === "first" ? "DESC" : "ASC");
4318
4300
  orderParts.push(
4319
4301
  sql`(${columnRef} IS NULL) ${nullsDir}`,
@@ -5180,13 +5162,14 @@ function generateId() {
5180
5162
 
5181
5163
  // src/utils/path.ts
5182
5164
  function parseSqlitePath(path) {
5183
- if (!path || path === "||") return [];
5165
+ const emptyPath = `${SQLITE_PATH_DELIMITER}${SQLITE_PATH_DELIMITER}`;
5166
+ if (!path || path === emptyPath) return [];
5184
5167
  const trimmed = path.slice(1, -1);
5185
5168
  if (trimmed === "") return [];
5186
- return trimmed.split("|");
5169
+ return trimmed.split(SQLITE_PATH_DELIMITER);
5187
5170
  }
5188
5171
  function isSqlitePath(value) {
5189
- return typeof value === "string" && value.startsWith("|") && value.endsWith("|");
5172
+ return typeof value === "string" && value.startsWith(SQLITE_PATH_DELIMITER) && value.endsWith(SQLITE_PATH_DELIMITER);
5190
5173
  }
5191
5174
  function normalizePath(value) {
5192
5175
  if (Array.isArray(value)) {
@@ -5201,20 +5184,20 @@ function normalizePath(value) {
5201
5184
  return [];
5202
5185
  }
5203
5186
  function isPostgresTextArray(value) {
5204
- return typeof value === "string" && value.startsWith("{") && value.endsWith("}");
5187
+ return typeof value === "string" && value.startsWith(PG_ARRAY_START) && value.endsWith(PG_ARRAY_END);
5205
5188
  }
5206
5189
  function parsePostgresTextArray(value) {
5207
5190
  const inner = value.slice(1, -1);
5208
5191
  if (inner === "") return [];
5209
- return inner.split(",");
5192
+ return inner.split(PG_PATH_ELEMENT_SEPARATOR);
5210
5193
  }
5211
5194
 
5212
5195
  // src/query/execution/result-mapper.ts
5213
5196
  function transformPathColumns(rows, state, _dialect) {
5214
5197
  const pathAliases = [];
5215
- for (const t of state.traversals) {
5216
- if (t.variableLength?.pathAlias !== void 0) {
5217
- pathAliases.push(t.variableLength.pathAlias);
5198
+ for (const traversal of state.traversals) {
5199
+ if (traversal.variableLength?.pathAlias !== void 0) {
5200
+ pathAliases.push(traversal.variableLength.pathAlias);
5218
5201
  }
5219
5202
  }
5220
5203
  if (pathAliases.length === 0) return rows;
@@ -5238,8 +5221,8 @@ function transformPathColumns(rows, state, _dialect) {
5238
5221
  }
5239
5222
  return changed ? result : rows;
5240
5223
  }
5241
- var RESERVED_NODE_KEYS3 = /* @__PURE__ */ new Set(["id", "kind", "meta"]);
5242
- var RESERVED_EDGE_KEYS3 = /* @__PURE__ */ new Set(["id", "kind", "fromId", "toId", "meta"]);
5224
+ var RESERVED_NODE_KEYS2 = /* @__PURE__ */ new Set(["id", "kind", "meta"]);
5225
+ var RESERVED_EDGE_KEYS2 = /* @__PURE__ */ new Set(["id", "kind", "fromId", "toId", "meta"]);
5243
5226
  function nullToUndefined3(value) {
5244
5227
  return value === null ? void 0 : value;
5245
5228
  }
@@ -5277,7 +5260,7 @@ function buildSelectableNode(row, alias) {
5277
5260
  deletedAt
5278
5261
  }
5279
5262
  };
5280
- assignPropsExcludingReserved(result, rawProps, RESERVED_NODE_KEYS3);
5263
+ assignPropsExcludingReserved(result, rawProps, RESERVED_NODE_KEYS2);
5281
5264
  return result;
5282
5265
  }
5283
5266
  function buildSelectableNodeOrUndefined(row, alias) {
@@ -5319,7 +5302,7 @@ function buildSelectableEdge(row, alias) {
5319
5302
  deletedAt
5320
5303
  }
5321
5304
  };
5322
- assignPropsExcludingReserved(result, rawProps, RESERVED_EDGE_KEYS3);
5305
+ assignPropsExcludingReserved(result, rawProps, RESERVED_EDGE_KEYS2);
5323
5306
  return result;
5324
5307
  }
5325
5308
  function buildSelectContext(row, startAlias, traversals) {
@@ -5447,7 +5430,7 @@ async function* createStreamIterable(batchSize, paginate) {
5447
5430
  }
5448
5431
  }
5449
5432
  function getStreamBatchSize(options) {
5450
- return options?.batchSize ?? 1e3;
5433
+ return options?.batchSize ?? DEFAULT_STREAM_BATCH_SIZE;
5451
5434
  }
5452
5435
 
5453
5436
  // src/query/ast.ts
@@ -5859,6 +5842,9 @@ function buildSelectiveContext(row, plans, traversals) {
5859
5842
  return context;
5860
5843
  }
5861
5844
  function buildOptionalAliasValue(row, plan) {
5845
+ if (plan.idOutputName === void 0) {
5846
+ return void 0;
5847
+ }
5862
5848
  const idValue = row[plan.idOutputName];
5863
5849
  if (idValue === null || idValue === void 0) {
5864
5850
  return void 0;
@@ -7335,7 +7321,7 @@ var ExecutableQuery = class _ExecutableQuery {
7335
7321
  );
7336
7322
  }
7337
7323
  const isBackward = options.last !== void 0 || options.before !== void 0;
7338
- const limit = options.first ?? options.last ?? 20;
7324
+ const limit = options.first ?? options.last ?? DEFAULT_PAGINATION_LIMIT;
7339
7325
  const cursor = options.after ?? options.before;
7340
7326
  let cursorData;
7341
7327
  if (cursor) {
@@ -7658,7 +7644,8 @@ var TraversalBuilder = class _TraversalBuilder {
7658
7644
  }
7659
7645
  /**
7660
7646
  * Enables variable-length (recursive) traversal.
7661
- * By default, traverses unlimited depth with cycle prevention.
7647
+ * Defaults to MAX_RECURSIVE_DEPTH (10) hops with cycle prevention.
7648
+ * Use `maxHops` to override (up to MAX_EXPLICIT_RECURSIVE_DEPTH).
7662
7649
  */
7663
7650
  recursive(options) {
7664
7651
  const minDepth = options?.minHops ?? this.#variableLength.minDepth;
@@ -8919,6 +8906,35 @@ function createEdgeCollection(config) {
8919
8906
  executeHardDelete: executeEdgeHardDelete2,
8920
8907
  matchesTemporalMode
8921
8908
  } = config;
8909
+ const mapRows = (rows) => rows.map((row) => narrowEdge(rowToEdge2(row)));
8910
+ async function findEdgesFrom(from, target) {
8911
+ const rows = await target.findEdgesByKind({
8912
+ graphId,
8913
+ kind,
8914
+ fromKind: from.kind,
8915
+ fromId: from.id,
8916
+ excludeDeleted: true
8917
+ });
8918
+ return mapRows(rows);
8919
+ }
8920
+ async function findEdgesTo(to, target) {
8921
+ const rows = await target.findEdgesByKind({
8922
+ graphId,
8923
+ kind,
8924
+ toKind: to.kind,
8925
+ toId: to.id,
8926
+ excludeDeleted: true
8927
+ });
8928
+ return mapRows(rows);
8929
+ }
8930
+ function buildFindByEndpointsOptions(options) {
8931
+ const result = {};
8932
+ if (options?.matchOn !== void 0)
8933
+ result.matchOn = options.matchOn;
8934
+ if (options?.props !== void 0)
8935
+ result.props = options.props;
8936
+ return result;
8937
+ }
8922
8938
  return {
8923
8939
  async create(from, to, props, options) {
8924
8940
  const result = await executeEdgeCreate2(
@@ -8974,24 +8990,32 @@ function createEdgeCollection(config) {
8974
8990
  return narrowEdge(result);
8975
8991
  },
8976
8992
  async findFrom(from) {
8977
- const rows = await backend.findEdgesByKind({
8978
- graphId,
8979
- kind,
8980
- fromKind: from.kind,
8981
- fromId: from.id,
8982
- excludeDeleted: true
8983
- });
8984
- return rows.map((row) => narrowEdge(rowToEdge2(row)));
8993
+ return findEdgesFrom(from, backend);
8985
8994
  },
8986
8995
  async findTo(to) {
8987
- const rows = await backend.findEdgesByKind({
8988
- graphId,
8989
- kind,
8990
- toKind: to.kind,
8991
- toId: to.id,
8992
- excludeDeleted: true
8993
- });
8994
- return rows.map((row) => narrowEdge(rowToEdge2(row)));
8996
+ return findEdgesTo(to, backend);
8997
+ },
8998
+ batchFindFrom(from) {
8999
+ return { executeOn: (target) => findEdgesFrom(from, target) };
9000
+ },
9001
+ batchFindTo(to) {
9002
+ return { executeOn: (target) => findEdgesTo(to, target) };
9003
+ },
9004
+ batchFindByEndpoints(from, to, options) {
9005
+ return {
9006
+ executeOn: async (target) => {
9007
+ const result = await config.executeFindByEndpoints(
9008
+ kind,
9009
+ from.kind,
9010
+ from.id,
9011
+ to.kind,
9012
+ to.id,
9013
+ target,
9014
+ buildFindByEndpointsOptions(options)
9015
+ );
9016
+ return result === void 0 ? [] : [narrowEdge(result)];
9017
+ }
9018
+ };
8995
9019
  },
8996
9020
  async delete(id) {
8997
9021
  await executeEdgeDelete2(id, backend);
@@ -9025,7 +9049,7 @@ function createEdgeCollection(config) {
9025
9049
  if (options?.limit !== void 0) params.limit = options.limit;
9026
9050
  if (options?.offset !== void 0) params.offset = options.offset;
9027
9051
  const rows = await backend.findEdgesByKind(params);
9028
- return rows.map((row) => narrowEdge(rowToEdge2(row)));
9052
+ return mapRows(rows);
9029
9053
  },
9030
9054
  async count(options) {
9031
9055
  const mode = options?.temporalMode ?? defaultTemporalMode;
@@ -9154,11 +9178,6 @@ function createEdgeCollection(config) {
9154
9178
  await deleteAll(backend);
9155
9179
  },
9156
9180
  async findByEndpoints(from, to, options) {
9157
- const findOptions = {};
9158
- if (options?.matchOn !== void 0)
9159
- findOptions.matchOn = options.matchOn;
9160
- if (options?.props !== void 0)
9161
- findOptions.props = options.props;
9162
9181
  const result = await config.executeFindByEndpoints(
9163
9182
  kind,
9164
9183
  from.kind,
@@ -9166,7 +9185,7 @@ function createEdgeCollection(config) {
9166
9185
  to.kind,
9167
9186
  to.id,
9168
9187
  backend,
9169
- findOptions
9188
+ buildFindByEndpointsOptions(options)
9170
9189
  );
9171
9190
  return result === void 0 ? void 0 : narrowEdge(result);
9172
9191
  },
@@ -10400,6 +10419,9 @@ async function executeEdgeGetOrCreateByEndpoints(ctx, kind, fromKind, fromId, to
10400
10419
  return { edge: edge2, action: "updated" };
10401
10420
  }
10402
10421
  const cardinality = registration.cardinality ?? "many";
10422
+ if (deletedRow === void 0) {
10423
+ throw new Error("Expected deletedRow to be defined");
10424
+ }
10403
10425
  const matchedDeletedRow = deletedRow;
10404
10426
  const effectiveValidTo = matchedDeletedRow.valid_to;
10405
10427
  const constraintContext = {
@@ -10519,6 +10541,9 @@ async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend,
10519
10541
  });
10520
10542
  } else {
10521
10543
  const bestRow = liveRow ?? deletedRow;
10544
+ if (bestRow === void 0) {
10545
+ throw new Error("Expected at least one of liveRow or deletedRow");
10546
+ }
10522
10547
  toFetch.push({
10523
10548
  index,
10524
10549
  row: bestRow,
@@ -10819,11 +10844,12 @@ function getNodeRegistration(graph, kind) {
10819
10844
  if (registration === void 0) throw new KindNotFoundError(kind, "node");
10820
10845
  return registration;
10821
10846
  }
10847
+ var CACHE_KEY_SEPARATOR = "\0";
10822
10848
  function buildNodeCacheKey(graphId, kind, id) {
10823
- return `${graphId}\0${kind}\0${id}`;
10849
+ return `${graphId}${CACHE_KEY_SEPARATOR}${kind}${CACHE_KEY_SEPARATOR}${id}`;
10824
10850
  }
10825
10851
  function buildUniqueCacheKey(graphId, nodeKind, constraintName, key) {
10826
- return `${graphId}\0${nodeKind}\0${constraintName}\0${key}`;
10852
+ return `${graphId}${CACHE_KEY_SEPARATOR}${nodeKind}${CACHE_KEY_SEPARATOR}${constraintName}${CACHE_KEY_SEPARATOR}${key}`;
10827
10853
  }
10828
10854
  function createNodeAlreadyExistsError(kind, id) {
10829
10855
  return new ValidationError(
@@ -10860,6 +10886,23 @@ function createPendingUniqueRow(graphId, nodeKind, constraintName, key, nodeId)
10860
10886
  deleted_at: void 0
10861
10887
  };
10862
10888
  }
10889
+ function resolveConstraint(graph, kind, constraintName) {
10890
+ const registration = getNodeRegistration(graph, kind);
10891
+ const constraints = registration.unique ?? [];
10892
+ const constraint = constraints.find(
10893
+ (candidate) => candidate.name === constraintName
10894
+ );
10895
+ if (constraint === void 0) {
10896
+ throw new NodeConstraintNotFoundError(constraintName, kind);
10897
+ }
10898
+ return constraint;
10899
+ }
10900
+ function createUniquenessContext(graphId, registry, backend) {
10901
+ return { graphId, registry, backend };
10902
+ }
10903
+ function createEmbeddingSyncContext(graphId, nodeKind, nodeId, backend) {
10904
+ return { graphId, nodeKind, nodeId, backend };
10905
+ }
10863
10906
  function createNodeBatchValidationBackend(graphId, registry, backend) {
10864
10907
  const nodeCache = /* @__PURE__ */ new Map();
10865
10908
  const pendingNodes = /* @__PURE__ */ new Map();
@@ -10868,12 +10911,8 @@ function createNodeBatchValidationBackend(graphId, registry, backend) {
10868
10911
  async function getNodeCached(lookupGraphId, kind, id) {
10869
10912
  const cacheKey = buildNodeCacheKey(lookupGraphId, kind, id);
10870
10913
  const pendingNode = pendingNodes.get(cacheKey);
10871
- if (pendingNode !== void 0) {
10872
- return pendingNode;
10873
- }
10874
- if (nodeCache.has(cacheKey)) {
10875
- return nodeCache.get(cacheKey);
10876
- }
10914
+ if (pendingNode !== void 0) return pendingNode;
10915
+ if (nodeCache.has(cacheKey)) return nodeCache.get(cacheKey);
10877
10916
  const existing = await backend.getNode(lookupGraphId, kind, id);
10878
10917
  nodeCache.set(cacheKey, existing);
10879
10918
  return existing;
@@ -10895,16 +10934,14 @@ function createNodeBatchValidationBackend(graphId, registry, backend) {
10895
10934
  pendingOwner
10896
10935
  );
10897
10936
  }
10898
- if (uniqueCache.has(cacheKey)) {
10899
- return uniqueCache.get(cacheKey);
10900
- }
10937
+ if (uniqueCache.has(cacheKey)) return uniqueCache.get(cacheKey);
10901
10938
  const existing = await backend.checkUnique(params);
10902
10939
  uniqueCache.set(cacheKey, existing);
10903
10940
  return existing;
10904
10941
  }
10905
10942
  function registerPendingNode(params) {
10906
10943
  const cacheKey = buildNodeCacheKey(params.graphId, params.kind, params.id);
10907
- const pendingNode = {
10944
+ pendingNodes.set(cacheKey, {
10908
10945
  graph_id: params.graphId,
10909
10946
  kind: params.kind,
10910
10947
  id: params.id,
@@ -10915,14 +10952,11 @@ function createNodeBatchValidationBackend(graphId, registry, backend) {
10915
10952
  created_at: "",
10916
10953
  updated_at: "",
10917
10954
  deleted_at: void 0
10918
- };
10919
- pendingNodes.set(cacheKey, pendingNode);
10955
+ });
10920
10956
  }
10921
10957
  function registerPendingUniqueEntries(kind, id, props, constraints) {
10922
10958
  for (const constraint of constraints) {
10923
- if (!checkWherePredicate(constraint, props)) {
10924
- continue;
10925
- }
10959
+ if (!checkWherePredicate(constraint, props)) continue;
10926
10960
  const key = computeUniqueKey(
10927
10961
  props,
10928
10962
  constraint.fields,
@@ -10984,14 +11018,9 @@ async function validateAndPrepareNodeCreate(ctx, input, id, backend) {
10984
11018
  backend
10985
11019
  };
10986
11020
  await checkDisjointnessConstraint(constraintContext, kind, id);
10987
- const uniquenessContext = {
10988
- graphId: ctx.graphId,
10989
- registry: ctx.registry,
10990
- backend
10991
- };
10992
11021
  const uniqueConstraints = registration.unique ?? [];
10993
11022
  await checkUniquenessConstraints(
10994
- uniquenessContext,
11023
+ createUniquenessContext(ctx.graphId, ctx.registry, backend),
10995
11024
  kind,
10996
11025
  id,
10997
11026
  validatedProps,
@@ -11014,64 +11043,99 @@ async function validateAndPrepareNodeCreate(ctx, input, id, backend) {
11014
11043
  };
11015
11044
  }
11016
11045
  async function finalizeNodeCreate(ctx, prepared, backend) {
11017
- const uniquenessContext = {
11018
- graphId: ctx.graphId,
11019
- registry: ctx.registry,
11020
- backend
11021
- };
11022
11046
  await insertUniquenessEntries(
11023
- uniquenessContext,
11047
+ createUniquenessContext(ctx.graphId, ctx.registry, backend),
11024
11048
  prepared.kind,
11025
11049
  prepared.id,
11026
11050
  prepared.validatedProps,
11027
11051
  prepared.uniqueConstraints
11028
11052
  );
11029
- const embeddingSyncContext = {
11030
- graphId: ctx.graphId,
11031
- nodeKind: prepared.kind,
11032
- nodeId: prepared.id,
11033
- backend
11034
- };
11035
11053
  await syncEmbeddings(
11036
- embeddingSyncContext,
11054
+ createEmbeddingSyncContext(
11055
+ ctx.graphId,
11056
+ prepared.kind,
11057
+ prepared.id,
11058
+ backend
11059
+ ),
11037
11060
  prepared.nodeKind.schema,
11038
11061
  prepared.validatedProps
11039
11062
  );
11040
11063
  }
11041
- async function executeNodeCreateInternal(ctx, input, backend, options) {
11042
- const kind = input.kind;
11043
- const id = input.id ?? generateId();
11044
- const opContext = ctx.createOperationContext("create", "node", kind, id);
11045
- return ctx.withOperationHooks(opContext, async () => {
11046
- const prepared = await validateAndPrepareNodeCreate(
11047
- ctx,
11048
- input,
11049
- id,
11050
- backend
11051
- );
11052
- let row;
11053
- {
11054
- row = await backend.insertNode(prepared.insertParams);
11055
- }
11056
- await finalizeNodeCreate(ctx, prepared, backend);
11057
- if (row === void 0) return;
11058
- return rowToNode(row);
11064
+ async function performNodeUpdate(ctx, input, backend, options) {
11065
+ const { kind, id } = input;
11066
+ const registration = getNodeRegistration(ctx.graph, kind);
11067
+ const existing = await backend.getNode(ctx.graphId, kind, id);
11068
+ if (!existing || existing.deleted_at && !options?.clearDeleted) {
11069
+ throw new NodeNotFoundError(kind, id);
11070
+ }
11071
+ const existingProps = JSON.parse(existing.props);
11072
+ const mergedProps = { ...existingProps, ...input.props };
11073
+ const nodeKind = registration.type;
11074
+ const validatedProps = validateNodeProps(nodeKind.schema, mergedProps, {
11075
+ kind,
11076
+ operation: "update",
11077
+ id
11059
11078
  });
11079
+ const validTo = validateOptionalIsoDate(input.validTo, "validTo");
11080
+ await updateUniquenessEntries(
11081
+ createUniquenessContext(ctx.graphId, ctx.registry, backend),
11082
+ kind,
11083
+ id,
11084
+ existingProps,
11085
+ validatedProps,
11086
+ registration.unique ?? []
11087
+ );
11088
+ const updateParams = {
11089
+ graphId: ctx.graphId,
11090
+ kind,
11091
+ id,
11092
+ props: validatedProps,
11093
+ incrementVersion: true
11094
+ };
11095
+ if (validTo !== void 0) updateParams.validTo = validTo;
11096
+ if (options?.clearDeleted) updateParams.clearDeleted = true;
11097
+ const row = await backend.updateNode(updateParams);
11098
+ await syncEmbeddings(
11099
+ createEmbeddingSyncContext(ctx.graphId, kind, id, backend),
11100
+ nodeKind.schema,
11101
+ validatedProps
11102
+ );
11103
+ return rowToNode(row);
11060
11104
  }
11061
- async function executeNodeCreate(ctx, input, backend) {
11062
- const result = await executeNodeCreateInternal(ctx, input, backend);
11063
- if (!result) {
11064
- throw new DatabaseOperationError(
11065
- "Node create failed: expected created node row",
11066
- { operation: "insert", entity: "node" }
11067
- );
11105
+ async function enforceDeleteBehavior(ctx, kind, id, mode, backend, registration) {
11106
+ const deleteBehavior = registration.onDelete ?? "restrict";
11107
+ const connectedEdges = await backend.findEdgesConnectedTo({
11108
+ graphId: ctx.graphId,
11109
+ nodeKind: kind,
11110
+ nodeId: id
11111
+ });
11112
+ if (connectedEdges.length === 0) return;
11113
+ switch (deleteBehavior) {
11114
+ case "restrict": {
11115
+ const edgeKinds = [...new Set(connectedEdges.map((edge) => edge.kind))];
11116
+ throw new RestrictedDeleteError({
11117
+ nodeKind: kind,
11118
+ nodeId: id,
11119
+ edgeCount: connectedEdges.length,
11120
+ edgeKinds
11121
+ });
11122
+ }
11123
+ case "cascade":
11124
+ case "disconnect": {
11125
+ for (const edge of connectedEdges) {
11126
+ await (mode === "hard" ? backend.hardDeleteEdge({
11127
+ graphId: ctx.graphId,
11128
+ id: edge.id
11129
+ }) : backend.deleteEdge({
11130
+ graphId: ctx.graphId,
11131
+ id: edge.id
11132
+ }));
11133
+ }
11134
+ break;
11135
+ }
11068
11136
  }
11069
- return result;
11070
11137
  }
11071
- async function executeNodeCreateNoReturnBatch(ctx, inputs, backend) {
11072
- if (inputs.length === 0) {
11073
- return;
11074
- }
11138
+ async function prepareBatchCreates(ctx, inputs, backend) {
11075
11139
  const {
11076
11140
  backend: validationBackend,
11077
11141
  registerPendingNode,
@@ -11098,46 +11162,109 @@ async function executeNodeCreateNoReturnBatch(ctx, inputs, backend) {
11098
11162
  const batchInsertParams = preparedCreates.map(
11099
11163
  (prepared) => prepared.insertParams
11100
11164
  );
11101
- if (backend.insertNodesBatch === void 0) {
11102
- for (const insertParams of batchInsertParams) {
11103
- await (backend.insertNodeNoReturn?.(insertParams) ?? backend.insertNode(insertParams));
11104
- }
11105
- } else {
11106
- await backend.insertNodesBatch(batchInsertParams);
11107
- }
11108
- for (const prepared of preparedCreates) {
11109
- await finalizeNodeCreate(ctx, prepared, backend);
11165
+ return { preparedCreates, batchInsertParams };
11166
+ }
11167
+ async function findUniqueRowAcrossKinds(backend, graphId, constraintName, key, kindsToCheck, includeDeleted) {
11168
+ for (const kindToCheck of kindsToCheck) {
11169
+ const row = await backend.checkUnique({
11170
+ graphId,
11171
+ nodeKind: kindToCheck,
11172
+ constraintName,
11173
+ key,
11174
+ includeDeleted
11175
+ });
11176
+ if (row !== void 0) return row;
11110
11177
  }
11178
+ return void 0;
11111
11179
  }
11112
- async function executeNodeCreateBatch(ctx, inputs, backend) {
11113
- if (inputs.length === 0) {
11114
- return [];
11180
+ async function batchCheckUniqueAcrossKinds(backend, graphId, constraintName, uniqueKeys, kindsToCheck, includeDeleted) {
11181
+ const existingByKey = /* @__PURE__ */ new Map();
11182
+ for (const kindToCheck of kindsToCheck) {
11183
+ if (backend.checkUniqueBatch === void 0) {
11184
+ for (const key of uniqueKeys) {
11185
+ if (existingByKey.has(key)) continue;
11186
+ const row = await backend.checkUnique({
11187
+ graphId,
11188
+ nodeKind: kindToCheck,
11189
+ constraintName,
11190
+ key,
11191
+ includeDeleted
11192
+ });
11193
+ if (row !== void 0) {
11194
+ existingByKey.set(row.key, row);
11195
+ }
11196
+ }
11197
+ } else {
11198
+ const rows = await backend.checkUniqueBatch({
11199
+ graphId,
11200
+ nodeKind: kindToCheck,
11201
+ constraintName,
11202
+ keys: uniqueKeys,
11203
+ includeDeleted
11204
+ });
11205
+ for (const row of rows) {
11206
+ if (!existingByKey.has(row.key)) {
11207
+ existingByKey.set(row.key, row);
11208
+ }
11209
+ }
11210
+ }
11115
11211
  }
11116
- const {
11117
- backend: validationBackend,
11118
- registerPendingNode,
11119
- registerPendingUniqueEntries
11120
- } = createNodeBatchValidationBackend(ctx.graphId, ctx.registry, backend);
11121
- const preparedCreates = [];
11122
- for (const input of inputs) {
11123
- const id = input.id ?? generateId();
11212
+ return existingByKey;
11213
+ }
11214
+ async function executeNodeCreateInternal(ctx, input, backend, options) {
11215
+ const kind = input.kind;
11216
+ const id = input.id ?? generateId();
11217
+ const opContext = ctx.createOperationContext("create", "node", kind, id);
11218
+ return ctx.withOperationHooks(opContext, async () => {
11124
11219
  const prepared = await validateAndPrepareNodeCreate(
11125
11220
  ctx,
11126
11221
  input,
11127
11222
  id,
11128
- validationBackend
11223
+ backend
11129
11224
  );
11130
- preparedCreates.push(prepared);
11131
- registerPendingNode(prepared.insertParams);
11132
- registerPendingUniqueEntries(
11133
- prepared.kind,
11134
- prepared.id,
11135
- prepared.validatedProps,
11136
- prepared.uniqueConstraints
11225
+ let row;
11226
+ {
11227
+ row = await backend.insertNode(prepared.insertParams);
11228
+ }
11229
+ await finalizeNodeCreate(ctx, prepared, backend);
11230
+ if (row === void 0) return;
11231
+ return rowToNode(row);
11232
+ });
11233
+ }
11234
+ async function executeNodeCreate(ctx, input, backend) {
11235
+ const result = await executeNodeCreateInternal(ctx, input, backend);
11236
+ if (!result) {
11237
+ throw new DatabaseOperationError(
11238
+ "Node create failed: expected created node row",
11239
+ { operation: "insert", entity: "node" }
11137
11240
  );
11138
11241
  }
11139
- const batchInsertParams = preparedCreates.map(
11140
- (prepared) => prepared.insertParams
11242
+ return result;
11243
+ }
11244
+ async function executeNodeCreateNoReturnBatch(ctx, inputs, backend) {
11245
+ if (inputs.length === 0) return;
11246
+ const { preparedCreates, batchInsertParams } = await prepareBatchCreates(
11247
+ ctx,
11248
+ inputs,
11249
+ backend
11250
+ );
11251
+ if (backend.insertNodesBatch === void 0) {
11252
+ for (const insertParams of batchInsertParams) {
11253
+ await (backend.insertNodeNoReturn?.(insertParams) ?? backend.insertNode(insertParams));
11254
+ }
11255
+ } else {
11256
+ await backend.insertNodesBatch(batchInsertParams);
11257
+ }
11258
+ for (const prepared of preparedCreates) {
11259
+ await finalizeNodeCreate(ctx, prepared, backend);
11260
+ }
11261
+ }
11262
+ async function executeNodeCreateBatch(ctx, inputs, backend) {
11263
+ if (inputs.length === 0) return [];
11264
+ const { preparedCreates, batchInsertParams } = await prepareBatchCreates(
11265
+ ctx,
11266
+ inputs,
11267
+ backend
11141
11268
  );
11142
11269
  let rows;
11143
11270
  if (backend.insertNodesBatchReturning === void 0) {
@@ -11155,170 +11282,40 @@ async function executeNodeCreateBatch(ctx, inputs, backend) {
11155
11282
  return rows.map((row) => rowToNode(row));
11156
11283
  }
11157
11284
  async function executeNodeUpdate(ctx, input, backend, options) {
11158
- const kind = input.kind;
11159
- const id = input.id;
11160
- const opContext = ctx.createOperationContext("update", "node", kind, id);
11161
- return ctx.withOperationHooks(opContext, async () => {
11162
- const registration = getNodeRegistration(ctx.graph, kind);
11163
- const existing = await backend.getNode(ctx.graphId, kind, id);
11164
- if (!existing || existing.deleted_at && !options?.clearDeleted) {
11165
- throw new NodeNotFoundError(kind, id);
11166
- }
11167
- const existingProps = JSON.parse(existing.props);
11168
- const mergedProps = { ...existingProps, ...input.props };
11169
- const nodeKind = registration.type;
11170
- const validatedProps = validateNodeProps(nodeKind.schema, mergedProps, {
11171
- kind,
11172
- operation: "update",
11173
- id
11174
- });
11175
- const validTo = validateOptionalIsoDate(input.validTo, "validTo");
11176
- const uniquenessContext = {
11177
- graphId: ctx.graphId,
11178
- registry: ctx.registry,
11179
- backend
11180
- };
11181
- await updateUniquenessEntries(
11182
- uniquenessContext,
11183
- kind,
11184
- id,
11185
- existingProps,
11186
- validatedProps,
11187
- registration.unique ?? []
11188
- );
11189
- const updateParams = {
11190
- graphId: ctx.graphId,
11191
- kind,
11192
- id,
11193
- props: validatedProps,
11194
- incrementVersion: true
11195
- };
11196
- if (validTo !== void 0) updateParams.validTo = validTo;
11197
- if (options?.clearDeleted) updateParams.clearDeleted = true;
11198
- const row = await backend.updateNode(updateParams);
11199
- const embeddingSyncContext = {
11200
- graphId: ctx.graphId,
11201
- nodeKind: kind,
11202
- nodeId: id,
11203
- backend
11204
- };
11205
- await syncEmbeddings(embeddingSyncContext, nodeKind.schema, validatedProps);
11206
- return rowToNode(row);
11207
- });
11285
+ const opContext = ctx.createOperationContext(
11286
+ "update",
11287
+ "node",
11288
+ input.kind,
11289
+ input.id
11290
+ );
11291
+ return ctx.withOperationHooks(
11292
+ opContext,
11293
+ () => performNodeUpdate(ctx, input, backend, options)
11294
+ );
11208
11295
  }
11209
11296
  async function executeNodeUpsertUpdate(ctx, input, backend, options) {
11210
- const kind = input.kind;
11211
- const id = input.id;
11212
- const registration = getNodeRegistration(ctx.graph, kind);
11213
- const existing = await backend.getNode(ctx.graphId, kind, id);
11214
- if (!existing || existing.deleted_at && !options?.clearDeleted) {
11215
- throw new NodeNotFoundError(kind, id);
11216
- }
11217
- const existingProps = JSON.parse(existing.props);
11218
- const mergedProps = { ...existingProps, ...input.props };
11219
- const nodeKind = registration.type;
11220
- const validatedProps = validateNodeProps(nodeKind.schema, mergedProps, {
11221
- kind,
11222
- operation: "update",
11223
- id
11224
- });
11225
- const validTo = validateOptionalIsoDate(input.validTo, "validTo");
11226
- const uniquenessContext = {
11227
- graphId: ctx.graphId,
11228
- registry: ctx.registry,
11229
- backend
11230
- };
11231
- await updateUniquenessEntries(
11232
- uniquenessContext,
11233
- kind,
11234
- id,
11235
- existingProps,
11236
- validatedProps,
11237
- registration.unique ?? []
11238
- );
11239
- const updateParams = {
11240
- graphId: ctx.graphId,
11241
- kind,
11242
- id,
11243
- props: validatedProps,
11244
- incrementVersion: true
11245
- };
11246
- if (validTo !== void 0) updateParams.validTo = validTo;
11247
- if (options?.clearDeleted) updateParams.clearDeleted = true;
11248
- const row = await backend.updateNode(updateParams);
11249
- const embeddingSyncContext = {
11250
- graphId: ctx.graphId,
11251
- nodeKind: kind,
11252
- nodeId: id,
11253
- backend
11254
- };
11255
- await syncEmbeddings(embeddingSyncContext, nodeKind.schema, validatedProps);
11256
- return rowToNode(row);
11297
+ return performNodeUpdate(ctx, input, backend, options);
11257
11298
  }
11258
11299
  async function executeNodeDelete(ctx, kind, id, backend) {
11259
11300
  const opContext = ctx.createOperationContext("delete", "node", kind, id);
11260
11301
  return ctx.withOperationHooks(opContext, async () => {
11261
11302
  const registration = getNodeRegistration(ctx.graph, kind);
11262
11303
  const existing = await backend.getNode(ctx.graphId, kind, id);
11263
- if (!existing || existing.deleted_at) {
11264
- return;
11265
- }
11304
+ if (!existing || existing.deleted_at) return;
11266
11305
  const existingProps = JSON.parse(existing.props);
11267
- const deleteBehavior = registration.onDelete ?? "restrict";
11268
- const connectedEdges = await backend.findEdgesConnectedTo({
11269
- graphId: ctx.graphId,
11270
- nodeKind: kind,
11271
- nodeId: id
11272
- });
11273
- if (connectedEdges.length > 0) {
11274
- switch (deleteBehavior) {
11275
- case "restrict": {
11276
- const edgeKinds = [
11277
- ...new Set(connectedEdges.map((edge) => edge.kind))
11278
- ];
11279
- throw new RestrictedDeleteError({
11280
- nodeKind: kind,
11281
- nodeId: id,
11282
- edgeCount: connectedEdges.length,
11283
- edgeKinds
11284
- });
11285
- }
11286
- case "cascade":
11287
- case "disconnect": {
11288
- for (const edge of connectedEdges) {
11289
- await backend.deleteEdge({
11290
- graphId: ctx.graphId,
11291
- id: edge.id
11292
- });
11293
- }
11294
- break;
11295
- }
11296
- }
11297
- }
11298
- await backend.deleteNode({
11299
- graphId: ctx.graphId,
11300
- kind,
11301
- id
11302
- });
11303
- const uniquenessContext = {
11304
- graphId: ctx.graphId,
11305
- registry: ctx.registry,
11306
- backend
11307
- };
11306
+ await enforceDeleteBehavior(ctx, kind, id, "soft", backend, registration);
11307
+ await backend.deleteNode({ graphId: ctx.graphId, kind, id });
11308
11308
  await deleteUniquenessEntries(
11309
- uniquenessContext,
11309
+ createUniquenessContext(ctx.graphId, ctx.registry, backend),
11310
11310
  kind,
11311
11311
  existingProps,
11312
11312
  registration.unique ?? []
11313
11313
  );
11314
11314
  const nodeKind = registration.type;
11315
- const embeddingSyncContext = {
11316
- graphId: ctx.graphId,
11317
- nodeKind: kind,
11318
- nodeId: id,
11319
- backend
11320
- };
11321
- await deleteNodeEmbeddings(embeddingSyncContext, nodeKind.schema);
11315
+ await deleteNodeEmbeddings(
11316
+ createEmbeddingSyncContext(ctx.graphId, kind, id, backend),
11317
+ nodeKind.schema
11318
+ );
11322
11319
  });
11323
11320
  }
11324
11321
  async function executeNodeHardDelete(ctx, kind, id, backend) {
@@ -11326,59 +11323,14 @@ async function executeNodeHardDelete(ctx, kind, id, backend) {
11326
11323
  return ctx.withOperationHooks(opContext, async () => {
11327
11324
  const registration = getNodeRegistration(ctx.graph, kind);
11328
11325
  const existing = await backend.getNode(ctx.graphId, kind, id);
11329
- if (!existing) {
11330
- return;
11331
- }
11332
- const deleteBehavior = registration.onDelete ?? "restrict";
11333
- const connectedEdges = await backend.findEdgesConnectedTo({
11334
- graphId: ctx.graphId,
11335
- nodeKind: kind,
11336
- nodeId: id
11337
- });
11338
- if (connectedEdges.length > 0) {
11339
- switch (deleteBehavior) {
11340
- case "restrict": {
11341
- const edgeKinds = [
11342
- ...new Set(connectedEdges.map((edge) => edge.kind))
11343
- ];
11344
- throw new RestrictedDeleteError({
11345
- nodeKind: kind,
11346
- nodeId: id,
11347
- edgeCount: connectedEdges.length,
11348
- edgeKinds
11349
- });
11350
- }
11351
- case "cascade":
11352
- case "disconnect": {
11353
- for (const edge of connectedEdges) {
11354
- await backend.hardDeleteEdge({
11355
- graphId: ctx.graphId,
11356
- id: edge.id
11357
- });
11358
- }
11359
- break;
11360
- }
11361
- }
11362
- }
11326
+ if (!existing) return;
11327
+ await enforceDeleteBehavior(ctx, kind, id, "hard", backend, registration);
11363
11328
  const hardDelete = async (target) => {
11364
- await target.hardDeleteNode({
11365
- graphId: ctx.graphId,
11366
- kind,
11367
- id
11368
- });
11329
+ await target.hardDeleteNode({ graphId: ctx.graphId, kind, id });
11369
11330
  };
11370
11331
  await ("transaction" in backend && backend.capabilities.transactions ? backend.transaction(async (tx) => hardDelete(tx)) : hardDelete(backend));
11371
11332
  });
11372
11333
  }
11373
- function resolveConstraint(graph, kind, constraintName) {
11374
- const registration = getNodeRegistration(graph, kind);
11375
- const constraints = registration.unique ?? [];
11376
- const constraint = constraints.find((c) => c.name === constraintName);
11377
- if (constraint === void 0) {
11378
- throw new NodeConstraintNotFoundError(constraintName, kind);
11379
- }
11380
- return constraint;
11381
- }
11382
11334
  async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, props, backend, options) {
11383
11335
  const ifExists = options?.ifExists ?? "return";
11384
11336
  const registration = getNodeRegistration(ctx.graph, kind);
@@ -11389,8 +11341,11 @@ async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, pro
11389
11341
  });
11390
11342
  const constraint = resolveConstraint(ctx.graph, kind, constraintName);
11391
11343
  if (!checkWherePredicate(constraint, validatedProps)) {
11392
- const input = { kind, props: validatedProps };
11393
- const node = await executeNodeCreate(ctx, input, backend);
11344
+ const node = await executeNodeCreate(
11345
+ ctx,
11346
+ { kind, props: validatedProps },
11347
+ backend
11348
+ );
11394
11349
  return { node, action: "created" };
11395
11350
  }
11396
11351
  const key = computeUniqueKey(
@@ -11403,23 +11358,20 @@ async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, pro
11403
11358
  constraint.scope,
11404
11359
  ctx.registry
11405
11360
  );
11406
- let existingUniqueRow;
11407
- for (const kindToCheck of kindsToCheck) {
11408
- const row = await backend.checkUnique({
11409
- graphId: ctx.graphId,
11410
- nodeKind: kindToCheck,
11411
- constraintName: constraint.name,
11412
- key,
11413
- includeDeleted: true
11414
- });
11415
- if (row !== void 0) {
11416
- existingUniqueRow = row;
11417
- break;
11418
- }
11419
- }
11361
+ const existingUniqueRow = await findUniqueRowAcrossKinds(
11362
+ backend,
11363
+ ctx.graphId,
11364
+ constraint.name,
11365
+ key,
11366
+ kindsToCheck,
11367
+ true
11368
+ );
11420
11369
  if (existingUniqueRow === void 0) {
11421
- const input = { kind, props: validatedProps };
11422
- const node = await executeNodeCreate(ctx, input, backend);
11370
+ const node = await executeNodeCreate(
11371
+ ctx,
11372
+ { kind, props: validatedProps },
11373
+ backend
11374
+ );
11423
11375
  return { node, action: "created" };
11424
11376
  }
11425
11377
  const existingRow = await backend.getNode(
@@ -11428,8 +11380,11 @@ async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, pro
11428
11380
  existingUniqueRow.node_id
11429
11381
  );
11430
11382
  if (existingRow === void 0) {
11431
- const input = { kind, props: validatedProps };
11432
- const node = await executeNodeCreate(ctx, input, backend);
11383
+ const node = await executeNodeCreate(
11384
+ ctx,
11385
+ { kind, props: validatedProps },
11386
+ backend
11387
+ );
11433
11388
  return { node, action: "created" };
11434
11389
  }
11435
11390
  const isSoftDeleted = existingRow.deleted_at !== void 0;
@@ -11468,20 +11423,14 @@ async function executeNodeFindByConstraint(ctx, kind, constraintName, props, bac
11468
11423
  constraint.scope,
11469
11424
  ctx.registry
11470
11425
  );
11471
- let existingUniqueRow;
11472
- for (const kindToCheck of kindsToCheck) {
11473
- const row = await backend.checkUnique({
11474
- graphId: ctx.graphId,
11475
- nodeKind: kindToCheck,
11476
- constraintName: constraint.name,
11477
- key,
11478
- includeDeleted: false
11479
- });
11480
- if (row !== void 0) {
11481
- existingUniqueRow = row;
11482
- break;
11483
- }
11484
- }
11426
+ const existingUniqueRow = await findUniqueRowAcrossKinds(
11427
+ backend,
11428
+ ctx.graphId,
11429
+ constraint.name,
11430
+ key,
11431
+ kindsToCheck,
11432
+ false
11433
+ );
11485
11434
  if (existingUniqueRow === void 0) return void 0;
11486
11435
  const existingRow = await backend.getNode(
11487
11436
  ctx.graphId,
@@ -11492,11 +11441,7 @@ async function executeNodeFindByConstraint(ctx, kind, constraintName, props, bac
11492
11441
  return void 0;
11493
11442
  return rowToNode(existingRow);
11494
11443
  }
11495
- async function executeNodeBulkFindByConstraint(ctx, kind, constraintName, items, backend) {
11496
- if (items.length === 0) return [];
11497
- const registration = getNodeRegistration(ctx.graph, kind);
11498
- const nodeKind = registration.type;
11499
- const constraint = resolveConstraint(ctx.graph, kind, constraintName);
11444
+ function validateAndComputeKeys(nodeKind, kind, constraint, items) {
11500
11445
  const validated = [];
11501
11446
  for (const item of items) {
11502
11447
  const validatedProps = validateNodeProps(nodeKind.schema, item.props, {
@@ -11511,49 +11456,35 @@ async function executeNodeBulkFindByConstraint(ctx, kind, constraintName, items,
11511
11456
  ) : void 0;
11512
11457
  validated.push({ validatedProps, key });
11513
11458
  }
11514
- const uniqueKeys = [
11459
+ return validated;
11460
+ }
11461
+ function collectUniqueKeys(validated) {
11462
+ return [
11515
11463
  ...new Set(
11516
- validated.map((v) => v.key).filter((k) => k !== void 0)
11464
+ validated.map((entry) => entry.key).filter((key) => key !== void 0)
11517
11465
  )
11518
11466
  ];
11467
+ }
11468
+ async function executeNodeBulkFindByConstraint(ctx, kind, constraintName, items, backend) {
11469
+ if (items.length === 0) return [];
11470
+ const registration = getNodeRegistration(ctx.graph, kind);
11471
+ const nodeKind = registration.type;
11472
+ const constraint = resolveConstraint(ctx.graph, kind, constraintName);
11473
+ const validated = validateAndComputeKeys(nodeKind, kind, constraint, items);
11474
+ const uniqueKeys = collectUniqueKeys(validated);
11519
11475
  const kindsToCheck = getKindsForUniquenessCheck(
11520
11476
  kind,
11521
11477
  constraint.scope,
11522
11478
  ctx.registry
11523
11479
  );
11524
- const existingByKey = /* @__PURE__ */ new Map();
11525
- if (uniqueKeys.length > 0) {
11526
- for (const kindToCheck of kindsToCheck) {
11527
- if (backend.checkUniqueBatch === void 0) {
11528
- for (const key of uniqueKeys) {
11529
- if (existingByKey.has(key)) continue;
11530
- const row = await backend.checkUnique({
11531
- graphId: ctx.graphId,
11532
- nodeKind: kindToCheck,
11533
- constraintName: constraint.name,
11534
- key,
11535
- includeDeleted: false
11536
- });
11537
- if (row !== void 0) {
11538
- existingByKey.set(row.key, row);
11539
- }
11540
- }
11541
- } else {
11542
- const rows = await backend.checkUniqueBatch({
11543
- graphId: ctx.graphId,
11544
- nodeKind: kindToCheck,
11545
- constraintName: constraint.name,
11546
- keys: uniqueKeys,
11547
- includeDeleted: false
11548
- });
11549
- for (const row of rows) {
11550
- if (!existingByKey.has(row.key)) {
11551
- existingByKey.set(row.key, row);
11552
- }
11553
- }
11554
- }
11555
- }
11556
- }
11480
+ const existingByKey = uniqueKeys.length > 0 ? await batchCheckUniqueAcrossKinds(
11481
+ backend,
11482
+ ctx.graphId,
11483
+ constraint.name,
11484
+ uniqueKeys,
11485
+ kindsToCheck,
11486
+ false
11487
+ ) : /* @__PURE__ */ new Map();
11557
11488
  const results = Array.from({ length: items.length });
11558
11489
  const seenKeys = /* @__PURE__ */ new Map();
11559
11490
  for (const [index, { key }] of validated.entries()) {
@@ -11591,73 +11522,28 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
11591
11522
  const registration = getNodeRegistration(ctx.graph, kind);
11592
11523
  const nodeKind = registration.type;
11593
11524
  const constraint = resolveConstraint(ctx.graph, kind, constraintName);
11594
- const validated = [];
11595
- for (const item of items) {
11596
- const validatedProps = validateNodeProps(nodeKind.schema, item.props, {
11597
- kind,
11598
- operation: "create"
11599
- });
11600
- const applies = checkWherePredicate(constraint, validatedProps);
11601
- const key = applies ? computeUniqueKey(
11602
- validatedProps,
11603
- constraint.fields,
11604
- constraint.collation
11605
- ) : void 0;
11606
- validated.push({ validatedProps, key });
11607
- }
11608
- const uniqueKeys = [
11609
- ...new Set(
11610
- validated.map((v) => v.key).filter((k) => k !== void 0)
11611
- )
11612
- ];
11525
+ const validated = validateAndComputeKeys(nodeKind, kind, constraint, items);
11526
+ const uniqueKeys = collectUniqueKeys(validated);
11613
11527
  const kindsToCheck = getKindsForUniquenessCheck(
11614
11528
  kind,
11615
11529
  constraint.scope,
11616
11530
  ctx.registry
11617
11531
  );
11618
- const existingByKey = /* @__PURE__ */ new Map();
11619
- if (uniqueKeys.length > 0) {
11620
- for (const kindToCheck of kindsToCheck) {
11621
- if (backend.checkUniqueBatch === void 0) {
11622
- for (const key of uniqueKeys) {
11623
- if (existingByKey.has(key)) continue;
11624
- const row = await backend.checkUnique({
11625
- graphId: ctx.graphId,
11626
- nodeKind: kindToCheck,
11627
- constraintName: constraint.name,
11628
- key,
11629
- includeDeleted: true
11630
- });
11631
- if (row !== void 0) {
11632
- existingByKey.set(row.key, row);
11633
- }
11634
- }
11635
- } else {
11636
- const rows = await backend.checkUniqueBatch({
11637
- graphId: ctx.graphId,
11638
- nodeKind: kindToCheck,
11639
- constraintName: constraint.name,
11640
- keys: uniqueKeys,
11641
- includeDeleted: true
11642
- });
11643
- for (const row of rows) {
11644
- if (!existingByKey.has(row.key)) {
11645
- existingByKey.set(row.key, row);
11646
- }
11647
- }
11648
- }
11649
- }
11650
- }
11532
+ const existingByKey = uniqueKeys.length > 0 ? await batchCheckUniqueAcrossKinds(
11533
+ backend,
11534
+ ctx.graphId,
11535
+ constraint.name,
11536
+ uniqueKeys,
11537
+ kindsToCheck,
11538
+ true
11539
+ ) : /* @__PURE__ */ new Map();
11651
11540
  const toCreate = [];
11652
11541
  const toFetch = [];
11653
11542
  const duplicateOf = [];
11654
11543
  const seenKeys = /* @__PURE__ */ new Map();
11655
11544
  for (const [index, { validatedProps, key }] of validated.entries()) {
11656
11545
  if (key === void 0) {
11657
- toCreate.push({
11658
- index,
11659
- input: { kind, props: validatedProps }
11660
- });
11546
+ toCreate.push({ index, input: { kind, props: validatedProps } });
11661
11547
  continue;
11662
11548
  }
11663
11549
  const previousIndex = seenKeys.get(key);
@@ -11668,10 +11554,7 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
11668
11554
  seenKeys.set(key, index);
11669
11555
  const existing = existingByKey.get(key);
11670
11556
  if (existing === void 0) {
11671
- toCreate.push({
11672
- index,
11673
- input: { kind, props: validatedProps }
11674
- });
11557
+ toCreate.push({ index, input: { kind, props: validatedProps } });
11675
11558
  } else {
11676
11559
  toFetch.push({
11677
11560
  index,
@@ -11705,8 +11588,11 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
11705
11588
  nodeId
11706
11589
  );
11707
11590
  if (existingRow === void 0) {
11708
- const input = { kind, props: validatedProps };
11709
- const node = await executeNodeCreate(ctx, input, backend);
11591
+ const node = await executeNodeCreate(
11592
+ ctx,
11593
+ { kind, props: validatedProps },
11594
+ backend
11595
+ );
11710
11596
  results[index] = { node, action: "created" };
11711
11597
  continue;
11712
11598
  }