@nicia-ai/typegraph 0.31.0 → 0.32.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 (125) hide show
  1. package/dist/backend/postgres/index.cjs +16 -16
  2. package/dist/backend/postgres/index.d.cts +5 -5
  3. package/dist/backend/postgres/index.d.ts +5 -5
  4. package/dist/backend/postgres/index.js +6 -6
  5. package/dist/backend/postgres/pglite.cjs +9 -9
  6. package/dist/backend/postgres/pglite.d.cts +2 -2
  7. package/dist/backend/postgres/pglite.d.ts +2 -2
  8. package/dist/backend/postgres/pglite.js +6 -6
  9. package/dist/backend/sqlite/index.cjs +14 -14
  10. package/dist/backend/sqlite/index.d.cts +6 -6
  11. package/dist/backend/sqlite/index.d.ts +6 -6
  12. package/dist/backend/sqlite/index.js +5 -5
  13. package/dist/backend/sqlite/libsql.cjs +10 -10
  14. package/dist/backend/sqlite/libsql.d.cts +2 -2
  15. package/dist/backend/sqlite/libsql.d.ts +2 -2
  16. package/dist/backend/sqlite/libsql.js +6 -6
  17. package/dist/backend/sqlite/local.cjs +10 -10
  18. package/dist/backend/sqlite/local.d.cts +2 -2
  19. package/dist/backend/sqlite/local.d.ts +2 -2
  20. package/dist/backend/sqlite/local.js +6 -6
  21. package/dist/{chunk-XKJQQQVR.js → chunk-2BVHPOIG.js} +3 -3
  22. package/dist/{chunk-XKJQQQVR.js.map → chunk-2BVHPOIG.js.map} +1 -1
  23. package/dist/{chunk-RZ4DH4E7.cjs → chunk-2LAT5BIK.cjs} +662 -217
  24. package/dist/chunk-2LAT5BIK.cjs.map +1 -0
  25. package/dist/{chunk-CIINW6PS.cjs → chunk-3HQDMOBK.cjs} +64 -64
  26. package/dist/{chunk-CIINW6PS.cjs.map → chunk-3HQDMOBK.cjs.map} +1 -1
  27. package/dist/{chunk-6SA7UIQJ.cjs → chunk-3QRBXYT5.cjs} +6 -6
  28. package/dist/{chunk-6SA7UIQJ.cjs.map → chunk-3QRBXYT5.cjs.map} +1 -1
  29. package/dist/{chunk-4A4GUZTQ.js → chunk-7WW3WL6E.js} +5 -5
  30. package/dist/{chunk-4A4GUZTQ.js.map → chunk-7WW3WL6E.js.map} +1 -1
  31. package/dist/{chunk-2HZGWCB4.js → chunk-C4C4Q7A6.js} +3 -3
  32. package/dist/chunk-C4C4Q7A6.js.map +1 -0
  33. package/dist/{chunk-SFFJ2IKN.cjs → chunk-CAMMC3E4.cjs} +58 -58
  34. package/dist/{chunk-SFFJ2IKN.cjs.map → chunk-CAMMC3E4.cjs.map} +1 -1
  35. package/dist/{chunk-O4VUR6SI.js → chunk-CEF2QOTO.js} +3 -3
  36. package/dist/{chunk-O4VUR6SI.js.map → chunk-CEF2QOTO.js.map} +1 -1
  37. package/dist/{chunk-V4IQYOQ4.cjs → chunk-CFNT3ITG.cjs} +3 -3
  38. package/dist/chunk-CFNT3ITG.cjs.map +1 -0
  39. package/dist/{chunk-LJLMDDCW.js → chunk-CWFPJ3RC.js} +3 -3
  40. package/dist/{chunk-LJLMDDCW.js.map → chunk-CWFPJ3RC.js.map} +1 -1
  41. package/dist/{chunk-7JGLPAFV.cjs → chunk-EEYV6UOE.cjs} +16 -16
  42. package/dist/chunk-EEYV6UOE.cjs.map +1 -0
  43. package/dist/{chunk-ASYQDPPU.cjs → chunk-FDN43KXV.cjs} +19 -19
  44. package/dist/{chunk-ASYQDPPU.cjs.map → chunk-FDN43KXV.cjs.map} +1 -1
  45. package/dist/{chunk-THX25XW6.js → chunk-HFBRAOF7.js} +27 -7
  46. package/dist/chunk-HFBRAOF7.js.map +1 -0
  47. package/dist/{chunk-54JVNOAQ.cjs → chunk-JKRKIEVA.cjs} +5 -5
  48. package/dist/{chunk-54JVNOAQ.cjs.map → chunk-JKRKIEVA.cjs.map} +1 -1
  49. package/dist/{chunk-5DTPBFX5.cjs → chunk-LAZGHOZW.cjs} +10 -10
  50. package/dist/{chunk-5DTPBFX5.cjs.map → chunk-LAZGHOZW.cjs.map} +1 -1
  51. package/dist/{chunk-N2MBPTAF.cjs → chunk-LM2IC4ZJ.cjs} +14 -14
  52. package/dist/{chunk-N2MBPTAF.cjs.map → chunk-LM2IC4ZJ.cjs.map} +1 -1
  53. package/dist/{chunk-STP7QVUB.js → chunk-NDM5PXEH.js} +5 -5
  54. package/dist/{chunk-STP7QVUB.js.map → chunk-NDM5PXEH.js.map} +1 -1
  55. package/dist/{chunk-2ZY4K43M.js → chunk-PIHXFF73.js} +3 -3
  56. package/dist/{chunk-2ZY4K43M.js.map → chunk-PIHXFF73.js.map} +1 -1
  57. package/dist/{chunk-ATTXBMAX.js → chunk-PRMKPFN5.js} +3 -3
  58. package/dist/{chunk-ATTXBMAX.js.map → chunk-PRMKPFN5.js.map} +1 -1
  59. package/dist/{chunk-3JBJEYWE.cjs → chunk-SB65GJNY.cjs} +32 -12
  60. package/dist/chunk-SB65GJNY.cjs.map +1 -0
  61. package/dist/{chunk-VZX2KSY3.js → chunk-TUA3MEJJ.js} +5 -5
  62. package/dist/{chunk-VZX2KSY3.js.map → chunk-TUA3MEJJ.js.map} +1 -1
  63. package/dist/{chunk-MAQJYNJR.js → chunk-W4ZX2GCP.js} +14 -16
  64. package/dist/chunk-W4ZX2GCP.js.map +1 -0
  65. package/dist/{chunk-UIFEEPME.js → chunk-WNORITK6.js} +593 -149
  66. package/dist/chunk-WNORITK6.js.map +1 -0
  67. package/dist/{chunk-VMEWZU2N.cjs → chunk-WWVV44DY.cjs} +11 -11
  68. package/dist/{chunk-VMEWZU2N.cjs.map → chunk-WWVV44DY.cjs.map} +1 -1
  69. package/dist/{chunk-UJ4V3YUQ.js → chunk-XKNAK27R.js} +3 -3
  70. package/dist/{chunk-UJ4V3YUQ.js.map → chunk-XKNAK27R.js.map} +1 -1
  71. package/dist/{chunk-GKFWM3DS.js → chunk-XQFAJVYW.js} +3 -3
  72. package/dist/{chunk-GKFWM3DS.js.map → chunk-XQFAJVYW.js.map} +1 -1
  73. package/dist/{chunk-FLOI7QOT.cjs → chunk-YL4F3CMD.cjs} +59 -59
  74. package/dist/{chunk-FLOI7QOT.cjs.map → chunk-YL4F3CMD.cjs.map} +1 -1
  75. package/dist/{chunk-5CN7B4CZ.cjs → chunk-YW7GHMF4.cjs} +17 -17
  76. package/dist/{chunk-5CN7B4CZ.cjs.map → chunk-YW7GHMF4.cjs.map} +1 -1
  77. package/dist/{ddl-BJcPrB4L.d.ts → ddl-C8e8zDAE.d.ts} +3 -3
  78. package/dist/{ddl-CPZ7mB7X.d.cts → ddl-CwyG4HoQ.d.cts} +3 -3
  79. package/dist/graph-merge/index.cjs +193 -49
  80. package/dist/graph-merge/index.cjs.map +1 -1
  81. package/dist/graph-merge/index.d.cts +3 -3
  82. package/dist/graph-merge/index.d.ts +3 -3
  83. package/dist/graph-merge/index.js +180 -36
  84. package/dist/graph-merge/index.js.map +1 -1
  85. package/dist/index.cjs +89 -85
  86. package/dist/index.d.cts +7 -7
  87. package/dist/index.d.ts +7 -7
  88. package/dist/index.js +12 -12
  89. package/dist/indexes/index.cjs +10 -10
  90. package/dist/indexes/index.d.cts +4 -4
  91. package/dist/indexes/index.d.ts +4 -4
  92. package/dist/indexes/index.js +3 -3
  93. package/dist/interchange/index.cjs +15 -15
  94. package/dist/interchange/index.d.cts +7 -7
  95. package/dist/interchange/index.d.ts +7 -7
  96. package/dist/interchange/index.js +2 -2
  97. package/dist/{manager-By-WEd8M.d.ts → manager-8htmuGr-.d.ts} +1 -1
  98. package/dist/{manager-Np7VVSlE.d.cts → manager-aVgxbGt-.d.cts} +1 -1
  99. package/dist/{postgres-BdIb7tS_.d.ts → postgres-Dhom7iiX.d.ts} +1 -1
  100. package/dist/{postgres-4J2tmauh.d.cts → postgres-jgXmD45C.d.cts} +1 -1
  101. package/dist/profiler/index.d.cts +5 -5
  102. package/dist/profiler/index.d.ts +5 -5
  103. package/dist/schema/index.cjs +26 -26
  104. package/dist/schema/index.d.cts +4 -4
  105. package/dist/schema/index.d.ts +4 -4
  106. package/dist/schema/index.js +3 -3
  107. package/dist/{sqlite-aM_PAz-O.d.ts → sqlite-BfLsCEqO.d.ts} +1 -1
  108. package/dist/{sqlite-Gatk_iw_.d.cts → sqlite-DcQ_BCUW.d.cts} +1 -1
  109. package/dist/{store-DuCbdqsh.d.cts → store-view-lTcb_cnp.d.cts} +639 -311
  110. package/dist/{store-MloRPwb9.d.ts → store-view-pBOUrQte.d.ts} +639 -311
  111. package/dist/{types-DoByHGyU.d.cts → types-5RQwzWXx.d.cts} +1 -1
  112. package/dist/{types-K3vpaJAL.d.ts → types-DGDiXAYc.d.ts} +1 -1
  113. package/dist/{types-BKQljXom.d.ts → types-Dk8r09KY.d.ts} +1 -1
  114. package/dist/{types-C1CYxWrL.d.cts → types-Dvmn-eal.d.cts} +1 -1
  115. package/dist/{where-Dt49bvo6.d.ts → where-CHZFELX0.d.ts} +1 -1
  116. package/dist/{where-DydZjGOb.d.cts → where-Cx_glEEB.d.cts} +1 -1
  117. package/package.json +2 -2
  118. package/dist/chunk-2HZGWCB4.js.map +0 -1
  119. package/dist/chunk-3JBJEYWE.cjs.map +0 -1
  120. package/dist/chunk-7JGLPAFV.cjs.map +0 -1
  121. package/dist/chunk-MAQJYNJR.js.map +0 -1
  122. package/dist/chunk-RZ4DH4E7.cjs.map +0 -1
  123. package/dist/chunk-THX25XW6.js.map +0 -1
  124. package/dist/chunk-UIFEEPME.js.map +0 -1
  125. package/dist/chunk-V4IQYOQ4.cjs.map +0 -1
@@ -1,20 +1,361 @@
1
1
  import { quoteIdentifier, EMPTY_REQUIRED_COLUMNS, addRequiredColumn, markSelectiveFieldAsRequired, markFieldRefAsRequired, NODE_COLUMNS, shouldProjectColumn, mapSelectiveSystemFieldToColumn, isIdFieldRef, isAggregateExpr, EDGE_COLUMNS } from './chunk-3EUKJEQ3.js';
2
- import { loadAndMergeGraphExtensionDocument, ensureSchema, loadAndVerifyGraph, mergeGraphExtension, commitNewSchemaVersion, applyDeprecatedKinds, loadActiveSchemaWithBootstrap, parseSerializedSchema, computeClosuresFromOntology, createEmptyClosures, KindRegistry, extensionKindNames, serializeSchemaProperties, buildGraphExtensionOntologyKeySet, compileTimeOntologyKey, getTypeName, validateNodeProps, validateEdgeProps } from './chunk-XKJQQQVR.js';
3
- import { nowIso, isKnownKind, validateOptionalIsoDate, getNodeKinds, getEdgeKinds } from './chunk-MAQJYNJR.js';
4
- import { generateIndexDDL } from './chunk-2ZY4K43M.js';
2
+ import { loadAndMergeGraphExtensionDocument, ensureSchema, loadAndVerifyGraph, mergeGraphExtension, commitNewSchemaVersion, applyDeprecatedKinds, loadActiveSchemaWithBootstrap, parseSerializedSchema, computeClosuresFromOntology, createEmptyClosures, KindRegistry, extensionKindNames, serializeSchemaProperties, buildGraphExtensionOntologyKeySet, compileTimeOntologyKey, getTypeName, validateNodeProps, validateEdgeProps } from './chunk-2BVHPOIG.js';
3
+ import { nowIso, isKnownKind, validateCanonicalIsoDate, validateOptionalCanonicalIsoDate, getNodeKinds, getEdgeKinds } from './chunk-W4ZX2GCP.js';
4
+ import { generateIndexDDL } from './chunk-PIHXFF73.js';
5
5
  import { NODE_META_KEYS, EDGE_META_KEYS } from './chunk-IJORSAC3.js';
6
6
  import { createSchemaIntrospector, resolveFieldTypeInfoAtJsonPointer, getSearchableMetadata, DEFAULT_SEARCHABLE_LANGUAGE } from './chunk-MXE2U3EX.js';
7
7
  import { resolveEmbeddingFields } from './chunk-454I6GDF.js';
8
8
  import { IncompatibleChangeError, filterReservedKeys, RESERVED_NODE_KEYS, RESERVED_EDGE_KEYS, RemoveCompileTimeKindError, KindHasReferentsError, validateProjectionField } from './chunk-YCV72E6L.js';
9
9
  import { runOptionallyInTransaction } from './chunk-SAJSMR2B.js';
10
10
  import { sortedReplacer, canonicalEqual, isMissingTableError } from './chunk-M6OC455F.js';
11
- import { getDialect, assertVectorMinScore, compileNodeIndexFieldKeys, compileIndexWhere, vectorScoreExpression, vectorMinScoreCondition } from './chunk-2HZGWCB4.js';
11
+ import { getDialect, assertVectorMinScore, compileNodeIndexFieldKeys, compileIndexWhere, vectorScoreExpression, vectorMinScoreCondition } from './chunk-C4C4Q7A6.js';
12
12
  import { MAX_PG_IDENTIFIER_LENGTH, DEFAULT_PAGINATION_LIMIT, DEFAULT_STREAM_BATCH_SIZE, sha256Hex, SQLITE_PATH_DELIMITER, PG_ARRAY_START, PG_ARRAY_END, PG_PATH_ELEMENT_SEPARATOR, fnv1aBase36 } from './chunk-2YMGNYXY.js';
13
13
  import { ConfigurationError, UnsupportedPredicateError, ValidationError, KindNotFoundError, EndpointError, EagerMaterializationError, CompilerInvariantError, DatabaseOperationError, EdgeNotFoundError, NodeIndexNotFoundError, NodeConstraintNotFoundError, RestrictedDeleteError, NodeNotFoundError, EndpointNotFoundError, UniquenessError, CardinalityError, DisjointError } from './chunk-TQOYM4LN.js';
14
14
  import { jsonPointer, parseJsonPointer, resolveJsonPointer, normalizeJsonPointer, joinJsonPointers } from './chunk-K5P5OZXS.js';
15
15
  import { sql, Placeholder } from 'drizzle-orm';
16
16
  import { nanoid } from 'nanoid';
17
17
 
18
+ // src/core/temporal.ts
19
+ function resolveReadCoordinate(mode, asOf, suggestion) {
20
+ if (mode !== "asOf" && asOf !== void 0) {
21
+ throw new ValidationError(
22
+ `Temporal mode "${mode}" does not take an asOf timestamp.`,
23
+ {
24
+ issues: [
25
+ {
26
+ path: "asOf",
27
+ message: `asOf is only valid with mode "asOf", not "${mode}"`
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ suggestion: 'Pin an instant with store.asOf(timestamp) or store.view({ mode: "asOf", asOf }); drop asOf for other modes.'
33
+ }
34
+ );
35
+ }
36
+ assertValidAsOf(
37
+ mode,
38
+ asOf,
39
+ suggestion === void 0 ? void 0 : { suggestion }
40
+ );
41
+ return { valid: asOf === void 0 ? { mode } : { mode, asOf } };
42
+ }
43
+ function assertValidAsOf(mode, asOf, options) {
44
+ if (mode === "asOf" && asOf === void 0) {
45
+ throw new ValidationError(
46
+ 'Temporal mode "asOf" requires a timestamp',
47
+ {
48
+ issues: [
49
+ { path: "asOf", message: "Timestamp is required for asOf mode" }
50
+ ]
51
+ },
52
+ {
53
+ suggestion: options?.suggestion ?? 'Provide an ISO-8601 timestamp for asOf mode, e.g. "2026-01-01T00:00:00.000Z".'
54
+ }
55
+ );
56
+ }
57
+ if (asOf !== void 0) {
58
+ validateCanonicalIsoDate(asOf, "asOf");
59
+ }
60
+ }
61
+ function describeCoordinate(coordinate) {
62
+ const { mode, asOf } = coordinate.valid;
63
+ return asOf === void 0 ? `mode "${mode}"` : `mode "${mode}" asOf ${asOf}`;
64
+ }
65
+ function coordinateContext(coordinate) {
66
+ const { mode, asOf } = coordinate.valid;
67
+ return { temporalMode: mode, ...asOf !== void 0 && { asOf } };
68
+ }
69
+
70
+ // src/store/collections/temporal-read-params.ts
71
+ function withCoordinate(coordinate) {
72
+ const { mode, asOf } = coordinate.valid;
73
+ return asOf === void 0 ? { temporalMode: mode } : { temporalMode: mode, asOf };
74
+ }
75
+ function resolveTemporalReadParams(options, defaultTemporalMode) {
76
+ const { valid } = resolveReadCoordinate(
77
+ options?.temporalMode ?? defaultTemporalMode,
78
+ options?.asOf
79
+ );
80
+ const { mode, asOf } = valid;
81
+ const base = {
82
+ excludeDeleted: mode !== "includeTombstones",
83
+ temporalMode: mode
84
+ };
85
+ if (mode === "current" || mode === "asOf") {
86
+ return { ...base, asOf: asOf ?? nowIso() };
87
+ }
88
+ return base;
89
+ }
90
+
91
+ // src/store/types.ts
92
+ var CURRENT_ONLY_READ_NAMES = [
93
+ "findByConstraint",
94
+ "bulkFindByConstraint",
95
+ "bulkFindByIndex"
96
+ ];
97
+
98
+ // src/store/store-view.ts
99
+ var NON_KIND_KEYS = /* @__PURE__ */ new Set([
100
+ "then",
101
+ "catch",
102
+ "finally",
103
+ "toJSON"
104
+ ]);
105
+ function createReadOnlyRefusal(entity, method, coordinate) {
106
+ return () => {
107
+ throw new ConfigurationError(
108
+ `'${method}' is not available on a read-only StoreView (${describeCoordinate(coordinate)}). A time-pinned view is a read perspective \u2014 perform writes on the live Store.`,
109
+ {
110
+ code: "STORE_VIEW_READ_ONLY",
111
+ entity,
112
+ method,
113
+ ...coordinateContext(coordinate)
114
+ }
115
+ );
116
+ };
117
+ }
118
+ function createCurrentOnlyRefusal(entity, method, coordinate) {
119
+ return () => Promise.reject(
120
+ new ConfigurationError(
121
+ `'${method}' is not available on a StoreView (${describeCoordinate(coordinate)}). Constraint / index / endpoint lookups read current state only and cannot honor a temporal coordinate \u2014 use a current-mode view or the live Store.`,
122
+ {
123
+ code: "STORE_VIEW_CURRENT_ONLY",
124
+ entity,
125
+ method,
126
+ ...coordinateContext(coordinate)
127
+ }
128
+ )
129
+ );
130
+ }
131
+ var CURRENT_ONLY_READS = new Set(
132
+ CURRENT_ONLY_READ_NAMES
133
+ );
134
+ function readOnlyCollectionProxy(reads, live, coordinate, entity) {
135
+ const isCurrent = coordinate.valid.mode === "current";
136
+ const target = Object.freeze(reads);
137
+ return new Proxy(target, {
138
+ get(target2, property, receiver) {
139
+ if (typeof property === "string" && !Object.hasOwn(target2, property) && Object.hasOwn(live, property)) {
140
+ if (CURRENT_ONLY_READS.has(property)) {
141
+ return isCurrent ? live[property] : createCurrentOnlyRefusal(entity, property, coordinate);
142
+ }
143
+ return createReadOnlyRefusal(entity, property, coordinate);
144
+ }
145
+ return Reflect.get(target2, property, receiver);
146
+ },
147
+ has(target2, property) {
148
+ return typeof property === "string" && Object.hasOwn(live, property) || Reflect.has(target2, property);
149
+ },
150
+ set() {
151
+ return false;
152
+ },
153
+ defineProperty() {
154
+ return false;
155
+ },
156
+ deleteProperty() {
157
+ return false;
158
+ }
159
+ });
160
+ }
161
+ function pinnedNodeCollection(live, coordinate) {
162
+ const temporal = withCoordinate(coordinate);
163
+ const reads = {
164
+ getById: (id) => live.getById(id, temporal),
165
+ getByIds: (ids) => live.getByIds(ids, temporal),
166
+ // `live.find` is the NodeCollection read, not Array#find — the
167
+ // (filter, temporal) shape trips the array-method heuristics.
168
+ // eslint-disable-next-line unicorn/no-array-callback-reference, unicorn/no-array-method-this-argument
169
+ find: (filter) => live.find(filter, temporal),
170
+ count: () => live.count(temporal)
171
+ };
172
+ return readOnlyCollectionProxy(
173
+ reads,
174
+ live,
175
+ coordinate,
176
+ "node"
177
+ );
178
+ }
179
+ function pinnedEdgeCollection(live, coordinate) {
180
+ const temporal = withCoordinate(coordinate);
181
+ const reads = {
182
+ getById: (id) => live.getById(id, temporal),
183
+ getByIds: (ids) => live.getByIds(ids, temporal),
184
+ // `live.find` is the EdgeCollection read, not Array#find — the
185
+ // (filter, temporal) shape trips the array-method heuristics.
186
+ // eslint-disable-next-line unicorn/no-array-callback-reference, unicorn/no-array-method-this-argument
187
+ find: (filter) => live.find(filter, temporal),
188
+ count: (filter) => live.count(filter, temporal),
189
+ findFrom: (from) => live.findFrom(from, temporal),
190
+ findTo: (to) => live.findTo(to, temporal),
191
+ findByEndpoints: (from, to, options) => live.findByEndpoints(from, to, options, temporal)
192
+ };
193
+ return readOnlyCollectionProxy(reads, live, coordinate, "edge");
194
+ }
195
+ function pinnedCollections(live, coordinate, wrap) {
196
+ const cache = /* @__PURE__ */ new Map();
197
+ return new Proxy(
198
+ {},
199
+ {
200
+ get(_target, kind) {
201
+ if (typeof kind !== "string" || NON_KIND_KEYS.has(kind)) return;
202
+ const cached = cache.get(kind);
203
+ if (cached !== void 0) return cached;
204
+ const wrapped = wrap(live[kind], coordinate);
205
+ cache.set(kind, wrapped);
206
+ return wrapped;
207
+ }
208
+ }
209
+ );
210
+ }
211
+ var READ_SEARCH_METHOD_NAMES = [
212
+ "fulltext",
213
+ "vector",
214
+ "hybrid"
215
+ ];
216
+ var READ_SEARCH_METHODS = new Set(
217
+ READ_SEARCH_METHOD_NAMES
218
+ );
219
+ function searchRefusal(method, coordinate, isCurrent) {
220
+ return isCurrent ? new ConfigurationError(
221
+ `store.search.${method} is a maintenance write and is not available on a read-only StoreView. Run it on the live Store.`,
222
+ {
223
+ code: "STORE_VIEW_READ_ONLY",
224
+ method,
225
+ ...coordinateContext(coordinate)
226
+ }
227
+ ) : new ConfigurationError(
228
+ `store.search.${method} is not available on a StoreView (${describeCoordinate(coordinate)}). The fulltext / vector index reflects current state only; historical relevance is out of scope for a temporal view. Use a current-mode view or query the live Store.`,
229
+ {
230
+ code: "STORE_VIEW_SEARCH_UNSUPPORTED",
231
+ method,
232
+ ...coordinateContext(coordinate)
233
+ }
234
+ );
235
+ }
236
+ function pinnedSearch(store, coordinate) {
237
+ const isCurrent = coordinate.valid.mode === "current";
238
+ const live = isCurrent ? store.search : void 0;
239
+ return new Proxy({}, {
240
+ get(target, method, receiver) {
241
+ if (typeof method !== "string" || NON_KIND_KEYS.has(method)) {
242
+ return;
243
+ }
244
+ if (Object.hasOwn(Object.prototype, method)) {
245
+ const inheritedValue = Reflect.get(target, method, receiver);
246
+ return inheritedValue;
247
+ }
248
+ if (live !== void 0 && READ_SEARCH_METHODS.has(method)) {
249
+ return (...args) => live[method](...args);
250
+ }
251
+ return () => Promise.reject(searchRefusal(method, coordinate, isCurrent));
252
+ }
253
+ });
254
+ }
255
+ var StoreView = class {
256
+ #store;
257
+ #coordinate;
258
+ #nodes;
259
+ #edges;
260
+ #search;
261
+ constructor(store, coordinate) {
262
+ this.#store = store;
263
+ this.#coordinate = resolveReadCoordinate(
264
+ coordinate.mode,
265
+ coordinate.asOf,
266
+ 'Use store.asOf("2026-01-01T00:00:00.000Z") or store.view({ mode: "asOf", asOf }).'
267
+ );
268
+ }
269
+ /** The temporal mode this view reads in. */
270
+ get mode() {
271
+ return this.#coordinate.valid.mode;
272
+ }
273
+ /** The pinned `asOf` timestamp, or `undefined` for non-`asOf` modes. */
274
+ get asOf() {
275
+ return this.#coordinate.valid.asOf;
276
+ }
277
+ /** Read-only node collections pinned to this view's coordinate. */
278
+ get nodes() {
279
+ this.#nodes ??= pinnedCollections(
280
+ this.#store.nodes,
281
+ this.#coordinate,
282
+ pinnedNodeCollection
283
+ );
284
+ return this.#nodes;
285
+ }
286
+ /** Read-only edge collections pinned to this view's coordinate. */
287
+ get edges() {
288
+ this.#edges ??= pinnedCollections(
289
+ this.#store.edges,
290
+ this.#coordinate,
291
+ pinnedEdgeCollection
292
+ );
293
+ return this.#edges;
294
+ }
295
+ /**
296
+ * A query builder pinned to this view's coordinate. The temporal axis is
297
+ * sealed: calling `.temporal(...)` on the returned builder throws, so the
298
+ * view's coordinate cannot be overridden on a per-query basis.
299
+ */
300
+ query() {
301
+ return this.#store.sealedQuery(this.#coordinate);
302
+ }
303
+ /** Extracts a subgraph at this view's pinned coordinate. */
304
+ subgraph(rootId, options) {
305
+ return this.#store.subgraph(rootId, {
306
+ ...options,
307
+ ...withCoordinate(this.#coordinate)
308
+ });
309
+ }
310
+ /** Shortest path between two nodes at this view's pinned coordinate. */
311
+ shortestPath(from, to, options) {
312
+ return this.#store.algorithms.shortestPath(from, to, {
313
+ ...options,
314
+ ...withCoordinate(this.#coordinate)
315
+ });
316
+ }
317
+ /** Nodes reachable from `from` at this view's pinned coordinate. */
318
+ reachable(from, options) {
319
+ return this.#store.algorithms.reachable(from, {
320
+ ...options,
321
+ ...withCoordinate(this.#coordinate)
322
+ });
323
+ }
324
+ /** Whether `to` is reachable from `from` at this view's pinned coordinate. */
325
+ canReach(from, to, options) {
326
+ return this.#store.algorithms.canReach(from, to, {
327
+ ...options,
328
+ ...withCoordinate(this.#coordinate)
329
+ });
330
+ }
331
+ /** The k-hop neighborhood of `node` at this view's pinned coordinate. */
332
+ neighbors(node, options) {
333
+ return this.#store.algorithms.neighbors(node, {
334
+ ...options,
335
+ ...withCoordinate(this.#coordinate)
336
+ });
337
+ }
338
+ /** Counts active edges incident to `node` at this view's pinned coordinate. */
339
+ degree(node, options) {
340
+ return this.#store.algorithms.degree(node, {
341
+ ...options,
342
+ ...withCoordinate(this.#coordinate)
343
+ });
344
+ }
345
+ /**
346
+ * Read-only search facade. On a `current` view the read methods
347
+ * (`fulltext` / `vector` / `hybrid`) delegate to the live `store.search`,
348
+ * while the mutating `rebuildFulltext` is refused — the view is read-only.
349
+ * On any non-`current` pin every search method refuses: the fulltext /
350
+ * vector index reflects current state only, so historical relevance is
351
+ * out of scope.
352
+ */
353
+ get search() {
354
+ this.#search ??= pinnedSearch(this.#store, this.#coordinate);
355
+ return this.#search;
356
+ }
357
+ };
358
+
18
359
  // src/query/subquery-utils.ts
19
360
  function normalizeValueType(valueType) {
20
361
  if (valueType === void 0 || valueType === "unknown") {
@@ -2505,7 +2846,7 @@ function runVectorPredicatePass(ast, dialect, vectorStrategy) {
2505
2846
  `Vector minScore must be a finite number, got ${String(minScore)}`
2506
2847
  );
2507
2848
  }
2508
- if (vectorPredicate.metric === "cosine" && (minScore < -1 || minScore > 1)) {
2849
+ if (vectorPredicate.metric === "cosine" && Math.abs(minScore) > 1) {
2509
2850
  throw new UnsupportedPredicateError(
2510
2851
  `Cosine minScore must be between -1 and 1, got ${String(minScore)}`
2511
2852
  );
@@ -3604,6 +3945,11 @@ function defineSubgraphProject(_graph) {
3604
3945
  }
3605
3946
  async function executeSubgraph(params) {
3606
3947
  const { options } = params;
3948
+ const { valid: coordinate } = resolveReadCoordinate(
3949
+ options.temporalMode ?? params.graph.defaults.temporalMode,
3950
+ options.asOf
3951
+ );
3952
+ const temporalMode = coordinate.mode;
3607
3953
  const maxDepth = Math.min(
3608
3954
  options.maxDepth ?? DEFAULT_SUBGRAPH_MAX_DEPTH,
3609
3955
  MAX_EXPLICIT_RECURSIVE_DEPTH
@@ -3617,8 +3963,8 @@ async function executeSubgraph(params) {
3617
3963
  excludeRoot: options.excludeRoot ?? false,
3618
3964
  direction: options.direction ?? "out",
3619
3965
  cyclePolicy: options.cyclePolicy ?? "prevent",
3620
- temporalMode: options.temporalMode ?? params.graph.defaults.temporalMode,
3621
- asOf: options.asOf,
3966
+ temporalMode,
3967
+ asOf: coordinate.asOf,
3622
3968
  dialect: params.dialect,
3623
3969
  schema: params.schema ?? DEFAULT_SQL_SCHEMA,
3624
3970
  backend: params.backend
@@ -8405,27 +8751,34 @@ var QueryBuilder = class _QueryBuilder {
8405
8751
  * Sets temporal mode.
8406
8752
  *
8407
8753
  * @param mode - The temporal mode to use
8408
- * @param asOf - Required timestamp for "asOf" mode (ISO 8601 string)
8409
- * @throws ValidationError if mode is "asOf" but no timestamp is provided
8754
+ * @param asOf - Required timestamp for "asOf" mode (ISO 8601 string).
8755
+ * Rejected for every other mode — pinning an instant is only meaningful
8756
+ * in "asOf" mode, so `temporal("current", t)` is a caller error, not a
8757
+ * silently-dropped argument.
8758
+ * @throws ValidationError if mode is "asOf" but no timestamp is provided, or
8759
+ * if an asOf is supplied with a non-"asOf" mode.
8410
8760
  */
8411
8761
  temporal(mode, asOf) {
8412
- if (mode === "asOf" && asOf === void 0) {
8413
- throw new ValidationError(
8414
- 'Temporal mode "asOf" requires a timestamp',
8415
- {
8416
- issues: [
8417
- { path: "asOf", message: "Timestamp is required for asOf mode" }
8418
- ]
8419
- },
8762
+ if (this.#config.sealedCoordinate !== void 0) {
8763
+ const coordinate2 = this.#config.sealedCoordinate;
8764
+ throw new ConfigurationError(
8765
+ `.temporal() is not available on a StoreView query \u2014 the view's temporal coordinate (${describeCoordinate(coordinate2)}) is sealed. Re-coordinate on the live Store via store.query() or store.view(...).`,
8420
8766
  {
8421
- suggestion: `Use .temporal("asOf", "2024-01-15T10:00:00.000Z") or .temporal("current") for current time.`
8767
+ code: "STORE_VIEW_SEALED_QUERY",
8768
+ ...coordinateContext(coordinate2),
8769
+ requestedMode: mode
8422
8770
  }
8423
8771
  );
8424
8772
  }
8773
+ const coordinate = resolveReadCoordinate(
8774
+ mode,
8775
+ asOf,
8776
+ `Use .temporal("asOf", "2024-01-15T10:00:00.000Z") or .temporal("current") for current time.`
8777
+ );
8425
8778
  return new _QueryBuilder(this.#config, {
8426
8779
  ...this.#state,
8427
- temporalMode: mode,
8428
- asOf
8780
+ temporalMode: coordinate.valid.mode,
8781
+ asOf: coordinate.valid.asOf
8429
8782
  });
8430
8783
  }
8431
8784
  /**
@@ -9100,8 +9453,12 @@ function createQueryBuilder(graphId, registry, options) {
9100
9453
  defaultTraversalExpansion: options?.defaultTraversalExpansion ?? "inverse",
9101
9454
  ...options?.backend !== void 0 && { backend: options.backend },
9102
9455
  ...options?.dialect !== void 0 && { dialect: options.dialect },
9103
- ...options?.schema !== void 0 && { schema: options.schema }
9456
+ ...options?.schema !== void 0 && { schema: options.schema },
9457
+ ...options?.sealedCoordinate !== void 0 && {
9458
+ sealedCoordinate: options.sealedCoordinate
9459
+ }
9104
9460
  };
9461
+ const sealed = options?.sealedCoordinate?.valid;
9105
9462
  const initialState = {
9106
9463
  startAlias: "",
9107
9464
  currentAlias: "",
@@ -9113,8 +9470,8 @@ function createQueryBuilder(graphId, registry, options) {
9113
9470
  orderBy: [],
9114
9471
  limit: void 0,
9115
9472
  offset: void 0,
9116
- temporalMode: "current",
9117
- asOf: void 0,
9473
+ temporalMode: sealed?.mode ?? "current",
9474
+ asOf: sealed?.asOf,
9118
9475
  groupBy: void 0,
9119
9476
  having: void 0,
9120
9477
  fusion: void 0,
@@ -10511,9 +10868,13 @@ function extractEdgeTypes(graph) {
10511
10868
  var DEFAULT_ALGORITHM_MAX_HOPS = 10;
10512
10869
  var DEFAULT_NEIGHBOR_DEPTH = 1;
10513
10870
  function resolveTemporalOptions(ctx, options) {
10871
+ const { valid } = resolveReadCoordinate(
10872
+ options.temporalMode ?? ctx.defaultTemporalMode,
10873
+ options.asOf
10874
+ );
10514
10875
  return {
10515
- temporalMode: options.temporalMode ?? ctx.defaultTemporalMode,
10516
- ...options.asOf !== void 0 && { asOf: options.asOf }
10876
+ temporalMode: valid.mode,
10877
+ ...valid.asOf !== void 0 && { asOf: valid.asOf }
10517
10878
  };
10518
10879
  }
10519
10880
  function resolveTemporalFilter(ctx, options, tableAlias) {
@@ -10792,31 +11153,34 @@ function createEdgeCollection(config) {
10792
11153
  executeUpsertUpdate: executeEdgeUpsertUpdate2,
10793
11154
  executeDelete: executeEdgeDelete2,
10794
11155
  executeHardDelete: executeEdgeHardDelete2,
10795
- matchesTemporalMode
11156
+ temporalRowMatcher
10796
11157
  } = config;
10797
11158
  const mapRows = (rows) => rows.map((row) => narrowEdge(rowToEdge2(row)));
10798
- async function findEdgesFrom(from, target) {
10799
- const rows = await target.findEdgesByKind({
11159
+ function buildEndpointFindParams(endpoint, options) {
11160
+ return {
10800
11161
  graphId,
10801
11162
  kind,
10802
- fromKind: from.kind,
10803
- fromId: from.id,
10804
- excludeDeleted: true
10805
- });
11163
+ ...endpoint,
11164
+ ...resolveTemporalReadParams(options, defaultTemporalMode)
11165
+ };
11166
+ }
11167
+ async function findEdgesFrom(from, target, options) {
11168
+ const rows = await target.findEdgesByKind(
11169
+ buildEndpointFindParams(
11170
+ { fromKind: from.kind, fromId: from.id },
11171
+ options
11172
+ )
11173
+ );
10806
11174
  return mapRows(rows);
10807
11175
  }
10808
- async function findEdgesTo(to, target) {
10809
- const rows = await target.findEdgesByKind({
10810
- graphId,
10811
- kind,
10812
- toKind: to.kind,
10813
- toId: to.id,
10814
- excludeDeleted: true
10815
- });
11176
+ async function findEdgesTo(to, target, options) {
11177
+ const rows = await target.findEdgesByKind(
11178
+ buildEndpointFindParams({ toKind: to.kind, toId: to.id }, options)
11179
+ );
10816
11180
  return mapRows(rows);
10817
11181
  }
10818
- function buildFindByEndpointsOptions(options) {
10819
- const result = {};
11182
+ function buildFindByEndpointsOptions(options, temporal) {
11183
+ const result = { ...resolveTemporalReadParams(temporal, defaultTemporalMode) };
10820
11184
  if (options?.matchOn !== void 0)
10821
11185
  result.matchOn = options.matchOn;
10822
11186
  if (options?.props !== void 0) result.props = options.props;
@@ -10834,11 +11198,12 @@ function createEdgeCollection(config) {
10834
11198
  const row = await backend.getEdge(graphId, id);
10835
11199
  if (!row) return void 0;
10836
11200
  if (row.kind !== kind) return void 0;
10837
- if (!matchesTemporalMode(row, options)) return void 0;
11201
+ if (!temporalRowMatcher(options)(row)) return void 0;
10838
11202
  return narrowEdge(rowToEdge2(row));
10839
11203
  },
10840
11204
  async getByIds(ids, options) {
10841
11205
  if (ids.length === 0) return [];
11206
+ const matches = temporalRowMatcher(options);
10842
11207
  if (backend.getEdges !== void 0) {
10843
11208
  const rows = await backend.getEdges(graphId, ids);
10844
11209
  const rowMap = /* @__PURE__ */ new Map();
@@ -10849,7 +11214,7 @@ function createEdgeCollection(config) {
10849
11214
  const row = rowMap.get(id);
10850
11215
  if (!row) return;
10851
11216
  if (row.kind !== kind) return;
10852
- if (!matchesTemporalMode(row, options)) return;
11217
+ if (!matches(row)) return;
10853
11218
  return narrowEdge(rowToEdge2(row));
10854
11219
  });
10855
11220
  }
@@ -10858,7 +11223,7 @@ function createEdgeCollection(config) {
10858
11223
  const row = await backend.getEdge(graphId, id);
10859
11224
  if (!row) return;
10860
11225
  if (row.kind !== kind) return;
10861
- if (!matchesTemporalMode(row, options)) return;
11226
+ if (!matches(row)) return;
10862
11227
  return narrowEdge(rowToEdge2(row));
10863
11228
  })
10864
11229
  );
@@ -10870,19 +11235,19 @@ function createEdgeCollection(config) {
10870
11235
  );
10871
11236
  return narrowEdge(result);
10872
11237
  },
10873
- async findFrom(from) {
10874
- return findEdgesFrom(from, backend);
11238
+ async findFrom(from, options) {
11239
+ return findEdgesFrom(from, backend, options);
10875
11240
  },
10876
- async findTo(to) {
10877
- return findEdgesTo(to, backend);
11241
+ async findTo(to, options) {
11242
+ return findEdgesTo(to, backend, options);
10878
11243
  },
10879
- batchFindFrom(from) {
10880
- return { executeOn: (target) => findEdgesFrom(from, target) };
11244
+ batchFindFrom(from, options) {
11245
+ return { executeOn: (target) => findEdgesFrom(from, target, options) };
10881
11246
  },
10882
- batchFindTo(to) {
10883
- return { executeOn: (target) => findEdgesTo(to, target) };
11247
+ batchFindTo(to, options) {
11248
+ return { executeOn: (target) => findEdgesTo(to, target, options) };
10884
11249
  },
10885
- batchFindByEndpoints(from, to, options) {
11250
+ batchFindByEndpoints(from, to, options, temporal) {
10886
11251
  return {
10887
11252
  executeOn: async (target) => {
10888
11253
  const result = await config.executeFindByEndpoints(
@@ -10892,7 +11257,7 @@ function createEdgeCollection(config) {
10892
11257
  to.kind,
10893
11258
  to.id,
10894
11259
  target,
10895
- buildFindByEndpointsOptions(options)
11260
+ buildFindByEndpointsOptions(options, temporal)
10896
11261
  );
10897
11262
  return result === void 0 ? [] : [narrowEdge(result)];
10898
11263
  }
@@ -10904,50 +11269,38 @@ function createEdgeCollection(config) {
10904
11269
  async hardDelete(id) {
10905
11270
  await executeEdgeHardDelete2(id, backend);
10906
11271
  },
10907
- async find(options) {
10908
- const untypedOptions = options;
10909
- if (untypedOptions?.where !== void 0) {
11272
+ async find(filter, temporal) {
11273
+ const untypedFilter = filter;
11274
+ if (untypedFilter?.where !== void 0) {
10910
11275
  throw new UnsupportedPredicateError(
10911
11276
  `store.edges.${kind}.find({ where }) is not supported. Use store.query().traverse(...).whereEdge(...) for edge property filters.`,
10912
11277
  { kind, operation: "find" }
10913
11278
  );
10914
11279
  }
10915
- const mode = options?.temporalMode ?? defaultTemporalMode;
10916
11280
  const params = {
10917
11281
  graphId,
10918
11282
  kind,
10919
- excludeDeleted: mode !== "includeTombstones",
10920
- temporalMode: mode
11283
+ ...resolveTemporalReadParams(temporal, defaultTemporalMode)
10921
11284
  };
10922
- if (mode === "current" || mode === "asOf") {
10923
- params.asOf = options?.asOf ?? nowIso();
10924
- }
10925
- if (options?.from?.kind !== void 0)
10926
- params.fromKind = options.from.kind;
10927
- if (options?.from?.id !== void 0) params.fromId = options.from.id;
10928
- if (options?.to?.kind !== void 0) params.toKind = options.to.kind;
10929
- if (options?.to?.id !== void 0) params.toId = options.to.id;
10930
- if (options?.limit !== void 0) params.limit = options.limit;
10931
- if (options?.offset !== void 0) params.offset = options.offset;
11285
+ if (filter?.from?.kind !== void 0) params.fromKind = filter.from.kind;
11286
+ if (filter?.from?.id !== void 0) params.fromId = filter.from.id;
11287
+ if (filter?.to?.kind !== void 0) params.toKind = filter.to.kind;
11288
+ if (filter?.to?.id !== void 0) params.toId = filter.to.id;
11289
+ if (filter?.limit !== void 0) params.limit = filter.limit;
11290
+ if (filter?.offset !== void 0) params.offset = filter.offset;
10932
11291
  const rows = await backend.findEdgesByKind(params);
10933
11292
  return mapRows(rows);
10934
11293
  },
10935
- async count(options) {
10936
- const mode = options?.temporalMode ?? defaultTemporalMode;
11294
+ async count(filter, temporal) {
10937
11295
  const params = {
10938
11296
  graphId,
10939
11297
  kind,
10940
- excludeDeleted: mode !== "includeTombstones",
10941
- temporalMode: mode
11298
+ ...resolveTemporalReadParams(temporal, defaultTemporalMode)
10942
11299
  };
10943
- if (mode === "current" || mode === "asOf") {
10944
- params.asOf = options?.asOf ?? nowIso();
10945
- }
10946
- if (options?.from?.kind !== void 0)
10947
- params.fromKind = options.from.kind;
10948
- if (options?.from?.id !== void 0) params.fromId = options.from.id;
10949
- if (options?.to?.kind !== void 0) params.toKind = options.to.kind;
10950
- if (options?.to?.id !== void 0) params.toId = options.to.id;
11300
+ if (filter?.from?.kind !== void 0) params.fromKind = filter.from.kind;
11301
+ if (filter?.from?.id !== void 0) params.fromId = filter.from.id;
11302
+ if (filter?.to?.kind !== void 0) params.toKind = filter.to.kind;
11303
+ if (filter?.to?.id !== void 0) params.toId = filter.to.id;
10951
11304
  return backend.countEdgesByKind(params);
10952
11305
  },
10953
11306
  async bulkCreate(items) {
@@ -11048,7 +11401,7 @@ function createEdgeCollection(config) {
11048
11401
  }
11049
11402
  await deleteAll(backend);
11050
11403
  },
11051
- async findByEndpoints(from, to, options) {
11404
+ async findByEndpoints(from, to, options, temporal) {
11052
11405
  const result = await config.executeFindByEndpoints(
11053
11406
  kind,
11054
11407
  from.kind,
@@ -11056,7 +11409,7 @@ function createEdgeCollection(config) {
11056
11409
  to.kind,
11057
11410
  to.id,
11058
11411
  backend,
11059
- buildFindByEndpointsOptions(options)
11412
+ buildFindByEndpointsOptions(options, temporal)
11060
11413
  );
11061
11414
  return result === void 0 ? void 0 : narrowEdge(result);
11062
11415
  },
@@ -11171,7 +11524,7 @@ function createNodeCollection(config) {
11171
11524
  executeUpsertUpdate: executeNodeUpsertUpdate2,
11172
11525
  executeDelete: executeNodeDelete2,
11173
11526
  executeHardDelete: executeNodeHardDelete2,
11174
- matchesTemporalMode,
11527
+ temporalRowMatcher,
11175
11528
  createQuery,
11176
11529
  executeGetOrCreateByConstraint,
11177
11530
  executeBulkGetOrCreateByConstraint,
@@ -11193,16 +11546,17 @@ function createNodeCollection(config) {
11193
11546
  async getById(id, options) {
11194
11547
  const row = await backend.getNode(graphId, kind, id);
11195
11548
  if (!row) return void 0;
11196
- if (!matchesTemporalMode(row, options)) return void 0;
11549
+ if (!temporalRowMatcher(options)(row)) return void 0;
11197
11550
  return narrowNode(rowToNode2(row));
11198
11551
  },
11199
11552
  async getByIds(ids, options) {
11200
11553
  if (ids.length === 0) return [];
11201
11554
  const rowsById = await getNodeRowsByIds(backend, graphId, kind, ids);
11555
+ const matches = temporalRowMatcher(options);
11202
11556
  return ids.map((id) => {
11203
11557
  const row = rowsById.get(id);
11204
11558
  if (!row) return;
11205
- if (!matchesTemporalMode(row, options)) return;
11559
+ if (!matches(row)) return;
11206
11560
  return narrowNode(rowToNode2(row));
11207
11561
  });
11208
11562
  },
@@ -11219,50 +11573,40 @@ function createNodeCollection(config) {
11219
11573
  async hardDelete(id) {
11220
11574
  await executeNodeHardDelete2(kind, id, backend);
11221
11575
  },
11222
- async find(options) {
11223
- if (options?.where !== void 0 && createQuery === void 0) {
11576
+ async find(filter, temporal) {
11577
+ if (filter?.where !== void 0 && createQuery === void 0) {
11224
11578
  throw new ConfigurationError(
11225
11579
  `store.nodes.${kind}.find({ where }) requires a query-capable store`,
11226
11580
  { kind, operation: "find" }
11227
11581
  );
11228
11582
  }
11229
- if (options?.where !== void 0 && createQuery !== void 0) {
11230
- const mode2 = options.temporalMode ?? defaultTemporalMode;
11231
- let query = createQuery().from(kind, "_n").temporal(
11232
- mode2,
11233
- mode2 === "asOf" ? options.asOf ?? nowIso() : void 0
11234
- ).whereNode("_n", options.where).select((ctx) => ctx._n);
11235
- if (options.limit !== void 0) query = query.limit(options.limit);
11236
- if (options.offset !== void 0) query = query.offset(options.offset);
11583
+ if (filter?.where !== void 0 && createQuery !== void 0) {
11584
+ const { temporalMode, asOf } = resolveTemporalReadParams(
11585
+ temporal,
11586
+ defaultTemporalMode
11587
+ );
11588
+ let query = createQuery().from(kind, "_n").temporal(asOf === void 0 ? temporalMode : "asOf", asOf).whereNode("_n", filter.where).select((ctx) => ctx._n);
11589
+ if (filter.limit !== void 0) query = query.limit(filter.limit);
11590
+ if (filter.offset !== void 0) query = query.offset(filter.offset);
11237
11591
  const results = await query.execute();
11238
11592
  return results;
11239
11593
  }
11240
- const mode = options?.temporalMode ?? defaultTemporalMode;
11241
11594
  const params = {
11242
11595
  graphId,
11243
11596
  kind,
11244
- excludeDeleted: mode !== "includeTombstones",
11245
- temporalMode: mode
11597
+ ...resolveTemporalReadParams(temporal, defaultTemporalMode)
11246
11598
  };
11247
- if (mode === "current" || mode === "asOf") {
11248
- params.asOf = options?.asOf ?? nowIso();
11249
- }
11250
- if (options?.limit !== void 0) params.limit = options.limit;
11251
- if (options?.offset !== void 0) params.offset = options.offset;
11599
+ if (filter?.limit !== void 0) params.limit = filter.limit;
11600
+ if (filter?.offset !== void 0) params.offset = filter.offset;
11252
11601
  const rows = await backend.findNodesByKind(params);
11253
11602
  return rows.map((row) => narrowNode(rowToNode2(row)));
11254
11603
  },
11255
- async count(options) {
11256
- const mode = options?.temporalMode ?? defaultTemporalMode;
11604
+ async count(temporal) {
11257
11605
  const params = {
11258
11606
  graphId,
11259
11607
  kind,
11260
- excludeDeleted: mode !== "includeTombstones",
11261
- temporalMode: mode
11608
+ ...resolveTemporalReadParams(temporal, defaultTemporalMode)
11262
11609
  };
11263
- if (mode === "current" || mode === "asOf") {
11264
- params.asOf = options?.asOf ?? nowIso();
11265
- }
11266
11610
  return backend.countNodesByKind(params);
11267
11611
  },
11268
11612
  async upsertById(id, props, options) {
@@ -12593,8 +12937,11 @@ async function validateAndPrepareEdgeCreate(ctx, input, id, backend) {
12593
12937
  kind,
12594
12938
  operation: "create"
12595
12939
  });
12596
- const validFrom = validateOptionalIsoDate(input.validFrom, "validFrom");
12597
- const validTo = validateOptionalIsoDate(input.validTo, "validTo");
12940
+ const validFrom = validateOptionalCanonicalIsoDate(
12941
+ input.validFrom,
12942
+ "validFrom"
12943
+ );
12944
+ const validTo = validateOptionalCanonicalIsoDate(input.validTo, "validTo");
12598
12945
  const cardinality = registration.cardinality ?? "many";
12599
12946
  const constraintContext = {
12600
12947
  graphId: ctx.graphId,
@@ -12744,7 +13091,7 @@ async function executeEdgeUpdate(ctx, input, backend) {
12744
13091
  operation: "update",
12745
13092
  id
12746
13093
  });
12747
- const validTo = validateOptionalIsoDate(input.validTo, "validTo");
13094
+ const validTo = validateOptionalCanonicalIsoDate(input.validTo, "validTo");
12748
13095
  const updateParams = {
12749
13096
  graphId: ctx.graphId,
12750
13097
  id,
@@ -12770,7 +13117,7 @@ async function executeEdgeUpsertUpdate(ctx, input, backend, options) {
12770
13117
  operation: "update",
12771
13118
  id
12772
13119
  });
12773
- const validTo = validateOptionalIsoDate(input.validTo, "validTo");
13120
+ const validTo = validateOptionalCanonicalIsoDate(input.validTo, "validTo");
12774
13121
  const updateParams = {
12775
13122
  graphId: ctx.graphId,
12776
13123
  id,
@@ -12910,7 +13257,11 @@ async function executeEdgeFindByEndpoints(ctx, kind, fromKind, fromId, toKind, t
12910
13257
  fromId,
12911
13258
  toKind,
12912
13259
  toId,
12913
- excludeDeleted: true
13260
+ excludeDeleted: options?.excludeDeleted ?? true,
13261
+ ...options?.temporalMode !== void 0 && {
13262
+ temporalMode: options.temporalMode
13263
+ },
13264
+ ...options?.asOf !== void 0 && { asOf: options.asOf }
12914
13265
  });
12915
13266
  if (candidateRows.length === 0) return void 0;
12916
13267
  if (matchOn.length === 0) return rowToEdge(candidateRows[0]);
@@ -13460,8 +13811,11 @@ async function validateAndPrepareNodeCreate(ctx, input, id, backend) {
13460
13811
  kind,
13461
13812
  operation: "create"
13462
13813
  });
13463
- const validFrom = validateOptionalIsoDate(input.validFrom, "validFrom");
13464
- const validTo = validateOptionalIsoDate(input.validTo, "validTo");
13814
+ const validFrom = validateOptionalCanonicalIsoDate(
13815
+ input.validFrom,
13816
+ "validFrom"
13817
+ );
13818
+ const validTo = validateOptionalCanonicalIsoDate(input.validTo, "validTo");
13465
13819
  const existingNode = await backend.getNode(ctx.graphId, kind, id);
13466
13820
  if (existingNode && !existingNode.deleted_at) {
13467
13821
  throw createNodeAlreadyExistsError(kind, id);
@@ -13535,7 +13889,7 @@ async function performNodeUpdate(ctx, input, backend, options) {
13535
13889
  operation: "update",
13536
13890
  id
13537
13891
  });
13538
- const validTo = validateOptionalIsoDate(input.validTo, "validTo");
13892
+ const validTo = validateOptionalCanonicalIsoDate(input.validTo, "validTo");
13539
13893
  await updateUniquenessEntries(
13540
13894
  createUniquenessContext(ctx.graphId, ctx.registry, backend),
13541
13895
  kind,
@@ -14604,7 +14958,7 @@ var Store = class _Store {
14604
14958
  ),
14605
14959
  executeDelete: (kind, id, backend) => executeNodeDelete(ctx, kind, id, backend),
14606
14960
  executeHardDelete: (kind, id, backend) => executeNodeHardDelete(ctx, kind, id, backend),
14607
- matchesTemporalMode: (row, options) => this.#matchesTemporalMode(row, options),
14961
+ temporalRowMatcher: (options) => this.#temporalRowMatcher(options),
14608
14962
  createQuery: () => this.query(),
14609
14963
  executeGetOrCreateByConstraint: (kind, constraintName, props, backend, options) => executeNodeGetOrCreateByConstraint(
14610
14964
  ctx,
@@ -14655,7 +15009,7 @@ var Store = class _Store {
14655
15009
  executeUpsertUpdate: (input, backend, options) => executeEdgeUpsertUpdate(ctx, input, backend, options),
14656
15010
  executeDelete: (id, backend) => executeEdgeDelete(ctx, id, backend),
14657
15011
  executeHardDelete: (id, backend) => executeEdgeHardDelete(ctx, id, backend),
14658
- matchesTemporalMode: (row, options) => this.#matchesTemporalMode(row, options),
15012
+ temporalRowMatcher: (options) => this.#temporalRowMatcher(options),
14659
15013
  createQuery: () => this.query(),
14660
15014
  executeGetOrCreateByEndpoints: (kind, fromKind, fromId, toKind, toId, props, backend, options) => executeEdgeGetOrCreateByEndpoints(
14661
15015
  ctx,
@@ -14703,6 +15057,78 @@ var Store = class _Store {
14703
15057
  query() {
14704
15058
  return this.#createQueryForBackend(this.#backend);
14705
15059
  }
15060
+ /**
15061
+ * Internal seam for {@link StoreView.query}: a query builder pinned to a
15062
+ * view's {@link ReadCoordinate} with its temporal axis sealed
15063
+ * (`.temporal()` throws). Not part of the stable public API — construct a
15064
+ * view via {@link Store.view} / {@link Store.asOf} and call `.query()`.
15065
+ */
15066
+ sealedQuery(coordinate) {
15067
+ return this.#createQueryForBackend(this.#backend, coordinate);
15068
+ }
15069
+ // === Temporal Views ===
15070
+ /**
15071
+ * Returns a read-only {@link StoreView} pinned to a valid-time instant.
15072
+ *
15073
+ * The view routes every supported read — `nodes` / `edges` collections,
15074
+ * `query()`, `subgraph()`, and the graph algorithms — through the
15075
+ * `asOf` coordinate, so they observe the graph as it was valid at `T`.
15076
+ * Writes stay on the live `Store`. Mirrors Datomic's `(d/as-of db t)`.
15077
+ *
15078
+ * @example
15079
+ * ```typescript
15080
+ * const past = store.asOf("2026-01-01T00:00:00.000Z");
15081
+ * const alice = await past.nodes.Person.getById(aliceId);
15082
+ * const names = await past
15083
+ * .query()
15084
+ * .from("Person", "p")
15085
+ * .whereNode("p", (p) => p.name.eq("Alice"))
15086
+ * .select((ctx) => ctx.p.name)
15087
+ * .execute();
15088
+ * ```
15089
+ *
15090
+ * @param asOf - ISO-8601 timestamp to pin the valid-time coordinate to.
15091
+ */
15092
+ asOf(asOf) {
15093
+ return new StoreView(this, { mode: "asOf", asOf });
15094
+ }
15095
+ /**
15096
+ * Returns a read-only {@link StoreView} pinned to an arbitrary public
15097
+ * temporal mode. Use {@link Store.asOf} for the common valid-time case;
15098
+ * reach for `view` to pin `"current"`, `"includeEnded"`, or
15099
+ * `"includeTombstones"`.
15100
+ *
15101
+ * @example
15102
+ * ```typescript
15103
+ * const withTombstones = store.view({ mode: "includeTombstones" });
15104
+ * const everyEverVersion = await withTombstones.nodes.Person.find();
15105
+ * ```
15106
+ *
15107
+ * @param coordinate - The `(mode, asOf)` coordinate to pin. `asOf` is
15108
+ * required when `mode` is `"asOf"` and rejected for every other mode.
15109
+ */
15110
+ view(coordinate) {
15111
+ return new StoreView(this, coordinate);
15112
+ }
15113
+ /**
15114
+ * Returns a read-only {@link StoreView} pinned to the current instant,
15115
+ * captured once at construction — a stable point-in-time snapshot. Unlike
15116
+ * `store.view({ mode: "current" })` (which tracks "now" live and can read
15117
+ * different surfaces against slightly different clocks), a snapshot pins one
15118
+ * `asOf` timestamp, so every surface observes the same instant. Sugar for
15119
+ * `store.asOf(new Date().toISOString())`; mirrors Datomic's `(d/db conn)`.
15120
+ *
15121
+ * @example
15122
+ * ```typescript
15123
+ * const snap = store.snapshot();
15124
+ * // Every read on `snap` sees the graph as of one fixed instant.
15125
+ * const a = await snap.nodes.Person.find();
15126
+ * const r = await snap.reachable(rootId, { edges: ["knows"] });
15127
+ * ```
15128
+ */
15129
+ snapshot() {
15130
+ return this.asOf(nowIso());
15131
+ }
14706
15132
  // === Search ===
14707
15133
  /**
14708
15134
  * Search-related operations (fulltext, hybrid, and rebuild).
@@ -14877,13 +15303,24 @@ var Store = class _Store {
14877
15303
  * // sequential, non-atomic — handle partial-failure recovery yourself
14878
15304
  * }
14879
15305
  * ```
15306
+ *
15307
+ * @param fn The callback run inside the transaction boundary.
15308
+ * @param options Optional {@link TransactionOptions} forwarded to the
15309
+ * backend (e.g. `isolationLevel: "serializable"` on Postgres). Backends
15310
+ * without isolation-level support ignore it; the non-transactional
15311
+ * fallback ignores it entirely.
14880
15312
  */
14881
- async transaction(fn) {
15313
+ async transaction(fn, options) {
14882
15314
  if (!this.#backend.capabilities.transactions) {
14883
- return fn({ nodes: this.nodes, edges: this.edges });
15315
+ return fn({
15316
+ nodes: this.nodes,
15317
+ edges: this.edges,
15318
+ backend: this.#backend
15319
+ });
14884
15320
  }
14885
15321
  return this.#backend.transaction(
14886
- async (txBackend, sql18) => fn(this.#buildTransactionContext(txBackend, sql18))
15322
+ async (txBackend, sql18) => fn(this.#buildTransactionContext(txBackend, sql18)),
15323
+ options
14887
15324
  );
14888
15325
  }
14889
15326
  /**
@@ -14983,7 +15420,7 @@ var Store = class _Store {
14983
15420
  txBackend,
14984
15421
  txEdgeOperations
14985
15422
  );
14986
- return sql18 === void 0 ? { nodes, edges } : { nodes, edges, sql: sql18 };
15423
+ return sql18 === void 0 ? { nodes, edges, backend: txBackend } : { nodes, edges, sql: sql18, backend: txBackend };
14987
15424
  }
14988
15425
  // === Graph Lifecycle ===
14989
15426
  /**
@@ -15687,33 +16124,40 @@ var Store = class _Store {
15687
16124
  }
15688
16125
  }
15689
16126
  // === Internal: Temporal Filtering ===
15690
- #matchesTemporalMode(row, options) {
15691
- const mode = options?.temporalMode ?? this.#graph.defaults.temporalMode;
15692
- const asOf = options?.asOf ?? nowIso();
15693
- switch (mode) {
15694
- case "current":
15695
- case "asOf": {
15696
- if (row.deleted_at) return false;
15697
- if (row.valid_from && asOf < row.valid_from) return false;
15698
- if (row.valid_to && asOf >= row.valid_to) return false;
15699
- return true;
15700
- }
15701
- case "includeEnded": {
15702
- return !row.deleted_at;
15703
- }
15704
- case "includeTombstones": {
15705
- return true;
16127
+ #temporalRowMatcher(options) {
16128
+ const { temporalMode, asOf } = resolveTemporalReadParams(
16129
+ options,
16130
+ this.#graph.defaults.temporalMode
16131
+ );
16132
+ return (row) => {
16133
+ switch (temporalMode) {
16134
+ case "current":
16135
+ case "asOf": {
16136
+ if (row.deleted_at) return false;
16137
+ if (asOf !== void 0 && row.valid_from && asOf < row.valid_from)
16138
+ return false;
16139
+ if (asOf !== void 0 && row.valid_to && asOf >= row.valid_to)
16140
+ return false;
16141
+ return true;
16142
+ }
16143
+ case "includeEnded": {
16144
+ return !row.deleted_at;
16145
+ }
16146
+ case "includeTombstones": {
16147
+ return true;
16148
+ }
15706
16149
  }
15707
- }
16150
+ };
15708
16151
  }
15709
- #createQueryForBackend(backend) {
16152
+ #createQueryForBackend(backend, sealedCoordinate) {
15710
16153
  return createQueryBuilder(this.graphId, this.#registry, {
15711
16154
  // TransactionBackend omits transaction/close, but query execution only needs
15712
16155
  // the read-path/query capabilities shared with GraphBackend.
15713
16156
  backend,
15714
16157
  dialect: backend.dialect,
15715
16158
  defaultTraversalExpansion: this.#defaultTraversalExpansion,
15716
- ...this.#schema !== void 0 && { schema: this.#schema }
16159
+ ...this.#schema !== void 0 && { schema: this.#schema },
16160
+ ...sealedCoordinate !== void 0 && { sealedCoordinate }
15717
16161
  });
15718
16162
  }
15719
16163
  };
@@ -15782,6 +16226,6 @@ async function createVerifiedStore(graph, backend, options) {
15782
16226
  return [store, result];
15783
16227
  }
15784
16228
 
15785
- export { DEFAULT_SQL_SCHEMA, ExecutableAggregateQuery, ExecutableQuery, MAX_EXPLICIT_RECURSIVE_DEPTH, MAX_RECURSIVE_DEPTH, PreparedQuery, QueryBuilder, StoreSearch, UnionableQuery, avg, composeFragments, computeUniqueKey, count, countDistinct, countDistinctEdges, countEdges, createFragment, createQueryBuilder, createSqlSchema, createStore, createStoreWithSchema, createVerifiedStore, defineSubgraphProject, exists, field, fieldRef, generateId, having, havingEq, havingGt, havingGte, havingLt, havingLte, inSubquery, isParameterRef, limitFragment, max, min, notExists, notInSubquery, offsetFragment, orderByFragment, param, sum };
15786
- //# sourceMappingURL=chunk-UIFEEPME.js.map
15787
- //# sourceMappingURL=chunk-UIFEEPME.js.map
16229
+ export { DEFAULT_SQL_SCHEMA, ExecutableAggregateQuery, ExecutableQuery, MAX_EXPLICIT_RECURSIVE_DEPTH, MAX_RECURSIVE_DEPTH, PreparedQuery, QueryBuilder, StoreSearch, StoreView, UnionableQuery, avg, composeFragments, computeUniqueKey, count, countDistinct, countDistinctEdges, countEdges, createFragment, createQueryBuilder, createSqlSchema, createStore, createStoreWithSchema, createVerifiedStore, defineSubgraphProject, exists, field, fieldRef, generateId, having, havingEq, havingGt, havingGte, havingLt, havingLte, inSubquery, isParameterRef, limitFragment, max, min, notExists, notInSubquery, offsetFragment, orderByFragment, param, sum };
16230
+ //# sourceMappingURL=chunk-WNORITK6.js.map
16231
+ //# sourceMappingURL=chunk-WNORITK6.js.map