@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/jobs.d.ts
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The durable job queue (JOBS-FORMAT): enqueue, the
|
|
3
|
-
* single-statement guarded claim (§3 — one statement is one
|
|
4
|
-
* transaction, so no double-claim without any distributed lock),
|
|
5
|
-
* retry with exponential backoff and jitter (§4), recovery as
|
|
6
|
-
* re-claim of expired leases (§5), polling workers with same-process
|
|
7
|
-
* wake-on-enqueue (§6), and the per-job flow checkpoint store the DAG
|
|
8
|
-
* composition binds (§7) — completion marks the job done and records
|
|
9
|
-
* the result in ONE guarded transaction.
|
|
10
|
-
*
|
|
11
|
-
* Every worker transition is guarded by `state='leased' AND
|
|
12
|
-
* lease_owner=?`: execution is at-least-once, completion is
|
|
13
|
-
* exactly-once. `now` and `random` are injectable — the runtime
|
|
14
|
-
* defaults are the clock and `Math.random`; every test injects.
|
|
15
|
-
*
|
|
16
|
-
* The worker LIFECYCLE holds two invariants that a long-running process
|
|
17
|
-
* depends on, and neither is a detail:
|
|
18
|
-
*
|
|
19
|
-
* - **No handler value can break the loop.** A handler is host code and
|
|
20
|
-
* may resolve with something JSON cannot express, or reject with a
|
|
21
|
-
* value whose own `message` throws when read. Both are normalized
|
|
22
|
-
* totally, and `runOne` is isolated inside the loop, so the worst a
|
|
23
|
-
* single job can do is fail its own attempt. A rejected claim-execute
|
|
24
|
-
* loop would stop draining the queue silently.
|
|
25
|
-
* - **Shutdown is bounded.** Handlers receive an `AbortSignal` and
|
|
26
|
-
* `stop()` takes a deadline, so a handler that never settles cannot
|
|
27
|
-
* hold `stop()` — and therefore `store.close()`, and therefore the
|
|
28
|
-
* database file — open forever. A loop the deadline could not drain
|
|
29
|
-
* is CANCELLED, not merely left behind: when its handler finally
|
|
30
|
-
* settles it exits without another claim, store write or poll
|
|
31
|
-
* timer, and its abandoned job recovers by lease expiry (§5).
|
|
32
|
-
*/
|
|
33
|
-
export declare const JOBS_TABLE = "_jaren_jobs";
|
|
34
|
-
export declare const JOB_CHECKPOINTS_TABLE = "_jaren_job_checkpoints";
|
|
35
|
-
/** §4 defaults, all overridable per worker. */
|
|
36
|
-
export declare const JOB_DEFAULTS: Readonly<{
|
|
37
|
-
maxAttempts: 5;
|
|
38
|
-
leaseMs: 30000;
|
|
39
|
-
pollInterval: 500;
|
|
40
|
-
backoffBase: 1000;
|
|
41
|
-
backoffCap: 60000;
|
|
42
|
-
/** How long `stop()` waits for in-flight handlers after signalling
|
|
43
|
-
* abort, before it stops waiting and reports what is still running.
|
|
44
|
-
* Bounded on purpose: an unbounded wait makes one stuck handler
|
|
45
|
-
* indistinguishable from a hung process. */
|
|
46
|
-
stopGraceMs: 5000;
|
|
47
|
-
}>;
|
|
48
|
-
/**
|
|
49
|
-
* A diagnostic string for ANY value, including ones that fight back — a
|
|
50
|
-
* getter that throws, a null-prototype object, a revoked proxy, a
|
|
51
|
-
* symbol. Total by construction: an error report is never the thing that
|
|
52
|
-
* fails.
|
|
53
|
-
* @param {any} value
|
|
54
|
-
* @returns {string}
|
|
55
|
-
*/
|
|
56
|
-
export declare function describeValue(value: any): string;
|
|
57
|
-
/**
|
|
58
|
-
* JSON text for a job result, or `null` when the value cannot be
|
|
59
|
-
* expressed — a BigInt, a cycle, a `toJSON` that throws. The caller
|
|
60
|
-
* treats that as a failed attempt, never as a broken worker.
|
|
61
|
-
* @param {any} value
|
|
62
|
-
* @returns {{ text: string | null } | { reason: string }}
|
|
63
|
-
*/
|
|
64
|
-
export declare function serializeResult(value: any): {
|
|
65
|
-
text: string | null;
|
|
66
|
-
} | {
|
|
67
|
-
reason: string;
|
|
68
|
-
};
|
|
69
|
-
/**
|
|
70
|
-
* The queue engine over one open connection.
|
|
71
|
-
* @param {{ connection: any, now?: () => number,
|
|
72
|
-
* random?: () => number,
|
|
73
|
-
* defaults?: Partial<typeof JOB_DEFAULTS> }} options
|
|
74
|
-
*/
|
|
75
|
-
export declare function createJobEngine(options: {
|
|
76
|
-
connection: any;
|
|
77
|
-
now?: () => number;
|
|
78
|
-
random?: () => number;
|
|
79
|
-
defaults?: Partial<typeof JOB_DEFAULTS>;
|
|
80
|
-
}): {
|
|
81
|
-
ready: any;
|
|
82
|
-
enqueue: (kind: any, payload: any, enqueueOptions: any) => any;
|
|
83
|
-
get: (id: any) => any;
|
|
84
|
-
counts: () => any;
|
|
85
|
-
claim: (claimOptions: {
|
|
86
|
-
kinds: string[];
|
|
87
|
-
owner: string;
|
|
88
|
-
leaseMs?: number;
|
|
89
|
-
}) => any;
|
|
90
|
-
complete: (id: any, owner: any, result: any) => any;
|
|
91
|
-
fail: (id: any, owner: any, error: any, workerDefaults: any) => any;
|
|
92
|
-
checkpointsFor: (job: {
|
|
93
|
-
id: string;
|
|
94
|
-
leaseOwner: string | null;
|
|
95
|
-
}) => {
|
|
96
|
-
load: (runId: any) => any;
|
|
97
|
-
save: (runId: any, nodeId: any, value: any) => any;
|
|
98
|
-
complete: (runId: any, result: any) => any;
|
|
99
|
-
};
|
|
100
|
-
createWorker: (workerOptions: {
|
|
101
|
-
handlers: Record<string, Function>;
|
|
102
|
-
concurrency?: number;
|
|
103
|
-
pollInterval?: number;
|
|
104
|
-
leaseMs?: number;
|
|
105
|
-
owner?: string;
|
|
106
|
-
backoffBase?: number;
|
|
107
|
-
backoffCap?: number;
|
|
108
|
-
}) => {
|
|
109
|
-
stats: () => {
|
|
110
|
-
claims: number;
|
|
111
|
-
completions: number;
|
|
112
|
-
failures: number;
|
|
113
|
-
polls: number;
|
|
114
|
-
wakes: number;
|
|
115
|
-
inFlight: number;
|
|
116
|
-
};
|
|
117
|
-
start(): /*elided*/ any;
|
|
118
|
-
/**
|
|
119
|
-
* Stop claiming, signal in-flight handlers to abort, and wait for
|
|
120
|
-
* the loops — but only up to `graceMs`. A handler that ignores its
|
|
121
|
-
* signal cannot hold the process open; the resolved record says so
|
|
122
|
-
* instead, and the lease expiry (§5) lets another worker re-claim.
|
|
123
|
-
* A loop the grace period could not drain is cancelled outright:
|
|
124
|
-
* when its handler finally settles it exits without another
|
|
125
|
-
* claim, store write or poll timer.
|
|
126
|
-
* @param {{ graceMs?: number }} [stopOptions]
|
|
127
|
-
* @returns {Promise<{ drained: boolean, inFlight: number }>}
|
|
128
|
-
*/
|
|
129
|
-
stop(stopOptions?: {
|
|
130
|
-
graceMs?: number;
|
|
131
|
-
}): Promise<{
|
|
132
|
-
drained: boolean;
|
|
133
|
-
inFlight: number;
|
|
134
|
-
}>;
|
|
135
|
-
};
|
|
136
|
-
/** Stop every worker, bounded. Resolves to the per-worker outcome so
|
|
137
|
-
* `close()` can report a handler it could not wait out rather than
|
|
138
|
-
* hanging on it. */
|
|
139
|
-
stopAll: (stopOptions: any) => Promise<any[]>;
|
|
140
|
-
};
|
package/dist/types/knn.d.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The candidate cut of a k-nearest plan: the arithmetic between
|
|
3
|
-
* the scores a statement fetched and the row identities the engine
|
|
4
|
-
* will decide over. No vector arithmetic lives here — a score is
|
|
5
|
-
* `derive.js`'s, through `@jarenjs/core/vector` — and no SQL: the
|
|
6
|
-
* fetch of the winners is the dialect's. This is the one place the
|
|
7
|
-
* margin is applied and the one place candidate identities are
|
|
8
|
-
* batched for it.
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* The inclusive score margin of the cut. The column's score is a dot
|
|
12
|
-
* product over binary32-normalized forms; the engine's key is the
|
|
13
|
-
* cosine of the raw doubles; measured, the two differ by at most
|
|
14
|
-
* ~1e-8. Any margin of at least twice that makes the engine's top
|
|
15
|
-
* `offset + limit` a SUBSET of the candidates: were a row the engine
|
|
16
|
-
* ranks inside the window cut, some candidate the engine ranks outside
|
|
17
|
-
* it would have to score higher by the column and lower by the engine,
|
|
18
|
-
* which two scores within half the margin of each other cannot do.
|
|
19
|
-
* This is a hundred times that bound — it admits, in practice, only
|
|
20
|
-
* true ties, and those the engine breaks by the document's own keys.
|
|
21
|
-
*/
|
|
22
|
-
export declare const KNN_MARGIN = 0.000001;
|
|
23
|
-
/**
|
|
24
|
-
* The most identities one fetch statement binds: under the parameter
|
|
25
|
-
* cap of every SQLite build the store runs on. A guard, not a design —
|
|
26
|
-
* a k-nearest window is a handful of rows, and this only matters for a
|
|
27
|
-
* collection of many exact duplicates.
|
|
28
|
-
*/
|
|
29
|
-
export declare const IDENTITY_CHUNK = 512;
|
|
30
|
-
/**
|
|
31
|
-
* The rows a k-nearest window can contain, from the scored fetch.
|
|
32
|
-
*
|
|
33
|
-
* `m = offset + limit` rows are needed. When at least `m` rows scored,
|
|
34
|
-
* the candidates are every scored row within `margin` of the m-th best
|
|
35
|
-
* score — ties at the boundary included by construction. When fewer
|
|
36
|
-
* did, the window reaches the unrankable tail (NULL columns, or a
|
|
37
|
-
* collection smaller than the window), which only the documents can
|
|
38
|
-
* order: every row is then a candidate, and the collection is no
|
|
39
|
-
* larger than the window.
|
|
40
|
-
* @param {{ identity: any, score: number | null }[]} rows - one per
|
|
41
|
-
* fetched row; `score` is `null` where the column held no vector
|
|
42
|
-
* @param {number} m - `offset + limit`
|
|
43
|
-
* @param {number} margin
|
|
44
|
-
* @returns {{ identities: any[], scored: number, full: boolean }} the
|
|
45
|
-
* candidate identities in ascending identity order — the
|
|
46
|
-
* collection's own order, which a stable sort over the candidates
|
|
47
|
-
* must see — with how many rows scored and whether every row was
|
|
48
|
-
* taken
|
|
49
|
-
*/
|
|
50
|
-
export declare function cutCandidates(rows: {
|
|
51
|
-
identity: any;
|
|
52
|
-
score: number | null;
|
|
53
|
-
}[], m: number, margin: number): {
|
|
54
|
-
identities: any[];
|
|
55
|
-
scored: number;
|
|
56
|
-
full: boolean;
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* The identities sliced into fetch batches: at most `IDENTITY_CHUNK`
|
|
60
|
-
* each, and each padded with `null` to the next power of two — a NULL
|
|
61
|
-
* in an IN list matches no row — so a handful of prepared statements
|
|
62
|
-
* serve every candidate count instead of one per count seen.
|
|
63
|
-
* @param {any[]} identities - in the order they should be fetched
|
|
64
|
-
* @returns {{ size: number, params: any[] }[]}
|
|
65
|
-
*/
|
|
66
|
-
export declare function identityBatches(identities: any[]): {
|
|
67
|
-
size: number;
|
|
68
|
-
params: any[];
|
|
69
|
-
}[];
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Event-time live views (LIVE-FORMAT §13): a `$resample` or
|
|
3
|
-
* `$rolling` document over a collection, maintained against an
|
|
4
|
-
* explicit watermark.
|
|
5
|
-
*
|
|
6
|
-
* There is no clock in this file, and there is none anywhere under it.
|
|
7
|
-
* A live view over time needs to know what "now" is — which bucket is
|
|
8
|
-
* still open, which reading counts as late — and the only honest
|
|
9
|
-
* source of that is the host, because the machine's clock is a
|
|
10
|
-
* different quantity from the instant a reading carries. So the
|
|
11
|
-
* watermark ARRIVES: it is a finite epoch supplied at registration and
|
|
12
|
-
* moved forward by `advance()`, it never goes backwards, and a test can
|
|
13
|
-
* put it wherever the story needs it without waiting for a timer.
|
|
14
|
-
*
|
|
15
|
-
* What the maintenance actually does:
|
|
16
|
-
*
|
|
17
|
-
* - **A bucket view keeps its rows by bucket.** A write touches one
|
|
18
|
-
* bucket (two, when it moves a reading across a boundary), and only
|
|
19
|
-
* those are folded again — through `resampleSeries` itself, over that
|
|
20
|
-
* bucket's own rows, so the aggregate is the kernel's and cannot
|
|
21
|
-
* drift from what a fresh query would answer.
|
|
22
|
-
* - **A rolling view keeps its rows in instant order.** A write at `t`
|
|
23
|
-
* can only change the windows ending in `[t, t + width)`, so exactly
|
|
24
|
-
* that stretch is recomputed — again by the kernel, over the slice
|
|
25
|
-
* that stretch can see.
|
|
26
|
-
*
|
|
27
|
-
* And what it refuses. A calendar ladder walks a wall clock, a named
|
|
28
|
-
* zone needs host code, `locf`/`linear` couple every bucket to its
|
|
29
|
-
* neighbours, and `first`/`last` name a row by a position a maintained
|
|
30
|
-
* map does not preserve. Each of those re-runs with its own reason
|
|
31
|
-
* rather than being approximated. So does a reading older than the
|
|
32
|
-
* declared lateness: the view re-runs, the emission carries a
|
|
33
|
-
* `lateData` record naming the instant and the boundary, and the row is
|
|
34
|
-
* never quietly folded into a bucket its reader already believed
|
|
35
|
-
* closed.
|
|
36
|
-
*
|
|
37
|
-
* `retention` is the horizon this view claims to work over. It is
|
|
38
|
-
* checked, not assumed: it must cover a whole window plus the lateness
|
|
39
|
-
* the caller allows, which is the span a single repair can read. It is
|
|
40
|
-
* NOT a compaction policy — the maintained state is bounded by
|
|
41
|
-
* `live.maxMaintained` exactly as every other strategy's is, and this
|
|
42
|
-
* file drops nothing that an answer still depends on.
|
|
43
|
-
*/
|
|
44
|
-
/**
|
|
45
|
-
* Validate the `eventTime` option into the record the classifier and
|
|
46
|
-
* the strategies read, or `null` when the caller declared none.
|
|
47
|
-
* @param {any} options - the live options
|
|
48
|
-
* @param {string} collection - for the error's `collection` property
|
|
49
|
-
* @returns {null | { member: string, watermark: number,
|
|
50
|
-
* allowedLateness: number, retention: number }}
|
|
51
|
-
* @throws {DbCompileError} `JD0053` for any member this does not admit
|
|
52
|
-
*/
|
|
53
|
-
export declare function normalizeEventTime(options: any, collection: string): null | {
|
|
54
|
-
member: string;
|
|
55
|
-
watermark: number;
|
|
56
|
-
allowedLateness: number;
|
|
57
|
-
retention: number;
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Classify a document as an event-time view, or say why it is not one.
|
|
61
|
-
*
|
|
62
|
-
* Returns `null` when the document does not name `$resample` or
|
|
63
|
-
* `$rolling` over this collection at all — the caller then goes on to
|
|
64
|
-
* §7's ordinary table. Every other outcome is a decision: a maintained
|
|
65
|
-
* description, or `{ strategy: 'rerun', reason }`.
|
|
66
|
-
* @param {any} inner - the unwrapped document
|
|
67
|
-
* @param {boolean} windowed - whether a `$subsequence` wrapped it
|
|
68
|
-
* @param {boolean} keyed
|
|
69
|
-
* @param {null | { member: string, watermark: number,
|
|
70
|
-
* allowedLateness: number, retention: number }} eventTime
|
|
71
|
-
* @returns {any}
|
|
72
|
-
*/
|
|
73
|
-
export declare function classifyEventTime(inner: any, windowed: boolean, keyed: boolean, eventTime: null | {
|
|
74
|
-
member: string;
|
|
75
|
-
watermark: number;
|
|
76
|
-
allowedLateness: number;
|
|
77
|
-
retention: number;
|
|
78
|
-
}): any;
|
|
79
|
-
/**
|
|
80
|
-
* `$resample` over a fixed ladder: one maintained fold per bucket.
|
|
81
|
-
* @param {any} description
|
|
82
|
-
* @param {any} context
|
|
83
|
-
*/
|
|
84
|
-
export declare function bucketStrategy(description: any, context: any): {
|
|
85
|
-
advance: (next: any) => void;
|
|
86
|
-
stats: () => {
|
|
87
|
-
lateData: number;
|
|
88
|
-
reruns: number;
|
|
89
|
-
recomputes: number;
|
|
90
|
-
watermark: any;
|
|
91
|
-
};
|
|
92
|
-
entries: () => number;
|
|
93
|
-
init: () => any;
|
|
94
|
-
apply(record: any): {
|
|
95
|
-
rebuild: boolean;
|
|
96
|
-
late: any;
|
|
97
|
-
rows?: undefined;
|
|
98
|
-
} | {
|
|
99
|
-
rebuild?: undefined;
|
|
100
|
-
late?: undefined;
|
|
101
|
-
rows: {
|
|
102
|
-
at: any;
|
|
103
|
-
value: number | null;
|
|
104
|
-
count: number;
|
|
105
|
-
}[] | ({
|
|
106
|
-
at: number;
|
|
107
|
-
value: number | null;
|
|
108
|
-
count: number;
|
|
109
|
-
} | undefined)[];
|
|
110
|
-
} | null;
|
|
111
|
-
/** A re-run rebuilds the whole state from the store — the only
|
|
112
|
-
* answer to a reading the maintained state cannot place. */
|
|
113
|
-
rebuild(): any;
|
|
114
|
-
};
|
|
115
|
-
/**
|
|
116
|
-
* `$rolling` over a fixed width: one output per input instant, with
|
|
117
|
-
* only the stretch a write can reach recomputed.
|
|
118
|
-
* @param {any} description
|
|
119
|
-
* @param {any} context
|
|
120
|
-
*/
|
|
121
|
-
export declare function rollingStrategy(description: any, context: any): {
|
|
122
|
-
advance: (next: any) => void;
|
|
123
|
-
stats: () => {
|
|
124
|
-
lateData: number;
|
|
125
|
-
reruns: number;
|
|
126
|
-
recomputes: number;
|
|
127
|
-
watermark: any;
|
|
128
|
-
};
|
|
129
|
-
entries: () => number;
|
|
130
|
-
init: () => any;
|
|
131
|
-
apply(record: any): {
|
|
132
|
-
rows?: undefined;
|
|
133
|
-
rebuild: boolean;
|
|
134
|
-
late: any;
|
|
135
|
-
} | {
|
|
136
|
-
rebuild?: undefined;
|
|
137
|
-
late?: undefined;
|
|
138
|
-
rows: any[];
|
|
139
|
-
} | null;
|
|
140
|
-
rebuild(): any;
|
|
141
|
-
};
|
package/dist/types/live.d.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Live queries (LIVE-FORMAT §§7–12): a registered query document
|
|
3
|
-
* whose result is maintained as capture records arrive, emitting
|
|
4
|
-
* RFC 6902 patches against its own `{ rows }` result document.
|
|
5
|
-
*
|
|
6
|
-
* The CLASSIFIER implements §7's normative table and nothing more —
|
|
7
|
-
* it unwraps the one-element array pack and literal `$subsequence`
|
|
8
|
-
* windows the same way the planner does, then reads the compiled
|
|
9
|
-
* plan: translated filters, order terms and aggregates are exactly
|
|
10
|
-
* the planner's, never a re-implementation. Everything outside the
|
|
11
|
-
* table re-runs on invalidation with the reason named (`live.mode`).
|
|
12
|
-
*
|
|
13
|
-
* Maintenance is synchronous inside capture delivery (§8): inserts
|
|
14
|
-
* carry their document in the patch, updates point-read the touched
|
|
15
|
-
* row, deletes are answered from maintained state. Per-row semantics
|
|
16
|
-
* reuse the ENGINE via packed one-row compilation (the residual
|
|
17
|
-
* discipline) — a live row evaluates exactly as the query would.
|
|
18
|
-
*/
|
|
19
|
-
/** The store-level live bounds and their defaults (§12: printed,
|
|
20
|
-
* never silent). */
|
|
21
|
-
export declare const LIVE_DEFAULTS: Readonly<{
|
|
22
|
-
maxQueries: 64;
|
|
23
|
-
maxMaintained: 10000;
|
|
24
|
-
}>;
|
|
25
|
-
/**
|
|
26
|
-
* Classify a collection query document against §7's table. Pure —
|
|
27
|
-
* given the document and the collection's planner shape, returns the
|
|
28
|
-
* strategy description, or a re-run description with the reason.
|
|
29
|
-
* @param {any} document
|
|
30
|
-
* @param {any} queryShape - the planner shape (collection, schema,
|
|
31
|
-
* columnByCanonical)
|
|
32
|
-
* @param {boolean} keyed - whether documents carry their key (a
|
|
33
|
-
* declared key pointer); unkeyed rows cannot be tracked by key
|
|
34
|
-
* @param {any} [eventTime] - the normalized `eventTime` option
|
|
35
|
-
* (`live-time.js`), or null when the caller declared none
|
|
36
|
-
* @returns {any}
|
|
37
|
-
*/
|
|
38
|
-
export declare function classifyLiveQuery(document: any, queryShape: any, keyed: boolean, eventTime?: any): any;
|
|
39
|
-
/**
|
|
40
|
-
* Diff two row arrays into sequential add/remove/replace ops under
|
|
41
|
-
* `/rows`, relying on REFERENCE identity for unchanged rows (the §9
|
|
42
|
-
* sharing contract makes identity the equality that matters). A
|
|
43
|
-
* working copy is replayed op by op, so the emitted patch transforms
|
|
44
|
-
* the old array into the new one BY CONSTRUCTION; a remove re-filled
|
|
45
|
-
* at the same index merges into a replace.
|
|
46
|
-
* @param {any[]} oldRows
|
|
47
|
-
* @param {any[]} newRows
|
|
48
|
-
* @returns {any[]} ops
|
|
49
|
-
*/
|
|
50
|
-
export declare function diffRows(oldRows: any[], newRows: any[]): any[];
|
|
51
|
-
/**
|
|
52
|
-
* The store-level live-query registry: registration against the §12
|
|
53
|
-
* bounds, capture-record delivery in commit order, lifecycle.
|
|
54
|
-
* @param {{ maxQueries: number, maxMaintained: number }} bounds
|
|
55
|
-
*/
|
|
56
|
-
export declare function createLiveRegistry(bounds: {
|
|
57
|
-
maxQueries: number;
|
|
58
|
-
maxMaintained: number;
|
|
59
|
-
}): {
|
|
60
|
-
register: (definition: any) => any;
|
|
61
|
-
count: () => number;
|
|
62
|
-
deliver(record: any): void;
|
|
63
|
-
closeAll(): void;
|
|
64
|
-
};
|
package/dist/types/migrate.d.ts
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Document migrations (D12): two model documents diff into a
|
|
3
|
-
* migration document whose steps are rendered DDL, JSLT data
|
|
4
|
-
* transforms and query assertions; the migration replays on a shadow
|
|
5
|
-
* database first; a history table records what ran with a
|
|
6
|
-
* signature-grade checksum. This is the phase-A payoff for storing
|
|
7
|
-
* documents rather than rows: a shape change is a transformation of
|
|
8
|
-
* VALUES, not a table rebuild.
|
|
9
|
-
*
|
|
10
|
-
* Identity is a hash, not a version number: `from`/`to` are
|
|
11
|
-
* `hashContent(canonicalizeJson(model))` — the identity of a SHAPE,
|
|
12
|
-
* which nobody has to remember to bump. The checksum discipline is
|
|
13
|
-
* D12's: `canonicalizeJson` + `hashContent` (signature-grade — throws
|
|
14
|
-
* on the unserializable), never the memo-grade `contentKey`.
|
|
15
|
-
*
|
|
16
|
-
* Like the query emitter, this module is part of the emitter layer:
|
|
17
|
-
* the structural SQL it composes (the history table's statements, the
|
|
18
|
-
* batched row walk) is built from dialect primitives, and every
|
|
19
|
-
* planner-produced statement is rendered by the dialect into the
|
|
20
|
-
* migration DOCUMENT — shown before it is ever executed.
|
|
21
|
-
*/
|
|
22
|
-
/** The migration format version. */
|
|
23
|
-
export declare const MIGRATION_VERSION = "0.1";
|
|
24
|
-
/** The history table name (outside the model's identifier namespace
|
|
25
|
-
* conventions on purpose — a collection cannot collide with it). */
|
|
26
|
-
export declare const HISTORY_TABLE = "_jaren_migrations";
|
|
27
|
-
/**
|
|
28
|
-
* The signature-grade identity of a model SHAPE.
|
|
29
|
-
* @param {any} model - A jaren-model document
|
|
30
|
-
* @returns {string}
|
|
31
|
-
*/
|
|
32
|
-
export declare function shapeHash(model: any): string;
|
|
33
|
-
/**
|
|
34
|
-
* The signature-grade checksum of a migration document.
|
|
35
|
-
* @param {any} migration
|
|
36
|
-
* @returns {string}
|
|
37
|
-
*/
|
|
38
|
-
export declare function migrationChecksum(migration: any): string;
|
|
39
|
-
/**
|
|
40
|
-
* Plan a migration between two model documents. The planner diffs the
|
|
41
|
-
* PHYSICAL plans (columns, indexes) and renders DDL through the
|
|
42
|
-
* dialect; a changed schema gets a DRAFT identity transform that
|
|
43
|
-
* refuses to run until the author fills it in — the planner cannot
|
|
44
|
-
* infer a data transform and does not pretend to. Renames are declared
|
|
45
|
-
* (`x-rename` on the target collection), never guessed.
|
|
46
|
-
* The physical mapping of a DERIVED index column depends on the driver
|
|
47
|
-
* that will run the migration (`derived`), because the two mappings
|
|
48
|
-
* really are different columns; a migration document planned for one is
|
|
49
|
-
* not the document the other needs.
|
|
50
|
-
* @param {any} fromModel
|
|
51
|
-
* @param {any} toModel
|
|
52
|
-
* @param {{ id?: string, dialect?: any,
|
|
53
|
-
* derived?: 'virtual' | 'stored', rtree?: boolean }} [options]
|
|
54
|
-
* @returns {{ migration: any, report: {
|
|
55
|
-
* renamed: { from: string, to: string }[],
|
|
56
|
-
* added: string[], removed: string[],
|
|
57
|
-
* schemaChanged: string[], drafts: string[],
|
|
58
|
-
* destructive: boolean } }}
|
|
59
|
-
*/
|
|
60
|
-
export declare function planMigration(fromModel: any, toModel: any, options?: {
|
|
61
|
-
id?: string;
|
|
62
|
-
dialect?: any;
|
|
63
|
-
derived?: 'virtual' | 'stored';
|
|
64
|
-
rtree?: boolean;
|
|
65
|
-
}): {
|
|
66
|
-
migration: any;
|
|
67
|
-
report: {
|
|
68
|
-
renamed: {
|
|
69
|
-
from: string;
|
|
70
|
-
to: string;
|
|
71
|
-
}[];
|
|
72
|
-
added: string[];
|
|
73
|
-
removed: string[];
|
|
74
|
-
schemaChanged: string[];
|
|
75
|
-
drafts: string[];
|
|
76
|
-
destructive: boolean;
|
|
77
|
-
};
|
|
78
|
-
};
|
|
79
|
-
/** `planMigration` handles the whole model — collections AND entities
|
|
80
|
-
* — since the relational order; this name says so. */
|
|
81
|
-
export declare const planModelMigration: typeof planMigration;
|
|
82
|
-
/**
|
|
83
|
-
* Create a model's WHOLE physical shape on a connection: collections,
|
|
84
|
-
* entity tables and join tables, exactly as `openStore` would. Used
|
|
85
|
-
* by the shadow baseline, the fresh reference database that shape
|
|
86
|
-
* equality compares against, and the tests.
|
|
87
|
-
* @param {any} connection
|
|
88
|
-
* @param {any} model
|
|
89
|
-
* @returns {any} value-or-promise
|
|
90
|
-
*/
|
|
91
|
-
export declare function createModelShape(connection: any, model: any): any;
|
|
92
|
-
/**
|
|
93
|
-
* The declared schema of a database, normalized for comparison: every
|
|
94
|
-
* object carrying SQL text (tables, indexes), whitespace-collapsed,
|
|
95
|
-
* history table excluded, sorted. Shape equality after a migration —
|
|
96
|
-
* this dump versus a fresh {@link createModelShape} — is the
|
|
97
|
-
* acceptance criterion for every rebuild.
|
|
98
|
-
* @param {any} connection
|
|
99
|
-
* @returns {any} value-or-promise of `{ type, name, owner, sql }[]`
|
|
100
|
-
*/
|
|
101
|
-
export declare function schemaShapeOf(connection: any): any;
|
|
102
|
-
/**
|
|
103
|
-
* Compare a migrated database's schema against the shape a fresh
|
|
104
|
-
* `createModelShape(model)` produces, via a throwaway reference
|
|
105
|
-
* database. Returns `null` when equal, or a one-line difference.
|
|
106
|
-
* @param {any} driver
|
|
107
|
-
* @param {any} connection - the migrated database
|
|
108
|
-
* @param {any} model - the target model
|
|
109
|
-
* @param {((connection: any) => any) | undefined} registerFunctions
|
|
110
|
-
* @returns {any} value-or-promise of `string | null`
|
|
111
|
-
*/
|
|
112
|
-
export declare function compareShapeToModel(driver: any, connection: any, model: any, registerFunctions: ((connection: any) => any) | undefined): any;
|
|
113
|
-
/**
|
|
114
|
-
* Report a database's migration state without touching it: what is
|
|
115
|
-
* applied, what is pending, whether an applied migration was edited,
|
|
116
|
-
* and — once the chain is fully applied — whether the physical shape
|
|
117
|
-
* DRIFTED from the model (someone changed the database by hand, §12).
|
|
118
|
-
* @param {{ driver: any, path?: string }} target
|
|
119
|
-
* @param {any[]} migrations - the full ordered list
|
|
120
|
-
* @param {{ baseline: any, model?: any,
|
|
121
|
-
* registerFunctions?: (connection: any) => any }} options
|
|
122
|
-
* @returns {Promise<{ applied: string[], pending: string[],
|
|
123
|
-
* drift: string | null, upToDate: boolean }>}
|
|
124
|
-
*/
|
|
125
|
-
export declare function migrationStatus(target: {
|
|
126
|
-
driver: any;
|
|
127
|
-
path?: string;
|
|
128
|
-
}, migrations: any[], options: {
|
|
129
|
-
baseline: any;
|
|
130
|
-
model?: any;
|
|
131
|
-
registerFunctions?: (connection: any) => any;
|
|
132
|
-
}): Promise<{
|
|
133
|
-
applied: string[];
|
|
134
|
-
pending: string[];
|
|
135
|
-
drift: string | null;
|
|
136
|
-
upToDate: boolean;
|
|
137
|
-
}>;
|
|
138
|
-
/**
|
|
139
|
-
* Apply pending migrations to a database.
|
|
140
|
-
*
|
|
141
|
-
* The contract: `migrations` is the FULL ordered list (applied and
|
|
142
|
-
* pending — the migrations directory); `baseline` is the model the
|
|
143
|
-
* store was first created with (the chain's anchor and the shadow's
|
|
144
|
-
* starting shape); `model` is the target model the code now carries.
|
|
145
|
-
* Each pending migration runs in ONE exclusive transaction with a
|
|
146
|
-
* savepoint per step; a failing step rolls the whole migration back.
|
|
147
|
-
* The whole chain replays on a `:memory:` shadow before the real
|
|
148
|
-
* store is touched.
|
|
149
|
-
*
|
|
150
|
-
* @param {{ driver: any, path?: string, busyTimeout?: number }} target
|
|
151
|
-
* @param {any[]} migrations
|
|
152
|
-
* @param {{ baseline: any, model?: any, compileSchema?: Function,
|
|
153
|
-
* dryRun?: boolean, batchSize?: number, onProgress?: Function,
|
|
154
|
-
* shadow?: boolean, shadowPath?: string }} options
|
|
155
|
-
* @returns {Promise<any>}
|
|
156
|
-
*/
|
|
157
|
-
export declare function migrate(target: {
|
|
158
|
-
driver: any;
|
|
159
|
-
path?: string;
|
|
160
|
-
busyTimeout?: number;
|
|
161
|
-
}, migrations: any[], options: {
|
|
162
|
-
baseline: any;
|
|
163
|
-
model?: any;
|
|
164
|
-
compileSchema?: Function;
|
|
165
|
-
dryRun?: boolean;
|
|
166
|
-
batchSize?: number;
|
|
167
|
-
onProgress?: Function;
|
|
168
|
-
shadow?: boolean;
|
|
169
|
-
shadowPath?: string;
|
|
170
|
-
}): Promise<any>;
|
package/dist/types/model.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The entity model walk: `x-entity` normalization with a CLOSED
|
|
3
|
-
* vocabulary, relation resolution with inverse agreement, and
|
|
4
|
-
* `explainMapping` — the derived physical shape as plain data, so the
|
|
5
|
-
* hybrid mapping rule is golden-testable rather than folklore.
|
|
6
|
-
*
|
|
7
|
-
* THE DESCENT DECISION (recorded here because TODO's D22 demands it
|
|
8
|
-
* be explicit): six copies of the `properties`/`prefixItems`/`items`/
|
|
9
|
-
* `allOf` descent spine exist in this repository, and this walk was
|
|
10
|
-
* the candidate seventh. It is NOT one. The entity walk is
|
|
11
|
-
* deliberately ONE level deep — it enumerates the TOP-LEVEL
|
|
12
|
-
* properties of an entity schema, resolves `$ref` and shallow-merges
|
|
13
|
-
* `allOf` at each property through the resolvers
|
|
14
|
-
* `@jarenjs/validate/normalize` exports for exactly this purpose, and
|
|
15
|
-
* never recurses further, because the mapping rule sends every nested
|
|
16
|
-
* shape to the JSONB document wholesale. A consumer with no recursion
|
|
17
|
-
* has no descent spine to share, so the shared-enumerator question
|
|
18
|
-
* (three different termination strategies across the six copies)
|
|
19
|
-
* stays open for the first consumer that actually recurses. No
|
|
20
|
-
* seventh copy was added.
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* Normalize the `entities` member of a model document.
|
|
24
|
-
* @param {any} model
|
|
25
|
-
* @returns {Map<string, any>} entity name -> normalized entity
|
|
26
|
-
*/
|
|
27
|
-
export declare function normalizeEntities(model: any): Map<string, any>;
|
|
28
|
-
/**
|
|
29
|
-
* The hybrid mapping, derived mechanically from §9.3's table and
|
|
30
|
-
* returned as DATA: per entity, the columns (name, type, source),
|
|
31
|
-
* the checks, the foreign keys, the indexes, and which properties
|
|
32
|
-
* live in the JSONB document.
|
|
33
|
-
* @param {any} model - a model document with `entities`
|
|
34
|
-
* @returns {any}
|
|
35
|
-
*/
|
|
36
|
-
export declare function explainMapping(model: any): any;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file RFC 6902 → dialect JSON-set primitives, so a one-field update
|
|
3
|
-
* does not rewrite a large document. The translation is decided
|
|
4
|
-
* AGAINST THE LIVE DOCUMENT: an RFC 6901 pointer cannot say whether
|
|
5
|
-
* `/a/0` names an array position or an object member called `"0"`, so
|
|
6
|
-
* each segment is discriminated by walking the document the patch was
|
|
7
|
-
* validated against, and the walked state is advanced op by op so a
|
|
8
|
-
* later operation sees what the earlier ones produced.
|
|
9
|
-
*
|
|
10
|
-
* Translatable in 0.1: `replace` anywhere, `add` of an object member,
|
|
11
|
-
* `add` at an array's end (`/-` or the index equal to its length), and
|
|
12
|
-
* `remove`. Everything else — `test`, `move`, `copy`, a mid-array
|
|
13
|
-
* insert (the shift has no single JSON-function spelling) — returns
|
|
14
|
-
* `null` and the store falls back to a whole-document write. The
|
|
15
|
-
* fallback is counted and exposed by the store, measured rather than
|
|
16
|
-
* assumed.
|
|
17
|
-
*/
|
|
18
|
-
export type JsonPathSegment = import('./dialect.js').JsonPathSegment;
|
|
19
|
-
/**
|
|
20
|
-
* Translate a whole patch into a dialect expression builder, or `null`
|
|
21
|
-
* when any operation needs the whole-document fallback. The caller has
|
|
22
|
-
* already applied the patch in memory (the copy-on-write engine
|
|
23
|
-
* validates the RESULT); this translation only decides how the same
|
|
24
|
-
* outcome reaches the database.
|
|
25
|
-
* @param {any[]} ops - RFC 6902 operations, already known applicable
|
|
26
|
-
* @param {any} doc - The stored document the patch applies to
|
|
27
|
-
* @param {any} dialect
|
|
28
|
-
* @returns {{ build: (docColumnSql: string,
|
|
29
|
-
* parameterIndexBase: number) => { expression: string,
|
|
30
|
-
* params: string[] } } | null}
|
|
31
|
-
*/
|
|
32
|
-
export declare function translatePatch(ops: any[], doc: any, dialect: any): {
|
|
33
|
-
build: (docColumnSql: string, parameterIndexBase: number) => {
|
|
34
|
-
expression: string;
|
|
35
|
-
params: string[];
|
|
36
|
-
};
|
|
37
|
-
} | null;
|