grafeo-ogm 2.1.0 → 2.2.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 (73) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +49 -0
  3. package/dist/cjs/compilers/mutation.compiler.d.ts.map +1 -1
  4. package/dist/cjs/compilers/mutation.compiler.js +23 -23
  5. package/dist/cjs/compilers/mutation.compiler.js.map +1 -1
  6. package/dist/cjs/compilers/where.compiler.d.ts +83 -6
  7. package/dist/cjs/compilers/where.compiler.d.ts.map +1 -1
  8. package/dist/cjs/compilers/where.compiler.js +156 -76
  9. package/dist/cjs/compilers/where.compiler.js.map +1 -1
  10. package/dist/cjs/execution/executor.d.ts +11 -1
  11. package/dist/cjs/execution/executor.d.ts.map +1 -1
  12. package/dist/cjs/execution/executor.js +6 -3
  13. package/dist/cjs/execution/executor.js.map +1 -1
  14. package/dist/cjs/index.d.ts +2 -2
  15. package/dist/cjs/index.d.ts.map +1 -1
  16. package/dist/cjs/index.js.map +1 -1
  17. package/dist/cjs/model.d.ts +38 -1
  18. package/dist/cjs/model.d.ts.map +1 -1
  19. package/dist/cjs/model.js +120 -2
  20. package/dist/cjs/model.js.map +1 -1
  21. package/dist/cjs/ogm.d.ts.map +1 -1
  22. package/dist/cjs/ogm.js +1 -0
  23. package/dist/cjs/ogm.js.map +1 -1
  24. package/dist/cjs/policy/explain.d.ts +59 -0
  25. package/dist/cjs/policy/explain.d.ts.map +1 -0
  26. package/dist/cjs/policy/explain.js +175 -0
  27. package/dist/cjs/policy/explain.js.map +1 -0
  28. package/dist/cjs/policy/resolver.d.ts +26 -2
  29. package/dist/cjs/policy/resolver.d.ts.map +1 -1
  30. package/dist/cjs/policy/resolver.js +103 -33
  31. package/dist/cjs/policy/resolver.js.map +1 -1
  32. package/dist/cjs/policy/types.d.ts +87 -0
  33. package/dist/cjs/policy/types.d.ts.map +1 -1
  34. package/dist/cjs/utils/write-coercion.d.ts +20 -19
  35. package/dist/cjs/utils/write-coercion.d.ts.map +1 -1
  36. package/dist/cjs/utils/write-coercion.js +120 -50
  37. package/dist/cjs/utils/write-coercion.js.map +1 -1
  38. package/dist/esm/compilers/mutation.compiler.d.ts.map +1 -1
  39. package/dist/esm/compilers/mutation.compiler.js +24 -24
  40. package/dist/esm/compilers/mutation.compiler.js.map +1 -1
  41. package/dist/esm/compilers/where.compiler.d.ts +83 -6
  42. package/dist/esm/compilers/where.compiler.d.ts.map +1 -1
  43. package/dist/esm/compilers/where.compiler.js +156 -77
  44. package/dist/esm/compilers/where.compiler.js.map +1 -1
  45. package/dist/esm/execution/executor.d.ts +11 -1
  46. package/dist/esm/execution/executor.d.ts.map +1 -1
  47. package/dist/esm/execution/executor.js +6 -3
  48. package/dist/esm/execution/executor.js.map +1 -1
  49. package/dist/esm/index.d.ts +2 -2
  50. package/dist/esm/index.d.ts.map +1 -1
  51. package/dist/esm/index.js.map +1 -1
  52. package/dist/esm/model.d.ts +38 -1
  53. package/dist/esm/model.d.ts.map +1 -1
  54. package/dist/esm/model.js +121 -3
  55. package/dist/esm/model.js.map +1 -1
  56. package/dist/esm/ogm.d.ts.map +1 -1
  57. package/dist/esm/ogm.js +1 -0
  58. package/dist/esm/ogm.js.map +1 -1
  59. package/dist/esm/policy/explain.d.ts +59 -0
  60. package/dist/esm/policy/explain.d.ts.map +1 -0
  61. package/dist/esm/policy/explain.js +169 -0
  62. package/dist/esm/policy/explain.js.map +1 -0
  63. package/dist/esm/policy/resolver.d.ts +26 -2
  64. package/dist/esm/policy/resolver.d.ts.map +1 -1
  65. package/dist/esm/policy/resolver.js +102 -33
  66. package/dist/esm/policy/resolver.js.map +1 -1
  67. package/dist/esm/policy/types.d.ts +87 -0
  68. package/dist/esm/policy/types.d.ts.map +1 -1
  69. package/dist/esm/utils/write-coercion.d.ts +20 -19
  70. package/dist/esm/utils/write-coercion.d.ts.map +1 -1
  71. package/dist/esm/utils/write-coercion.js +118 -48
  72. package/dist/esm/utils/write-coercion.js.map +1 -1
  73. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,76 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.2.0 (2026-09-23) — 🔎 Explain policy decisions
4
+
5
+ > **Policy-bound reads can now explain themselves.** When a policy hides a node, `find` could only show *that* it disappeared, never *which* named clause removed it, because every clause is compiled into a single `WHERE` predicate. The new `Model.explainPolicies()` evaluates each `read` policy separately for every candidate node, covering both the declarative `when:` form and the raw `cypher:` form, and returns the hidden nodes too ([#6](https://github.com/neomodular/grafeo-ogm/issues/6)).
6
+ >
7
+ > **Additive minor release.** No existing signature changes, and every existing query emits byte-identical Cypher (pinned by a new 17-case golden suite). The one observable change is a correction to `policiesEvaluated` in the audit metadata (see below).
8
+
9
+ ### ✨ `Model.explainPolicies()`
10
+
11
+ ```typescript
12
+ const report = await ogm
13
+ .withContext(ctx)
14
+ .model('Chart')
15
+ .explainPolicies({ where: { id_IN: candidateIds }, select: { id: true } });
16
+ // → [{ node, visible, overriddenBy, permissiveGranted, failedRestrictives,
17
+ // policies: [{ name, named, kind, source, applied, outcome }] }]
18
+ ```
19
+
20
+ - **Matches enforcement exactly.** Explain reuses the fragments `find` compiles, and `visible` is computed from the same composed predicate `find` puts in its `WHERE`. The verdict recomputed from the per-policy outcomes is checked against it, and a mismatch throws rather than returning a wrong explanation.
21
+ - **Outcomes:** `pass`, `fail`, `null` (NULL is reported separately from `false`), `abstain` (the policy emitted no predicate), `not-applied` (`appliesWhen` returned false), `skipped` (an override fired).
22
+ - **Candidates** are selected by `where` / `labels` exactly as in `find`. Full `select` / `selectionSet` is supported, and nested relationships are still filtered by their own policies.
23
+ - **Read-only:** when grafeo opens the session itself, it uses `READ` access mode. Candidates default to 100 per call; more than 1,000 is rejected.
24
+ - **An explicit bypass:** every call logs a `warn`, is tagged `explain: true` in the transaction metadata (even with `auditMetadata: false`), and throws on models without a policy binding and on policy-bypassed OGMs. `onDeny: 'throw'` is reported as `visible: false` instead of being thrown.
25
+ - Scope: `Model` and the `read` operation only. `InterfaceModel`, `count`, `aggregate`, and `delete` are not supported yet.
26
+ - New exported types: `PolicyExplanation`, `PolicyClauseExplanation`, `PolicyClauseOutcome`, and `ExecuteOptions`.
27
+
28
+ ### 🐛 `policiesEvaluated` lists only policies that applied
29
+
30
+ The audit metadata field is documented as "names of policies that fired", but it also listed restrictives whose `appliesWhen(ctx)` returned `false`, even though those contributed nothing to the query. They are no longer listed. Emitted Cypher is unchanged.
31
+
32
+ To produce this list, the resolver now evaluates restrictive `appliesWhen` itself, and the compiler (or `evaluateWriteRestrictives`) still evaluates it too. As a result, **restrictive `appliesWhen` callbacks run twice per query**. They are documented as pure compile-time gates, so this only matters if yours have side effects (counters, logging).
33
+
34
+ ### 🔧 Internal
35
+
36
+ - `WhereCompiler`'s policy clause is now built in two steps: `compilePolicyFragments()` (the per-policy parts) and `composePolicyClause()` (the combination). Output is byte-identical to 2.1.1. The new `compileForExplain()` returns the fragments without folding them into the `WHERE`.
37
+ - `PolicyResolver.resolveDetailed()` returns every operation-matching policy with its `applied` / `skipped` state, source, and registration index. `resolve()` is now a projection of it via `projectResolution()`.
38
+ - `Executor.execute()` accepts an optional 4th argument, `{ accessMode }`. It only affects sessions the executor opens itself; calls without it behave as before.
39
+
40
+ ### Tests
41
+
42
+ - `tests/policy/explain-refactor-golden.spec.ts`: 17 goldens captured from the 2.1.1 compiler, covering every fragment shape, interface inheritance, `@cypher` preludes, traversal, nested selection, count, aggregate, delete, override, and `InterfaceModel`.
43
+ - `tests/policy/explain.spec.ts`: 27 tests covering guards, clause forms, no short-circuiting, applicability, the outcome vocabulary, fidelity with `find` (including a forced mismatch), identity, selection and prelude scoping, and security signalling.
44
+ - 10 new resolver tests, 2 new audit-metadata tests, and `tests/executor-access-mode.spec.ts` (5 tests).
45
+
46
+ ## 2.1.1 (2026-08-13) — 📍 Point fields round-trip
47
+
48
+ > **The last member of the 2.1.0 type-faithfulness family.** Reads flatten a native Point into a plain `{ x, y[, z], srid }` object — but writing that object back bound it as a map property value, which Neo4j rejects at runtime ("Property values can only be of primitive types or arrays thereof"). A `Point` read through the OGM could not be written back through the OGM.
49
+ >
50
+ > **Pure patch:** nothing that previously worked changes behavior. Plain point writes previously failed loudly at the database; they now succeed as the README's scalar table always promised.
51
+
52
+ ### 🐛 Plain point objects are wrapped in `point()`
53
+
54
+ `Point` / `CartesianPoint` writes now wrap the parameter in Cypher's `point()` constructor whenever the value is a plain point-shaped object — cartesian (`x`/`y`) or geographic (`longitude`/`latitude`). `point()` accepts the read shape back verbatim, `srid` included, so the read → write round-trip is exact:
55
+
56
+ ```cypher
57
+ CREATE (n:`Event` { `location`: point($create0_location) })
58
+ // list fields wrap element-wise:
59
+ `route`: [wc_t IN $create0_route | point(wc_t)]
60
+ ```
61
+
62
+ WHERE equality and `_IN`/`_NOT_IN` params wrap the same way, so filters match natively-stored points instead of silently comparing a map against a POINT (`NULL` → row dropped). Driver `Point` instances still bind raw.
63
+
64
+ Unlike the temporal constructors, `point()` rejects an already-native POINT argument — so a list or batch column mixing plain maps with driver `Point` instances throws a clear `OGMError` at compile time, where it previously died as an opaque database error.
65
+
66
+ ### 🔧 Internal
67
+
68
+ The write-constructor helpers are no longer temporal-specific and were renamed accordingly (`wrapWriteExpr`, `wrapListItemExpr`, `wrapWhereParam`); each constructor family now carries an explicit list rule (`arrayMode: 'any'` for temporals — `datetime(datetime)` is legal Cypher — vs `'all'` for points). 2.1.0 temporal behavior is byte-identical.
69
+
70
+ ### Tests
71
+
72
+ - 7 new tests in `tests/type-faithful-writes.spec.ts` covering create/update wrapping, geographic + `CartesianPoint` input, driver-instance passthrough, list + mixed-list handling, WHERE `=`/`_IN`, and `createMany` columns.
73
+
3
74
  ## 2.1.0 (2026-08-13) — 🧭 Writes now store what the schema declares
4
75
 
5
76
  > **Every write path now binds values as the Neo4j type the schema promises.** Until now the compilers bound raw JS values and left the rest to the driver — and the driver packs every JS `number` as a Bolt FLOAT64 and every string as a String. So `Int`/`BigInt` fields landed as **Doubles** ([#5](https://github.com/neomodular/grafeo-ogm/issues/5)), the six temporal types landed as **Strings**, and `BigInt`'s documented string input landed as a **String** — while reads converted every native value back to a JS primitive, so the corruption was invisible until something type-sensitive touched the property. `@default` rode along: parsed, documented in the README, and applied nowhere.
package/README.md CHANGED
@@ -1302,6 +1302,54 @@ When `policies` is configured, every OGM-emitted query attaches transaction meta
1302
1302
 
1303
1303
  Disable via `policyDefaults: { auditMetadata: false }`. The fingerprint is intentionally key-only — no ctx values are leaked.
1304
1304
 
1305
+ `policiesEvaluated` lists only the policies that **applied** to the query. A restrictive whose `appliesWhen(ctx)` returned `false` is omitted (before v2.2.0 it was listed even though it contributed nothing). `explainPolicies` calls add `explain: true` and are always recorded, even with `auditMetadata: false`.
1306
+
1307
+ #### Explaining policy decisions
1308
+
1309
+ When a policy-bound read hides a node, `find` can only show *that* the node disappeared. `explainPolicies` shows *which* named clause decided it. It evaluates every `read` policy for the type separately, for each candidate node, without short-circuiting. Both `when:` and `cypher:` clauses are covered, and nodes the policies reject are returned too.
1310
+
1311
+ ```typescript
1312
+ const report = await ogm
1313
+ .withContext(ctx)
1314
+ .model('Chart')
1315
+ .explainPolicies({ where: { id_IN: candidateIds }, select: { id: true } });
1316
+
1317
+ // [{
1318
+ // node: { id: 'chart-8617' },
1319
+ // visible: false, // exactly what `find` would enforce
1320
+ // overriddenBy: null,
1321
+ // permissiveGranted: true,
1322
+ // failedRestrictives: ['chart.dose-translation-coverage'],
1323
+ // policies: [
1324
+ // { name: 'chart.read-grant', kind: 'permissive', source: 'Chart', applied: true, outcome: 'pass' },
1325
+ // { name: 'chart.weight-zone', kind: 'restrictive', source: 'Chart', applied: true, outcome: 'pass' },
1326
+ // { name: 'chart.text-field-scope', kind: 'restrictive', source: 'Chart', applied: false, outcome: 'not-applied' },
1327
+ // { name: 'chart.dose-translation-coverage', kind: 'restrictive', source: 'Chart', applied: true, outcome: 'fail' },
1328
+ // ],
1329
+ // }]
1330
+ ```
1331
+
1332
+ | `outcome` | Meaning |
1333
+ |---|---|
1334
+ | `pass` | Applied, and its predicate evaluated to `true`. |
1335
+ | `fail` | Applied, and it evaluated to `false`. This includes a restrictive hard deny (`when: () => false`). |
1336
+ | `null` | Applied, and it evaluated to NULL (for example, a missing property). Enforcement treats NULL as not-true. It is reported separately from `fail` because the fix is different. |
1337
+ | `abstain` | Applied, but it emitted no predicate. A permissive abstain grants nothing; a restrictive abstain restricts nothing. |
1338
+ | `not-applied` | `appliesWhen(ctx)` returned `false` (for an override: `when(ctx)` returned `false`). The policy was not evaluated. |
1339
+ | `skipped` | Not evaluated, because an earlier override fired. |
1340
+
1341
+ How it works:
1342
+
1343
+ - **Same predicates as `find`.** The explain query projects the exact compiled fragments `find` would enforce. `visible` is computed from the same composed predicate `find` puts in its `WHERE`. The verdict recomputed from the per-policy outcomes must agree with it; if it ever doesn't, the call throws instead of returning a wrong explanation.
1344
+ - **Candidate selection.** `where` and `labels` select candidates exactly as in `find`, including target-type policies on relationship filters. The root type's policy clause is reported, not used as a filter. Candidates that don't match `where` are simply absent from the result.
1345
+ - **Selection.** `select` / `selectionSet` accept everything `find` accepts. Relationships in the selection are still filtered by their own target-type policies. Only the root type's policies are explained.
1346
+ - **Read-only.** When grafeo opens the session itself, it opens it in `READ` access mode, so the server rejects any write. If you pass your own `transaction` or `session`, it is used as-is, and you control its access mode.
1347
+ - **Bounded.** `options.limit` defaults to 100, and values above 1,000 are rejected. Each candidate evaluates every policy, and the enforcement predicate is evaluated a second time for the cross-check, so explain costs more than a normal read. `sort` and `offset` are supported.
1348
+ - **Unnamed policies** are reported as `<source>.<kind>[<index>]` with `named: false`. Give every policy a `name` if you want stable, readable output.
1349
+ - **Default deny is reported, not thrown.** With `onDeny: 'throw'`, `explainPolicies` still returns rows with `visible: false` and `permissiveGranted: false`.
1350
+
1351
+ > **Security: `explainPolicies` bypasses policy filtering by design.** It returns nodes the bound context cannot see, together with their selected fields. Expose it only on admin-only diagnostic paths, and never let request input decide whether it runs. Every call logs a `warn` and is tagged `explain: true` in the transaction metadata. It is only available on policy-bound models (`ogm.withContext(ctx).model(...)`) and throws on a model with no policy binding or on a policy-bypassed OGM. In this release it covers `Model` and the `read` operation only: `InterfaceModel`, `count`, `aggregate`, and `delete` are not supported yet.
1352
+
1305
1353
  #### Limitations
1306
1354
 
1307
1355
  - **`@cypher` scalar fields inside a policy `where`-partial throw when the policy is injected into nested-selection enforcement.** Refactor the policy to use stored properties or a relationship traversal.
@@ -1879,6 +1927,7 @@ Open an issue on [GitHub](https://github.com/neomodular/grafeo-ogm/issues). For
1879
1927
  | `count(options?)` | `number` | Count matching nodes |
1880
1928
  | `aggregate(options)` | `AggregateResult` | Aggregate values (min, max, avg, count) |
1881
1929
  | `setLabels(options)` | `void` | Add or remove labels on matching nodes |
1930
+ | `explainPolicies(options?)` | `PolicyExplanation<T>[]` | Per-clause `read` policy outcomes per candidate, including hidden nodes (policy-bound models only; see [Explaining policy decisions](#explaining-policy-decisions)) |
1882
1931
 
1883
1932
  ### InterfaceModel
1884
1933
 
@@ -1 +1 @@
1
- {"version":3,"file":"mutation.compiler.d.ts","sourceRoot":"","sources":["../../../src/compilers/mutation.compiler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mutation.compiler.d.ts","sourceRoot":"","sources":["../../../src/compilers/mutation.compiler.ts"],"names":[],"mappings":"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"}
@@ -185,7 +185,7 @@ class MutationCompiler {
185
185
  (0, validation_1.assertSafePropertyName)(key, 'update property');
186
186
  const propDef = nodeDef.properties.get(key);
187
187
  const paramName = `update_${key}`;
188
- const valueExpr = (0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, value, propDef);
188
+ const valueExpr = (0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, value, propDef);
189
189
  setClauses.push(`n.${(0, validation_1.escapeIdentifier)(key)} = ${valueExpr}`);
190
190
  params[paramName] = (0, write_coercion_1.coerceWriteValue)(value, propDef);
191
191
  }
@@ -267,7 +267,7 @@ class MutationCompiler {
267
267
  (0, validation_1.assertSafePropertyName)(key, 'merge key');
268
268
  const propDef = nodeDef.properties.get(key);
269
269
  const paramName = `merge_${key}`;
270
- const valueExpr = (0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, value, propDef);
270
+ const valueExpr = (0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, value, propDef);
271
271
  mergeProps.push(`${(0, validation_1.escapeIdentifier)(key)}: ${valueExpr}`);
272
272
  mergeKeyNames.push(key);
273
273
  params[paramName] = (0, write_coercion_1.coerceWriteValue)(value, propDef);
@@ -308,7 +308,7 @@ class MutationCompiler {
308
308
  (0, validation_1.assertSafePropertyName)(key, 'create property');
309
309
  const propDef = nodeDef.properties.get(key);
310
310
  const paramName = `onCreate_${key}`;
311
- const valueExpr = (0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, value, propDef);
311
+ const valueExpr = (0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, value, propDef);
312
312
  createSets.push(`n.${(0, validation_1.escapeIdentifier)(key)} = ${valueExpr}`);
313
313
  params[paramName] = (0, write_coercion_1.coerceWriteValue)(value, propDef);
314
314
  }
@@ -326,7 +326,7 @@ class MutationCompiler {
326
326
  continue;
327
327
  const paramName = `onCreate_${propDef.name}`;
328
328
  const bound = (0, write_coercion_1.resolveDefaultWriteValue)(propDef);
329
- const valueExpr = (0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, bound, propDef);
329
+ const valueExpr = (0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, bound, propDef);
330
330
  createSets.push(`n.${(0, validation_1.escapeIdentifier)(propDef.name)} = ${valueExpr}`);
331
331
  params[paramName] = bound;
332
332
  }
@@ -342,7 +342,7 @@ class MutationCompiler {
342
342
  (0, validation_1.assertSafePropertyName)(key, 'update property');
343
343
  const propDef = nodeDef.properties.get(key);
344
344
  const paramName = `onMatch_${key}`;
345
- const valueExpr = (0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, value, propDef);
345
+ const valueExpr = (0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, value, propDef);
346
346
  updateSets.push(`n.${(0, validation_1.escapeIdentifier)(key)} = ${valueExpr}`);
347
347
  params[paramName] = (0, write_coercion_1.coerceWriteValue)(value, propDef);
348
348
  }
@@ -450,20 +450,20 @@ class MutationCompiler {
450
450
  throw new errors_1.OGMError('createMany with skipDuplicates requires at least one @id or @unique field in data');
451
451
  // MERGE on unique key(s)
452
452
  const mergeProps = mergeKeys
453
- .map((k) => `${(0, validation_1.escapeIdentifier)(k)}: ${(0, write_coercion_1.wrapTemporalListItemExpr)(`item.${(0, validation_1.escapeIdentifier)(k)}`, data.map((d) => d[k]), nodeDef.properties.get(k))}`)
453
+ .map((k) => `${(0, validation_1.escapeIdentifier)(k)}: ${(0, write_coercion_1.wrapListItemExpr)(`item.${(0, validation_1.escapeIdentifier)(k)}`, data.map((d) => d[k]), nodeDef.properties.get(k))}`)
454
454
  .join(', ');
455
455
  lines.push(`MERGE (n:${labelStr} { ${mergeProps} })`);
456
456
  // ON CREATE SET — remaining fields + generated IDs
457
457
  const onCreateSets = [];
458
458
  for (const key of scalarKeys)
459
459
  if (!mergeKeys.includes(key))
460
- onCreateSets.push(`n.${(0, validation_1.escapeIdentifier)(key)} = ${(0, write_coercion_1.wrapTemporalListItemExpr)(`item.${(0, validation_1.escapeIdentifier)(key)}`, data.map((d) => d[key]), nodeDef.properties.get(key))}`);
460
+ onCreateSets.push(`n.${(0, validation_1.escapeIdentifier)(key)} = ${(0, write_coercion_1.wrapListItemExpr)(`item.${(0, validation_1.escapeIdentifier)(key)}`, data.map((d) => d[key]), nodeDef.properties.get(key))}`);
461
461
  for (const field of generatedFields)
462
462
  onCreateSets.push(`n.${(0, validation_1.escapeIdentifier)(field)} = randomUUID()`);
463
463
  for (const propDef of defaultedProps) {
464
464
  const paramName = `default_${propDef.name}`;
465
465
  const bound = (0, write_coercion_1.resolveDefaultWriteValue)(propDef);
466
- onCreateSets.push(`n.${(0, validation_1.escapeIdentifier)(propDef.name)} = ${(0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, bound, propDef)}`);
466
+ onCreateSets.push(`n.${(0, validation_1.escapeIdentifier)(propDef.name)} = ${(0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, bound, propDef)}`);
467
467
  params[paramName] = bound;
468
468
  }
469
469
  if (onCreateSets.length > 0)
@@ -475,11 +475,11 @@ class MutationCompiler {
475
475
  for (const field of generatedFields)
476
476
  propParts.push(`${(0, validation_1.escapeIdentifier)(field)}: randomUUID()`);
477
477
  for (const key of scalarKeys)
478
- propParts.push(`${(0, validation_1.escapeIdentifier)(key)}: ${(0, write_coercion_1.wrapTemporalListItemExpr)(`item.${(0, validation_1.escapeIdentifier)(key)}`, data.map((d) => d[key]), nodeDef.properties.get(key))}`);
478
+ propParts.push(`${(0, validation_1.escapeIdentifier)(key)}: ${(0, write_coercion_1.wrapListItemExpr)(`item.${(0, validation_1.escapeIdentifier)(key)}`, data.map((d) => d[key]), nodeDef.properties.get(key))}`);
479
479
  for (const propDef of defaultedProps) {
480
480
  const paramName = `default_${propDef.name}`;
481
481
  const bound = (0, write_coercion_1.resolveDefaultWriteValue)(propDef);
482
- propParts.push(`${(0, validation_1.escapeIdentifier)(propDef.name)}: ${(0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, bound, propDef)}`);
482
+ propParts.push(`${(0, validation_1.escapeIdentifier)(propDef.name)}: ${(0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, bound, propDef)}`);
483
483
  params[paramName] = bound;
484
484
  }
485
485
  lines.push(`CREATE (n:${labelStr} { ${propParts.join(', ')} })`);
@@ -522,7 +522,7 @@ class MutationCompiler {
522
522
  (0, validation_1.assertSafePropertyName)(key, 'create property');
523
523
  const propDef = nodeDef.properties.get(key);
524
524
  const paramName = `${prefix}_${key}`;
525
- const valueExpr = (0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, value, propDef);
525
+ const valueExpr = (0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, value, propDef);
526
526
  parts.push(`${(0, validation_1.escapeIdentifier)(key)}: ${valueExpr}`);
527
527
  propParams[paramName] = (0, write_coercion_1.coerceWriteValue)(value, propDef);
528
528
  }
@@ -539,7 +539,7 @@ class MutationCompiler {
539
539
  continue;
540
540
  const paramName = `${prefix}_${propDef.name}`;
541
541
  const bound = (0, write_coercion_1.resolveDefaultWriteValue)(propDef);
542
- const valueExpr = (0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, bound, propDef);
542
+ const valueExpr = (0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, bound, propDef);
543
543
  parts.push(`${(0, validation_1.escapeIdentifier)(propDef.name)}: ${valueExpr}`);
544
544
  propParams[paramName] = bound;
545
545
  }
@@ -648,7 +648,7 @@ class MutationCompiler {
648
648
  (0, validation_1.assertSafePropertyName)(prop, 'edge property');
649
649
  const edgePropDef = this.getEdgePropDef(relDef, prop);
650
650
  const paramName = `${prefix}_create${ci}_edge_${prop}`;
651
- setItems.push(`${relVar}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
651
+ setItems.push(`${relVar}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
652
652
  params[paramName] = (0, write_coercion_1.coerceWriteValue)(val, edgePropDef);
653
653
  }
654
654
  if (setItems.length > 0)
@@ -701,7 +701,7 @@ class MutationCompiler {
701
701
  (0, validation_1.assertSafePropertyName)(prop, 'edge property');
702
702
  const edgePropDef = this.getEdgePropDef(relDef, prop);
703
703
  const paramName = `${prefix}_conn${ci}_edge_${prop}`;
704
- setItems.push(`r_conn_${startCounter + counter - 1}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
704
+ setItems.push(`r_conn_${startCounter + counter - 1}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
705
705
  params[paramName] = (0, write_coercion_1.coerceWriteValue)(val, edgePropDef);
706
706
  }
707
707
  if (setItems.length > 0)
@@ -773,7 +773,7 @@ class MutationCompiler {
773
773
  (0, validation_1.assertSafePropertyName)(prop, 'edge property');
774
774
  const edgePropDef = this.getEdgePropDef(relDef, prop);
775
775
  const paramName = `connect_${fieldName}_${ci}_edge_${prop}`;
776
- setItems.push(`${relVar}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
776
+ setItems.push(`${relVar}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
777
777
  params[paramName] = (0, write_coercion_1.coerceWriteValue)(val, edgePropDef);
778
778
  }
779
779
  if (setItems.length > 0)
@@ -851,7 +851,7 @@ class MutationCompiler {
851
851
  // Replace MERGE line with one that has a variable
852
852
  lines[lines.length - 1] = `MERGE ${mergeWithVar}`;
853
853
  // r.prop is relationship property (escape), connItem.edge.prop is parameter map (no escape)
854
- const setItems = edgeProps.map((p) => `r.${(0, validation_1.escapeIdentifier)(p)} = ${(0, write_coercion_1.wrapTemporalListItemExpr)(`connItem.edge.${p}`, spec.map((it) => it.edge?.[p]), this.getEdgePropDef(relDef, p))}`);
854
+ const setItems = edgeProps.map((p) => `r.${(0, validation_1.escapeIdentifier)(p)} = ${(0, write_coercion_1.wrapListItemExpr)(`connItem.edge.${p}`, spec.map((it) => it.edge?.[p]), this.getEdgePropDef(relDef, p))}`);
855
855
  lines.push(`SET ${setItems.join(', ')}`);
856
856
  }
857
857
  }
@@ -884,7 +884,7 @@ class MutationCompiler {
884
884
  continue;
885
885
  const edgePropDef = this.getEdgePropDef(relDef, prop);
886
886
  const paramName = `connect_${fieldName}_edge_${prop}`;
887
- setItems.push(`r.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
887
+ setItems.push(`r.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
888
888
  params[paramName] = (0, write_coercion_1.coerceWriteValue)(val, edgePropDef);
889
889
  }
890
890
  if (setItems.length > 0)
@@ -1200,7 +1200,7 @@ class MutationCompiler {
1200
1200
  (0, validation_1.assertSafePropertyName)(prop, 'edge property');
1201
1201
  const edgePropDef = this.getEdgePropDef(relDef, prop);
1202
1202
  const paramName = `${itemPrefix}_conn${ci}_edge_${prop}`;
1203
- setItems.push(`r_conn_${key}_${ci}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
1203
+ setItems.push(`r_conn_${key}_${ci}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
1204
1204
  params[paramName] = (0, write_coercion_1.coerceWriteValue)(val, edgePropDef);
1205
1205
  }
1206
1206
  if (setItems.length > 0)
@@ -1239,7 +1239,7 @@ class MutationCompiler {
1239
1239
  (0, validation_1.assertSafePropertyName)(prop, 'nested update property');
1240
1240
  const nodePropDef = targetNodeDef.properties.get(prop);
1241
1241
  const paramName = `${itemPrefix}_set_${prop}`;
1242
- setClauses.push(`${updateVar}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, val, nodePropDef)}`);
1242
+ setClauses.push(`${updateVar}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, val, nodePropDef)}`);
1243
1243
  setParams[paramName] = (0, write_coercion_1.coerceWriteValue)(val, nodePropDef);
1244
1244
  }
1245
1245
  // Pre-compute SET clauses for edge (relationship) properties
@@ -1252,7 +1252,7 @@ class MutationCompiler {
1252
1252
  (0, validation_1.assertSafePropertyName)(prop, 'edge update property');
1253
1253
  const edgePropDef = this.getEdgePropDef(relDef, prop);
1254
1254
  const paramName = `${itemPrefix}_edge_${prop}`;
1255
- edgeClauses.push(`${relVar}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapTemporalWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
1255
+ edgeClauses.push(`${relVar}.${(0, validation_1.escapeIdentifier)(prop)} = ${(0, write_coercion_1.wrapWriteExpr)(`$${paramName}`, val, edgePropDef)}`);
1256
1256
  edgeParams[paramName] = (0, write_coercion_1.coerceWriteValue)(val, edgePropDef);
1257
1257
  }
1258
1258
  // Pre-compute nested relationship operations
@@ -1339,7 +1339,7 @@ class MutationCompiler {
1339
1339
  (0, validation_1.assertSafePropertyName)(baseProp, 'where property');
1340
1340
  const paramName = `${prefix}_NOT_${notProp}`;
1341
1341
  const escapedProp = (0, validation_1.escapeIdentifier)(baseProp);
1342
- const paramRef = (0, write_coercion_1.wrapTemporalWhereParam)(`$${paramName}`, notVal, targetNodeDef?.properties.get(baseProp), notProp.slice(baseProp.length));
1342
+ const paramRef = (0, write_coercion_1.wrapWhereParam)(`$${paramName}`, notVal, targetNodeDef?.properties.get(baseProp), notProp.slice(baseProp.length));
1343
1343
  let expr;
1344
1344
  if (template === '%v = $%p')
1345
1345
  // Simple equality → negate to <>
@@ -1365,7 +1365,7 @@ class MutationCompiler {
1365
1365
  const { baseProp, template } = this.parseOperatorSuffix(prop);
1366
1366
  (0, validation_1.assertSafePropertyName)(baseProp, 'where property');
1367
1367
  const paramName = `${prefix}_${prop}`;
1368
- const paramRef = (0, write_coercion_1.wrapTemporalWhereParam)(`$${paramName}`, val, targetNodeDef?.properties.get(baseProp), prop.slice(baseProp.length));
1368
+ const paramRef = (0, write_coercion_1.wrapWhereParam)(`$${paramName}`, val, targetNodeDef?.properties.get(baseProp), prop.slice(baseProp.length));
1369
1369
  conditions.push(template
1370
1370
  .replace('%v', `${targetVar}.${(0, validation_1.escapeIdentifier)(baseProp)}`)
1371
1371
  .replace('$%p', paramRef));
@@ -1546,7 +1546,7 @@ class MutationCompiler {
1546
1546
  // Note: itemVar map access is NOT escaped (parameter map keys, not Cypher identifiers)
1547
1547
  // Temporal wrap keys off the FIRST item's value type — the UNWIND
1548
1548
  // fast path already requires shape-homogeneous items.
1549
- const valueRef = (0, write_coercion_1.wrapTemporalWhereParam)(`${itemVar}.where.node.${key}`, nodeWhere[key], targetNodeDef?.properties.get(baseProp), key.slice(baseProp.length));
1549
+ const valueRef = (0, write_coercion_1.wrapWhereParam)(`${itemVar}.where.node.${key}`, nodeWhere[key], targetNodeDef?.properties.get(baseProp), key.slice(baseProp.length));
1550
1550
  conditions.push(template
1551
1551
  .replace('%v', `${targetVar}.${(0, validation_1.escapeIdentifier)(baseProp)}`)
1552
1552
  .replace('$%p', valueRef));