@jarenjs/db 0.49.2 → 0.56.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/ARCHITECTURE.md +27 -15
- package/README.md +141 -41
- package/docs/JOBS-FORMAT.md +24 -8
- package/docs/LIVE-FORMAT.md +38 -9
- package/docs/MIGRATION-FORMAT.md +118 -36
- package/docs/MODEL-FORMAT.md +232 -30
- package/package.json +4 -5
- package/schemas/jaren-migration.draft-07.schema.json +73 -0
- package/schemas/jaren-migration.schema.json +73 -0
- package/src/capture.js +66 -28
- package/src/cli.js +225 -44
- package/src/ddl.js +23 -3
- package/src/dialects/sqlite.js +2 -1
- package/src/driver.js +63 -16
- package/src/drivers/wasm.js +1 -0
- package/src/emit-model.js +14 -0
- package/src/emit.js +10 -3
- package/src/entity.js +92 -47
- package/src/errors.js +25 -0
- package/src/index.js +2 -2
- package/src/jobs.js +40 -5
- package/src/live-time.js +12 -3
- package/src/live.js +11 -1
- package/src/migrate.js +397 -191
- package/src/model.js +173 -8
- package/src/plan.js +135 -38
- package/src/query.js +138 -13
- package/src/store.js +221 -66
- package/src/tracker.js +173 -48
- package/types/index.d.ts +152 -10
- package/types/node.d.ts +3 -1
- package/types/typed.d.ts +58 -2
- package/types/wasm.d.ts +7 -0
- package/dist/types/algebra.d.ts +0 -230
- package/dist/types/app.d.ts +0 -49
- package/dist/types/capture.d.ts +0 -85
- package/dist/types/cli.d.ts +0 -2
- package/dist/types/dag-job.d.ts +0 -40
- package/dist/types/ddl.d.ts +0 -229
- package/dist/types/derive.d.ts +0 -250
- package/dist/types/dialect.d.ts +0 -154
- package/dist/types/dialects/sqlite.d.ts +0 -9
- package/dist/types/driver.d.ts +0 -110
- package/dist/types/drivers/bun.d.ts +0 -47
- package/dist/types/drivers/node.d.ts +0 -37
- package/dist/types/drivers/wasm.d.ts +0 -65
- package/dist/types/emit-model.d.ts +0 -44
- package/dist/types/emit.d.ts +0 -75
- package/dist/types/entity.d.ts +0 -23
- package/dist/types/errors.d.ts +0 -170
- package/dist/types/graph.d.ts +0 -28
- package/dist/types/index.d.ts +0 -37
- package/dist/types/jobs.d.ts +0 -140
- package/dist/types/knn.d.ts +0 -69
- package/dist/types/live-time.d.ts +0 -141
- package/dist/types/live.d.ts +0 -64
- package/dist/types/migrate.d.ts +0 -170
- package/dist/types/model.d.ts +0 -36
- package/dist/types/patch-sql.d.ts +0 -37
- package/dist/types/plan.d.ts +0 -142
- package/dist/types/profile.d.ts +0 -80
- package/dist/types/query.d.ts +0 -112
- package/dist/types/residual.d.ts +0 -64
- package/dist/types/series.d.ts +0 -227
- package/dist/types/store.d.ts +0 -60
- package/dist/types/tracker.d.ts +0 -43
- package/dist/types/typed.d.ts +0 -15
- package/dist/types/types.d.ts +0 -26
- package/dist/types/udf.d.ts +0 -75
- package/dist/types/window.d.ts +0 -52
package/dist/types/plan.d.ts
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file AST → Plan. The planner walks the engine's PUBLISHED normalized
|
|
3
|
-
* AST (never the raw document), dispatches EXHAUSTIVELY on node kind —
|
|
4
|
-
* an unrecognised kind is an internal error naming the kind and the
|
|
5
|
-
* `AST_VERSION`, never a silent residual — and promotes constructs to
|
|
6
|
-
* native form strictly residual-by-default: everything starts as a
|
|
7
|
-
* residual and earns native status only where the equivalence proof
|
|
8
|
-
* exists (the truth table in ARCHITECTURE.md, pinned by the
|
|
9
|
-
* differential tests).
|
|
10
|
-
*
|
|
11
|
-
* The outcome of planning one document:
|
|
12
|
-
*
|
|
13
|
-
* { plan, mode: 'native' | 'row' | 'set' | 'knn', reasons, rowReturn,
|
|
14
|
-
* prefilters }
|
|
15
|
-
*
|
|
16
|
-
* - `native` — everything translated; the plan alone answers.
|
|
17
|
-
* - `row` — predicates, ordering and window pushed; only the
|
|
18
|
-
* projection runs in the engine, per fetched row (streams).
|
|
19
|
-
* `rowReturn` is the COMPLETE one-row document to run, binding
|
|
20
|
-
* included — the collection binding is named by the document, so a
|
|
21
|
-
* wrapper built anywhere else would have to guess it.
|
|
22
|
-
* - `set` — the pushed conjuncts narrow candidates; the WHOLE
|
|
23
|
-
* compiled document runs over the materialized candidates.
|
|
24
|
-
* - `knn` — the pushed conjuncts narrow, the vector column CUTS the
|
|
25
|
-
* candidates of a k-nearest window (`plan.rank`), and the whole
|
|
26
|
-
* compiled document runs over the cut — a set residual whose
|
|
27
|
-
* candidate set an ordering, not a predicate, chose (see "The
|
|
28
|
-
* k-nearest promotion" below).
|
|
29
|
-
*
|
|
30
|
-
* `reasons` names every construct that forced work off the database,
|
|
31
|
-
* with reason text drawn from the deliberate-residual table.
|
|
32
|
-
* `prefilters` names the IMPLIED conjuncts — predicates the planner
|
|
33
|
-
* ADDED because a spatial one provably implies them (see "Spatial
|
|
34
|
-
* promotions" below) — with the columns each reads and whether it
|
|
35
|
-
* decided or merely narrowed.
|
|
36
|
-
*/
|
|
37
|
-
/**
|
|
38
|
-
* Assert a node kind is one this planner has decided. Called on every
|
|
39
|
-
* dispatch; the throw names the kind and the AST version so a language
|
|
40
|
-
* change breaks the build instead of becoming an accidental residual.
|
|
41
|
-
* Exported so the throw itself is pinned by a test.
|
|
42
|
-
* @param {any} node
|
|
43
|
-
*/
|
|
44
|
-
export declare function assertDecidedKind(node: any): void;
|
|
45
|
-
/**
|
|
46
|
-
* Plan a whole document against one collection. The store's registered
|
|
47
|
-
* operators (Ring 2) ride in `shape.operators` — the planner recognises
|
|
48
|
-
* them as vocabulary but keeps them in the residual, and names them in
|
|
49
|
-
* the reasons when it does.
|
|
50
|
-
* @param {any} document - The raw query document (kept beside the AST
|
|
51
|
-
* for residual construction — the AST has no unparser)
|
|
52
|
-
* @param {any} shape - { collection, schema, columnByCanonical, operators? }
|
|
53
|
-
* @param {{ udf?: (fragment: any) => { name: string, key: string } | null }} [options]
|
|
54
|
-
* @returns {{
|
|
55
|
-
* analysis: any,
|
|
56
|
-
* plan: import('./algebra.js').Plan | null,
|
|
57
|
-
* mode: 'native' | 'row' | 'set' | 'knn',
|
|
58
|
-
* reasons: { construct: string, reason: string }[],
|
|
59
|
-
* rowReturn: any,
|
|
60
|
-
* udfs: string[],
|
|
61
|
-
* prefilters: { construct: string, via: 'columns' | 'rtree',
|
|
62
|
-
* columns: string[], exact: boolean }[],
|
|
63
|
-
* series: any,
|
|
64
|
-
* }}
|
|
65
|
-
*/
|
|
66
|
-
export declare function planQuery(document: any, shape: any, options?: {
|
|
67
|
-
udf?: (fragment: any) => {
|
|
68
|
-
name: string;
|
|
69
|
-
key: string;
|
|
70
|
-
} | null;
|
|
71
|
-
}): {
|
|
72
|
-
analysis: any;
|
|
73
|
-
plan: import('./algebra.js').Plan | null;
|
|
74
|
-
mode: 'native' | 'row' | 'set' | 'knn';
|
|
75
|
-
reasons: {
|
|
76
|
-
construct: string;
|
|
77
|
-
reason: string;
|
|
78
|
-
}[];
|
|
79
|
-
rowReturn: any;
|
|
80
|
-
udfs: string[];
|
|
81
|
-
prefilters: {
|
|
82
|
-
construct: string;
|
|
83
|
-
via: 'columns' | 'rtree';
|
|
84
|
-
columns: string[];
|
|
85
|
-
exact: boolean;
|
|
86
|
-
}[];
|
|
87
|
-
series: any;
|
|
88
|
-
};
|
|
89
|
-
/**
|
|
90
|
-
* Build the planner shape for one entity: canonical top-level paths
|
|
91
|
-
* map to REAL columns (flavor `entity-column`), epoch date columns to
|
|
92
|
-
* their derived integer twins (flavor `entity-epoch`), and everything
|
|
93
|
-
* else stays a document path over the entity's JSONB column (the
|
|
94
|
-
* phase-A guarded forms).
|
|
95
|
-
* @param {any} entity - normalized entity (model.js)
|
|
96
|
-
* @param {any} entityMapping - explainMapping(...).entities[name]
|
|
97
|
-
* @returns {any}
|
|
98
|
-
*/
|
|
99
|
-
export declare function entityShape(entity: any, entityMapping: any): any;
|
|
100
|
-
/**
|
|
101
|
-
* Resolve a singular member path on an entity binding to a flavored
|
|
102
|
-
* PlanRef.
|
|
103
|
-
* @param {any} node - a path AST node
|
|
104
|
-
* @param {number} slot
|
|
105
|
-
* @param {any} shape - from {@link entityShape}
|
|
106
|
-
* @returns {any | null}
|
|
107
|
-
*/
|
|
108
|
-
export declare function entityPathRef(node: any, slot: number, shape: any): any | null;
|
|
109
|
-
/**
|
|
110
|
-
* Plan one predicate over an entity binding: the same operator
|
|
111
|
-
* grammar as phase A, with entity-flavored refs. Reuses
|
|
112
|
-
* {@link planPredicate} for the recognition, then re-resolves refs
|
|
113
|
-
* through the flavor table.
|
|
114
|
-
* @param {any} node
|
|
115
|
-
* @param {number} slot
|
|
116
|
-
* @param {any} shape
|
|
117
|
-
* @returns {{ pred: any } | { refusal: { construct: string, reason: string } }}
|
|
118
|
-
*/
|
|
119
|
-
export declare function planEntityPredicate(node: any, slot: number, shape: any): {
|
|
120
|
-
pred: any;
|
|
121
|
-
} | {
|
|
122
|
-
refusal: {
|
|
123
|
-
construct: string;
|
|
124
|
-
reason: string;
|
|
125
|
-
};
|
|
126
|
-
};
|
|
127
|
-
/**
|
|
128
|
-
* Plan an ENTITY query document (one planner, two document kinds). The
|
|
129
|
-
* store's registered operators (Ring 2) are recognised as vocabulary and
|
|
130
|
-
* kept in the set residual over the fetched root, named in the reasons.
|
|
131
|
-
* @param {any} document
|
|
132
|
-
* @param {Map<string, any>} entities - normalized entities
|
|
133
|
-
* @param {any} mapping - explainMapping result
|
|
134
|
-
* @param {{ functions?: any, extensions?: any } | null} [operators]
|
|
135
|
-
* @returns {any}
|
|
136
|
-
*/
|
|
137
|
-
export declare function planEntityQuery(document: any, entities: Map<string, any>, mapping: any, operators?: {
|
|
138
|
-
functions?: any;
|
|
139
|
-
extensions?: any;
|
|
140
|
-
} | null): any;
|
|
141
|
-
/** The entity names a document's root paths reference (`$.Name[*]`). */
|
|
142
|
-
export declare function collectEntityRoots(document: any, entities: any): Set<any>;
|
package/dist/types/profile.d.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The safe execution profile (D15): a query document that arrives
|
|
3
|
-
* from a tenant, a remote client or a language model can reach a
|
|
4
|
-
* database, and injection being structurally impossible (parameter
|
|
5
|
-
* binding) says nothing about resource exhaustion or cross-tenant
|
|
6
|
-
* reads. A profile composes four INDEPENDENT bounds:
|
|
7
|
-
*
|
|
8
|
-
* 1. engine limits — `{sequenceItems, resultItems, steps, depth}`
|
|
9
|
-
* wired into every residual compilation, so the JavaScript
|
|
10
|
-
* portion of a query is bounded by the engine's own enforcement;
|
|
11
|
-
* 2. the mandatory row bound — every non-aggregate fetch carries a
|
|
12
|
-
* LIMIT of `maxRows + 1`, and fetching more than `maxRows` rows is
|
|
13
|
-
* the coded `JD2007`, never a silent truncation (D14);
|
|
14
|
-
* 3. reference containment — undeclared externals, host functions,
|
|
15
|
-
* collations or collections are the compile error `JD0011`; no UDF
|
|
16
|
-
* registration happens under a profile; optionally, a plan whose
|
|
17
|
-
* database narrative shows a full-table SCAN is refused;
|
|
18
|
-
* 4. mandatory predicates — a per-collection predicate conjoined into
|
|
19
|
-
* EVERY plan at its root, after translation, so no document shape
|
|
20
|
-
* can produce a fetch without it.
|
|
21
|
-
*
|
|
22
|
-
* The non-claims are part of the contract and live in
|
|
23
|
-
* MODEL-FORMAT.md §8: no statement timeout exists on the SQLite
|
|
24
|
-
* drivers (the capability slot is empty), so a long-running native
|
|
25
|
-
* aggregate is bounded by nothing here; the row bound covers fetched
|
|
26
|
-
* rows, not database-internal work.
|
|
27
|
-
*/
|
|
28
|
-
/** The `'safe'` profile: the documented defaults. */
|
|
29
|
-
export declare const SAFE_PROFILE: Readonly<{
|
|
30
|
-
limits: Readonly<{
|
|
31
|
-
sequenceItems: 100000;
|
|
32
|
-
resultItems: 10000;
|
|
33
|
-
steps: 1000000;
|
|
34
|
-
depth: 32;
|
|
35
|
-
}>;
|
|
36
|
-
maxRows: 1000;
|
|
37
|
-
externals: readonly never[];
|
|
38
|
-
functions: readonly never[];
|
|
39
|
-
collations: readonly never[];
|
|
40
|
-
collections: null;
|
|
41
|
-
predicates: Readonly<{}>;
|
|
42
|
-
refuseFullScan: false;
|
|
43
|
-
}>;
|
|
44
|
-
/**
|
|
45
|
-
* Normalize a profile option: the string `'safe'` is the default
|
|
46
|
-
* table; an object overrides individual members over those defaults
|
|
47
|
-
* (limits merge member-wise). The result is plain JSON — cacheable by
|
|
48
|
-
* content key — and frozen.
|
|
49
|
-
* @param {any} profile - `'safe'` or a partial profile object
|
|
50
|
-
* @returns {any}
|
|
51
|
-
*/
|
|
52
|
-
export declare function normalizeProfile(profile: any): any;
|
|
53
|
-
/**
|
|
54
|
-
* Translate a profile's mandatory predicate for one collection into a
|
|
55
|
-
* plan predicate. The predicate is HOST-authored configuration, so a
|
|
56
|
-
* predicate that does not translate natively is a host programming
|
|
57
|
-
* error (TypeError), not a coded document failure — there is no
|
|
58
|
-
* residual to hide it in: the whole point is that it binds the
|
|
59
|
-
* database-side fetch.
|
|
60
|
-
* @param {any} expression - A query expression over `$it`
|
|
61
|
-
* @param {any} shape - The collection's plan shape
|
|
62
|
-
* @returns {import('./algebra.js').PlanPredicate}
|
|
63
|
-
*/
|
|
64
|
-
export declare function translateProfilePredicate(expression: any, shape: any): import('./algebra.js').PlanPredicate;
|
|
65
|
-
/**
|
|
66
|
-
* Conjoin a mandatory predicate into a plan's root filter.
|
|
67
|
-
* @param {import('./algebra.js').Plan} plan
|
|
68
|
-
* @param {import('./algebra.js').PlanPredicate | null} predicate
|
|
69
|
-
* @returns {import('./algebra.js').Plan}
|
|
70
|
-
*/
|
|
71
|
-
export declare function applyMandatoryPredicate(plan: import('./algebra.js').Plan, predicate: import('./algebra.js').PlanPredicate | null): import('./algebra.js').Plan;
|
|
72
|
-
/**
|
|
73
|
-
* Cap a plan's window at the profile's detection bound
|
|
74
|
-
* (`maxRows + 1`): a result crossing `maxRows` is detected and
|
|
75
|
-
* refused, never silently truncated. Aggregates are exempt (one row).
|
|
76
|
-
* @param {import('./algebra.js').Plan} plan
|
|
77
|
-
* @param {number} maxRows
|
|
78
|
-
* @returns {import('./algebra.js').Plan}
|
|
79
|
-
*/
|
|
80
|
-
export declare function applyRowBound(plan: import('./algebra.js').Plan, maxRows: number): import('./algebra.js').Plan;
|
package/dist/types/query.d.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The query surface over one collection: the D2 provider
|
|
3
|
-
* (`execute(document, options)` — how a linq chain runs here with no
|
|
4
|
-
* import edge), the streaming cursor (`query`), and `explain()`.
|
|
5
|
-
*
|
|
6
|
-
* The statement cache is a CALLER of the core primitives:
|
|
7
|
-
* `createSemanticCache` keyed by the whole discriminating tuple —
|
|
8
|
-
* document plus collection, dialect, strictness, pushdown and profile.
|
|
9
|
-
* The identity is the tuple's COMPLETE serialization, never a
|
|
10
|
-
* fingerprint of it: a 32-bit content hash collides after tens of
|
|
11
|
-
* thousands of documents, and a collision here answers one query with
|
|
12
|
-
* another query's plan and rows. `store.stats()` exposes hits, misses
|
|
13
|
-
* and evictions so the cache is proven rather than assumed.
|
|
14
|
-
*
|
|
15
|
-
* Bind-time diversion: if any referenced external is missing or not a
|
|
16
|
-
* string or finite number, the call runs the always-compilable set
|
|
17
|
-
* residual over the full collection instead of the native statement —
|
|
18
|
-
* SQLite cannot bind a boolean, a `null` needs Jaren's semantics, and
|
|
19
|
-
* a missing external must raise the ENGINE's error, not a driver's.
|
|
20
|
-
* Two externals never bind at all and divert by their own rule: a
|
|
21
|
-
* region reaching the statement through derived slots diverts when it
|
|
22
|
-
* has no box, and a k-nearest probe — which the plan scores in the
|
|
23
|
-
* engine, never in SQL — diverts when it is not a vector of the
|
|
24
|
-
* column's width, so the engine answers what it answers everywhere.
|
|
25
|
-
*
|
|
26
|
-
* The k-nearest mode (`plan.rank`) is a set residual whose candidates
|
|
27
|
-
* an ordering chose: the statement fetches (identity, column) under
|
|
28
|
-
* the pushed WHERE, the engine scores and cuts (`knn.js`), the
|
|
29
|
-
* winners' documents are fetched by identity through the dialect, and
|
|
30
|
-
* the whole document runs over them.
|
|
31
|
-
*/
|
|
32
|
-
/**
|
|
33
|
-
* The store-wide query state shared by every collection's engine: one
|
|
34
|
-
* bounded statement cache, its counters, the UDF registration set, and
|
|
35
|
-
* the store's resolved registered operators (Ring 2 — `{ functions,
|
|
36
|
-
* extensions }` or `null`), threaded to every engine that builds a
|
|
37
|
-
* residual.
|
|
38
|
-
* @param {number} [bound]
|
|
39
|
-
* @param {{ functions?: any, extensions?: any } | null} [operators]
|
|
40
|
-
* @param {any} [zoneProvider] - D7's injected clock, or absent
|
|
41
|
-
* @returns {any}
|
|
42
|
-
*/
|
|
43
|
-
export declare function createQueryState(bound?: number, operators?: {
|
|
44
|
-
functions?: any;
|
|
45
|
-
extensions?: any;
|
|
46
|
-
} | null, zoneProvider?: any): any;
|
|
47
|
-
/**
|
|
48
|
-
* The query engine for one collection.
|
|
49
|
-
* @param {{ connection: any, state: any, collection: any,
|
|
50
|
-
* physicalPlan: any, profile?: any }} context - `collection` is the
|
|
51
|
-
* normalized collection; `physicalPlan` is the DDL plan
|
|
52
|
-
* (columns, indexes); `profile` is the store-level normalized
|
|
53
|
-
* profile, if one was opened with
|
|
54
|
-
* @returns {{ execute: Function, query: Function, explain: Function }}
|
|
55
|
-
*/
|
|
56
|
-
export declare function createQueryEngine(context: {
|
|
57
|
-
connection: any;
|
|
58
|
-
state: any;
|
|
59
|
-
collection: any;
|
|
60
|
-
physicalPlan: any;
|
|
61
|
-
profile?: any;
|
|
62
|
-
}): {
|
|
63
|
-
execute: Function;
|
|
64
|
-
query: Function;
|
|
65
|
-
explain: Function;
|
|
66
|
-
};
|
|
67
|
-
/** The default include depth bound (D14: printed, never silent). */
|
|
68
|
-
export declare const INCLUDE_DEPTH_DEFAULT = 3;
|
|
69
|
-
/**
|
|
70
|
-
* The store-level entity query engine: documents over the
|
|
71
|
-
* multi-entity root (`$.<Entity>[*]` bindings), planned to guarded
|
|
72
|
-
* selections and INNER equijoins, with the set residual running the
|
|
73
|
-
* whole document over the fetched root — the same honesty contract as
|
|
74
|
-
* phase A.
|
|
75
|
-
* @param {{ connection: any, entities: Map<string, any>, mapping: any,
|
|
76
|
-
* state: any }} context
|
|
77
|
-
* @returns {any}
|
|
78
|
-
*/
|
|
79
|
-
export declare function createEntityQueryEngine(context: {
|
|
80
|
-
connection: any;
|
|
81
|
-
entities: Map<string, any>;
|
|
82
|
-
mapping: any;
|
|
83
|
-
state: any;
|
|
84
|
-
}): any;
|
|
85
|
-
/**
|
|
86
|
-
* The one-statement graph loader: `entity.load(spec)` compiles an
|
|
87
|
-
* include tree to correlated subqueries projected as JSON — one
|
|
88
|
-
* statement regardless of depth (asserted by a counting driver in the
|
|
89
|
-
* tests, because N+1 is a test, not a promise). Per-relation `where`,
|
|
90
|
-
* `orderBy` and `take` are applied INSIDE the subquery; depth is
|
|
91
|
-
* bounded with the default printed in the refusal; cycles in the
|
|
92
|
-
* specification are rejected; and keyset pagination is chosen over a
|
|
93
|
-
* growing OFFSET whenever the top-level ordering is a single unique
|
|
94
|
-
* column, with the choice reported by `explainLoad`.
|
|
95
|
-
* @param {{ connection: any, entities: Map<string, any>, mapping: any,
|
|
96
|
-
* state: any }} context
|
|
97
|
-
* @param {string} entityName
|
|
98
|
-
* @returns {any}
|
|
99
|
-
*/
|
|
100
|
-
export declare function createLoadEngine(context: {
|
|
101
|
-
connection: any;
|
|
102
|
-
entities: Map<string, any>;
|
|
103
|
-
mapping: any;
|
|
104
|
-
state: any;
|
|
105
|
-
}, entityName: string): any;
|
|
106
|
-
export type ParamCollector = {
|
|
107
|
-
literal?: any;
|
|
108
|
-
external?: string;
|
|
109
|
-
}[];
|
|
110
|
-
/**
|
|
111
|
-
* @typedef {{ literal?: any, external?: string }[]} ParamCollector
|
|
112
|
-
*/
|
package/dist/types/residual.d.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Residual compilation: the part of a query that stays in
|
|
3
|
-
* JavaScript is a REAL compiled Jaren query — the same engine, the
|
|
4
|
-
* same semantics — never a reimplementation.
|
|
5
|
-
*
|
|
6
|
-
* Two modes (ARCHITECTURE.md):
|
|
7
|
-
*
|
|
8
|
-
* - `set` — the whole original document compiled once, run over the
|
|
9
|
-
* materialized candidate array. Re-applying pushed conjuncts is
|
|
10
|
-
* idempotent, so SQL-side narrowing never changes the answer.
|
|
11
|
-
* - `row` — only the projection stayed behind: each fetched row runs
|
|
12
|
-
* the planner's one-row document over the one-row array; the array
|
|
13
|
-
* wrapper packs the item sequence so an array-VALUED item stays
|
|
14
|
-
* unambiguous, and the per-row results concatenate in row order
|
|
15
|
-
* (streamable).
|
|
16
|
-
*
|
|
17
|
-
* Neither mode builds a query document here. The collection binding is
|
|
18
|
-
* named by the caller's document — `it`, `user`, anything — so a wrapper
|
|
19
|
-
* synthesized in this file could only guess it, and a guess that
|
|
20
|
-
* disagreed with the projection's references would surface as an
|
|
21
|
-
* unbound-external error at request time rather than at compile time.
|
|
22
|
-
* The planner knows the name and hands both modes something complete.
|
|
23
|
-
*/
|
|
24
|
-
/**
|
|
25
|
-
* Compile the whole document for set-mode evaluation. A profile's
|
|
26
|
-
* engine limits ride into the compilation so the JavaScript portion is
|
|
27
|
-
* bounded by the engine's own enforcement.
|
|
28
|
-
* @param {any} document
|
|
29
|
-
* @param {any} [limits]
|
|
30
|
-
* @param {{ functions?: any, extensions?: any } | null} [operators] -
|
|
31
|
-
* the store's registered operators, so the residual can evaluate them
|
|
32
|
-
* @param {any} [zoneProvider] - D7's injected clock, so a calendar
|
|
33
|
-
* ladder on a named zone compiles rather than being refused
|
|
34
|
-
* @returns {(candidates: any[], externals: any) => any}
|
|
35
|
-
*/
|
|
36
|
-
export declare function compileSetResidual(document: any, limits?: any, operators?: {
|
|
37
|
-
functions?: any;
|
|
38
|
-
extensions?: any;
|
|
39
|
-
} | null, zoneProvider?: any): (candidates: any[], externals: any) => any;
|
|
40
|
-
/**
|
|
41
|
-
* Compile the per-row projection for row-mode evaluation.
|
|
42
|
-
* @param {any} rowDocument - The planner's complete one-row document
|
|
43
|
-
* (`{ $for: { <the document's own binding>: '$[*]' },
|
|
44
|
-
* $return: [ <its $return> ] }`). It arrives whole because the binding
|
|
45
|
-
* and the projection that references it must agree, and the planner is
|
|
46
|
-
* the only place that knows the name.
|
|
47
|
-
* @param {any} [limits]
|
|
48
|
-
* @param {{ functions?: any, extensions?: any } | null} [operators]
|
|
49
|
-
* @param {any} [zoneProvider] - D7's injected clock
|
|
50
|
-
* @returns {(row: any, externals: any) => any[]} the row's items
|
|
51
|
-
*/
|
|
52
|
-
export declare function compileRowResidual(rowDocument: any, limits?: any, operators?: {
|
|
53
|
-
functions?: any;
|
|
54
|
-
extensions?: any;
|
|
55
|
-
} | null, zoneProvider?: any): (row: any, externals: any) => any[];
|
|
56
|
-
/**
|
|
57
|
-
* Map a flat item array onto the engine's result shape: an empty
|
|
58
|
-
* sequence is `undefined`, a singleton is the item, anything longer is
|
|
59
|
-
* the array (probed engine behaviour, pinned by the differential
|
|
60
|
-
* tests).
|
|
61
|
-
* @param {any[]} items
|
|
62
|
-
* @returns {any}
|
|
63
|
-
*/
|
|
64
|
-
export declare function sequenceResult(items: any[]): any;
|
package/dist/types/series.d.ts
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The temporal recognizer: which documents ask a §8.16 question,
|
|
3
|
-
* which of those a declared `(series, at)` index can answer, and what
|
|
4
|
-
* the honest reason is when it cannot.
|
|
5
|
-
*
|
|
6
|
-
* No SQL and no storage kind live here. The physical feature is the
|
|
7
|
-
* composite JSONPath index a model already declares
|
|
8
|
-
* (`{ "name": "by_series_at", "path": ["$.series", "$.at"] }`); this
|
|
9
|
-
* module only decides which of the three CLOSED shapes a planned
|
|
10
|
-
* selection is in:
|
|
11
|
-
*
|
|
12
|
-
* 1. **range** — an equality on every leading column of an instant
|
|
13
|
-
* index plus a half-open range on the instant column, ordered by
|
|
14
|
-
* the instant. The index seeks; nothing is left over.
|
|
15
|
-
* 2. **as-of** — the same prefix with ONE instant bound, ordered by
|
|
16
|
-
* the instant and cut to a finite window. One index seek per probe.
|
|
17
|
-
* 3. **bucket** — a fixed-width ladder over the instant column with
|
|
18
|
-
* the exact `sum|mean|min|max|count` aggregates, which is a
|
|
19
|
-
* `GROUP BY` over integer arithmetic.
|
|
20
|
-
*
|
|
21
|
-
* Everything else — a calendar ladder, a fill policy, a rolling window,
|
|
22
|
-
* an as-of JOIN, `first`/`last` — is a named core refinement: the
|
|
23
|
-
* database narrows through the index and `@jarenjs/core/series` (via
|
|
24
|
-
* the residual, which is the ENGINE running the caller's own document)
|
|
25
|
-
* decides. The narrowing is the contribution; the answer is always the
|
|
26
|
-
* engine's, which is what makes a refinement idempotent.
|
|
27
|
-
*
|
|
28
|
-
* Every refusal here has a CODE, and the code is the first word of the
|
|
29
|
-
* sentence the plan carries, so `explain().series.reasons[].code` and
|
|
30
|
-
* `explain().residual.reasons[].reason` cannot drift apart.
|
|
31
|
-
*/
|
|
32
|
-
/** The three §8.16 operators a whole document can BE. */
|
|
33
|
-
export declare const SERIES_ROOT_OPS: readonly string[];
|
|
34
|
-
/** Every §8.16 operator: naming one makes a document temporal. */
|
|
35
|
-
export declare const SERIES_OPS: readonly string[];
|
|
36
|
-
/**
|
|
37
|
-
* The D5 aggregates a `GROUP BY` reproduces exactly, and the plan's
|
|
38
|
-
* name for each. `count` is `rows` because it counts SOURCE ROWS —
|
|
39
|
-
* duplicates and measured gaps included — which is `COUNT(*)` and not
|
|
40
|
-
* `COUNT(value)`; the six value aggregates skip a `null` reading,
|
|
41
|
-
* which is what SQL's aggregates already do with SQL `NULL`.
|
|
42
|
-
*
|
|
43
|
-
* `first` and `last` are deliberately absent: they name a row by its
|
|
44
|
-
* position in the series, and a group's order is not the series' order.
|
|
45
|
-
*/
|
|
46
|
-
export declare const NATIVE_AGGREGATES: Readonly<{
|
|
47
|
-
mean: "avg";
|
|
48
|
-
sum: "sum";
|
|
49
|
-
min: "min";
|
|
50
|
-
max: "max";
|
|
51
|
-
count: "rows";
|
|
52
|
-
}>;
|
|
53
|
-
/**
|
|
54
|
-
* The closed reason table. A reason is a CODE and a sentence; the plan
|
|
55
|
-
* carries `"<code>: <sentence>"` so one string serves strict mode's
|
|
56
|
-
* refusal, `explain().residual.reasons` and the machine-readable
|
|
57
|
-
* `explain().series.reasons[].code` at once.
|
|
58
|
-
*/
|
|
59
|
-
export declare const SERIES_REASONS: Readonly<{
|
|
60
|
-
'missing-series-prefix': string;
|
|
61
|
-
'calendar-width': string;
|
|
62
|
-
'named-zone': string;
|
|
63
|
-
'fill-policy': string;
|
|
64
|
-
'rolling-refinement': string;
|
|
65
|
-
'asof-refinement': "an as-of join walks both sides once, so the index bounds the fetch and the kernel joins";
|
|
66
|
-
'nonliteral-spec': string;
|
|
67
|
-
'unsupported-aggregate': string;
|
|
68
|
-
'row-selector': string;
|
|
69
|
-
'instant-not-integer': string;
|
|
70
|
-
'value-not-numeric': string;
|
|
71
|
-
'nonnative-grouping': "the grouping key or the projection is not the closed bucket shape";
|
|
72
|
-
'invalid-spec': string;
|
|
73
|
-
}>;
|
|
74
|
-
/**
|
|
75
|
-
* One reason, in both spellings at once.
|
|
76
|
-
* @param {keyof SERIES_REASONS | string} code
|
|
77
|
-
* @param {string} construct - the operator or clause that forced it
|
|
78
|
-
* @returns {{ code: string, construct: string, reason: string }}
|
|
79
|
-
*/
|
|
80
|
-
export declare function seriesReason(code: keyof SERIES_REASONS | string, construct: string): {
|
|
81
|
-
code: string;
|
|
82
|
-
construct: string;
|
|
83
|
-
reason: string;
|
|
84
|
-
};
|
|
85
|
-
/**
|
|
86
|
-
* Every declared index whose LAST covered column is `column`, with the
|
|
87
|
-
* columns before it as the prefix that must be pinned.
|
|
88
|
-
*
|
|
89
|
-
* `minColumns` is what keeps an ordinary query ordinary. A collection
|
|
90
|
-
* that declares `(age)` and is asked for `age > 21` is not asking a
|
|
91
|
-
* temporal question, and nothing in a column can say otherwise — so
|
|
92
|
-
* the shape D9 actually names, a COMPOSITE index whose last column is
|
|
93
|
-
* the instant, is what makes a plain selection temporal. A document
|
|
94
|
-
* that named a §8.16 operator has already said so itself, and reads
|
|
95
|
-
* the singular index too.
|
|
96
|
-
* @param {any} shape - { indexes?: { name, columns }[] }
|
|
97
|
-
* @param {string} column
|
|
98
|
-
* @param {number} [minColumns]
|
|
99
|
-
* @returns {{ name: string, prefix: string[], column: string }[]}
|
|
100
|
-
*/
|
|
101
|
-
export declare function instantIndexesOver(shape: any, column: string, minColumns?: number): {
|
|
102
|
-
name: string;
|
|
103
|
-
prefix: string[];
|
|
104
|
-
column: string;
|
|
105
|
-
}[];
|
|
106
|
-
/**
|
|
107
|
-
* The index a fetch actually SEEKS through, or `null` when none does.
|
|
108
|
-
*
|
|
109
|
-
* A B-tree is seekable exactly as far as its leading columns are
|
|
110
|
-
* decided: a run of equalities, and then at most one range. So the
|
|
111
|
-
* index that wins is the one with the longest leading run of PINNED
|
|
112
|
-
* columns whose next column is the instant the query ranges over —
|
|
113
|
-
* which is `(series, at)` under an equality on the series, and is
|
|
114
|
-
* nothing at all under a bare instant bound, because a range on a
|
|
115
|
-
* trailing column reads every row of the index.
|
|
116
|
-
*
|
|
117
|
-
* With no instant column of its own (an as-of join reading an instant
|
|
118
|
-
* the model does not index) a pinned prefix alone still seeks, and is
|
|
119
|
-
* reported as what it is.
|
|
120
|
-
* @param {any} shape
|
|
121
|
-
* @param {string | null} column - the instant column, or `null`
|
|
122
|
-
* @param {{ pinned: Set<string>, bounds: Map<string, any> }} facts
|
|
123
|
-
* @param {number} [minColumns] - see {@link instantIndexesOver}
|
|
124
|
-
* @returns {{ name: string, prefix: string[], column: string | null } | null}
|
|
125
|
-
*/
|
|
126
|
-
export declare function seekingIndexFor(shape: any, column: string | null, facts: {
|
|
127
|
-
pinned: Set<string>;
|
|
128
|
-
bounds: Map<string, any>;
|
|
129
|
-
}, minColumns?: number): {
|
|
130
|
-
name: string;
|
|
131
|
-
prefix: string[];
|
|
132
|
-
column: string | null;
|
|
133
|
-
} | null;
|
|
134
|
-
/**
|
|
135
|
-
* Walk a pushed filter and report, per column, what it decided: which
|
|
136
|
-
* columns an equality pinned and what instant bounds a range put on
|
|
137
|
-
* one. Only a top-level conjunction counts — a disjunction or a
|
|
138
|
-
* negation decides nothing about a seek.
|
|
139
|
-
* @param {import('./algebra.js').PlanPredicate | null} filter
|
|
140
|
-
* @returns {{ pinned: Set<string>,
|
|
141
|
-
* bounds: Map<string, { from: any, fromOp: string | null,
|
|
142
|
-
* to: any, toOp: string | null }> }}
|
|
143
|
-
*/
|
|
144
|
-
export declare function filterFacts(filter: import('./algebra.js').PlanPredicate | null): {
|
|
145
|
-
pinned: Set<string>;
|
|
146
|
-
bounds: Map<string, {
|
|
147
|
-
from: any;
|
|
148
|
-
fromOp: string | null;
|
|
149
|
-
to: any;
|
|
150
|
-
toOp: string | null;
|
|
151
|
-
}>;
|
|
152
|
-
};
|
|
153
|
-
/**
|
|
154
|
-
* The fixed ladder a `$time-bucket`/`$resample` spec asks for, or the
|
|
155
|
-
* reason it is not one. `origin` is folded to an epoch here — a
|
|
156
|
-
* `{ offset }` context moves the ladder's default anchor off UTC's
|
|
157
|
-
* midnight, which is arithmetic, while a named zone is not.
|
|
158
|
-
*
|
|
159
|
-
* The width is read through the temporal kernel's OWN compiler, so
|
|
160
|
-
* `'PT1H'`, `3600000` and `'PT60M'` are the same ladder, the default
|
|
161
|
-
* anchor is the kernel's rather than a second guess at it, and a width
|
|
162
|
-
* mixing the two families was already refused when the query compiled.
|
|
163
|
-
* @param {{ every: any, origin?: any, zone?: any, offset?: any }} spec
|
|
164
|
-
* @param {(spec: any, options: any) => any} compileBuckets - the kernel's
|
|
165
|
-
* @returns {{ every: number, origin: number } | { code: string }}
|
|
166
|
-
*/
|
|
167
|
-
export declare function fixedLadder(spec: {
|
|
168
|
-
every: any;
|
|
169
|
-
origin?: any;
|
|
170
|
-
zone?: any;
|
|
171
|
-
offset?: any;
|
|
172
|
-
}, compileBuckets: (spec: any, options: any) => any): {
|
|
173
|
-
every: number;
|
|
174
|
-
origin: number;
|
|
175
|
-
} | {
|
|
176
|
-
code: string;
|
|
177
|
-
};
|
|
178
|
-
/**
|
|
179
|
-
* Whether a `PlanRef` can carry a native bucket ladder: the instant
|
|
180
|
-
* must be a declared whole epoch, because the boundary arithmetic in
|
|
181
|
-
* SQL is integer arithmetic and a truncating division over a real
|
|
182
|
-
* would put an instant before 1970 in the bucket after its own.
|
|
183
|
-
* @param {import('./algebra.js').PlanRef | null} ref
|
|
184
|
-
* @returns {string | null} the reason code, or `null` when it can
|
|
185
|
-
*/
|
|
186
|
-
export declare function instantRefusal(ref: import('./algebra.js').PlanRef | null): string | null;
|
|
187
|
-
/**
|
|
188
|
-
* Whether a `PlanRef` can carry a native VALUE aggregate.
|
|
189
|
-
* @param {import('./algebra.js').PlanRef | null} ref
|
|
190
|
-
* @returns {string | null}
|
|
191
|
-
*/
|
|
192
|
-
export declare function valueRefusal(ref: import('./algebra.js').PlanRef | null): string | null;
|
|
193
|
-
/**
|
|
194
|
-
* The one member name a `'$.on'`-style row selector reads, or `null`
|
|
195
|
-
* for anything a declared column cannot stand in for. The language's
|
|
196
|
-
* own reader (`compileSelector`) folds a single-segment path to a bare
|
|
197
|
-
* name; this reads the same two spellings out of the FROZEN literal a
|
|
198
|
-
* planner sees, and refuses everything else rather than guessing.
|
|
199
|
-
* @param {any} text
|
|
200
|
-
* @returns {string | null}
|
|
201
|
-
*/
|
|
202
|
-
export declare function singularSelector(text: any): string | null;
|
|
203
|
-
/**
|
|
204
|
-
* The explain record for one temporal document. Counts are the LAST
|
|
205
|
-
* ACTUAL execution's — never an estimate — and are `null` until the
|
|
206
|
-
* document has run once.
|
|
207
|
-
* @param {{ mode: 'native' | 'hybrid' | 'engine', operation: string,
|
|
208
|
-
* index?: string | null, prefix?: string[], range?: any,
|
|
209
|
-
* ladder?: any, aggregates?: string[], refinement?: string | null,
|
|
210
|
-
* reasons?: { code: string, construct: string, reason: string }[] }} facts
|
|
211
|
-
* @returns {any}
|
|
212
|
-
*/
|
|
213
|
-
export declare function seriesRecord(facts: {
|
|
214
|
-
mode: 'native' | 'hybrid' | 'engine';
|
|
215
|
-
operation: string;
|
|
216
|
-
index?: string | null;
|
|
217
|
-
prefix?: string[];
|
|
218
|
-
range?: any;
|
|
219
|
-
ladder?: any;
|
|
220
|
-
aggregates?: string[];
|
|
221
|
-
refinement?: string | null;
|
|
222
|
-
reasons?: {
|
|
223
|
-
code: string;
|
|
224
|
-
construct: string;
|
|
225
|
-
reason: string;
|
|
226
|
-
}[];
|
|
227
|
-
}): any;
|
package/dist/types/store.d.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The store: `openStore(model, options)` normalizes the model
|
|
3
|
-
* document, opens a database through the injected driver, applies (or
|
|
4
|
-
* verifies) the physical shape, and gives transactional,
|
|
5
|
-
* schema-validated reads and writes.
|
|
6
|
-
*
|
|
7
|
-
* The public surface is ASYNCHRONOUS — every method returns a promise
|
|
8
|
-
* — because the browser's OPFS story forces it regardless of any other
|
|
9
|
-
* backend. Where the driver is synchronous the same operations exist
|
|
10
|
-
* without the promise under `store.sync`, present only there — never a
|
|
11
|
-
* throwing stub — so portable code pays one declared microsecond and
|
|
12
|
-
* code that wants it back opts in knowingly. Internally everything
|
|
13
|
-
* composes through the sync-capable {@link chain}, so the async
|
|
14
|
-
* surface allocates exactly one promise per call, not one per step.
|
|
15
|
-
*
|
|
16
|
-
* Writes validate through an injected `compileSchema` hook with the
|
|
17
|
-
* `compileTypeTest` signature; absent, writes are unvalidated and
|
|
18
|
-
* `store.capabilities.validated === false` — a declared downgrade,
|
|
19
|
-
* never a silent one. `@jarenjs/validate` is never imported here.
|
|
20
|
-
*/
|
|
21
|
-
/** The model format version this store implements. */
|
|
22
|
-
export declare const MODEL_VERSION = "0.1";
|
|
23
|
-
/**
|
|
24
|
-
* Normalize and check a model document. Every failure is `JD0005` with
|
|
25
|
-
* a `docPath` into the model.
|
|
26
|
-
* @param {any} model
|
|
27
|
-
* @returns {Map<string, any>} collection name -> normalized collection
|
|
28
|
-
*/
|
|
29
|
-
export declare function normalizeModel(model: any): Map<string, any>;
|
|
30
|
-
/**
|
|
31
|
-
* Open (or create) a store described by a model document.
|
|
32
|
-
* @param {any} model - A `jaren-model` document (the 0.1 subset)
|
|
33
|
-
* @param {{ driver: any, path?: string, compileSchema?: Function,
|
|
34
|
-
* busyTimeout?: number, queueTimeout?: number, journalMode?: string,
|
|
35
|
-
* statementCacheBound?: number, profile?: any, operators?: any,
|
|
36
|
-
* functions?: any, extensions?: any, zoneProvider?: any,
|
|
37
|
-
* readOnly?: boolean }} options
|
|
38
|
-
* `zoneProvider` is D7's injected clock: a named zone in a temporal
|
|
39
|
-
* spec (`{ "every": "P1M", "zone": "Europe/Amsterdam" }`) is host code
|
|
40
|
-
* the database cannot have, so a store that never received one refuses
|
|
41
|
-
* such a document (`JQ0003`) rather than answering it in UTC. It
|
|
42
|
-
* reaches every residual compilation, which is where the calendar
|
|
43
|
-
* ladder actually walks.
|
|
44
|
-
* @returns {Promise<any>}
|
|
45
|
-
*/
|
|
46
|
-
export declare function openStore(model: any, options: {
|
|
47
|
-
driver: any;
|
|
48
|
-
path?: string;
|
|
49
|
-
compileSchema?: Function;
|
|
50
|
-
busyTimeout?: number;
|
|
51
|
-
queueTimeout?: number;
|
|
52
|
-
journalMode?: string;
|
|
53
|
-
statementCacheBound?: number;
|
|
54
|
-
profile?: any;
|
|
55
|
-
operators?: any;
|
|
56
|
-
functions?: any;
|
|
57
|
-
extensions?: any;
|
|
58
|
-
zoneProvider?: any;
|
|
59
|
-
readOnly?: boolean;
|
|
60
|
-
}): Promise<any>;
|