@jarenjs/db 0.49.2 → 0.66.1
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 +420 -71
- package/README.md +711 -79
- package/docs/HOSTS.md +269 -0
- package/docs/JOBS-FORMAT.md +309 -45
- package/docs/LIVE-FORMAT.md +156 -19
- package/docs/MIGRATION-FORMAT.md +247 -40
- package/docs/MODEL-FORMAT.md +968 -86
- package/package.json +21 -8
- package/schemas/jaren-migration.draft-07.schema.json +73 -0
- package/schemas/jaren-migration.schema.json +73 -0
- package/schemas/jaren-model.draft-07.schema.json +224 -162
- package/schemas/jaren-model.schema.json +224 -162
- package/src/algebra.js +227 -9
- package/src/backup.js +161 -0
- package/src/cancellation.js +48 -0
- package/src/capture.js +255 -44
- package/src/cli.js +337 -50
- package/src/cursor.js +411 -0
- package/src/dag-job.js +154 -21
- package/src/ddl.js +125 -11
- package/src/dialect.js +267 -112
- package/src/dialects/expression-read.js +158 -0
- package/src/dialects/postgres.js +618 -0
- package/src/dialects/rtree-ddl.js +129 -0
- package/src/dialects/sqlite.js +245 -12
- package/src/document-files.js +311 -0
- package/src/document-steps.js +422 -0
- package/src/documents.js +335 -0
- package/src/driver.js +503 -69
- package/src/drivers/bun.js +37 -1
- package/src/drivers/indexeddb-snapshot.js +149 -0
- package/src/drivers/node-pool.js +11 -0
- package/src/drivers/node-worker-endpoint.js +105 -0
- package/src/drivers/node-worker.js +204 -0
- package/src/drivers/node.js +41 -7
- package/src/drivers/postgres.js +331 -0
- package/src/drivers/wasm-oo1.js +97 -0
- package/src/drivers/wasm-session.js +67 -0
- package/src/drivers/wasm.js +18 -83
- package/src/drivers/worker-pool.js +183 -0
- package/src/drivers/worker-protocol.js +79 -0
- package/src/drivers/worker-queue.js +60 -0
- package/src/emit-model.js +14 -0
- package/src/emit.js +349 -51
- package/src/entity.js +102 -59
- package/src/errors.js +430 -2
- package/src/expression.js +284 -0
- package/src/graph.js +64 -8
- package/src/index.js +48 -19
- package/src/introspect.js +583 -0
- package/src/jobs.js +870 -99
- package/src/json-bytes.js +58 -0
- package/src/live-time.js +12 -3
- package/src/live.js +11 -1
- package/src/maintenance.js +175 -0
- package/src/migrate.js +606 -333
- package/src/model.js +241 -8
- package/src/plan.js +1238 -160
- package/src/pragmas.js +314 -0
- package/src/profile.js +151 -3
- package/src/query.js +1748 -312
- package/src/residual.js +17 -0
- package/src/series.js +12 -4
- package/src/store.js +1672 -276
- package/src/tracker.js +367 -68
- package/src/udf.js +88 -7
- package/types/index.d.ts +1246 -32
- package/types/node-pool.d.ts +28 -0
- package/types/node-worker.d.ts +54 -0
- package/types/node.d.ts +72 -3
- package/types/postgres.d.ts +46 -0
- package/types/typed.d.ts +81 -3
- package/types/wasm.d.ts +21 -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/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>;
|
package/dist/types/tracker.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The unit of work (§11): copy-on-write change tracking and
|
|
3
|
-
* minimal writes. Materialised entities are plain, DEEP-FROZEN JSON —
|
|
4
|
-
* no proxies anywhere — and the tracker retains exactly ONE reference
|
|
5
|
-
* per tracked entity: the frozen document itself is the snapshot.
|
|
6
|
-
* Mutation is replacement (`put(next)`); `saveChanges()` diffs
|
|
7
|
-
* snapshot against current with the suite's own diff engine and plans
|
|
8
|
-
* the MINIMAL set of parameterised statements: scalar/epoch/foreign-
|
|
9
|
-
* key column writes, `jsonb_set`/`jsonb_remove` chains for document
|
|
10
|
-
* paths, join-table synchronisation for many-to-many members, and a
|
|
11
|
-
* counted whole-row fallback for anything untranslatable.
|
|
12
|
-
*
|
|
13
|
-
* Ordering never violates a foreign key mid-transaction: inserts run
|
|
14
|
-
* parent-first, deletes child-first, updates in between, join rows
|
|
15
|
-
* after both endpoints exist. A foreign-key cycle among the entities
|
|
16
|
-
* being inserted or deleted is `JD0040`, reported, never a deadlock.
|
|
17
|
-
* The whole save is one transaction; the tracker is mutated ONLY
|
|
18
|
-
* after commit, so a failed save leaves it exactly as it was and a
|
|
19
|
-
* retry is possible.
|
|
20
|
-
*/
|
|
21
|
-
/** Rows per batched INSERT: bounded by the portable parameter budget. */
|
|
22
|
-
export declare const BATCH_PARAM_BUDGET = 900;
|
|
23
|
-
export declare const BATCH_ROW_BOUND = 100;
|
|
24
|
-
/**
|
|
25
|
-
* Deep-freeze a JSON value in place and return it. Idempotent; shared
|
|
26
|
-
* substructure (a graph load's children) freezes once.
|
|
27
|
-
* @template T
|
|
28
|
-
* @param {T} value
|
|
29
|
-
* @returns {T}
|
|
30
|
-
*/
|
|
31
|
-
export declare function deepFreeze<T>(value: T): T;
|
|
32
|
-
/**
|
|
33
|
-
* The store-level unit of work.
|
|
34
|
-
* @param {{ connection: any, entities: Map<string, any>, mapping: any,
|
|
35
|
-
* coreFor: (name: string) => any }} context
|
|
36
|
-
* @returns {any}
|
|
37
|
-
*/
|
|
38
|
-
export declare function createTracker(context: {
|
|
39
|
-
connection: any;
|
|
40
|
-
entities: Map<string, any>;
|
|
41
|
-
mapping: any;
|
|
42
|
-
coreFor: (name: string) => any;
|
|
43
|
-
}): any;
|
package/dist/types/typed.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The typed-store binding: a zero-cost identity whose ONLY job
|
|
3
|
-
* is carrying the generated `EntityMetaMap` into the type system —
|
|
4
|
-
* `typedStore<EntityMetaMap>(store)` narrows `entity(name)` to the
|
|
5
|
-
* generated document/input shapes and widens `load` results by their
|
|
6
|
-
* include specification. The runtime is the store it was given; every
|
|
7
|
-
* guarantee lives in `types/typed.d.ts` and the generated artifact.
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Bind a store to its generated entity metadata. Identity at runtime.
|
|
11
|
-
* @template E
|
|
12
|
-
* @param {any} store - an opened store whose model generated `E`
|
|
13
|
-
* @returns {any}
|
|
14
|
-
*/
|
|
15
|
-
export declare function typedStore<E>(store: any): any;
|
package/dist/types/types.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Schema-derived path typing: the collection's JSON Schema is the
|
|
3
|
-
* planner's type source (there is no engine-side inference in this
|
|
4
|
-
* phase — the store's own contract carries the types). Where the
|
|
5
|
-
* schema says nothing, the answer is `'unknown'` and the planner emits
|
|
6
|
-
* the defensive form; the guards in the truth table make `'unknown'`
|
|
7
|
-
* safe, so typing here only ever IMPROVES a plan (column choice), it
|
|
8
|
-
* never weakens one.
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* The planner-facing type of a member path.
|
|
12
|
-
* @param {any} schema - The collection's document schema
|
|
13
|
-
* @param {({ name: string } | { index: number })[]} segments
|
|
14
|
-
* @returns {'string' | 'integer' | 'number' | 'boolean' | 'unknown'}
|
|
15
|
-
*/
|
|
16
|
-
export declare function typeOfPath(schema: any, segments: ({
|
|
17
|
-
name: string;
|
|
18
|
-
} | {
|
|
19
|
-
index: number;
|
|
20
|
-
})[]): 'string' | 'integer' | 'number' | 'boolean' | 'unknown';
|
|
21
|
-
/**
|
|
22
|
-
* Whether a planner type is numeric (SQL comparison family).
|
|
23
|
-
* @param {string} type
|
|
24
|
-
* @returns {boolean}
|
|
25
|
-
*/
|
|
26
|
-
export declare function isNumericType(type: string): boolean;
|
package/dist/types/udf.d.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The UDF escape hatch (capability-gated): between native SQL
|
|
3
|
-
* and pulling rows sits registering a compiled predicate conjunct as a
|
|
4
|
-
* DETERMINISTIC function used in the WHERE clause. Only fragments the
|
|
5
|
-
* analysis proves deterministic and side-effect-free qualify — no
|
|
6
|
-
* externals (their values change per call, and a deterministic
|
|
7
|
-
* function must not close over changing state), no host functions, no
|
|
8
|
-
* collations. Registration is keyed by the fragment's COLLISION-FREE
|
|
9
|
-
* structural identity, so identical fragments share one registration
|
|
10
|
-
* per store and different fragments never do. A fingerprint could not
|
|
11
|
-
* decide this: two colliding fragments would claim one SQL function
|
|
12
|
-
* name, the second would silently reuse the first's predicate, and the
|
|
13
|
-
* WHERE clause would filter on the wrong condition. The SQL identifier
|
|
14
|
-
* still derives from a short fingerprint — names must be short — but a
|
|
15
|
-
* fingerprint clash between DIFFERENT identities is disambiguated with
|
|
16
|
-
* a suffix rather than collapsed.
|
|
17
|
-
*
|
|
18
|
-
* WHERE-clause use only: an INDEX over a registered function would
|
|
19
|
-
* make the database unwritable from any connection that has not
|
|
20
|
-
* registered the identical function — that schema-dependency hazard is
|
|
21
|
-
* why the model format declares no UDF-expression indexes.
|
|
22
|
-
*
|
|
23
|
-
* Ring 3 extends the hatch to registry `pushable:'scalar'`
|
|
24
|
-
* operators: a predicate fragment that uses a registered scalar operator
|
|
25
|
-
* (`$sqrt`, `$pow`, …) compiles WITH the store's `{ functions,
|
|
26
|
-
* extensions }` and pushes as the same deterministic UDF — SQLite drives
|
|
27
|
-
* the row iteration and the operator runs inside the callback, instead
|
|
28
|
-
* of every candidate crossing into the residual. The determinism rule is
|
|
29
|
-
* unchanged (no externals, no collations); a registered operator the
|
|
30
|
-
* pack did NOT mark `pushable:'scalar'` (a whole-series `$npv`, an
|
|
31
|
-
* aggregate) stays the residual — Ring 2 keeps it correct.
|
|
32
|
-
*/
|
|
33
|
-
/**
|
|
34
|
-
* Decide whether a raw predicate fragment qualifies for the hatch, and
|
|
35
|
-
* build its registration if so.
|
|
36
|
-
* @param {any} fragment - The raw conjunct (a JSON query expression
|
|
37
|
-
* over `$it`)
|
|
38
|
-
* @param {{ functions?: any, extensions?: any, pushableScalar?: Set<string> } | null}
|
|
39
|
-
* [operators] - the store's registered operators (Ring 3); only its
|
|
40
|
-
* `pushable:'scalar'` subset is admitted. `null`/absent keeps the
|
|
41
|
-
* original engine-internal-only rule (no host function pushes).
|
|
42
|
-
* @param {string} [binding='it'] - the name the caller's document gave
|
|
43
|
-
* the collection binding. The fragment references it, so the wrapper
|
|
44
|
-
* below must bind it: under any other name every reference reads as an
|
|
45
|
-
* external, the determinism check below rejects the fragment, and the
|
|
46
|
-
* hatch silently never engages.
|
|
47
|
-
* @returns {{ key: string, name: string,
|
|
48
|
-
* compile: () => (docText: string) => number } | null}
|
|
49
|
-
*/
|
|
50
|
-
export declare function deterministicFragment(fragment: any, operators?: {
|
|
51
|
-
functions?: any;
|
|
52
|
-
extensions?: any;
|
|
53
|
-
pushableScalar?: Set<string>;
|
|
54
|
-
} | null, binding?: string): {
|
|
55
|
-
key: string;
|
|
56
|
-
name: string;
|
|
57
|
-
compile: () => (docText: string) => number;
|
|
58
|
-
} | null;
|
|
59
|
-
/**
|
|
60
|
-
* Register a qualified fragment once per store, and answer the SQL name
|
|
61
|
-
* to call. Identity is the fragment's structural key, so the same
|
|
62
|
-
* fragment registers once and two different fragments always get two
|
|
63
|
-
* different functions — even when their short names fingerprint alike,
|
|
64
|
-
* which the suffix resolves.
|
|
65
|
-
* @param {any} connection
|
|
66
|
-
* @param {Map<string, string>} registered - The store's registrations,
|
|
67
|
-
* fragment identity → the SQL function name it owns
|
|
68
|
-
* @param {{ key: string, name: string, compile: () => Function }} fragment
|
|
69
|
-
* @returns {string} the function name to call in the WHERE clause
|
|
70
|
-
*/
|
|
71
|
-
export declare function registerFragment(connection: any, registered: Map<string, string>, fragment: {
|
|
72
|
-
key: string;
|
|
73
|
-
name: string;
|
|
74
|
-
compile: () => Function;
|
|
75
|
-
}): string;
|
package/dist/types/window.d.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The maintained sorted window for `orderBy` (+ optional
|
|
3
|
-
* `limit`) live queries — LIVE-FORMAT §7's window row. The structure
|
|
4
|
-
* keeps EVERY matching row in sorted order (which is what makes a
|
|
5
|
-
* delete inside the visible window answerable without a re-query: the
|
|
6
|
-
* successor is already here), and the visible result is the first
|
|
7
|
-
* `limit` entries. Ties are broken by the collection key token,
|
|
8
|
-
* always ascending — the total order LIVE-FORMAT §9 promises.
|
|
9
|
-
*
|
|
10
|
-
* String comparison is CODEPOINT order (SQLite BINARY over UTF-8 —
|
|
11
|
-
* probed, never assumed), which `<` on JS strings gets wrong for
|
|
12
|
-
* astral-vs-BMP pairs; `compareCodepoint` walks code points.
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* Compare two strings in Unicode code-point order.
|
|
16
|
-
* @param {string} a
|
|
17
|
-
* @param {string} b
|
|
18
|
-
* @returns {number}
|
|
19
|
-
*/
|
|
20
|
-
export declare function compareCodepoint(a: string, b: string): number;
|
|
21
|
-
export type WindowEntry = {
|
|
22
|
-
token: string;
|
|
23
|
-
sortValues: any[];
|
|
24
|
-
item: any;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* @typedef {{ token: string, sortValues: any[], item: any }} WindowEntry
|
|
28
|
-
*/
|
|
29
|
-
/**
|
|
30
|
-
* A maintained sorted set of rows under the declared order terms plus
|
|
31
|
-
* the key-token tiebreaker.
|
|
32
|
-
* @param {{ desc: boolean, emptyGreatest: boolean }[]} terms
|
|
33
|
-
* @param {number | null} limit - visible size; `null` = everything
|
|
34
|
-
*/
|
|
35
|
-
export declare function createSortedWindow(terms: {
|
|
36
|
-
desc: boolean;
|
|
37
|
-
emptyGreatest: boolean;
|
|
38
|
-
}[], limit: number | null): {
|
|
39
|
-
compare: (a: WindowEntry, b: WindowEntry) => number;
|
|
40
|
-
size: () => number;
|
|
41
|
-
/** The visible slice: the first `limit` entries (all, unbounded). */
|
|
42
|
-
visible: () => WindowEntry[];
|
|
43
|
-
/**
|
|
44
|
-
* Insert a row; the token MUST not be present.
|
|
45
|
-
* @param {string} token
|
|
46
|
-
* @param {any[]} sortValues
|
|
47
|
-
* @param {any} item
|
|
48
|
-
*/
|
|
49
|
-
insert(token: string, sortValues: any[], item: any): void;
|
|
50
|
-
/** Remove a row by token; absent tokens are a no-op. */
|
|
51
|
-
remove(token: any): boolean;
|
|
52
|
-
};
|