@jarenjs/db 0.34.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 +397 -0
- package/README.md +218 -0
- package/dist/types/algebra.d.ts +133 -0
- package/dist/types/app.d.ts +49 -0
- package/dist/types/capture.d.ts +85 -0
- package/dist/types/cli.d.ts +2 -0
- package/dist/types/dag-job.d.ts +40 -0
- package/dist/types/ddl.d.ts +170 -0
- package/dist/types/dialect.d.ts +130 -0
- package/dist/types/dialects/sqlite.d.ts +9 -0
- package/dist/types/driver.d.ts +128 -0
- package/dist/types/drivers/bun.d.ts +47 -0
- package/dist/types/drivers/node.d.ts +37 -0
- package/dist/types/drivers/wasm.d.ts +65 -0
- package/dist/types/emit-model.d.ts +44 -0
- package/dist/types/emit.d.ts +72 -0
- package/dist/types/entity.d.ts +23 -0
- package/dist/types/errors.d.ts +165 -0
- package/dist/types/graph.d.ts +28 -0
- package/dist/types/index.d.ts +35 -0
- package/dist/types/jobs.d.ts +134 -0
- package/dist/types/live.d.ts +62 -0
- package/dist/types/migrate.d.ts +163 -0
- package/dist/types/model.d.ts +36 -0
- package/dist/types/patch-sql.d.ts +37 -0
- package/dist/types/plan.d.ts +119 -0
- package/dist/types/profile.d.ts +80 -0
- package/dist/types/query.d.ts +100 -0
- package/dist/types/residual.d.ts +50 -0
- package/dist/types/store.d.ts +53 -0
- package/dist/types/tracker.d.ts +43 -0
- package/dist/types/typed.d.ts +15 -0
- package/dist/types/types.d.ts +26 -0
- package/dist/types/udf.d.ts +70 -0
- package/dist/types/window.d.ts +52 -0
- package/docs/JOBS-FORMAT.md +218 -0
- package/docs/LIVE-FORMAT.md +348 -0
- package/docs/MIGRATION-FORMAT.md +302 -0
- package/docs/MODEL-FORMAT.md +928 -0
- package/package.json +81 -0
- package/schemas/jaren-migration.draft-07.schema.json +144 -0
- package/schemas/jaren-migration.schema.json +144 -0
- package/schemas/jaren-model.draft-07.schema.json +149 -0
- package/schemas/jaren-model.schema.json +149 -0
- package/src/algebra.js +105 -0
- package/src/app.js +108 -0
- package/src/capture.js +584 -0
- package/src/cli.js +264 -0
- package/src/dag-job.js +86 -0
- package/src/ddl.js +588 -0
- package/src/dialect.js +297 -0
- package/src/dialects/sqlite.js +175 -0
- package/src/driver.js +419 -0
- package/src/drivers/bun.js +101 -0
- package/src/drivers/node.js +93 -0
- package/src/drivers/wasm.js +178 -0
- package/src/emit-model.js +208 -0
- package/src/emit.js +393 -0
- package/src/entity.js +367 -0
- package/src/errors.js +173 -0
- package/src/graph.js +101 -0
- package/src/index.js +64 -0
- package/src/jobs.js +507 -0
- package/src/live.js +899 -0
- package/src/migrate.js +1411 -0
- package/src/model.js +476 -0
- package/src/patch-sql.js +150 -0
- package/src/plan.js +1038 -0
- package/src/profile.js +131 -0
- package/src/query.js +1010 -0
- package/src/residual.js +91 -0
- package/src/store.js +1422 -0
- package/src/tracker.js +776 -0
- package/src/typed.js +19 -0
- package/src/types.js +36 -0
- package/src/udf.js +132 -0
- package/src/window.js +125 -0
- package/types/app.d.ts +36 -0
- package/types/bun.d.ts +9 -0
- package/types/index.d.ts +592 -0
- package/types/node.d.ts +15 -0
- package/types/typed.d.ts +108 -0
- package/types/wasm.d.ts +5 -0
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-authored declarations for @jarenjs/db — the deliberate public
|
|
3
|
+
* type surface (hand-authored declarations rather than emitted ones —
|
|
4
|
+
* the same decision linq made): the implementation stays plain JSDoc'd
|
|
5
|
+
* JavaScript, and this
|
|
6
|
+
* file is the contract. Anti-drift: the adopter surface is exercised
|
|
7
|
+
* value-position in `test/consumer/types.ts`, and the generated-types
|
|
8
|
+
* pipeline has its own committed oracle (`db-generated.ts`).
|
|
9
|
+
*
|
|
10
|
+
* THE LINE (same as linq's): the common path is precisely typed; the
|
|
11
|
+
* exotic path is honestly `unknown`, never a lie. Query documents,
|
|
12
|
+
* plans and dialect internals are `unknown` on purpose — they are
|
|
13
|
+
* data with their own formats — while the store, entity and
|
|
14
|
+
* unit-of-work surfaces the adopter lives on are exact. Entity-shaped
|
|
15
|
+
* precision (generated `T`s, include-widened loads) layers on top via
|
|
16
|
+
* `@jarenjs/db/typed`.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// ————— errors —————
|
|
20
|
+
|
|
21
|
+
export declare const DB_CODES: Readonly<Record<string, string>>;
|
|
22
|
+
|
|
23
|
+
export declare class DbCompileError extends Error {
|
|
24
|
+
constructor(code: string, reason: string, docPath?: string, cause?: Error);
|
|
25
|
+
readonly code: string;
|
|
26
|
+
readonly reason: string;
|
|
27
|
+
readonly docPath?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export declare class DbRuntimeError extends Error {
|
|
31
|
+
constructor(code: string, reason: string, options?: {
|
|
32
|
+
docPath?: string;
|
|
33
|
+
collection?: string;
|
|
34
|
+
key?: unknown;
|
|
35
|
+
errors?: unknown[];
|
|
36
|
+
cause?: unknown;
|
|
37
|
+
});
|
|
38
|
+
readonly code: string;
|
|
39
|
+
readonly reason: string;
|
|
40
|
+
readonly docPath?: string;
|
|
41
|
+
readonly collection?: string;
|
|
42
|
+
readonly key?: unknown;
|
|
43
|
+
readonly errors?: unknown[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ————— shared shapes —————
|
|
47
|
+
|
|
48
|
+
/** A single-column key, or the `{ prop: value, … }` composite form. */
|
|
49
|
+
export type EntityKeyArg = string | number | Readonly<Record<string, string | number>>;
|
|
50
|
+
|
|
51
|
+
export interface ExecuteOptions {
|
|
52
|
+
externals?: Readonly<Record<string, unknown>>;
|
|
53
|
+
strict?: boolean;
|
|
54
|
+
/** `false` forces the set residual — the oracle's harness switch. */
|
|
55
|
+
pushdown?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface LoadInclude extends LoadSpec {
|
|
59
|
+
/** Project the related-row COUNT instead of the rows. */
|
|
60
|
+
count?: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface LoadSpec {
|
|
64
|
+
/** A query expression over `$it` (translatable clauses only). */
|
|
65
|
+
where?: unknown;
|
|
66
|
+
orderBy?: unknown;
|
|
67
|
+
take?: number;
|
|
68
|
+
skip?: number;
|
|
69
|
+
/** The keyset cursor: needs a single unique-column ordering. */
|
|
70
|
+
after?: string | number;
|
|
71
|
+
maxDepth?: number;
|
|
72
|
+
include?: Readonly<Record<string, boolean | LoadInclude>>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface LoadExplanation {
|
|
76
|
+
sql: string;
|
|
77
|
+
pagination: 'keyset' | 'offset' | 'none';
|
|
78
|
+
includes: ReadonlyArray<{ path: string; kind: string; count: boolean }>;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** What `saveChanges()` returns: data, not a boolean (§11.6). */
|
|
82
|
+
export interface SaveReport {
|
|
83
|
+
inserted: number;
|
|
84
|
+
updated: number;
|
|
85
|
+
deleted: number;
|
|
86
|
+
joinInserted: number;
|
|
87
|
+
joinDeleted: number;
|
|
88
|
+
/** Whole-row writes for untranslatable diffs — counted, never silent. */
|
|
89
|
+
fallbacks: number;
|
|
90
|
+
statements: ReadonlyArray<{ sql: string; rows: number }>;
|
|
91
|
+
concurrency: { checked: number; unversioned: readonly string[] };
|
|
92
|
+
elapsedMs: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface StoreStats {
|
|
96
|
+
statementCache: { hits: number; misses: number; evictions: number };
|
|
97
|
+
udfRegistrations: number;
|
|
98
|
+
tracker: {
|
|
99
|
+
tracked: number;
|
|
100
|
+
pendingInserts: number;
|
|
101
|
+
pendingDeletes: number;
|
|
102
|
+
} | null;
|
|
103
|
+
liveQueries: number;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface StoreCapabilities {
|
|
107
|
+
readonly version: string;
|
|
108
|
+
readonly readOnly: boolean;
|
|
109
|
+
readonly validated: boolean;
|
|
110
|
+
readonly profiled: boolean;
|
|
111
|
+
readonly busyTimeoutMs: number | null;
|
|
112
|
+
readonly journalMode: string | null;
|
|
113
|
+
readonly capture: 'session' | 'journal' | 'none';
|
|
114
|
+
readonly captureLog: boolean;
|
|
115
|
+
readonly live: boolean;
|
|
116
|
+
readonly jobs: boolean;
|
|
117
|
+
readonly [capability: string]: unknown;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ————— collections (the phase-A storage subset) —————
|
|
121
|
+
|
|
122
|
+
export interface Collection<T = unknown> {
|
|
123
|
+
stats(): unknown;
|
|
124
|
+
insert(doc: T): Promise<string | number>;
|
|
125
|
+
get(key: string | number): Promise<T | undefined>;
|
|
126
|
+
put(doc: T, key?: string | number): Promise<string | number>;
|
|
127
|
+
patch(key: string | number, ops: readonly unknown[]): Promise<T>;
|
|
128
|
+
delete(key: string | number): Promise<boolean>;
|
|
129
|
+
/** The D2 provider: value-or-promise so a linq chain over a
|
|
130
|
+
* synchronous driver stays synchronous. */
|
|
131
|
+
execute(document: unknown, options?: ExecuteOptions): unknown;
|
|
132
|
+
query(document: unknown, options?: ExecuteOptions): unknown;
|
|
133
|
+
explain(document: unknown, options?: ExecuteOptions): Promise<unknown>;
|
|
134
|
+
/** Register a live query (LIVE-FORMAT §7); requires capture. */
|
|
135
|
+
live(document: unknown, options?: LiveOptions): Promise<LiveQuery>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface SyncCollection<T = unknown> {
|
|
139
|
+
stats(): unknown;
|
|
140
|
+
insert(doc: T): string | number;
|
|
141
|
+
get(key: string | number): T | undefined;
|
|
142
|
+
put(doc: T, key?: string | number): string | number;
|
|
143
|
+
patch(key: string | number, ops: readonly unknown[]): T;
|
|
144
|
+
delete(key: string | number): boolean;
|
|
145
|
+
execute(document: unknown, options?: ExecuteOptions): unknown;
|
|
146
|
+
explain(document: unknown, options?: ExecuteOptions): unknown;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ————— entities (phase B) —————
|
|
150
|
+
|
|
151
|
+
export interface UntrackedReads<T = unknown> {
|
|
152
|
+
get(key: EntityKeyArg): Promise<T | undefined>;
|
|
153
|
+
load(spec?: LoadSpec): Promise<T[]>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface EntitySet<T = unknown, I = unknown> {
|
|
157
|
+
create(doc: I): Promise<Readonly<T>>;
|
|
158
|
+
get(key: EntityKeyArg): Promise<Readonly<T> | undefined>;
|
|
159
|
+
update(key: EntityKeyArg, changes: Partial<T>): Promise<Readonly<T>>;
|
|
160
|
+
delete(key: EntityKeyArg): Promise<boolean>;
|
|
161
|
+
load(spec?: LoadSpec): Promise<ReadonlyArray<Readonly<T>>>;
|
|
162
|
+
explainLoad(spec?: LoadSpec): LoadExplanation;
|
|
163
|
+
/** Track a pending insert (local, synchronous — no round trip). */
|
|
164
|
+
add(doc: I): Readonly<T>;
|
|
165
|
+
/** Register the next version of a tracked entity. */
|
|
166
|
+
put(next: T): Readonly<T>;
|
|
167
|
+
/** Schedule a delete (local, synchronous). */
|
|
168
|
+
remove(key: EntityKeyArg | T): void;
|
|
169
|
+
/** Drop tracking without scheduling anything — conflict recovery. */
|
|
170
|
+
discard(key: EntityKeyArg | T): void;
|
|
171
|
+
asNoTracking(): UntrackedReads<T>;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface SyncUntrackedReads<T = unknown> {
|
|
175
|
+
get(key: EntityKeyArg): T | undefined;
|
|
176
|
+
load(spec?: LoadSpec): T[];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface SyncEntitySet<T = unknown, I = unknown> {
|
|
180
|
+
create(doc: I): Readonly<T>;
|
|
181
|
+
get(key: EntityKeyArg): Readonly<T> | undefined;
|
|
182
|
+
update(key: EntityKeyArg, changes: Partial<T>): Readonly<T>;
|
|
183
|
+
delete(key: EntityKeyArg): boolean;
|
|
184
|
+
load(spec?: LoadSpec): ReadonlyArray<Readonly<T>>;
|
|
185
|
+
explainLoad(spec?: LoadSpec): LoadExplanation;
|
|
186
|
+
add(doc: I): Readonly<T>;
|
|
187
|
+
put(next: T): Readonly<T>;
|
|
188
|
+
remove(key: EntityKeyArg | T): void;
|
|
189
|
+
discard(key: EntityKeyArg | T): void;
|
|
190
|
+
asNoTracking(): SyncUntrackedReads<T>;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ————— the store —————
|
|
194
|
+
|
|
195
|
+
export interface SyncStore {
|
|
196
|
+
collection(name: string): SyncCollection;
|
|
197
|
+
entity(name: string): SyncEntitySet;
|
|
198
|
+
transaction<R>(fn: (store: Store) => R): R;
|
|
199
|
+
execute?(document: unknown, options?: ExecuteOptions): unknown;
|
|
200
|
+
saveChanges?(): SaveReport;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface Store {
|
|
204
|
+
readonly capabilities: StoreCapabilities;
|
|
205
|
+
readonly dialect: Dialect;
|
|
206
|
+
stats(): StoreStats;
|
|
207
|
+
collection(name: string): Collection;
|
|
208
|
+
entity(name: string): EntitySet;
|
|
209
|
+
/** Entity documents over the multi-entity root (§10.1); present
|
|
210
|
+
* only when the model declares entities. Value-or-promise (D2). */
|
|
211
|
+
execute?(document: unknown, options?: ExecuteOptions): unknown;
|
|
212
|
+
explain?(document: unknown, options?: ExecuteOptions): Promise<unknown>;
|
|
213
|
+
/** The unit of work (§11); present only with entities. */
|
|
214
|
+
saveChanges?(): Promise<SaveReport>;
|
|
215
|
+
transaction<R>(fn: (store: Store) => R | Promise<R>): Promise<Awaited<R>>;
|
|
216
|
+
/** Register a change observer; requires capture. Returns unsubscribe. */
|
|
217
|
+
observe(fn: (record: ChangeRecord) => void): () => void;
|
|
218
|
+
/** Read the persisted log forward (JD2051 without capture.log). */
|
|
219
|
+
changesSince?(after: number): Promise<ChangeRecord[]>;
|
|
220
|
+
/** PRAGMA data_version — the coarse cross-connection signal. */
|
|
221
|
+
dataVersion(): Promise<number>;
|
|
222
|
+
/** Register a live query over an entity-root document (re-run
|
|
223
|
+
* strategy in this version); present only with entities. */
|
|
224
|
+
live?(document: unknown, options?: LiveOptions): Promise<LiveQuery>;
|
|
225
|
+
close(): Promise<void>;
|
|
226
|
+
/** The queue surface; present when opened with `jobs` (JOBS-FORMAT). */
|
|
227
|
+
readonly jobs?: JobsApi;
|
|
228
|
+
/** Present exactly when the driver is synchronous — never stubs. */
|
|
229
|
+
readonly sync?: SyncStore;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** One committed transaction's change record (LIVE-FORMAT §§1–5). */
|
|
233
|
+
export interface ChangeRecord {
|
|
234
|
+
/** Monotonic; continues across reopens when the log is enabled. */
|
|
235
|
+
seq: number;
|
|
236
|
+
at: number;
|
|
237
|
+
source: 'session' | 'journal';
|
|
238
|
+
collections: readonly string[];
|
|
239
|
+
/** RFC 6902 ops with `/<table>/<key>/<path…>` pointers. */
|
|
240
|
+
patch: ReadonlyArray<{ op: string; path: string; value?: unknown; from?: string }>;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export interface CaptureOptions {
|
|
244
|
+
/** 'auto' (default) picks sessions where the driver has them. */
|
|
245
|
+
mode?: 'auto' | 'session' | 'journal';
|
|
246
|
+
log?: boolean | { retention?: number };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ————— live queries (LIVE-FORMAT §§7–12) —————
|
|
250
|
+
|
|
251
|
+
export interface LiveOptions {
|
|
252
|
+
/** Fixed at registration; a query whose inputs change is a new
|
|
253
|
+
* registration. */
|
|
254
|
+
externals?: Record<string, unknown>;
|
|
255
|
+
/** 'incremental' DEMANDS incrementality (JD0051 when the shape
|
|
256
|
+
* re-runs); 'rerun' forces the re-run strategy. */
|
|
257
|
+
mode?: 'auto' | 'incremental' | 'rerun';
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export interface LiveMode {
|
|
261
|
+
readonly strategy: 'rows' | 'window' | 'accumulator' | 'group' | 'rerun';
|
|
262
|
+
readonly mode: 'incremental' | 'rerun';
|
|
263
|
+
/** Present exactly when the strategy is 'rerun': the named reason. */
|
|
264
|
+
readonly reason?: string;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export interface LiveEvent {
|
|
268
|
+
/** RFC 6902 ops against the `{ rows }` result document. */
|
|
269
|
+
patch?: ReadonlyArray<{ op: string; path: string; value?: unknown }>;
|
|
270
|
+
seq?: number;
|
|
271
|
+
/** A maintenance failure (JD2060 …): the query closed after this. */
|
|
272
|
+
error?: unknown;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export interface LiveStats {
|
|
276
|
+
records: number;
|
|
277
|
+
matched: number;
|
|
278
|
+
emissions: number;
|
|
279
|
+
/** min/max extremum-removal recomputes (accumulator strategy). */
|
|
280
|
+
fallbacks?: number;
|
|
281
|
+
/** whole-query re-executions (re-run strategy). */
|
|
282
|
+
reruns?: number;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export interface LiveQuery {
|
|
286
|
+
/** The maintained result document; a fresh object per emission with
|
|
287
|
+
* unaffected rows REFERENCE-IDENTICAL (§9). */
|
|
288
|
+
readonly result: { readonly rows: readonly unknown[] };
|
|
289
|
+
readonly state: 'live' | 'closed' | 'errored';
|
|
290
|
+
readonly error: unknown;
|
|
291
|
+
readonly mode: LiveMode;
|
|
292
|
+
stats(): LiveStats;
|
|
293
|
+
subscribe(observer: (event: LiveEvent) => void): () => void;
|
|
294
|
+
close(): void;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export interface LiveBounds {
|
|
298
|
+
/** Registrations beyond it are JD0052 (default 64). */
|
|
299
|
+
maxQueries?: number;
|
|
300
|
+
/** Per-query ceiling on maintained entries — rows, window entries
|
|
301
|
+
* and contributions all count (default 10 000; JD2060 beyond). */
|
|
302
|
+
maxMaintained?: number;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export interface OpenStoreOptions {
|
|
306
|
+
driver: Driver;
|
|
307
|
+
path?: string;
|
|
308
|
+
/** Change capture (LIVE-FORMAT): off unless requested. */
|
|
309
|
+
capture?: boolean | CaptureOptions;
|
|
310
|
+
/** Live-query bounds (LIVE-FORMAT §12). */
|
|
311
|
+
live?: LiveBounds;
|
|
312
|
+
/** The durable job queue (JOBS-FORMAT); off unless requested. */
|
|
313
|
+
jobs?: boolean | JobsOptions;
|
|
314
|
+
/** The injected validation hook (D10); absent means unvalidated,
|
|
315
|
+
* declared through `capabilities.validated`. */
|
|
316
|
+
compileSchema?: (schema: unknown) => (doc: unknown) => unknown;
|
|
317
|
+
busyTimeout?: number;
|
|
318
|
+
journalMode?: string;
|
|
319
|
+
statementCacheBound?: number;
|
|
320
|
+
profile?: unknown;
|
|
321
|
+
readOnly?: boolean;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export declare function openStore(model: unknown, options: OpenStoreOptions): Promise<Store>;
|
|
325
|
+
export declare function normalizeModel(model: unknown): Map<string, unknown>;
|
|
326
|
+
export declare const MODEL_VERSION: string;
|
|
327
|
+
|
|
328
|
+
// ————— the dialect and driver seams —————
|
|
329
|
+
|
|
330
|
+
/** A dialect is data plus spelling primitives; consumers treat it as
|
|
331
|
+
* opaque beyond the members shown. */
|
|
332
|
+
export interface Dialect {
|
|
333
|
+
readonly name: string;
|
|
334
|
+
quoteIdentifier(name: string): string;
|
|
335
|
+
stringLiteral(value: string): string;
|
|
336
|
+
readonly [primitive: string]: unknown;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export interface Driver {
|
|
340
|
+
readonly name: string;
|
|
341
|
+
readonly dialect: Dialect;
|
|
342
|
+
open(options?: unknown): unknown;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export declare const sqliteDialect: Dialect;
|
|
346
|
+
export declare function createDialect(spec: unknown): Dialect;
|
|
347
|
+
export declare const SQLITE_FLOOR: string;
|
|
348
|
+
|
|
349
|
+
// ————— entities: models, mapping, generated types —————
|
|
350
|
+
|
|
351
|
+
export declare function normalizeEntities(model: unknown): Map<string, unknown>;
|
|
352
|
+
export declare function explainMapping(model: unknown): unknown;
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Build the EMIT-FORMAT model document for a model's entities.
|
|
356
|
+
* `compile` is `compileEmitModel` from `@jarenjs/emit`, injected so db
|
|
357
|
+
* never depends on emit; render the result with `renderTypeScript`.
|
|
358
|
+
*/
|
|
359
|
+
export declare function entityEmitModel(model: unknown, options: {
|
|
360
|
+
compile: (schema: unknown, options?: unknown) => unknown;
|
|
361
|
+
source?: string;
|
|
362
|
+
reserved?: string[];
|
|
363
|
+
}): unknown;
|
|
364
|
+
|
|
365
|
+
// ————— the unit of work —————
|
|
366
|
+
|
|
367
|
+
export declare function createTracker(context: unknown): unknown;
|
|
368
|
+
export declare function parseChangeset(bytes: Uint8Array): unknown[];
|
|
369
|
+
export declare function translateOperations(
|
|
370
|
+
connection: unknown, shapes: Map<string, unknown>, operations: unknown[],
|
|
371
|
+
): unknown;
|
|
372
|
+
export declare function keyToken(parts: readonly unknown[]): string;
|
|
373
|
+
export declare function createCaptureEngine(options: unknown): unknown;
|
|
374
|
+
export declare const CHANGES_TABLE: string;
|
|
375
|
+
export declare const DEFAULT_RETENTION: number;
|
|
376
|
+
/** Deep-freeze a JSON value in place and return it (idempotent). */
|
|
377
|
+
export declare function deepFreeze<T>(value: T): T;
|
|
378
|
+
export declare const BATCH_PARAM_BUDGET: number;
|
|
379
|
+
export declare const BATCH_ROW_BOUND: number;
|
|
380
|
+
|
|
381
|
+
// ————— migrations —————
|
|
382
|
+
|
|
383
|
+
export interface MigrateOptions {
|
|
384
|
+
baseline: unknown;
|
|
385
|
+
model?: unknown;
|
|
386
|
+
compileSchema?: (schema: unknown) => (doc: unknown) => unknown;
|
|
387
|
+
dryRun?: boolean;
|
|
388
|
+
batchSize?: number;
|
|
389
|
+
shadow?: boolean;
|
|
390
|
+
/** Re-register declared deterministic functions on every connection
|
|
391
|
+
* the migration opens (real, shadow, reference) — §10. */
|
|
392
|
+
registerFunctions?: (connection: unknown) => unknown;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export declare function migrate(
|
|
396
|
+
target: unknown, migrations: readonly unknown[], options: MigrateOptions,
|
|
397
|
+
): Promise<unknown>;
|
|
398
|
+
export declare function planMigration(from: unknown, to: unknown, options?: unknown): unknown;
|
|
399
|
+
/** The whole-model diff — collections AND entities (MIGRATION-FORMAT §9). */
|
|
400
|
+
export declare function planModelMigration(from: unknown, to: unknown, options?: unknown): unknown;
|
|
401
|
+
export interface MigrationStatusReport {
|
|
402
|
+
applied: string[];
|
|
403
|
+
pending: string[];
|
|
404
|
+
/** A one-line difference when the database drifted; null in sync. */
|
|
405
|
+
drift: string | null;
|
|
406
|
+
upToDate: boolean;
|
|
407
|
+
}
|
|
408
|
+
export declare function migrationStatus(
|
|
409
|
+
target: { driver: Driver; path?: string },
|
|
410
|
+
migrations: readonly unknown[],
|
|
411
|
+
options: { baseline: unknown; model?: unknown;
|
|
412
|
+
registerFunctions?: (connection: unknown) => unknown },
|
|
413
|
+
): Promise<MigrationStatusReport>;
|
|
414
|
+
/** Create a model's whole physical shape on a connection. */
|
|
415
|
+
export declare function createModelShape(connection: unknown, model: unknown): unknown;
|
|
416
|
+
/** The declared schema, normalized for shape-equality comparison. */
|
|
417
|
+
export declare function schemaShapeOf(connection: unknown):
|
|
418
|
+
Promise<Array<{ type: string; name: string; owner: string; sql: string }>>
|
|
419
|
+
| Array<{ type: string; name: string; owner: string; sql: string }>;
|
|
420
|
+
/** Null when the database's shape equals a fresh build of the model. */
|
|
421
|
+
export declare function compareShapeToModel(
|
|
422
|
+
driver: Driver, connection: unknown, model: unknown,
|
|
423
|
+
registerFunctions?: (connection: unknown) => unknown,
|
|
424
|
+
): Promise<string | null> | string | null;
|
|
425
|
+
export declare function shapeHash(model: unknown): string;
|
|
426
|
+
export declare function migrationChecksum(migration: unknown): string;
|
|
427
|
+
export declare const MIGRATION_VERSION: string;
|
|
428
|
+
export declare const HISTORY_TABLE: string;
|
|
429
|
+
|
|
430
|
+
// ————— the machinery exports —————
|
|
431
|
+
// The planner/emitter/residual/profile internals are public for tools
|
|
432
|
+
// and tests; their documents have their own formats, so their types
|
|
433
|
+
// are deliberately WIDE (unknown), never wrong.
|
|
434
|
+
|
|
435
|
+
export declare function planCollection(name: string, collection: unknown, dialect: Dialect): unknown;
|
|
436
|
+
export declare function compileIndexPath(path: string, schema: unknown): unknown;
|
|
437
|
+
export declare function schemaTypeAt(schema: unknown, segments: unknown): unknown;
|
|
438
|
+
export declare const KEY_COLUMN: string;
|
|
439
|
+
export declare const DOC_COLUMN: string;
|
|
440
|
+
export declare function planQuery(document: unknown, shape: unknown, options?: unknown): unknown;
|
|
441
|
+
export declare function assertDecidedKind(node: unknown): void;
|
|
442
|
+
export declare function entityShape(entity: unknown, entityMapping: unknown): unknown;
|
|
443
|
+
export declare function entityPathRef(node: unknown, slot: number, shape: unknown): unknown;
|
|
444
|
+
export declare function planEntityPredicate(node: unknown, slot: number, shape: unknown): unknown;
|
|
445
|
+
export declare function planEntityQuery(document: unknown, entities: unknown, mapping: unknown): unknown;
|
|
446
|
+
export declare function emitPlan(plan: unknown, dialect: Dialect, physical: unknown): unknown;
|
|
447
|
+
export declare function createEntityPredicateEmitters(dialect: Dialect, param: unknown): unknown;
|
|
448
|
+
export declare function emitEntityPlan(plan: unknown, dialect: Dialect, physicalOf: unknown): unknown;
|
|
449
|
+
export declare function mergeEntityRow(entityMapping: unknown, row: unknown, docField?: string): unknown;
|
|
450
|
+
export declare function parseGraphRow(node: unknown, row: unknown, docField?: string): unknown;
|
|
451
|
+
export declare function selectPlan(collection: string): unknown;
|
|
452
|
+
export declare function conjoin(plan: unknown, predicate: unknown): unknown;
|
|
453
|
+
export declare function assertNoSqlText(plan: unknown): void;
|
|
454
|
+
export declare const PLAN_VERSION: number;
|
|
455
|
+
export declare function typeOfPath(shape: unknown, segments: unknown): unknown;
|
|
456
|
+
export declare function isNumericType(type: unknown): boolean;
|
|
457
|
+
export declare function compileSetResidual(document: unknown, limits?: unknown): unknown;
|
|
458
|
+
export declare function compileRowResidual(rowReturn: unknown, limits?: unknown): unknown;
|
|
459
|
+
export declare function sequenceResult(items: unknown[]): unknown;
|
|
460
|
+
export declare function deterministicFragment(fragment: unknown): unknown;
|
|
461
|
+
export declare function registerFragment(connection: unknown, registered: Set<string>, fragment: unknown): void;
|
|
462
|
+
export declare function createQueryEngine(context: unknown): unknown;
|
|
463
|
+
export declare function createQueryState(bound?: number): unknown;
|
|
464
|
+
export declare function createEntityQueryEngine(context: unknown): unknown;
|
|
465
|
+
export declare function createLoadEngine(context: unknown, entityName: string): unknown;
|
|
466
|
+
export declare const INCLUDE_DEPTH_DEFAULT: number;
|
|
467
|
+
export declare function normalizeProfile(profile: unknown): unknown;
|
|
468
|
+
export declare const SAFE_PROFILE: unknown;
|
|
469
|
+
export declare function translateProfilePredicate(predicate: unknown, shape: unknown): unknown;
|
|
470
|
+
export declare function applyMandatoryPredicate(plan: unknown, predicate: unknown): unknown;
|
|
471
|
+
export declare function applyRowBound(plan: unknown, maxRows: number): unknown;
|
|
472
|
+
export declare function translatePatch(ops: readonly unknown[], doc: unknown, dialect: Dialect): unknown;
|
|
473
|
+
export declare function planEntity(name: string, entityMapping: unknown, mapping: unknown, dialect: Dialect): unknown;
|
|
474
|
+
export declare function planJoinTable(name: string, joinTable: unknown, mapping: unknown, dialect: Dialect): unknown;
|
|
475
|
+
export declare function entityCore(connection: unknown, entity: unknown, entityMapping: unknown, validate: unknown): unknown;
|
|
476
|
+
export declare function chain<T, R>(value: T | Promise<T>, next: (value: T) => R): R | Promise<R>;
|
|
477
|
+
export declare function toPromise<T>(value: T | Promise<T>): Promise<T>;
|
|
478
|
+
export declare function isThenable(value: unknown): boolean;
|
|
479
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
480
|
+
export declare function openConnection(raw: unknown, options: unknown): unknown;
|
|
481
|
+
export declare function wrapStatement(statement: unknown): unknown;
|
|
482
|
+
export declare function lazyOpen(spec: unknown, reason: string, use: unknown, args?: unknown): unknown;
|
|
483
|
+
export declare function classifyLiveQuery(
|
|
484
|
+
document: unknown, queryShape: unknown, keyed: boolean): unknown;
|
|
485
|
+
export declare function createLiveRegistry(
|
|
486
|
+
bounds: { maxQueries: number; maxMaintained: number }): unknown;
|
|
487
|
+
export declare function diffRows(oldRows: readonly unknown[], newRows: readonly unknown[]):
|
|
488
|
+
Array<{ op: string; path: string; value?: unknown }>;
|
|
489
|
+
export declare const LIVE_DEFAULTS: { maxQueries: number; maxMaintained: number };
|
|
490
|
+
export declare function createSortedWindow(
|
|
491
|
+
terms: unknown[], limit: number | null): unknown;
|
|
492
|
+
export declare function compareCodepoint(a: string, b: string): number;
|
|
493
|
+
export declare function collectEntityRoots(
|
|
494
|
+
document: unknown, entities: ReadonlyMap<string, unknown>): Set<string>;
|
|
495
|
+
|
|
496
|
+
// ————— the job queue (JOBS-FORMAT) —————
|
|
497
|
+
|
|
498
|
+
export interface JobRecord {
|
|
499
|
+
readonly id: string;
|
|
500
|
+
readonly kind: string;
|
|
501
|
+
readonly payload: unknown;
|
|
502
|
+
readonly state: 'pending' | 'leased' | 'done' | 'failed' | 'dead';
|
|
503
|
+
readonly runAt: number;
|
|
504
|
+
readonly attempts: number;
|
|
505
|
+
readonly maxAttempts: number;
|
|
506
|
+
readonly leaseUntil: number | null;
|
|
507
|
+
readonly leaseOwner: string | null;
|
|
508
|
+
readonly lastError: string | null;
|
|
509
|
+
readonly result: unknown;
|
|
510
|
+
readonly createdAt: number;
|
|
511
|
+
readonly updatedAt: number;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export interface JobCounts {
|
|
515
|
+
pending: number;
|
|
516
|
+
leased: number;
|
|
517
|
+
done: number;
|
|
518
|
+
failed: number;
|
|
519
|
+
dead: number;
|
|
520
|
+
/** Pending/failed totals per kind — how a handler-less kind REPORTS. */
|
|
521
|
+
pendingKinds: Record<string, number>;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export interface JobWorker {
|
|
525
|
+
start(): JobWorker;
|
|
526
|
+
/** Resolves after in-flight handlers settle. */
|
|
527
|
+
stop(): Promise<void>;
|
|
528
|
+
stats(): { claims: number; completions: number; failures: number;
|
|
529
|
+
polls: number; wakes: number };
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
export interface JobWorkerOptions {
|
|
533
|
+
handlers: Record<string,
|
|
534
|
+
(payload: unknown, context: { job: JobRecord, checkpointsFor: Function }) => unknown>;
|
|
535
|
+
concurrency?: number;
|
|
536
|
+
pollInterval?: number;
|
|
537
|
+
leaseMs?: number;
|
|
538
|
+
owner?: string;
|
|
539
|
+
backoffBase?: number;
|
|
540
|
+
backoffCap?: number;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
export interface JobsApi {
|
|
544
|
+
enqueue(kind: string, payload?: unknown,
|
|
545
|
+
options?: { id?: string; runAt?: number; maxAttempts?: number }): Promise<string>;
|
|
546
|
+
get(id: string): Promise<JobRecord | undefined>;
|
|
547
|
+
counts(): Promise<JobCounts>;
|
|
548
|
+
/** The low-level guarded claim the worker itself uses (§3). */
|
|
549
|
+
claim(options: { kinds: string[]; owner: string; leaseMs?: number }):
|
|
550
|
+
Promise<JobRecord | undefined>;
|
|
551
|
+
complete(id: string, owner: string, result?: unknown): Promise<boolean>;
|
|
552
|
+
fail(id: string, owner: string, error: unknown): Promise<boolean>;
|
|
553
|
+
/** The per-job flow checkpoint store binding (§7). */
|
|
554
|
+
checkpointsFor(job: JobRecord): {
|
|
555
|
+
load(runId: string): unknown;
|
|
556
|
+
save(runId: string, nodeId: string, value: unknown): unknown;
|
|
557
|
+
complete(runId: string, result: unknown): unknown;
|
|
558
|
+
};
|
|
559
|
+
createWorker(options: JobWorkerOptions): JobWorker;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export interface JobsOptions {
|
|
563
|
+
maxAttempts?: number;
|
|
564
|
+
leaseMs?: number;
|
|
565
|
+
pollInterval?: number;
|
|
566
|
+
backoffBase?: number;
|
|
567
|
+
backoffCap?: number;
|
|
568
|
+
/** Injectable clock and randomness — every test injects both. */
|
|
569
|
+
now?: () => number;
|
|
570
|
+
random?: () => number;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
export declare function createDagJobRunner(store: Store, options: {
|
|
574
|
+
compileDag: Function;
|
|
575
|
+
documents: Record<string, unknown>;
|
|
576
|
+
tasks?: Record<string, Function>;
|
|
577
|
+
concurrency?: number;
|
|
578
|
+
pollInterval?: number;
|
|
579
|
+
leaseMs?: number;
|
|
580
|
+
owner?: string;
|
|
581
|
+
backoffBase?: number;
|
|
582
|
+
backoffCap?: number;
|
|
583
|
+
}): JobWorker;
|
|
584
|
+
|
|
585
|
+
export declare function createJobEngine(options: {
|
|
586
|
+
connection: unknown; now?: () => number; random?: () => number;
|
|
587
|
+
defaults?: JobsOptions }): unknown;
|
|
588
|
+
export declare const JOBS_TABLE: string;
|
|
589
|
+
export declare const JOB_CHECKPOINTS_TABLE: string;
|
|
590
|
+
export declare const JOB_DEFAULTS: Readonly<{
|
|
591
|
+
maxAttempts: number; leaseMs: number; pollInterval: number;
|
|
592
|
+
backoffBase: number; backoffCap: number }>;
|
package/types/node.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Hand-authored declarations for @jarenjs/db/node (strategy 1). */
|
|
2
|
+
import type { Driver } from '@jarenjs/db';
|
|
3
|
+
|
|
4
|
+
export interface NodeOpenOptions {
|
|
5
|
+
path?: string;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
readOnly?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** The `node:sqlite` binding; the builtin loads lazily inside open(). */
|
|
11
|
+
export declare function nodeDriver(): Driver;
|
|
12
|
+
/** Adapt an already-constructed DatabaseSync-shaped database. */
|
|
13
|
+
export declare function adaptNodeDatabase(db: unknown): unknown;
|
|
14
|
+
/** Construct and adapt from a loaded `node:sqlite`-shaped module. */
|
|
15
|
+
export declare function fromNodeModule(mod: unknown, path: string, options?: NodeOpenOptions): unknown;
|