@cavelang/query 0.5.0 → 0.13.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.
- package/README.md +23 -1
- package/dist/src/compile.d.ts +28 -1
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +110 -26
- package/dist/src/compile.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/package.json +5 -5
- package/src/compile.ts +139 -27
- package/src/index.ts +2 -1
package/README.md
CHANGED
|
@@ -16,6 +16,9 @@ query(store, `?cause CAUSE app/crash
|
|
|
16
16
|
|
|
17
17
|
query(store, '?x PART-OF monorepo') // inverse verb → same physical query
|
|
18
18
|
query(store, 'terrier EXTENDS+ animal') // transitive
|
|
19
|
+
|
|
20
|
+
query(store, '?x USES postgres', { aliases: true }) // + rows about aliased names (§13.6)
|
|
21
|
+
query(store, 'server IS compromised', { asOf: '2026-01-15' }) // belief state at a past moment (§12.3)
|
|
19
22
|
```
|
|
20
23
|
|
|
21
24
|
## Pattern language (§12.1)
|
|
@@ -65,6 +68,21 @@ covers one second.
|
|
|
65
68
|
`?x EXTENDS+ ?x` finds nodes on cycles, not every reachable pair.
|
|
66
69
|
- Transitive patterns support endpoint slots only; tag/context/WHERE
|
|
67
70
|
filters on them are rejected rather than silently ignored.
|
|
71
|
+
- **`{ aliases: true }` resolves entity terms through the alias closure**
|
|
72
|
+
(§13.6): current positive `ALIAS` claims as undirected edges. Matching
|
|
73
|
+
widens — bound terms match aliased spellings, repeated variables compare
|
|
74
|
+
alias-equal, transitive hops cross alias links — while bindings and rows
|
|
75
|
+
keep stored names untouched (union-of-rows, never silent merging). The
|
|
76
|
+
closure always reads current beliefs, even under `{ all: true }`.
|
|
77
|
+
Values, attribute names and verbs are not entities and never resolve.
|
|
78
|
+
- **`{ asOf }` resolves beliefs as of a past moment** (§12.3): only rows
|
|
79
|
+
recorded up to the boundary participate, then resolution proceeds as
|
|
80
|
+
usual — so a claim retracted later is still believed at the boundary,
|
|
81
|
+
and one first recorded later is unknown. The boundary is a date (whole
|
|
82
|
+
UTC day included), a timestamp (whole second included), or a
|
|
83
|
+
transaction id (that append included). The alias closure and transitive
|
|
84
|
+
hops reconstruct at the same instant; `{ all: true }` composes as
|
|
85
|
+
full-history-up-to-the-boundary.
|
|
68
86
|
|
|
69
87
|
## Tests
|
|
70
88
|
|
|
@@ -74,4 +92,8 @@ pnpm --filter @cavelang/query test
|
|
|
74
92
|
|
|
75
93
|
Every §12.1 example pattern and every §12.2 filter runs against a live
|
|
76
94
|
in-memory store, including inverse and transitive-inverse cases,
|
|
77
|
-
current-vs-history semantics
|
|
95
|
+
current-vs-history semantics, negated patterns, the §13.6 alias
|
|
96
|
+
closure (term widening, transitive hops across aliases, unmerge by
|
|
97
|
+
retraction, value/attribute exemption) and §12.3 as-of resolution
|
|
98
|
+
(tx/date/timestamp boundaries, later retraction, as-of alias closure
|
|
99
|
+
and transitive edges).
|
package/dist/src/compile.d.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* CAVE-Q → SQL compilation (spec §12).
|
|
3
3
|
*
|
|
4
4
|
* Patterns run over *current beliefs* by default — the latest transaction
|
|
5
|
-
* per claim key (spec §9.1) — pass `all` to match the full history
|
|
5
|
+
* per claim key (spec §9.1) — pass `all` to match the full history, or
|
|
6
|
+
* `asOf` to resolve the belief state at a past moment (spec §12.3).
|
|
6
7
|
* Inverse verbs compile to the same physical query as their primary
|
|
7
8
|
* (spec §12.1): `?x PART-OF monorepo` and `monorepo CONTAINS ?x` produce
|
|
8
9
|
* identical SQL against canonical rows, with the pattern's subject binding
|
|
@@ -12,6 +13,7 @@
|
|
|
12
13
|
* CTE over current, positive, non-retracted edges (depth-capped at 32).
|
|
13
14
|
*/
|
|
14
15
|
import type { Row, Store } from '@cavelang/store';
|
|
16
|
+
import * as Pattern from './pattern.ts';
|
|
15
17
|
/** One query solution: variable bindings plus the matched row (absent for transitive hops). */
|
|
16
18
|
export type Match = {
|
|
17
19
|
readonly bindings: Readonly<Record<string, string>>;
|
|
@@ -20,6 +22,23 @@ export type Match = {
|
|
|
20
22
|
export type Options = {
|
|
21
23
|
/** Match all appended rows, not only current beliefs. */
|
|
22
24
|
readonly all?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve entity terms through the alias closure — current positive
|
|
27
|
+
* `ALIAS` claims read as undirected edges (spec §13.6). Union-of-rows:
|
|
28
|
+
* matching widens to aliased names; bindings and rows keep the stored
|
|
29
|
+
* names untouched.
|
|
30
|
+
*/
|
|
31
|
+
readonly aliases?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve beliefs as of a past moment (spec §12.3): a date
|
|
34
|
+
* (`2026-01-15`, the whole UTC day included), a timestamp (the whole
|
|
35
|
+
* second included), or an exact transaction id (UUIDv7, included).
|
|
36
|
+
* Rows recorded after the boundary are invisible — current-belief
|
|
37
|
+
* resolution, the alias closure and transitive hops all reconstruct
|
|
38
|
+
* the belief state at that boundary. Composes with `all`, which then
|
|
39
|
+
* matches the full history up to the boundary.
|
|
40
|
+
*/
|
|
41
|
+
readonly asOf?: string;
|
|
23
42
|
};
|
|
24
43
|
/**
|
|
25
44
|
* Runs a CAVE-Q query against a store.
|
|
@@ -28,7 +47,15 @@ export type Options = {
|
|
|
28
47
|
* query(store, '?x USES jwt')
|
|
29
48
|
* query(store, '?cause CAUSE app/crash\n WHERE conf >= 0.7')
|
|
30
49
|
* query(store, 'terrier EXTENDS+ animal')
|
|
50
|
+
* query(store, 'server IS compromised', { asOf: '2026-01-15' })
|
|
31
51
|
* ```
|
|
32
52
|
*/
|
|
33
53
|
export declare const query: (store: Store, input: string, options?: Options) => Match[];
|
|
54
|
+
/**
|
|
55
|
+
* Runs an already-parsed pattern against a store — the programmatic
|
|
56
|
+
* entry point for callers that build or specialize patterns as values
|
|
57
|
+
* (the §24 rules engine substitutes bindings into premise patterns
|
|
58
|
+
* between joins) rather than as text.
|
|
59
|
+
*/
|
|
60
|
+
export declare const match: (store: Store, pattern: Pattern.t, options?: Options) => Match[];
|
|
34
61
|
//# sourceMappingURL=compile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC,+FAA+F;AAC/F,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACnD,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,yDAAyD;IACzD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAA;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AA8UD;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,KAAK,EAAE,OAAO,MAAM,EAAE,UAAS,OAAY,KAAG,KAAK,EACnC,CAAA;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,KAAK,EAAE,SAAS,OAAO,CAAC,CAAC,EAAE,UAAS,OAAY,KAAG,KAAK,EAwBpF,CAAA"}
|
package/dist/src/compile.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* CAVE-Q → SQL compilation (spec §12).
|
|
3
3
|
*
|
|
4
4
|
* Patterns run over *current beliefs* by default — the latest transaction
|
|
5
|
-
* per claim key (spec §9.1) — pass `all` to match the full history
|
|
5
|
+
* per claim key (spec §9.1) — pass `all` to match the full history, or
|
|
6
|
+
* `asOf` to resolve the belief state at a past moment (spec §12.3).
|
|
6
7
|
* Inverse verbs compile to the same physical query as their primary
|
|
7
8
|
* (spec §12.1): `?x PART-OF monorepo` and `monorepo CONTAINS ?x` produce
|
|
8
9
|
* identical SQL against canonical rows, with the pattern's subject binding
|
|
@@ -14,28 +15,68 @@
|
|
|
14
15
|
import { Uuidv7, Value } from '@cavelang/core';
|
|
15
16
|
import { Registry } from '@cavelang/canonical';
|
|
16
17
|
import * as Pattern from "./pattern.js";
|
|
17
|
-
const currentSql = `
|
|
18
|
-
SELECT c.* FROM cave_claim c
|
|
19
|
-
JOIN (
|
|
20
|
-
SELECT claim_key, MAX(tx) AS max_tx
|
|
21
|
-
FROM cave_claim GROUP BY claim_key
|
|
22
|
-
) latest ON c.claim_key = latest.claim_key AND c.tx = latest.max_tx
|
|
23
|
-
`;
|
|
24
18
|
/**
|
|
25
19
|
* UUIDv7 interval `[lo, hi)` for a tx filter value: a bare date covers the
|
|
26
20
|
* whole UTC day, a timestamp covers one second. Interval semantics keep
|
|
27
21
|
* adjacent operators distinguishable (`<=` includes the boundary day that
|
|
28
22
|
* `<` excludes) and make `WHERE tx = 2026-01-01` mean "recorded that day".
|
|
29
23
|
*/
|
|
30
|
-
const txBounds = (text) => {
|
|
24
|
+
const txBounds = (text, label = 'tx date') => {
|
|
31
25
|
const hasTime = text.includes('T');
|
|
32
26
|
const start = Date.parse(hasTime ? text : `${text}T00:00:00Z`);
|
|
33
27
|
if (Number.isNaN(start)) {
|
|
34
|
-
throw new Error(`CAVE-Q: cannot parse
|
|
28
|
+
throw new Error(`CAVE-Q: cannot parse ${label} ${JSON.stringify(text)}`);
|
|
35
29
|
}
|
|
36
30
|
const end = start + (hasTime ? 1_000 : 86_400_000);
|
|
37
31
|
return { lo: Uuidv7.at(start, 0, new Uint8Array(8)), hi: Uuidv7.at(end, 0, new Uint8Array(8)) };
|
|
38
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* SQL tx condition for an as-of boundary (spec §12.3). A UUIDv7 names an
|
|
35
|
+
* exact transaction, included — belief as of that append; a date or
|
|
36
|
+
* timestamp is inclusive of the whole named day/second, the same interval
|
|
37
|
+
* semantics as `WHERE tx <=` (§12.2). Both forms inline as literals: the
|
|
38
|
+
* id is shape-validated hex-and-dashes and the interval bound comes from
|
|
39
|
+
* `Uuidv7.at` — no free-form text reaches the SQL, and a literal keeps
|
|
40
|
+
* the fragment embeddable in CTEs that positional parameters would
|
|
41
|
+
* complicate.
|
|
42
|
+
*/
|
|
43
|
+
const asOfCondition = (asOf) => {
|
|
44
|
+
const id = asOf.toLowerCase();
|
|
45
|
+
return Uuidv7.is(id) ? `tx <= '${id}'` : `tx < '${txBounds(asOf, 'as-of boundary').hi}'`;
|
|
46
|
+
};
|
|
47
|
+
/** Row universe under resolution: every appended row, or only rows recorded up to the as-of boundary. */
|
|
48
|
+
const claimsSql = (asOf) => asOf === undefined ? 'cave_claim' : `(SELECT * FROM cave_claim WHERE ${asOfCondition(asOf)})`;
|
|
49
|
+
const currentSql = (asOf) => `
|
|
50
|
+
SELECT c.* FROM cave_claim c
|
|
51
|
+
JOIN (
|
|
52
|
+
SELECT claim_key, MAX(tx) AS max_tx
|
|
53
|
+
FROM ${claimsSql(asOf)} GROUP BY claim_key
|
|
54
|
+
) latest ON c.claim_key = latest.claim_key AND c.tx = latest.max_tx
|
|
55
|
+
`;
|
|
56
|
+
/**
|
|
57
|
+
* Alias closure CTEs (spec §13.6): `alias_edge` is the current positive
|
|
58
|
+
* `ALIAS` claims symmetrized (each written direction is its own claim key —
|
|
59
|
+
* both assert the same undirected link); `alias_pair` its transitive
|
|
60
|
+
* closure — every ordered pair of names currently believed to denote one
|
|
61
|
+
* entity. Resolution always reads *current* beliefs, even under `all`:
|
|
62
|
+
* the closure is entity resolution as believed now, not as believed when
|
|
63
|
+
* a row landed — except under `asOf`, where "now" is the boundary itself
|
|
64
|
+
* and the closure reconstructs entity resolution as believed then
|
|
65
|
+
* (spec §12.3).
|
|
66
|
+
*/
|
|
67
|
+
const aliasPairSql = (asOf) => `alias_edge(a, b) AS (
|
|
68
|
+
SELECT c.subject, c.object FROM (${currentSql(asOf)}) c
|
|
69
|
+
WHERE c.verb = 'ALIAS' AND c.negated = 0 AND c.conf > 0 AND c.object IS NOT NULL
|
|
70
|
+
UNION
|
|
71
|
+
SELECT c.object, c.subject FROM (${currentSql(asOf)}) c
|
|
72
|
+
WHERE c.verb = 'ALIAS' AND c.negated = 0 AND c.conf > 0 AND c.object IS NOT NULL
|
|
73
|
+
), alias_pair(a, b) AS (
|
|
74
|
+
SELECT a, b FROM alias_edge
|
|
75
|
+
UNION
|
|
76
|
+
SELECT p.a, e.b FROM alias_pair p JOIN alias_edge e ON e.a = p.b
|
|
77
|
+
)`;
|
|
78
|
+
/** SQL for "these two expressions name the same entity" under the closure. */
|
|
79
|
+
const aliasSame = (left, right) => `(${left} = ${right} OR EXISTS (SELECT 1 FROM alias_pair p WHERE p.a = ${left} AND p.b = ${right}))`;
|
|
39
80
|
const compile = (pattern, registry, options) => {
|
|
40
81
|
// Inverse resolution (spec §12.1): swap the pattern's endpoint slots and
|
|
41
82
|
// query the primary verb.
|
|
@@ -57,27 +98,35 @@ const compile = (pattern, registry, options) => {
|
|
|
57
98
|
if (verb.kind === 'verb' && verb.transitive) {
|
|
58
99
|
return compileTransitive(pattern, verb.name, subjectSlot, objectSlot, options);
|
|
59
100
|
}
|
|
101
|
+
const aliases = options.aliases === true;
|
|
102
|
+
// Alias closure applies to entity columns only: values and attribute
|
|
103
|
+
// names are not entities, and verb aliasing is a separate, undesigned
|
|
104
|
+
// lifecycle question.
|
|
105
|
+
const entityColumns = ['subject', 'object'];
|
|
60
106
|
const conditions = [`c.negated = ${pattern.negated ? 1 : 0}`];
|
|
61
107
|
const params = [];
|
|
62
108
|
/** var name → row columns it binds; repeated vars add join conditions. */
|
|
63
109
|
const varColumns = new Map();
|
|
64
110
|
const slot = (value, column, requireNotNull) => {
|
|
65
111
|
switch (value.kind) {
|
|
66
|
-
case 'term':
|
|
112
|
+
case 'term': {
|
|
113
|
+
const match = aliases && entityColumns.includes(column) ? aliasSame('?', `c.${column}`) : `c.${column} = ?`;
|
|
114
|
+
const termParams = aliases && entityColumns.includes(column) ? [value.text, value.text] : [value.text];
|
|
67
115
|
// A date/number term in object position must also match metric
|
|
68
116
|
// rows, which store their value in value_text with object NULL
|
|
69
117
|
// (`latency IS 30ms` ⇒ pattern `latency IS 30ms` matches).
|
|
70
118
|
if (column === 'object') {
|
|
71
119
|
const parsed = Value.parse(value.text);
|
|
72
120
|
if (parsed.kind === 'number' || parsed.kind === 'date') {
|
|
73
|
-
conditions.push(
|
|
74
|
-
params.push(
|
|
121
|
+
conditions.push(`(${match} OR (c.object IS NULL AND c.value_text = ?))`);
|
|
122
|
+
params.push(...termParams, value.text);
|
|
75
123
|
return;
|
|
76
124
|
}
|
|
77
125
|
}
|
|
78
|
-
conditions.push(
|
|
79
|
-
params.push(
|
|
126
|
+
conditions.push(match);
|
|
127
|
+
params.push(...termParams);
|
|
80
128
|
return;
|
|
129
|
+
}
|
|
81
130
|
case 'var': {
|
|
82
131
|
const columns = varColumns.get(value.name) ?? [];
|
|
83
132
|
columns.push(column);
|
|
@@ -114,7 +163,9 @@ const compile = (pattern, registry, options) => {
|
|
|
114
163
|
}
|
|
115
164
|
for (const columns of varColumns.values()) {
|
|
116
165
|
for (let i = 1; i < columns.length; i++) {
|
|
117
|
-
conditions.push(
|
|
166
|
+
conditions.push(aliases && entityColumns.includes(columns[0]) && entityColumns.includes(columns[i]) ?
|
|
167
|
+
aliasSame(`c.${columns[0]}`, `c.${columns[i]}`) :
|
|
168
|
+
`c.${columns[0]} = c.${columns[i]}`);
|
|
118
169
|
}
|
|
119
170
|
}
|
|
120
171
|
for (const context of pattern.contexts) {
|
|
@@ -198,8 +249,9 @@ const compile = (pattern, registry, options) => {
|
|
|
198
249
|
if (options.all !== true && !pattern.filters.some(filter => filter.field === 'conf')) {
|
|
199
250
|
conditions.push('c.conf > 0');
|
|
200
251
|
}
|
|
201
|
-
const base = options.all === true ?
|
|
202
|
-
const
|
|
252
|
+
const base = options.all === true ? `SELECT * FROM ${claimsSql(options.asOf)}` : currentSql(options.asOf);
|
|
253
|
+
const withClause = aliases ? `WITH RECURSIVE ${aliasPairSql(options.asOf)} ` : '';
|
|
254
|
+
const sql = `${withClause}SELECT c.* FROM (${base}) c WHERE ${conditions.join(' AND ')} ORDER BY c.tx`;
|
|
203
255
|
const bind = (row) => {
|
|
204
256
|
const bindings = {};
|
|
205
257
|
for (const [name, columns] of varColumns) {
|
|
@@ -214,32 +266,41 @@ const compileTransitive = (pattern, verb, subjectSlot, objectSlot, options) => {
|
|
|
214
266
|
pattern.payload.kind === 'attribute') {
|
|
215
267
|
throw new Error('CAVE-Q: transitive patterns support subject/object slots only (spec §12.1)');
|
|
216
268
|
}
|
|
217
|
-
const
|
|
269
|
+
const aliases = options.aliases === true;
|
|
270
|
+
const base = options.all === true ? `SELECT * FROM ${claimsSql(options.asOf)}` : currentSql(options.asOf);
|
|
271
|
+
/** Endpoint equality: exact, or alias-equal under the closure (spec §13.6). */
|
|
272
|
+
const same = (left, right) => aliases ? aliasSame(left, right) : `${left} = ${right}`;
|
|
218
273
|
const conditions = [];
|
|
219
274
|
const params = [verb];
|
|
220
275
|
if (subjectSlot.kind === 'term') {
|
|
221
|
-
conditions.push('h.src
|
|
276
|
+
conditions.push(same('h.src', '?'));
|
|
222
277
|
params.push(subjectSlot.text);
|
|
278
|
+
if (aliases) {
|
|
279
|
+
params.push(subjectSlot.text);
|
|
280
|
+
}
|
|
223
281
|
}
|
|
224
282
|
if (objectSlot?.kind === 'term') {
|
|
225
|
-
conditions.push('h.dst
|
|
283
|
+
conditions.push(same('h.dst', '?'));
|
|
226
284
|
params.push(objectSlot.text);
|
|
285
|
+
if (aliases) {
|
|
286
|
+
params.push(objectSlot.text);
|
|
287
|
+
}
|
|
227
288
|
}
|
|
228
289
|
// A repeated variable forces equality here just as in single-hop
|
|
229
290
|
// patterns: `?x EXTENDS+ ?x` asks for nodes on a cycle, not for every
|
|
230
291
|
// reachable pair.
|
|
231
292
|
if (subjectSlot.kind === 'var' && objectSlot?.kind === 'var' && subjectSlot.name === objectSlot.name) {
|
|
232
|
-
conditions.push('h.src
|
|
293
|
+
conditions.push(same('h.src', 'h.dst'));
|
|
233
294
|
}
|
|
234
295
|
const sql = `
|
|
235
|
-
WITH RECURSIVE cur AS (
|
|
296
|
+
WITH RECURSIVE ${aliases ? `${aliasPairSql(options.asOf)}, ` : ''}cur AS (
|
|
236
297
|
SELECT c.subject AS src, c.object AS dst
|
|
237
298
|
FROM (${base}) c
|
|
238
299
|
WHERE c.verb = ? AND c.negated = 0 AND c.conf > 0 AND c.object IS NOT NULL
|
|
239
300
|
), hops(src, dst, depth) AS (
|
|
240
301
|
SELECT src, dst, 1 FROM cur
|
|
241
302
|
UNION
|
|
242
|
-
SELECT h.src, cur.dst, h.depth + 1 FROM hops h JOIN cur ON cur.src
|
|
303
|
+
SELECT h.src, cur.dst, h.depth + 1 FROM hops h JOIN cur ON ${same('cur.src', 'h.dst')}
|
|
243
304
|
WHERE h.depth < 32
|
|
244
305
|
)
|
|
245
306
|
SELECT DISTINCT h.src AS src, h.dst AS dst FROM hops h
|
|
@@ -264,12 +325,35 @@ ORDER BY h.src, h.dst`;
|
|
|
264
325
|
* query(store, '?x USES jwt')
|
|
265
326
|
* query(store, '?cause CAUSE app/crash\n WHERE conf >= 0.7')
|
|
266
327
|
* query(store, 'terrier EXTENDS+ animal')
|
|
328
|
+
* query(store, 'server IS compromised', { asOf: '2026-01-15' })
|
|
267
329
|
* ```
|
|
268
330
|
*/
|
|
269
|
-
export const query = (store, input, options = {}) =>
|
|
270
|
-
|
|
331
|
+
export const query = (store, input, options = {}) => match(store, Pattern.parse(input), options);
|
|
332
|
+
/**
|
|
333
|
+
* Runs an already-parsed pattern against a store — the programmatic
|
|
334
|
+
* entry point for callers that build or specialize patterns as values
|
|
335
|
+
* (the §24 rules engine substitutes bindings into premise patterns
|
|
336
|
+
* between joins) rather than as text.
|
|
337
|
+
*/
|
|
338
|
+
export const match = (store, pattern, options = {}) => {
|
|
271
339
|
const compiled = compile(pattern, store.registry(), options);
|
|
272
340
|
const rows = store.db.prepare(compiled.sql).all(...compiled.params);
|
|
341
|
+
if (compiled.transitive && options.aliases === true) {
|
|
342
|
+
// Distinct (src, dst) pairs can repeat a binding set when an endpoint
|
|
343
|
+
// matched through different spellings of one aliased entity; a
|
|
344
|
+
// transitive match carries no row, so identical bindings are identical
|
|
345
|
+
// answers.
|
|
346
|
+
const seen = new Set();
|
|
347
|
+
return rows.flatMap(row => {
|
|
348
|
+
const bindings = compiled.bind(row);
|
|
349
|
+
const key = JSON.stringify(bindings);
|
|
350
|
+
if (seen.has(key)) {
|
|
351
|
+
return [];
|
|
352
|
+
}
|
|
353
|
+
seen.add(key);
|
|
354
|
+
return [{ bindings }];
|
|
355
|
+
});
|
|
356
|
+
}
|
|
273
357
|
return rows.map(row => compiled.transitive ?
|
|
274
358
|
{ bindings: compiled.bind(row) } :
|
|
275
359
|
{ bindings: compiled.bind(row), row: row });
|
package/dist/src/compile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
* query(store, '?x HAS bug: ?bug #security')
|
|
9
9
|
* query(store, '?x PART-OF monorepo') // inverse verbs compile to canonical rows
|
|
10
10
|
* query(store, 'terrier EXTENDS+ animal') // transitive
|
|
11
|
+
* query(store, '?x IS live', { asOf: '2026-01-15' }) // belief state at a past moment (§12.3)
|
|
11
12
|
* ```
|
|
12
13
|
*/
|
|
13
14
|
export * as Pattern from './pattern.ts';
|
|
14
|
-
export { query } from './compile.ts';
|
|
15
|
+
export { match, query } from './compile.ts';
|
|
15
16
|
export type { Match, Options } from './compile.ts';
|
|
16
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAC3C,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/src/index.js
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* query(store, '?x HAS bug: ?bug #security')
|
|
9
9
|
* query(store, '?x PART-OF monorepo') // inverse verbs compile to canonical rows
|
|
10
10
|
* query(store, 'terrier EXTENDS+ animal') // transitive
|
|
11
|
+
* query(store, '?x IS live', { asOf: '2026-01-15' }) // belief state at a past moment (§12.3)
|
|
11
12
|
* ```
|
|
12
13
|
*/
|
|
13
14
|
export * as Pattern from "./pattern.js";
|
|
14
|
-
export { query } from "./compile.js";
|
|
15
|
+
export { match, query } from "./compile.js";
|
|
15
16
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cavelang/query",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CAVE-Q — graph-pattern queries (?x vars, wildcards, inverse verbs, transitive hops, WHERE filters) compiled to SQL.",
|
|
6
6
|
"license": "CC0-1.0",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@cavelang/canonical": "0.
|
|
36
|
-
"@cavelang/
|
|
37
|
-
"@cavelang/
|
|
38
|
-
"@cavelang/store": "0.
|
|
35
|
+
"@cavelang/canonical": "0.13.0",
|
|
36
|
+
"@cavelang/core": "0.13.0",
|
|
37
|
+
"@cavelang/parser": "0.13.0",
|
|
38
|
+
"@cavelang/store": "0.13.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsc -b",
|
package/src/compile.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* CAVE-Q → SQL compilation (spec §12).
|
|
3
3
|
*
|
|
4
4
|
* Patterns run over *current beliefs* by default — the latest transaction
|
|
5
|
-
* per claim key (spec §9.1) — pass `all` to match the full history
|
|
5
|
+
* per claim key (spec §9.1) — pass `all` to match the full history, or
|
|
6
|
+
* `asOf` to resolve the belief state at a past moment (spec §12.3).
|
|
6
7
|
* Inverse verbs compile to the same physical query as their primary
|
|
7
8
|
* (spec §12.1): `?x PART-OF monorepo` and `monorepo CONTAINS ?x` produce
|
|
8
9
|
* identical SQL against canonical rows, with the pattern's subject binding
|
|
@@ -26,32 +27,95 @@ export type Match = {
|
|
|
26
27
|
export type Options = {
|
|
27
28
|
/** Match all appended rows, not only current beliefs. */
|
|
28
29
|
readonly all?: boolean
|
|
30
|
+
/**
|
|
31
|
+
* Resolve entity terms through the alias closure — current positive
|
|
32
|
+
* `ALIAS` claims read as undirected edges (spec §13.6). Union-of-rows:
|
|
33
|
+
* matching widens to aliased names; bindings and rows keep the stored
|
|
34
|
+
* names untouched.
|
|
35
|
+
*/
|
|
36
|
+
readonly aliases?: boolean
|
|
37
|
+
/**
|
|
38
|
+
* Resolve beliefs as of a past moment (spec §12.3): a date
|
|
39
|
+
* (`2026-01-15`, the whole UTC day included), a timestamp (the whole
|
|
40
|
+
* second included), or an exact transaction id (UUIDv7, included).
|
|
41
|
+
* Rows recorded after the boundary are invisible — current-belief
|
|
42
|
+
* resolution, the alias closure and transitive hops all reconstruct
|
|
43
|
+
* the belief state at that boundary. Composes with `all`, which then
|
|
44
|
+
* matches the full history up to the boundary.
|
|
45
|
+
*/
|
|
46
|
+
readonly asOf?: string
|
|
29
47
|
}
|
|
30
48
|
|
|
31
|
-
const currentSql = `
|
|
32
|
-
SELECT c.* FROM cave_claim c
|
|
33
|
-
JOIN (
|
|
34
|
-
SELECT claim_key, MAX(tx) AS max_tx
|
|
35
|
-
FROM cave_claim GROUP BY claim_key
|
|
36
|
-
) latest ON c.claim_key = latest.claim_key AND c.tx = latest.max_tx
|
|
37
|
-
`
|
|
38
|
-
|
|
39
49
|
/**
|
|
40
50
|
* UUIDv7 interval `[lo, hi)` for a tx filter value: a bare date covers the
|
|
41
51
|
* whole UTC day, a timestamp covers one second. Interval semantics keep
|
|
42
52
|
* adjacent operators distinguishable (`<=` includes the boundary day that
|
|
43
53
|
* `<` excludes) and make `WHERE tx = 2026-01-01` mean "recorded that day".
|
|
44
54
|
*/
|
|
45
|
-
const txBounds = (text: string): { lo: string, hi: string } => {
|
|
55
|
+
const txBounds = (text: string, label = 'tx date'): { lo: string, hi: string } => {
|
|
46
56
|
const hasTime = text.includes('T')
|
|
47
57
|
const start = Date.parse(hasTime ? text : `${text}T00:00:00Z`)
|
|
48
58
|
if (Number.isNaN(start)) {
|
|
49
|
-
throw new Error(`CAVE-Q: cannot parse
|
|
59
|
+
throw new Error(`CAVE-Q: cannot parse ${label} ${JSON.stringify(text)}`)
|
|
50
60
|
}
|
|
51
61
|
const end = start + (hasTime ? 1_000 : 86_400_000)
|
|
52
62
|
return { lo: Uuidv7.at(start, 0, new Uint8Array(8)), hi: Uuidv7.at(end, 0, new Uint8Array(8)) }
|
|
53
63
|
}
|
|
54
64
|
|
|
65
|
+
/**
|
|
66
|
+
* SQL tx condition for an as-of boundary (spec §12.3). A UUIDv7 names an
|
|
67
|
+
* exact transaction, included — belief as of that append; a date or
|
|
68
|
+
* timestamp is inclusive of the whole named day/second, the same interval
|
|
69
|
+
* semantics as `WHERE tx <=` (§12.2). Both forms inline as literals: the
|
|
70
|
+
* id is shape-validated hex-and-dashes and the interval bound comes from
|
|
71
|
+
* `Uuidv7.at` — no free-form text reaches the SQL, and a literal keeps
|
|
72
|
+
* the fragment embeddable in CTEs that positional parameters would
|
|
73
|
+
* complicate.
|
|
74
|
+
*/
|
|
75
|
+
const asOfCondition = (asOf: string): string => {
|
|
76
|
+
const id = asOf.toLowerCase()
|
|
77
|
+
return Uuidv7.is(id) ? `tx <= '${id}'` : `tx < '${txBounds(asOf, 'as-of boundary').hi}'`
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Row universe under resolution: every appended row, or only rows recorded up to the as-of boundary. */
|
|
81
|
+
const claimsSql = (asOf: undefined | string): string =>
|
|
82
|
+
asOf === undefined ? 'cave_claim' : `(SELECT * FROM cave_claim WHERE ${asOfCondition(asOf)})`
|
|
83
|
+
|
|
84
|
+
const currentSql = (asOf: undefined | string): string => `
|
|
85
|
+
SELECT c.* FROM cave_claim c
|
|
86
|
+
JOIN (
|
|
87
|
+
SELECT claim_key, MAX(tx) AS max_tx
|
|
88
|
+
FROM ${claimsSql(asOf)} GROUP BY claim_key
|
|
89
|
+
) latest ON c.claim_key = latest.claim_key AND c.tx = latest.max_tx
|
|
90
|
+
`
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Alias closure CTEs (spec §13.6): `alias_edge` is the current positive
|
|
94
|
+
* `ALIAS` claims symmetrized (each written direction is its own claim key —
|
|
95
|
+
* both assert the same undirected link); `alias_pair` its transitive
|
|
96
|
+
* closure — every ordered pair of names currently believed to denote one
|
|
97
|
+
* entity. Resolution always reads *current* beliefs, even under `all`:
|
|
98
|
+
* the closure is entity resolution as believed now, not as believed when
|
|
99
|
+
* a row landed — except under `asOf`, where "now" is the boundary itself
|
|
100
|
+
* and the closure reconstructs entity resolution as believed then
|
|
101
|
+
* (spec §12.3).
|
|
102
|
+
*/
|
|
103
|
+
const aliasPairSql = (asOf: undefined | string): string => `alias_edge(a, b) AS (
|
|
104
|
+
SELECT c.subject, c.object FROM (${currentSql(asOf)}) c
|
|
105
|
+
WHERE c.verb = 'ALIAS' AND c.negated = 0 AND c.conf > 0 AND c.object IS NOT NULL
|
|
106
|
+
UNION
|
|
107
|
+
SELECT c.object, c.subject FROM (${currentSql(asOf)}) c
|
|
108
|
+
WHERE c.verb = 'ALIAS' AND c.negated = 0 AND c.conf > 0 AND c.object IS NOT NULL
|
|
109
|
+
), alias_pair(a, b) AS (
|
|
110
|
+
SELECT a, b FROM alias_edge
|
|
111
|
+
UNION
|
|
112
|
+
SELECT p.a, e.b FROM alias_pair p JOIN alias_edge e ON e.a = p.b
|
|
113
|
+
)`
|
|
114
|
+
|
|
115
|
+
/** SQL for "these two expressions name the same entity" under the closure. */
|
|
116
|
+
const aliasSame = (left: string, right: string): string =>
|
|
117
|
+
`(${left} = ${right} OR EXISTS (SELECT 1 FROM alias_pair p WHERE p.a = ${left} AND p.b = ${right}))`
|
|
118
|
+
|
|
55
119
|
type Compiled = {
|
|
56
120
|
readonly sql: string
|
|
57
121
|
readonly params: (string | number)[]
|
|
@@ -83,27 +147,35 @@ const compile = (pattern: Pattern.t, registry: Registry.t, options: Options): Co
|
|
|
83
147
|
return compileTransitive(pattern, verb.name, subjectSlot, objectSlot, options)
|
|
84
148
|
}
|
|
85
149
|
|
|
150
|
+
const aliases = options.aliases === true
|
|
151
|
+
// Alias closure applies to entity columns only: values and attribute
|
|
152
|
+
// names are not entities, and verb aliasing is a separate, undesigned
|
|
153
|
+
// lifecycle question.
|
|
154
|
+
const entityColumns = ['subject', 'object']
|
|
86
155
|
const conditions: string[] = [`c.negated = ${pattern.negated ? 1 : 0}`]
|
|
87
156
|
const params: (string | number)[] = []
|
|
88
157
|
/** var name → row columns it binds; repeated vars add join conditions. */
|
|
89
158
|
const varColumns = new Map<string, string[]>()
|
|
90
159
|
const slot = (value: Pattern.Slot, column: string, requireNotNull: boolean): void => {
|
|
91
160
|
switch (value.kind) {
|
|
92
|
-
case 'term':
|
|
161
|
+
case 'term': {
|
|
162
|
+
const match = aliases && entityColumns.includes(column) ? aliasSame('?', `c.${column}`) : `c.${column} = ?`
|
|
163
|
+
const termParams = aliases && entityColumns.includes(column) ? [value.text, value.text] : [value.text]
|
|
93
164
|
// A date/number term in object position must also match metric
|
|
94
165
|
// rows, which store their value in value_text with object NULL
|
|
95
166
|
// (`latency IS 30ms` ⇒ pattern `latency IS 30ms` matches).
|
|
96
167
|
if (column === 'object') {
|
|
97
168
|
const parsed = Value.parse(value.text)
|
|
98
169
|
if (parsed.kind === 'number' || parsed.kind === 'date') {
|
|
99
|
-
conditions.push(
|
|
100
|
-
params.push(
|
|
170
|
+
conditions.push(`(${match} OR (c.object IS NULL AND c.value_text = ?))`)
|
|
171
|
+
params.push(...termParams, value.text)
|
|
101
172
|
return
|
|
102
173
|
}
|
|
103
174
|
}
|
|
104
|
-
conditions.push(
|
|
105
|
-
params.push(
|
|
175
|
+
conditions.push(match)
|
|
176
|
+
params.push(...termParams)
|
|
106
177
|
return
|
|
178
|
+
}
|
|
107
179
|
case 'var': {
|
|
108
180
|
const columns = varColumns.get(value.name) ?? []
|
|
109
181
|
columns.push(column)
|
|
@@ -140,7 +212,11 @@ const compile = (pattern: Pattern.t, registry: Registry.t, options: Options): Co
|
|
|
140
212
|
}
|
|
141
213
|
for (const columns of varColumns.values()) {
|
|
142
214
|
for (let i = 1; i < columns.length; i++) {
|
|
143
|
-
conditions.push(
|
|
215
|
+
conditions.push(
|
|
216
|
+
aliases && entityColumns.includes(columns[0]!) && entityColumns.includes(columns[i]!) ?
|
|
217
|
+
aliasSame(`c.${columns[0]}`, `c.${columns[i]}`) :
|
|
218
|
+
`c.${columns[0]} = c.${columns[i]}`
|
|
219
|
+
)
|
|
144
220
|
}
|
|
145
221
|
}
|
|
146
222
|
for (const context of pattern.contexts) {
|
|
@@ -224,8 +300,9 @@ const compile = (pattern: Pattern.t, registry: Registry.t, options: Options): Co
|
|
|
224
300
|
conditions.push('c.conf > 0')
|
|
225
301
|
}
|
|
226
302
|
|
|
227
|
-
const base = options.all === true ?
|
|
228
|
-
const
|
|
303
|
+
const base = options.all === true ? `SELECT * FROM ${claimsSql(options.asOf)}` : currentSql(options.asOf)
|
|
304
|
+
const withClause = aliases ? `WITH RECURSIVE ${aliasPairSql(options.asOf)} ` : ''
|
|
305
|
+
const sql = `${withClause}SELECT c.* FROM (${base}) c WHERE ${conditions.join(' AND ')} ORDER BY c.tx`
|
|
229
306
|
const bind = (row: Record<string, unknown>): Record<string, string> => {
|
|
230
307
|
const bindings: Record<string, string> = {}
|
|
231
308
|
for (const [name, columns] of varColumns) {
|
|
@@ -247,32 +324,42 @@ const compileTransitive = (
|
|
|
247
324
|
pattern.payload.kind === 'attribute') {
|
|
248
325
|
throw new Error('CAVE-Q: transitive patterns support subject/object slots only (spec §12.1)')
|
|
249
326
|
}
|
|
250
|
-
const
|
|
327
|
+
const aliases = options.aliases === true
|
|
328
|
+
const base = options.all === true ? `SELECT * FROM ${claimsSql(options.asOf)}` : currentSql(options.asOf)
|
|
329
|
+
/** Endpoint equality: exact, or alias-equal under the closure (spec §13.6). */
|
|
330
|
+
const same = (left: string, right: string): string =>
|
|
331
|
+
aliases ? aliasSame(left, right) : `${left} = ${right}`
|
|
251
332
|
const conditions: string[] = []
|
|
252
333
|
const params: (string | number)[] = [verb]
|
|
253
334
|
if (subjectSlot.kind === 'term') {
|
|
254
|
-
conditions.push('h.src
|
|
335
|
+
conditions.push(same('h.src', '?'))
|
|
255
336
|
params.push(subjectSlot.text)
|
|
337
|
+
if (aliases) {
|
|
338
|
+
params.push(subjectSlot.text)
|
|
339
|
+
}
|
|
256
340
|
}
|
|
257
341
|
if (objectSlot?.kind === 'term') {
|
|
258
|
-
conditions.push('h.dst
|
|
342
|
+
conditions.push(same('h.dst', '?'))
|
|
259
343
|
params.push(objectSlot.text)
|
|
344
|
+
if (aliases) {
|
|
345
|
+
params.push(objectSlot.text)
|
|
346
|
+
}
|
|
260
347
|
}
|
|
261
348
|
// A repeated variable forces equality here just as in single-hop
|
|
262
349
|
// patterns: `?x EXTENDS+ ?x` asks for nodes on a cycle, not for every
|
|
263
350
|
// reachable pair.
|
|
264
351
|
if (subjectSlot.kind === 'var' && objectSlot?.kind === 'var' && subjectSlot.name === objectSlot.name) {
|
|
265
|
-
conditions.push('h.src
|
|
352
|
+
conditions.push(same('h.src', 'h.dst'))
|
|
266
353
|
}
|
|
267
354
|
const sql = `
|
|
268
|
-
WITH RECURSIVE cur AS (
|
|
355
|
+
WITH RECURSIVE ${aliases ? `${aliasPairSql(options.asOf)}, ` : ''}cur AS (
|
|
269
356
|
SELECT c.subject AS src, c.object AS dst
|
|
270
357
|
FROM (${base}) c
|
|
271
358
|
WHERE c.verb = ? AND c.negated = 0 AND c.conf > 0 AND c.object IS NOT NULL
|
|
272
359
|
), hops(src, dst, depth) AS (
|
|
273
360
|
SELECT src, dst, 1 FROM cur
|
|
274
361
|
UNION
|
|
275
|
-
SELECT h.src, cur.dst, h.depth + 1 FROM hops h JOIN cur ON cur.src
|
|
362
|
+
SELECT h.src, cur.dst, h.depth + 1 FROM hops h JOIN cur ON ${same('cur.src', 'h.dst')}
|
|
276
363
|
WHERE h.depth < 32
|
|
277
364
|
)
|
|
278
365
|
SELECT DISTINCT h.src AS src, h.dst AS dst FROM hops h
|
|
@@ -298,12 +385,37 @@ ORDER BY h.src, h.dst`
|
|
|
298
385
|
* query(store, '?x USES jwt')
|
|
299
386
|
* query(store, '?cause CAUSE app/crash\n WHERE conf >= 0.7')
|
|
300
387
|
* query(store, 'terrier EXTENDS+ animal')
|
|
388
|
+
* query(store, 'server IS compromised', { asOf: '2026-01-15' })
|
|
301
389
|
* ```
|
|
302
390
|
*/
|
|
303
|
-
export const query = (store: Store, input: string, options: Options = {}): Match[] =>
|
|
304
|
-
|
|
391
|
+
export const query = (store: Store, input: string, options: Options = {}): Match[] =>
|
|
392
|
+
match(store, Pattern.parse(input), options)
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Runs an already-parsed pattern against a store — the programmatic
|
|
396
|
+
* entry point for callers that build or specialize patterns as values
|
|
397
|
+
* (the §24 rules engine substitutes bindings into premise patterns
|
|
398
|
+
* between joins) rather than as text.
|
|
399
|
+
*/
|
|
400
|
+
export const match = (store: Store, pattern: Pattern.t, options: Options = {}): Match[] => {
|
|
305
401
|
const compiled = compile(pattern, store.registry(), options)
|
|
306
402
|
const rows = store.db.prepare(compiled.sql).all(...compiled.params) as Record<string, unknown>[]
|
|
403
|
+
if (compiled.transitive && options.aliases === true) {
|
|
404
|
+
// Distinct (src, dst) pairs can repeat a binding set when an endpoint
|
|
405
|
+
// matched through different spellings of one aliased entity; a
|
|
406
|
+
// transitive match carries no row, so identical bindings are identical
|
|
407
|
+
// answers.
|
|
408
|
+
const seen = new Set<string>()
|
|
409
|
+
return rows.flatMap(row => {
|
|
410
|
+
const bindings = compiled.bind(row)
|
|
411
|
+
const key = JSON.stringify(bindings)
|
|
412
|
+
if (seen.has(key)) {
|
|
413
|
+
return []
|
|
414
|
+
}
|
|
415
|
+
seen.add(key)
|
|
416
|
+
return [{ bindings }]
|
|
417
|
+
})
|
|
418
|
+
}
|
|
307
419
|
return rows.map(row =>
|
|
308
420
|
compiled.transitive ?
|
|
309
421
|
{ bindings: compiled.bind(row) } :
|
package/src/index.ts
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
* query(store, '?x HAS bug: ?bug #security')
|
|
9
9
|
* query(store, '?x PART-OF monorepo') // inverse verbs compile to canonical rows
|
|
10
10
|
* query(store, 'terrier EXTENDS+ animal') // transitive
|
|
11
|
+
* query(store, '?x IS live', { asOf: '2026-01-15' }) // belief state at a past moment (§12.3)
|
|
11
12
|
* ```
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
export * as Pattern from './pattern.ts'
|
|
15
|
-
export { query } from './compile.ts'
|
|
16
|
+
export { match, query } from './compile.ts'
|
|
16
17
|
export type { Match, Options } from './compile.ts'
|