@jarenjs/db 0.46.5 → 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 +133 -17
- package/README.md +270 -36
- package/docs/JOBS-FORMAT.md +24 -8
- package/docs/LIVE-FORMAT.md +139 -7
- package/docs/MIGRATION-FORMAT.md +118 -36
- package/docs/MODEL-FORMAT.md +251 -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/algebra.js +22 -3
- package/src/capture.js +66 -28
- package/src/cli.js +225 -44
- package/src/ddl.js +23 -3
- package/src/dialect.js +13 -0
- package/src/dialects/sqlite.js +21 -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 +42 -9
- package/src/entity.js +92 -47
- package/src/errors.js +28 -0
- package/src/index.js +2 -2
- package/src/jobs.js +40 -5
- package/src/live-time.js +605 -0
- package/src/live.js +52 -9
- package/src/migrate.js +397 -191
- package/src/model.js +173 -8
- package/src/plan.js +834 -47
- package/src/query.js +296 -22
- package/src/residual.js +15 -6
- package/src/series.js +349 -0
- package/src/store.js +243 -69
- package/src/tracker.js +173 -48
- package/types/index.d.ts +206 -12
- 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 -199
- 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 -149
- 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 -167
- 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.d.ts +0 -62
- 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 -140
- package/dist/types/profile.d.ts +0 -80
- package/dist/types/query.d.ts +0 -111
- package/dist/types/residual.d.ts +0 -61
- package/dist/types/store.d.ts +0 -53
- 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
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Entity types from models (D17): build an EMIT MODEL DOCUMENT
|
|
3
|
-
* — the published contract from EMIT-FORMAT.md — that renders entity
|
|
4
|
-
* interfaces, input variants and the typed-store metadata from the
|
|
5
|
-
* same model document the runtime validates against.
|
|
6
|
-
*
|
|
7
|
-
* The seam (EMIT-FORMAT §4.1, recorded here as the order demanded):
|
|
8
|
-
* the schema compiler is INJECTED (`options.compile` is
|
|
9
|
-
* `compileEmitModel` from `@jarenjs/emit`), called with
|
|
10
|
-
* `extensions: ['x-entity']` so the vocabulary rides the member nodes
|
|
11
|
-
* verbatim; this module then post-processes the MODEL DOCUMENT —
|
|
12
|
-
* replacing relation member types with references, flipping
|
|
13
|
-
* optionality, adding declarations — and never renders a character of
|
|
14
|
-
* TypeScript itself. Emit stays database-free, db stays
|
|
15
|
-
* renderer-free, and the injection keeps `@jarenjs/emit` out of db's
|
|
16
|
-
* dependency graph (the generator script wires the two).
|
|
17
|
-
*
|
|
18
|
-
* What the artifact says, deliberately:
|
|
19
|
-
* - entity interfaces are CLOSED objects (excess-property checking is
|
|
20
|
-
* the point of generated types; the runtime validator stays
|
|
21
|
-
* authoritative for what a database accepts);
|
|
22
|
-
* - relation members are optional references — present only when a
|
|
23
|
-
* graph load included them; `date-time`/`date` strings carry the
|
|
24
|
-
* `DateTime` brand so the linq date operators light up;
|
|
25
|
-
* - the `<Name>Input` variant makes defaulted and generated members
|
|
26
|
-
* optional, drops to-one/to-many relation members (`create`/`add`
|
|
27
|
-
* refuse them), and types many-to-many members as key-or-document
|
|
28
|
-
* arrays (what `add()` accepts);
|
|
29
|
-
* - `EntityMetaMap` carries doc/input/key/relations per entity — the
|
|
30
|
-
* generic typed-store surface (`@jarenjs/db/typed`) binds to it.
|
|
31
|
-
*/
|
|
32
|
-
/**
|
|
33
|
-
* Build the emit-model document for a model's entities.
|
|
34
|
-
* @param {any} model - a jaren-model document with `entities`
|
|
35
|
-
* @param {{ compile: (schema: any, options?: any) => any,
|
|
36
|
-
* source?: string, reserved?: string[] }} options - `compile` is
|
|
37
|
-
* `compileEmitModel` (injected; see the header)
|
|
38
|
-
* @returns {any} an EMIT-FORMAT `0.1` model document
|
|
39
|
-
*/
|
|
40
|
-
export declare function entityEmitModel(model: any, options: {
|
|
41
|
-
compile: (schema: any, options?: any) => any;
|
|
42
|
-
source?: string;
|
|
43
|
-
reserved?: string[];
|
|
44
|
-
}): any;
|
package/dist/types/emit.d.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Plan → SQL through a dialect. This is the query layer's shared
|
|
3
|
-
* emitter, the same division of labour as `createDialect`'s DDL/DML
|
|
4
|
-
* builders: structural SQL composition lives here, every
|
|
5
|
-
* dialect-varying spelling (identifiers, parameters, string literals,
|
|
6
|
-
* JSON access, `json_type`, `typeof`, string-operator forms, NULLS
|
|
7
|
-
* placement, EXPLAIN phrasing) comes from the dialect. Values are
|
|
8
|
-
* NEVER interpolated into the text: every literal and every external
|
|
9
|
-
* becomes an ordered parameter slot, which is what makes injection
|
|
10
|
-
* structurally impossible.
|
|
11
|
-
*
|
|
12
|
-
* Every emitted predicate is TOTAL (two-valued) by construction — the
|
|
13
|
-
* `json_type` guards from the truth table in ARCHITECTURE.md — so
|
|
14
|
-
* `NOT`/`AND`/`OR` compose classically and SQL's three-valued NULL
|
|
15
|
-
* logic never decides a row.
|
|
16
|
-
*/
|
|
17
|
-
export type ParamSlot = {
|
|
18
|
-
external: string;
|
|
19
|
-
} | {
|
|
20
|
-
literal: unknown;
|
|
21
|
-
} | {
|
|
22
|
-
derived: {
|
|
23
|
-
kind: 'bboxAxis';
|
|
24
|
-
external: string;
|
|
25
|
-
axis: 'w' | 's' | 'e' | 'n';
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Emit one plan as SQL plus its ordered parameter slots.
|
|
30
|
-
* @param {import('./algebra.js').Plan} plan
|
|
31
|
-
* @param {any} dialect
|
|
32
|
-
* @param {{ table: string, keyColumn: string, docColumn: string }} physical
|
|
33
|
-
* @returns {{ sql: string, slots: ParamSlot[] }}
|
|
34
|
-
*/
|
|
35
|
-
export declare function emitPlan(plan: import('./algebra.js').Plan, dialect: any, physical: {
|
|
36
|
-
table: string;
|
|
37
|
-
keyColumn: string;
|
|
38
|
-
docColumn: string;
|
|
39
|
-
}): {
|
|
40
|
-
sql: string;
|
|
41
|
-
slots: ParamSlot[];
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* The entity predicate emitters, shared by the entity plan emitter
|
|
45
|
-
* and the graph-load builder: given an alias and its document column,
|
|
46
|
-
* emit one predicate with the flavor-correct forms.
|
|
47
|
-
* @param {any} dialect
|
|
48
|
-
* @param {(slot: ParamSlot) => string} param
|
|
49
|
-
* @returns {{ emitPred: (aliasSql: string, docSql: string, pred: any) => string }}
|
|
50
|
-
*/
|
|
51
|
-
export declare function createEntityPredicateEmitters(dialect: any, param: (slot: ParamSlot) => string): {
|
|
52
|
-
emitPred: (aliasSql: string, docSql: string, pred: any) => string;
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
* Emit an entity plan (`entity-select` or `entity-join`) as SQL plus
|
|
56
|
-
* ordered parameter slots. Entity-COLUMN refs compare real typed
|
|
57
|
-
* columns with TOTAL forms and no `json_type` guard — a column-mapped
|
|
58
|
-
* property has no present-`null` (§9.3), so presence IS `IS NOT
|
|
59
|
-
* NULL`; entity-EPOCH refs compare the derived integer column against
|
|
60
|
-
* a plan-time epoch translation; entity-DOC refs ride the phase-A
|
|
61
|
-
* guarded truth table over the entity's JSONB column. Join emission
|
|
62
|
-
* appends BOTH bindings' row identities in binding order, which is
|
|
63
|
-
* exactly the engine's nested-loop order — determinism the oracle
|
|
64
|
-
* depends on.
|
|
65
|
-
* @param {any} plan - from `planEntityQuery`
|
|
66
|
-
* @param {any} dialect
|
|
67
|
-
* @param {(entity: string) => { table: string }} physicalOf
|
|
68
|
-
* @returns {{ sql: string, slots: ParamSlot[] }}
|
|
69
|
-
*/
|
|
70
|
-
export declare function emitEntityPlan(plan: any, dialect: any, physicalOf: (entity: string) => {
|
|
71
|
-
table: string;
|
|
72
|
-
}): {
|
|
73
|
-
sql: string;
|
|
74
|
-
slots: ParamSlot[];
|
|
75
|
-
};
|
package/dist/types/entity.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Entity sets: create / read by key / update / delete over the
|
|
3
|
-
* hybrid mapping. The physical row is the mapped scalar columns, the
|
|
4
|
-
* foreign-key columns, and one JSONB `doc` column for everything
|
|
5
|
-
* else; a write SPLITS the completed document along the mapping and a
|
|
6
|
-
* read MERGES it back. Defaults apply in JavaScript before validation
|
|
7
|
-
* — the value the application sees and the value stored are the same
|
|
8
|
-
* — and identity follows the declared strategy (caller, uuid, auto).
|
|
9
|
-
*
|
|
10
|
-
* Epoch date columns are DERIVED: the document keeps the RFC 3339
|
|
11
|
-
* string, the column carries `getEpochOf…RFC3339(value)` so range
|
|
12
|
-
* predicates are index-friendly; reads take the string from the
|
|
13
|
-
* document and skip the derived column.
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* The write/read machinery for one entity, prepared once.
|
|
17
|
-
* @param {any} connection
|
|
18
|
-
* @param {any} entity - the normalized entity (model.js)
|
|
19
|
-
* @param {any} entityMapping - `explainMapping(...).entities[name]`
|
|
20
|
-
* @param {((doc: any) => any) | null} validate
|
|
21
|
-
* @returns {any}
|
|
22
|
-
*/
|
|
23
|
-
export declare function entityCore(connection: any, entity: any, entityMapping: any, validate: ((doc: any) => any) | null): any;
|
package/dist/types/errors.d.ts
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Error types for @jarenjs/db, built on `@jarenjs/core`'s coded
|
|
3
|
-
* contract: every failure carries a stable `code` (JD0xxx compile-time,
|
|
4
|
-
* JD2xxx runtime), a bare `reason`, a composed `message`, and — where a
|
|
5
|
-
* position in the model document exists — a `docPath`. Runtime errors
|
|
6
|
-
* additionally carry the `collection` and, where one exists, the `key`
|
|
7
|
-
* as own properties. Database errors are wrapped, never leaked raw: the
|
|
8
|
-
* reason keeps the original text, `cause` keeps the original error. The
|
|
9
|
-
* normative table lives in docs/MODEL-FORMAT.md §7, proven in sync with
|
|
10
|
-
* `DB_CODES` below by a test.
|
|
11
|
-
*/
|
|
12
|
-
import { CodedError } from '@jarenjs/core/errors';
|
|
13
|
-
/**
|
|
14
|
-
* The runtime code table (the `CSV_CODES` shape): one entry per code
|
|
15
|
-
* this package can raise, proven in sync with MODEL-FORMAT.md §7's
|
|
16
|
-
* normative table by a test.
|
|
17
|
-
*/
|
|
18
|
-
export declare const DB_CODES: Readonly<{
|
|
19
|
-
JD0001: "the SQLite library is below the supported floor";
|
|
20
|
-
JD0002: "the declared model disagrees with the existing database";
|
|
21
|
-
JD0003: "the driver binding is unavailable on this runtime";
|
|
22
|
-
JD0004: "a declared index cannot be mapped to a column";
|
|
23
|
-
JD0005: "the model document is invalid";
|
|
24
|
-
JD0010: "strict mode refused a residual";
|
|
25
|
-
JD0011: "the profile refused the document";
|
|
26
|
-
JD0012: "work waited too long for the open transaction to settle";
|
|
27
|
-
JD0030: "an unknown x-entity member was declared";
|
|
28
|
-
JD0031: "relation declarations contradict each other";
|
|
29
|
-
JD0032: "the include specification is invalid";
|
|
30
|
-
JD0040: "the save spans a relation cycle";
|
|
31
|
-
JD0050: "live queries require change capture";
|
|
32
|
-
JD0051: "the demanded live mode is unavailable";
|
|
33
|
-
JD0052: "the live-query bound was reached";
|
|
34
|
-
JD0020: "the migration's from-shape does not match the database";
|
|
35
|
-
JD0021: "the migration is missing a required data transform";
|
|
36
|
-
JD0022: "an applied migration disagrees with the history record";
|
|
37
|
-
JD0023: "a migration step failed";
|
|
38
|
-
JD2001: "insert found the key already present";
|
|
39
|
-
JD2002: "a usable key could not be resolved for the write";
|
|
40
|
-
JD2003: "the write failed schema validation";
|
|
41
|
-
JD2004: "an undeclared collection was requested";
|
|
42
|
-
JD2005: "a database operation failed";
|
|
43
|
-
JD2006: "patch found no document at the key";
|
|
44
|
-
JD2007: "the result exceeded the profile row bound";
|
|
45
|
-
JD2040: "the row changed under an optimistic update";
|
|
46
|
-
JD2050: "a changeset could not be decoded";
|
|
47
|
-
JD2051: "the change log is not enabled";
|
|
48
|
-
JD2060: "the maintained live state exceeded its bound";
|
|
49
|
-
JD2061: "another context owns the database";
|
|
50
|
-
JD2062: "the store closed with job handlers still in flight";
|
|
51
|
-
}>;
|
|
52
|
-
/**
|
|
53
|
-
* A defect found while opening a store — in the model document, the
|
|
54
|
-
* declared indexes, the driver binding, or the database's agreement
|
|
55
|
-
* with the declaration. Codes:
|
|
56
|
-
*
|
|
57
|
-
* - `JD0001` — the SQLite library reported a version below the
|
|
58
|
-
* supported floor; the reason names the version found
|
|
59
|
-
* - `JD0002` — a declared collection already exists in the database
|
|
60
|
-
* with a different shape; nothing was altered — changing shape is
|
|
61
|
-
* the migration story, a later capability
|
|
62
|
-
* - `JD0003` — the runtime builtin behind a driver could not be
|
|
63
|
-
* loaded here (Node cannot resolve `bun:`; Bun ships no
|
|
64
|
-
* `node:sqlite`), or an injected handle is missing
|
|
65
|
-
* - `JD0004` — a declared index cannot be mapped to a column: its
|
|
66
|
-
* path does not select exactly one member (wildcards, slices,
|
|
67
|
-
* filters and descendants are not indexable), or its `derive`
|
|
68
|
-
* declaration is not one the storage vocabulary carries; the reason
|
|
69
|
-
* names the expression or the member and `docPath` points at it
|
|
70
|
-
* - `JD0005` — the model document is invalid; `docPath` points at
|
|
71
|
-
* the offending member
|
|
72
|
-
* - `JD0010` — `strict: true` and part of the query would have run
|
|
73
|
-
* outside the database; the reason names the forcing construct
|
|
74
|
-
* - `JD0011` — the active profile refused the document before any
|
|
75
|
-
* execution: an undeclared external, host function, collation or
|
|
76
|
-
* collection, or a refused full-table scan; the reason names it
|
|
77
|
-
* - `JD0030` — an unknown member inside an `x-entity` block; a
|
|
78
|
-
* silently ignored mapping directive is a data-loss bug waiting
|
|
79
|
-
* - `JD0031` — two relation declarations whose inverses contradict
|
|
80
|
-
* (different `via`, impossible `many` pairings)
|
|
81
|
-
* - `JD0032` — a graph-load include specification is invalid: an
|
|
82
|
-
* unknown relation, a cycle, an untranslatable filter, or the
|
|
83
|
-
* depth bound exceeded (the bound is printed, never silent)
|
|
84
|
-
* - `JD0040` — `saveChanges()` cannot order its statements: the
|
|
85
|
-
* entities being inserted or deleted form a foreign-key cycle
|
|
86
|
-
* (self-references included); break the save in two
|
|
87
|
-
* - `JD0050` — a live query was registered on a store opened without
|
|
88
|
-
* `capture`; the patch stream is the invalidation source
|
|
89
|
-
* - `JD0051` — `mode: 'incremental'` was demanded but the document
|
|
90
|
-
* classifies as re-run; the reason names the forcing construct
|
|
91
|
-
* - `JD0052` — registering would exceed the store's `live.maxQueries`
|
|
92
|
-
* bound; the bound is printed, never silent
|
|
93
|
-
* - `JD0020` — a migration's `from` hash does not match the
|
|
94
|
-
* database's recorded shape; running it would corrupt
|
|
95
|
-
* - `JD0021` — a draft transform was not filled in, or a document no
|
|
96
|
-
* longer validates after the migration (a narrowing without an
|
|
97
|
-
* adequate transform)
|
|
98
|
-
* - `JD0022` — the migration list disagrees with the applied history
|
|
99
|
-
* (an edited file, a missing file, a reordered sequence)
|
|
100
|
-
* - `JD0023` — a step failed: an assertion returned rows, DDL was
|
|
101
|
-
* rejected, or a transform produced an unstorable value
|
|
102
|
-
*/
|
|
103
|
-
export declare class DbCompileError extends CodedError {
|
|
104
|
-
/**
|
|
105
|
-
* @param {string} code
|
|
106
|
-
* @param {string} reason - The bare reason; `message` is composed per
|
|
107
|
-
* the coded contract.
|
|
108
|
-
* @param {string} [docPath] - JSON Pointer into the model document,
|
|
109
|
-
* where one exists.
|
|
110
|
-
* @param {Error} [cause]
|
|
111
|
-
*/
|
|
112
|
-
constructor(code: string, reason: string, docPath?: string, cause?: Error);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* A failure while reading or writing an open store. Codes:
|
|
116
|
-
*
|
|
117
|
-
* - `JD2001` — `insert` hit a document already stored under the key
|
|
118
|
-
* - `JD2002` — the declared key pointer resolved to nothing or to a
|
|
119
|
-
* non-scalar, or an explicit key argument is not a string or number
|
|
120
|
-
* - `JD2003` — the injected validation hook rejected the document
|
|
121
|
-
* that a write would have stored; `errors` carries the hook's
|
|
122
|
-
* findings when it produced any
|
|
123
|
-
* - `JD2004` — `collection()` named a collection the model does not
|
|
124
|
-
* declare
|
|
125
|
-
* - `JD2005` — the database rejected an operation for a reason that
|
|
126
|
-
* is not a duplicate key; the original error is the `cause`
|
|
127
|
-
* - `JD2006` — `patch` addressed a key with no stored document
|
|
128
|
-
* - `JD2007` — a fetch crossed the profile's `maxRows` bound; the
|
|
129
|
-
* result is refused whole, never silently truncated
|
|
130
|
-
* - `JD2040` — an optimistic update or delete matched no row: the
|
|
131
|
-
* declared version changed under the save (or the row is gone);
|
|
132
|
-
* the error names the entity and key, and the whole save rolled
|
|
133
|
-
* back
|
|
134
|
-
* - `JD2050` — a session changeset carried bytes this decoder does
|
|
135
|
-
* not recognise (a future SQLite format change would land here)
|
|
136
|
-
* - `JD2051` — `changesSince` was called on a store whose capture
|
|
137
|
-
* has no persisted log
|
|
138
|
-
* - `JD2060` — maintenance crossed the live query's `maxMaintained`
|
|
139
|
-
* bound; the query delivered this error and closed rather than
|
|
140
|
-
* degrade
|
|
141
|
-
* - `JD2061` — a second context tried to open a database whose
|
|
142
|
-
* storage grants one context exclusive access (the owner topology
|
|
143
|
-
* of LIVE-FORMAT §11); connect to the owner instead
|
|
144
|
-
*/
|
|
145
|
-
export declare class DbRuntimeError extends CodedError {
|
|
146
|
-
collection: string | undefined;
|
|
147
|
-
key: string | number | undefined;
|
|
148
|
-
errors: unknown[] | undefined;
|
|
149
|
-
/**
|
|
150
|
-
* @param {string} code
|
|
151
|
-
* @param {string} reason - The bare reason; `message` is composed per
|
|
152
|
-
* the coded contract.
|
|
153
|
-
* @param {{ docPath?: string, collection?: string,
|
|
154
|
-
* key?: string | number, errors?: unknown[], cause?: unknown }} [details]
|
|
155
|
-
* - `docPath` points into the model document (the collection the
|
|
156
|
-
* failure belongs to); `collection`/`key` are installed as own
|
|
157
|
-
* properties; `errors` carries validation findings; `cause` follows
|
|
158
|
-
* the coded contract's `hasOwn` form.
|
|
159
|
-
*/
|
|
160
|
-
constructor(code: string, reason: string, details?: {
|
|
161
|
-
docPath?: string;
|
|
162
|
-
collection?: string;
|
|
163
|
-
key?: string | number;
|
|
164
|
-
errors?: unknown[];
|
|
165
|
-
cause?: unknown;
|
|
166
|
-
});
|
|
167
|
-
}
|
package/dist/types/graph.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Row → entity-graph reconstruction. One place owns the merge
|
|
3
|
-
* discipline (§9.3): mapped scalar columns fold back into the JSONB
|
|
4
|
-
* document's parse (booleans un-integer, SQL NULL reads back ABSENT,
|
|
5
|
-
* derived epoch columns are skipped because the string never left the
|
|
6
|
-
* document), foreign-key columns fold in the same way, and — for the
|
|
7
|
-
* one-statement graph loads — projected relation JSON parses
|
|
8
|
-
* recursively into child arrays or single children.
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* Merge one database row back into its entity document.
|
|
12
|
-
* @param {any} entityMapping - `explainMapping(...).entities[name]`
|
|
13
|
-
* @param {any} row - a row carrying the entity's columns plus the
|
|
14
|
-
* rendered document text
|
|
15
|
-
* @param {string} [docField] - the column the document text rides in
|
|
16
|
-
* @returns {any}
|
|
17
|
-
*/
|
|
18
|
-
export declare function mergeEntityRow(entityMapping: any, row: any, docField?: string): any;
|
|
19
|
-
/**
|
|
20
|
-
* Parse one graph-load row: the root entity's merge plus every
|
|
21
|
-
* included relation's projected JSON, recursively.
|
|
22
|
-
* @param {any} node - the include-plan node
|
|
23
|
-
* `{ entityMapping, includes: { name, field, many, count, child }[] }`
|
|
24
|
-
* @param {any} row
|
|
25
|
-
* @param {string} docField
|
|
26
|
-
* @returns {any}
|
|
27
|
-
*/
|
|
28
|
-
export declare function parseGraphRow(node: any, row: any, docField?: string): any;
|
package/dist/types/index.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file @jarenjs/db — document storage over SQLite through two seams:
|
|
3
|
-
* a driver (how a connection is made: `@jarenjs/db/node`, `/bun`, or
|
|
4
|
-
* `/wasm` with an injected handle) and a dialect (how SQL is spelled).
|
|
5
|
-
* This root subpath never touches a runtime builtin — a browser
|
|
6
|
-
* bundler resolves it clean; the bindings live behind their own
|
|
7
|
-
* subpaths and load their builtin lazily inside `open()`.
|
|
8
|
-
*/
|
|
9
|
-
export { openStore, normalizeModel, MODEL_VERSION } from './store.js';
|
|
10
|
-
export { createDialect } from './dialect.js';
|
|
11
|
-
export { sqliteDialect } from './dialects/sqlite.js';
|
|
12
|
-
export { SQLITE_FLOOR, chain, toPromise, isThenable, compareVersions, openConnection, wrapStatement, lazyOpen, } from './driver.js';
|
|
13
|
-
export { planCollection, compileIndexPath, schemaTypeAt, KEY_COLUMN, DOC_COLUMN, normalizeDeclaredSql, comparableDeclaredSql, } from './ddl.js';
|
|
14
|
-
export { planQuery, assertDecidedKind, entityShape, entityPathRef, planEntityPredicate, planEntityQuery, } from './plan.js';
|
|
15
|
-
export { emitPlan, createEntityPredicateEmitters, emitEntityPlan } from './emit.js';
|
|
16
|
-
export { mergeEntityRow, parseGraphRow } from './graph.js';
|
|
17
|
-
export { selectPlan, conjoin, assertNoSqlText, PLAN_VERSION } from './algebra.js';
|
|
18
|
-
export { typeOfPath, isNumericType } from './types.js';
|
|
19
|
-
export { compileSetResidual, compileRowResidual, sequenceResult } from './residual.js';
|
|
20
|
-
export { deterministicFragment, registerFragment } from './udf.js';
|
|
21
|
-
export { DERIVE_KINDS, DERIVE_MAPPING, PHYSICAL_KINDS, BBOX_COMPONENTS, BBOX_INDEX_ORDER, PRECISION_MIN, PRECISION_MAX, DIMS_MIN, DIMS_MAX, deriveGeohash, deriveBboxEdge, deriveVector, derivedValue, derivedMappingFor, memberAt, storedMemberForm, registerDeriveFunctions, probeVector, columnScore, } from './derive.js';
|
|
22
|
-
export { KNN_MARGIN, IDENTITY_CHUNK, cutCandidates, identityBatches } from './knn.js';
|
|
23
|
-
export { createQueryEngine, createQueryState, createEntityQueryEngine, createLoadEngine, INCLUDE_DEPTH_DEFAULT, } from './query.js';
|
|
24
|
-
export { normalizeProfile, SAFE_PROFILE, translateProfilePredicate, applyMandatoryPredicate, applyRowBound, } from './profile.js';
|
|
25
|
-
export { translatePatch } from './patch-sql.js';
|
|
26
|
-
export { normalizeEntities, explainMapping } from './model.js';
|
|
27
|
-
export { planEntity, planJoinTable } from './ddl.js';
|
|
28
|
-
export { entityCore } from './entity.js';
|
|
29
|
-
export { entityEmitModel } from './emit-model.js';
|
|
30
|
-
export { parseChangeset, translateOperations, keyToken, createCaptureEngine, CHANGES_TABLE, DEFAULT_RETENTION, } from './capture.js';
|
|
31
|
-
export { createTracker, deepFreeze, BATCH_PARAM_BUDGET, BATCH_ROW_BOUND, } from './tracker.js';
|
|
32
|
-
export { planMigration, planModelMigration, migrate, migrationStatus, shapeHash, migrationChecksum, createModelShape, schemaShapeOf, compareShapeToModel, MIGRATION_VERSION, HISTORY_TABLE, } from './migrate.js';
|
|
33
|
-
export { DbCompileError, DbRuntimeError, DB_CODES } from './errors.js';
|
|
34
|
-
export { classifyLiveQuery, createLiveRegistry, diffRows, LIVE_DEFAULTS } from './live.js';
|
|
35
|
-
export { createSortedWindow, compareCodepoint } from './window.js';
|
|
36
|
-
export { createJobEngine, JOBS_TABLE, JOB_CHECKPOINTS_TABLE, JOB_DEFAULTS, describeValue, serializeResult, } from './jobs.js';
|
|
37
|
-
export { createDagJobRunner } from './dag-job.js';
|
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
|
-
}[];
|
package/dist/types/live.d.ts
DELETED
|
@@ -1,62 +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
|
-
* @returns {any}
|
|
35
|
-
*/
|
|
36
|
-
export declare function classifyLiveQuery(document: any, queryShape: any, keyed: boolean): any;
|
|
37
|
-
/**
|
|
38
|
-
* Diff two row arrays into sequential add/remove/replace ops under
|
|
39
|
-
* `/rows`, relying on REFERENCE identity for unchanged rows (the §9
|
|
40
|
-
* sharing contract makes identity the equality that matters). A
|
|
41
|
-
* working copy is replayed op by op, so the emitted patch transforms
|
|
42
|
-
* the old array into the new one BY CONSTRUCTION; a remove re-filled
|
|
43
|
-
* at the same index merges into a replace.
|
|
44
|
-
* @param {any[]} oldRows
|
|
45
|
-
* @param {any[]} newRows
|
|
46
|
-
* @returns {any[]} ops
|
|
47
|
-
*/
|
|
48
|
-
export declare function diffRows(oldRows: any[], newRows: any[]): any[];
|
|
49
|
-
/**
|
|
50
|
-
* The store-level live-query registry: registration against the §12
|
|
51
|
-
* bounds, capture-record delivery in commit order, lifecycle.
|
|
52
|
-
* @param {{ maxQueries: number, maxMaintained: number }} bounds
|
|
53
|
-
*/
|
|
54
|
-
export declare function createLiveRegistry(bounds: {
|
|
55
|
-
maxQueries: number;
|
|
56
|
-
maxMaintained: number;
|
|
57
|
-
}): {
|
|
58
|
-
register: (definition: any) => any;
|
|
59
|
-
count: () => number;
|
|
60
|
-
deliver(record: any): void;
|
|
61
|
-
closeAll(): void;
|
|
62
|
-
};
|