@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
package/types/index.d.ts
CHANGED
|
@@ -84,7 +84,9 @@ export interface ExecuteOptions {
|
|
|
84
84
|
pushdown?: boolean;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
/** An include's clauses: the root's without `after` — a keyset cursor
|
|
88
|
+
* paginates the root alone; an include windows with `skip`/`take`. */
|
|
89
|
+
export interface LoadInclude extends Omit<LoadSpec, 'after'> {
|
|
88
90
|
/** Project the related-row COUNT instead of the rows. */
|
|
89
91
|
count?: boolean;
|
|
90
92
|
}
|
|
@@ -128,6 +130,8 @@ export interface StoreStats {
|
|
|
128
130
|
tracked: number;
|
|
129
131
|
pendingInserts: number;
|
|
130
132
|
pendingDeletes: number;
|
|
133
|
+
/** Pending `link`/`unlink` records: one per entity, own key and member (§11.7). */
|
|
134
|
+
pendingMemberships: number;
|
|
131
135
|
} | null;
|
|
132
136
|
liveQueries: number;
|
|
133
137
|
}
|
|
@@ -143,6 +147,10 @@ export interface StoreCapabilities {
|
|
|
143
147
|
readonly captureLog: boolean;
|
|
144
148
|
readonly live: boolean;
|
|
145
149
|
readonly jobs: boolean;
|
|
150
|
+
/** Whether a temporal spec naming a ZONE compiles here (D7's
|
|
151
|
+
* injected clock was supplied at open). Without it such a document
|
|
152
|
+
* is refused rather than answered in UTC. */
|
|
153
|
+
readonly zoneProvider: boolean;
|
|
146
154
|
readonly [capability: string]: unknown;
|
|
147
155
|
}
|
|
148
156
|
|
|
@@ -182,12 +190,44 @@ export interface SyncCollection<T = unknown> {
|
|
|
182
190
|
|
|
183
191
|
// ————— entities (phase B) —————
|
|
184
192
|
|
|
193
|
+
/** One row of an entity's relation table (MODEL-FORMAT §10.1): the
|
|
194
|
+
* declared relation as plain data a query producer can lower a hop
|
|
195
|
+
* from — never a document dialect. For a foreign-key relation `via`
|
|
196
|
+
* names the key property, `fkEntity` the entity holding it, `fkTargets`
|
|
197
|
+
* the entity it references and `targetKey` the key property it
|
|
198
|
+
* references there (the column a hop's equality compares `via` with);
|
|
199
|
+
* `kind` says which side holds the key (`oneToOne`: the declaring
|
|
200
|
+
* entity; `oneToMany`: the target). A many-to-many carries its
|
|
201
|
+
* `joinTable` and the target's `targetKey`. */
|
|
202
|
+
export interface RelationEntry {
|
|
203
|
+
readonly to: string;
|
|
204
|
+
readonly kind: 'oneToOne' | 'oneToMany' | 'manyToMany';
|
|
205
|
+
readonly via?: string;
|
|
206
|
+
readonly fkEntity?: string;
|
|
207
|
+
readonly fkTargets?: string;
|
|
208
|
+
readonly joinTable?: string;
|
|
209
|
+
readonly targetKey: string;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** An entity's relation table: one entry per declared relation member. */
|
|
213
|
+
export type RelationTable = Readonly<Record<string, RelationEntry>>;
|
|
214
|
+
|
|
215
|
+
/** The identity every entity set of one store shares — two sets with one
|
|
216
|
+
* `scope` may be joined in one document — carrying the relation tables
|
|
217
|
+
* of every root, keyed by entity name, so a hop can chain into another
|
|
218
|
+
* root of the same scope. */
|
|
219
|
+
export interface EntityScope {
|
|
220
|
+
readonly relations: Readonly<Record<string, RelationTable>>;
|
|
221
|
+
}
|
|
222
|
+
|
|
185
223
|
export interface UntrackedReads<T = unknown> {
|
|
186
224
|
get(key: EntityKeyArg): Promise<T | undefined>;
|
|
187
225
|
load(spec?: LoadSpec): Promise<T[]>;
|
|
188
226
|
}
|
|
189
227
|
|
|
190
228
|
export interface EntitySet<T = unknown, I = unknown> {
|
|
229
|
+
/** The provider phantom: a chain over this set infers its item type. */
|
|
230
|
+
readonly __item?: T;
|
|
191
231
|
create(doc: I): Promise<Readonly<T>>;
|
|
192
232
|
get(key: EntityKeyArg): Promise<Readonly<T> | undefined>;
|
|
193
233
|
update(key: EntityKeyArg, changes: Partial<T>): Promise<Readonly<T>>;
|
|
@@ -202,7 +242,27 @@ export interface EntitySet<T = unknown, I = unknown> {
|
|
|
202
242
|
remove(key: EntityKeyArg | T): void;
|
|
203
243
|
/** Drop tracking without scheduling anything — conflict recovery. */
|
|
204
244
|
discard(key: EntityKeyArg | T): void;
|
|
245
|
+
/** Attach / detach one many-to-many membership through the unit of
|
|
246
|
+
* work (§11.7): local bookkeeping, written by `saveChanges()` as join
|
|
247
|
+
* rows against the join table as it stands then — idempotent. `own`
|
|
248
|
+
* and `target` are each a key or a document carrying the key. */
|
|
249
|
+
link(own: EntityKeyArg | T, member: string, target: EntityKeyArg | object): void;
|
|
250
|
+
unlink(own: EntityKeyArg | T, member: string, target: EntityKeyArg | object): void;
|
|
205
251
|
asNoTracking(): UntrackedReads<T>;
|
|
252
|
+
/** The provider contract over this entity's root (MODEL-FORMAT §10.1):
|
|
253
|
+
* the document is over the multi-entity root and arrives whole; the
|
|
254
|
+
* answer is the engine's result shape, value-or-promise (D2). */
|
|
255
|
+
execute<R = unknown>(document: unknown, options?: ExecuteOptions): ValueOrPromise<SequenceResult<R>>;
|
|
256
|
+
explain(document: unknown, options?: ExecuteOptions): Promise<unknown>;
|
|
257
|
+
/** The root expression this set's rows are bound through (`$.<Name>[*]`). */
|
|
258
|
+
readonly root: string;
|
|
259
|
+
/** The identity every entity set of one store shares: two sets with one
|
|
260
|
+
* `scope` may be joined in one document; it carries every root's
|
|
261
|
+
* relation table. */
|
|
262
|
+
readonly scope: EntityScope;
|
|
263
|
+
/** This entity's relation table (MODEL-FORMAT §10.1) — what a query
|
|
264
|
+
* producer lowers a relation hop from. */
|
|
265
|
+
readonly relations: RelationTable;
|
|
206
266
|
}
|
|
207
267
|
|
|
208
268
|
export interface SyncUntrackedReads<T = unknown> {
|
|
@@ -211,6 +271,8 @@ export interface SyncUntrackedReads<T = unknown> {
|
|
|
211
271
|
}
|
|
212
272
|
|
|
213
273
|
export interface SyncEntitySet<T = unknown, I = unknown> {
|
|
274
|
+
/** The provider phantom: a chain over this set infers its item type. */
|
|
275
|
+
readonly __item?: T;
|
|
214
276
|
create(doc: I): Readonly<T>;
|
|
215
277
|
get(key: EntityKeyArg): Readonly<T> | undefined;
|
|
216
278
|
update(key: EntityKeyArg, changes: Partial<T>): Readonly<T>;
|
|
@@ -221,7 +283,15 @@ export interface SyncEntitySet<T = unknown, I = unknown> {
|
|
|
221
283
|
put(next: T): Readonly<T>;
|
|
222
284
|
remove(key: EntityKeyArg | T): void;
|
|
223
285
|
discard(key: EntityKeyArg | T): void;
|
|
286
|
+
link(own: EntityKeyArg | T, member: string, target: EntityKeyArg | object): void;
|
|
287
|
+
unlink(own: EntityKeyArg | T, member: string, target: EntityKeyArg | object): void;
|
|
224
288
|
asNoTracking(): SyncUntrackedReads<T>;
|
|
289
|
+
/** The provider contract over this entity's root, answering values. */
|
|
290
|
+
execute<R = unknown>(document: unknown, options?: ExecuteOptions): SequenceResult<R>;
|
|
291
|
+
explain(document: unknown, options?: ExecuteOptions): unknown;
|
|
292
|
+
readonly root: string;
|
|
293
|
+
readonly scope: EntityScope;
|
|
294
|
+
readonly relations: RelationTable;
|
|
225
295
|
}
|
|
226
296
|
|
|
227
297
|
// ————— the store —————
|
|
@@ -233,6 +303,14 @@ export interface SyncStore {
|
|
|
233
303
|
entity(name: string): SyncEntitySet;
|
|
234
304
|
transaction<R>(fn: (store: Store) => R): R;
|
|
235
305
|
execute?<R = unknown>(document: unknown, options?: ExecuteOptions): SequenceResult<R>;
|
|
306
|
+
explain?(document: unknown, options?: ExecuteOptions): unknown;
|
|
307
|
+
/** The entity roots this store-level provider serves (present with
|
|
308
|
+
* entities): it has no single root of its own, so a chain over it is
|
|
309
|
+
* refused by name — chain over `entity(name)` instead. */
|
|
310
|
+
readonly roots?: readonly string[];
|
|
311
|
+
/** The relation tables of every entity, keyed by entity name (present
|
|
312
|
+
* with entities; MODEL-FORMAT §10.1). */
|
|
313
|
+
readonly relations?: Readonly<Record<string, RelationTable>>;
|
|
236
314
|
saveChanges?(): SaveReport;
|
|
237
315
|
}
|
|
238
316
|
|
|
@@ -249,6 +327,13 @@ export interface Store {
|
|
|
249
327
|
* in the engine's result shape. */
|
|
250
328
|
execute?<R = unknown>(document: unknown, options?: ExecuteOptions): ValueOrPromise<SequenceResult<R>>;
|
|
251
329
|
explain?(document: unknown, options?: ExecuteOptions): Promise<unknown>;
|
|
330
|
+
/** The entity roots this store-level provider serves (present with
|
|
331
|
+
* entities): it has no single root of its own, so a chain over it is
|
|
332
|
+
* refused by name — chain over `entity(name)` instead. */
|
|
333
|
+
readonly roots?: readonly string[];
|
|
334
|
+
/** The relation tables of every entity, keyed by entity name (present
|
|
335
|
+
* with entities; MODEL-FORMAT §10.1). */
|
|
336
|
+
readonly relations?: Readonly<Record<string, RelationTable>>;
|
|
252
337
|
/** The unit of work (§11); present only with entities. */
|
|
253
338
|
saveChanges?(): Promise<SaveReport>;
|
|
254
339
|
transaction<R>(fn: (store: Store) => R | Promise<R>): Promise<Awaited<R>>;
|
|
@@ -297,10 +382,30 @@ export interface LiveOptions {
|
|
|
297
382
|
/** 'incremental' DEMANDS incrementality (JD0051 when the shape
|
|
298
383
|
* re-runs); 'rerun' forces the re-run strategy. */
|
|
299
384
|
mode?: 'auto' | 'incremental' | 'rerun';
|
|
385
|
+
/** Event time for a `$resample` / `$rolling` view (LIVE-FORMAT §13).
|
|
386
|
+
* Its members are closed: anything else is JD0053. */
|
|
387
|
+
eventTime?: LiveEventTime;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export interface LiveEventTime {
|
|
391
|
+
/** A singular row selector naming the instant member, e.g. '$.at'.
|
|
392
|
+
* It must be the member the spec aggregates by. */
|
|
393
|
+
path: string;
|
|
394
|
+
/** A finite epoch in milliseconds. Never a clock reading — the host
|
|
395
|
+
* supplies it, and `advance()` is the only way it moves. */
|
|
396
|
+
watermark: number;
|
|
397
|
+
/** How far behind the watermark a reading may still be applied
|
|
398
|
+
* (default 0). Older readings emit `lateData` and re-run. */
|
|
399
|
+
allowedLateness?: number;
|
|
400
|
+
/** The horizon this view claims, in milliseconds. It must cover the
|
|
401
|
+
* window (or bucket) width plus `allowedLateness`, or the view is
|
|
402
|
+
* classified as a re-run. */
|
|
403
|
+
retention: number;
|
|
300
404
|
}
|
|
301
405
|
|
|
302
406
|
export interface LiveMode {
|
|
303
|
-
readonly strategy: 'rows' | 'window' | 'accumulator' | 'group'
|
|
407
|
+
readonly strategy: 'rows' | 'window' | 'accumulator' | 'group'
|
|
408
|
+
| 'bucket' | 'rolling' | 'rerun';
|
|
304
409
|
readonly mode: 'incremental' | 'rerun';
|
|
305
410
|
/** Present exactly when the strategy is 'rerun': the named reason. */
|
|
306
411
|
readonly reason?: string;
|
|
@@ -312,6 +417,17 @@ export interface LiveEvent {
|
|
|
312
417
|
seq?: number;
|
|
313
418
|
/** A maintenance failure (JD2060 …): the query closed after this. */
|
|
314
419
|
error?: unknown;
|
|
420
|
+
/** Present when a reading behind the lateness boundary forced this
|
|
421
|
+
* emission: the view re-read, and the row was never folded in as
|
|
422
|
+
* though it had arrived on time (LIVE-FORMAT §13). */
|
|
423
|
+
lateData?: {
|
|
424
|
+
reason: 'late-data';
|
|
425
|
+
at: number;
|
|
426
|
+
key: string;
|
|
427
|
+
watermark: number;
|
|
428
|
+
allowedLateness: number;
|
|
429
|
+
boundary: number;
|
|
430
|
+
};
|
|
315
431
|
}
|
|
316
432
|
|
|
317
433
|
export interface LiveStats {
|
|
@@ -320,8 +436,15 @@ export interface LiveStats {
|
|
|
320
436
|
emissions: number;
|
|
321
437
|
/** min/max extremum-removal recomputes (accumulator strategy). */
|
|
322
438
|
fallbacks?: number;
|
|
323
|
-
/** whole-query re-executions (re-run strategy
|
|
439
|
+
/** whole-query re-executions (re-run strategy, and the re-read a
|
|
440
|
+
* late reading forces). */
|
|
324
441
|
reruns?: number;
|
|
442
|
+
/** readings that arrived behind the lateness boundary (event time). */
|
|
443
|
+
lateData?: number;
|
|
444
|
+
/** buckets or window stretches folded again (event time). */
|
|
445
|
+
recomputes?: number;
|
|
446
|
+
/** the current watermark (event time). */
|
|
447
|
+
watermark?: number;
|
|
325
448
|
}
|
|
326
449
|
|
|
327
450
|
export interface LiveQuery {
|
|
@@ -333,6 +456,10 @@ export interface LiveQuery {
|
|
|
333
456
|
readonly mode: LiveMode;
|
|
334
457
|
stats(): LiveStats;
|
|
335
458
|
subscribe(observer: (event: LiveEvent) => void): () => void;
|
|
459
|
+
/** Move the event-time watermark forward. Present only on a view
|
|
460
|
+
* registered with `eventTime`; a non-finite or backward value is a
|
|
461
|
+
* TypeError. */
|
|
462
|
+
advance?(watermark: number): void;
|
|
336
463
|
close(): void;
|
|
337
464
|
}
|
|
338
465
|
|
|
@@ -356,11 +483,26 @@ export interface OpenStoreOptions {
|
|
|
356
483
|
/** The injected validation hook (D10); absent means unvalidated,
|
|
357
484
|
* declared through `capabilities.validated`. */
|
|
358
485
|
compileSchema?: (schema: unknown) => (doc: unknown) => unknown;
|
|
486
|
+
/** D7's injected clock — `{ toParts(epoch, zone), toEpoch(parts, zone,
|
|
487
|
+
* disambiguation) }`. A temporal spec naming a zone
|
|
488
|
+
* (`{ "every": "P1M", "zone": "Europe/Amsterdam" }`) compiles only
|
|
489
|
+
* where one was injected; without it the document is refused rather
|
|
490
|
+
* than answered in UTC. No time-zone database is bundled. */
|
|
491
|
+
zoneProvider?: unknown;
|
|
359
492
|
busyTimeout?: number;
|
|
493
|
+
/** How long work waits for an open transaction to settle before
|
|
494
|
+
* `JD0012` (MODEL-FORMAT §5.1); reaches every driver. */
|
|
495
|
+
queueTimeout?: number;
|
|
360
496
|
journalMode?: string;
|
|
361
497
|
statementCacheBound?: number;
|
|
362
498
|
profile?: unknown;
|
|
363
499
|
readOnly?: boolean;
|
|
500
|
+
/** A `createJsltRegistry()` registry (Ring 2/3): the operators a
|
|
501
|
+
* query may use, and the pushable subset. */
|
|
502
|
+
operators?: unknown;
|
|
503
|
+
/** Raw registry-free operators; never pushed. */
|
|
504
|
+
functions?: Record<string, unknown>;
|
|
505
|
+
extensions?: Record<string, unknown>;
|
|
364
506
|
}
|
|
365
507
|
|
|
366
508
|
export declare function openStore(model: unknown, options: OpenStoreOptions): Promise<Store>;
|
|
@@ -381,7 +523,9 @@ export interface Dialect {
|
|
|
381
523
|
export interface Driver {
|
|
382
524
|
readonly name: string;
|
|
383
525
|
readonly dialect: Dialect;
|
|
384
|
-
|
|
526
|
+
/** Open a connection (value-or-promise) at `path` (`':memory:'` for
|
|
527
|
+
* none) with the driver's own options. */
|
|
528
|
+
open(path: string, options?: unknown): unknown;
|
|
385
529
|
}
|
|
386
530
|
|
|
387
531
|
export declare const sqliteDialect: Dialect;
|
|
@@ -392,6 +536,12 @@ export declare const SQLITE_FLOOR: string;
|
|
|
392
536
|
|
|
393
537
|
export declare function normalizeEntities(model: unknown): Map<string, unknown>;
|
|
394
538
|
export declare function explainMapping(model: unknown): unknown;
|
|
539
|
+
/** The relation tables of normalized entities, keyed by entity name
|
|
540
|
+
* then by relation member (MODEL-FORMAT §10.1) — what every entity set
|
|
541
|
+
* exposes as `relations` and every scope carries for all its roots. */
|
|
542
|
+
export declare function relationTables(
|
|
543
|
+
entities: Map<string, unknown>,
|
|
544
|
+
): Readonly<Record<string, RelationTable>>;
|
|
395
545
|
|
|
396
546
|
/**
|
|
397
547
|
* Build the EMIT-FORMAT model document for a model's entities.
|
|
@@ -475,7 +625,9 @@ export declare const HISTORY_TABLE: string;
|
|
|
475
625
|
// are deliberately WIDE (unknown), never wrong.
|
|
476
626
|
|
|
477
627
|
export declare function planCollection(name: string, collection: unknown, dialect: Dialect): unknown;
|
|
478
|
-
export declare function compileIndexPath(
|
|
628
|
+
export declare function compileIndexPath(expression: string, docPath: string): unknown;
|
|
629
|
+
export declare function normalizeDeclaredSql(sql: string): string;
|
|
630
|
+
export declare function comparableDeclaredSql(sql: string): string;
|
|
479
631
|
export declare function schemaTypeAt(schema: unknown, segments: unknown): unknown;
|
|
480
632
|
export declare const KEY_COLUMN: string;
|
|
481
633
|
export declare const DOC_COLUMN: string;
|
|
@@ -523,7 +675,7 @@ export declare function openConnection(raw: unknown, options: unknown): unknown;
|
|
|
523
675
|
export declare function wrapStatement(statement: unknown): unknown;
|
|
524
676
|
export declare function lazyOpen(spec: unknown, reason: string, use: unknown, args?: unknown): unknown;
|
|
525
677
|
export declare function classifyLiveQuery(
|
|
526
|
-
document: unknown, queryShape: unknown, keyed: boolean): unknown;
|
|
678
|
+
document: unknown, queryShape: unknown, keyed: boolean, eventTime?: unknown): unknown;
|
|
527
679
|
export declare function createLiveRegistry(
|
|
528
680
|
bounds: { maxQueries: number; maxMaintained: number }): unknown;
|
|
529
681
|
export declare function diffRows(oldRows: readonly unknown[], newRows: readonly unknown[]):
|
|
@@ -534,6 +686,38 @@ export declare function createSortedWindow(
|
|
|
534
686
|
export declare function compareCodepoint(a: string, b: string): number;
|
|
535
687
|
export declare function collectEntityRoots(
|
|
536
688
|
document: unknown, entities: ReadonlyMap<string, unknown>): Set<string>;
|
|
689
|
+
/** The root expression an entity's rows are bound through (`$.<Name>[*]`) —
|
|
690
|
+
* what an entity set exposes as `root` and what `collectEntityRoots` reads. */
|
|
691
|
+
export declare function entityRoot(name: string): string;
|
|
692
|
+
|
|
693
|
+
// ————— the derived-index and k-nearest machinery —————
|
|
694
|
+
// Constants carry their real shapes; the functions take and answer the
|
|
695
|
+
// planner's own records, which have no published type — WIDE, never
|
|
696
|
+
// wrong (the line at the top of this file).
|
|
697
|
+
|
|
698
|
+
export declare const DERIVE_KINDS: ReadonlySet<string>;
|
|
699
|
+
export declare const DERIVE_MAPPING: Readonly<Record<string, string | null>>;
|
|
700
|
+
export declare const PHYSICAL_KINDS: ReadonlySet<string>;
|
|
701
|
+
export declare const BBOX_COMPONENTS: readonly ['w', 's', 'e', 'n'];
|
|
702
|
+
export declare const BBOX_INDEX_ORDER: readonly ['w', 'e', 's', 'n'];
|
|
703
|
+
export declare const PRECISION_MIN: number;
|
|
704
|
+
export declare const PRECISION_MAX: number;
|
|
705
|
+
export declare const DIMS_MIN: number;
|
|
706
|
+
export declare const DIMS_MAX: number;
|
|
707
|
+
export declare function derivedMappingFor(kind: string, driverMapping: unknown): unknown;
|
|
708
|
+
export declare function deriveGeohash(value: unknown, precision: number): unknown;
|
|
709
|
+
export declare function deriveBboxEdge(value: unknown, component: 'w' | 's' | 'e' | 'n'): unknown;
|
|
710
|
+
export declare function deriveVector(member: unknown, dims: number): unknown;
|
|
711
|
+
export declare function storedMemberForm(member: unknown): unknown;
|
|
712
|
+
export declare function derivedValue(column: unknown, member: unknown): unknown;
|
|
713
|
+
export declare function memberAt(doc: unknown, segments: unknown): unknown;
|
|
714
|
+
export declare function registerDeriveFunctions(connection: unknown): unknown;
|
|
715
|
+
export declare function probeVector(value: unknown, dims: number): unknown;
|
|
716
|
+
export declare function columnScore(bytes: unknown, dims: number, probe: unknown): unknown;
|
|
717
|
+
export declare const KNN_MARGIN: number;
|
|
718
|
+
export declare const IDENTITY_CHUNK: number;
|
|
719
|
+
export declare function cutCandidates(rows: unknown[], m: number, margin: number): unknown;
|
|
720
|
+
export declare function identityBatches(identities: unknown[]): unknown;
|
|
537
721
|
|
|
538
722
|
// ————— the job queue (JOBS-FORMAT) —————
|
|
539
723
|
|
|
@@ -565,21 +749,25 @@ export interface JobCounts {
|
|
|
565
749
|
|
|
566
750
|
export interface JobWorker {
|
|
567
751
|
start(): JobWorker;
|
|
568
|
-
/**
|
|
569
|
-
|
|
752
|
+
/** Stop claiming, signal in-flight handlers, and wait up to `graceMs`
|
|
753
|
+
* (JOBS-FORMAT §6): the record says whether every loop drained. */
|
|
754
|
+
stop(options?: { graceMs?: number }): Promise<{ drained: boolean; inFlight: number }>;
|
|
570
755
|
stats(): { claims: number; completions: number; failures: number;
|
|
571
|
-
polls: number; wakes: number };
|
|
756
|
+
polls: number; wakes: number; claimErrors: number; inFlight: number };
|
|
572
757
|
}
|
|
573
758
|
|
|
574
759
|
export interface JobWorkerOptions {
|
|
575
|
-
handlers: Record<string,
|
|
576
|
-
|
|
760
|
+
handlers: Record<string, (payload: unknown, context: {
|
|
761
|
+
job: JobRecord; checkpointsFor: Function; signal: AbortSignal }) => unknown>;
|
|
762
|
+
/** A positive integer; the loops claiming concurrently. */
|
|
577
763
|
concurrency?: number;
|
|
578
764
|
pollInterval?: number;
|
|
579
765
|
leaseMs?: number;
|
|
580
766
|
owner?: string;
|
|
581
767
|
backoffBase?: number;
|
|
582
768
|
backoffCap?: number;
|
|
769
|
+
/** How long `stop()` waits for in-flight handlers by default. */
|
|
770
|
+
stopGraceMs?: number;
|
|
583
771
|
}
|
|
584
772
|
|
|
585
773
|
export interface JobsApi {
|
|
@@ -607,6 +795,7 @@ export interface JobsOptions {
|
|
|
607
795
|
pollInterval?: number;
|
|
608
796
|
backoffBase?: number;
|
|
609
797
|
backoffCap?: number;
|
|
798
|
+
stopGraceMs?: number;
|
|
610
799
|
/** Injectable clock and randomness — every test injects both. */
|
|
611
800
|
now?: () => number;
|
|
612
801
|
random?: () => number;
|
|
@@ -622,6 +811,7 @@ export declare function createDagJobRunner(store: Store, options: {
|
|
|
622
811
|
owner?: string;
|
|
623
812
|
backoffBase?: number;
|
|
624
813
|
backoffCap?: number;
|
|
814
|
+
stopGraceMs?: number;
|
|
625
815
|
}): JobWorker;
|
|
626
816
|
|
|
627
817
|
export declare function createJobEngine(options: {
|
|
@@ -631,4 +821,8 @@ export declare const JOBS_TABLE: string;
|
|
|
631
821
|
export declare const JOB_CHECKPOINTS_TABLE: string;
|
|
632
822
|
export declare const JOB_DEFAULTS: Readonly<{
|
|
633
823
|
maxAttempts: number; leaseMs: number; pollInterval: number;
|
|
634
|
-
backoffBase: number; backoffCap: number }>;
|
|
824
|
+
backoffBase: number; backoffCap: number; stopGraceMs: number }>;
|
|
825
|
+
/** A total diagnostic string for any value, including ones that fight back. */
|
|
826
|
+
export declare function describeValue(value: unknown): string;
|
|
827
|
+
/** A job result as the queue stores it: JSON text, or the reason it could not be. */
|
|
828
|
+
export declare function serializeResult(value: unknown): unknown;
|
package/types/node.d.ts
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
import type { Driver } from '@jarenjs/db';
|
|
3
3
|
|
|
4
4
|
export interface NodeOpenOptions {
|
|
5
|
-
|
|
5
|
+
/** The busy timeout in milliseconds. */
|
|
6
6
|
timeout?: number;
|
|
7
7
|
readOnly?: boolean;
|
|
8
|
+
/** How long work waits for an open transaction (`JD0012` after). */
|
|
9
|
+
queueTimeout?: number;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
/** The `node:sqlite` binding; the builtin loads lazily inside open(). */
|
package/types/typed.d.ts
CHANGED
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
import type {
|
|
16
16
|
EntityKeyArg, LoadExplanation, SaveReport, Store, StoreCapabilities,
|
|
17
17
|
StoreStats, Collection, ExecuteOptions, SequenceResult, ValueOrPromise,
|
|
18
|
+
Dialect, ChangeRecord, LiveOptions, LiveQuery, JobsApi, SyncStore,
|
|
19
|
+
EntityScope, RelationEntry, RelationTable,
|
|
18
20
|
} from '@jarenjs/db';
|
|
19
21
|
|
|
20
22
|
/** The self-referential constraint an interface can satisfy: generated
|
|
@@ -36,9 +38,14 @@ export type TypedInclude<E extends MetaMap<E>, M extends EntityMeta> = {
|
|
|
36
38
|
readonly [K in keyof M['relations']]?:
|
|
37
39
|
true
|
|
38
40
|
| { count: true }
|
|
39
|
-
|
|
|
41
|
+
| TypedIncludeSpec<E, E[M['relations'][K]['entity'] & keyof E]>;
|
|
40
42
|
};
|
|
41
43
|
|
|
44
|
+
/** An include's clauses: the root's without `after` (a keyset cursor
|
|
45
|
+
* paginates the root alone; an include windows with `skip`/`take`). */
|
|
46
|
+
export type TypedIncludeSpec<E extends MetaMap<E>, M extends EntityMeta> =
|
|
47
|
+
TypedLoadSpecBase & { include?: TypedInclude<E, M> };
|
|
48
|
+
|
|
42
49
|
export interface TypedLoadSpecBase {
|
|
43
50
|
/** A query expression over `$it` — its format is the runtime's. */
|
|
44
51
|
where?: unknown;
|
|
@@ -68,15 +75,31 @@ export type Loaded<
|
|
|
68
75
|
: Loaded<E, E[M['relations'][K]['entity'] & keyof E], I[K]> | null;
|
|
69
76
|
} : NonNullable<unknown>);
|
|
70
77
|
|
|
78
|
+
/** The relation members `link`/`unlink` take: the many-to-many ones —
|
|
79
|
+
* exactly the relation members the generated INPUT type also carries,
|
|
80
|
+
* since a membership array is writable where a projection is not. */
|
|
81
|
+
export type MembershipMember<M extends EntityMeta> =
|
|
82
|
+
keyof M['relations'] & keyof M['input'] & string;
|
|
83
|
+
|
|
84
|
+
/** What a membership names on the target side: the target's key, or a
|
|
85
|
+
* document carrying it. */
|
|
86
|
+
export type MembershipTarget<E extends MetaMap<E>, M extends EntityMeta, K extends keyof M['relations']> =
|
|
87
|
+
E[M['relations'][K]['entity'] & keyof E]['key'] | M['relations'][K]['doc'];
|
|
88
|
+
|
|
71
89
|
export interface TypedUntrackedReads<E extends MetaMap<E>, M extends EntityMeta> {
|
|
72
90
|
get(key: EntityKeyArg): Promise<M['doc'] | undefined>;
|
|
73
91
|
load<const S extends TypedLoadSpec<E, M>>(spec?: S): Promise<Array<Loaded<E, M, S>>>;
|
|
74
92
|
}
|
|
75
93
|
|
|
76
94
|
export interface TypedEntitySet<E extends MetaMap<E>, M extends EntityMeta> {
|
|
95
|
+
/** The provider phantom: `from(typed.entity('User'))` infers `User`
|
|
96
|
+
* without a cast. */
|
|
97
|
+
readonly __item?: M['doc'];
|
|
77
98
|
create(doc: M['input']): Promise<Readonly<M['doc']>>;
|
|
78
99
|
get(key: EntityKeyArg): Promise<Readonly<M['doc']> | undefined>;
|
|
79
|
-
|
|
100
|
+
/** A relation member is a projection, never stored state: `update()`
|
|
101
|
+
* refuses it (`JD2003`), and the type does not offer it. */
|
|
102
|
+
update(key: EntityKeyArg, changes: Partial<Omit<M['doc'], keyof M['relations']>>): Promise<Readonly<M['doc']>>;
|
|
80
103
|
delete(key: EntityKeyArg): Promise<boolean>;
|
|
81
104
|
load<const S extends TypedLoadSpec<E, M>>(spec?: S):
|
|
82
105
|
Promise<Array<Readonly<Loaded<E, M, S>>>>;
|
|
@@ -85,18 +108,51 @@ export interface TypedEntitySet<E extends MetaMap<E>, M extends EntityMeta> {
|
|
|
85
108
|
put(next: M['doc']): Readonly<M['doc']>;
|
|
86
109
|
remove(key: EntityKeyArg | M['doc']): void;
|
|
87
110
|
discard(key: EntityKeyArg | M['doc']): void;
|
|
111
|
+
/** Attach / detach one many-to-many membership through the unit of
|
|
112
|
+
* work (MODEL-FORMAT §11.7): `member` is one of the relation members
|
|
113
|
+
* `create`/`add` also take as an array — never a projection — and
|
|
114
|
+
* `target` the target's key or a document carrying it. */
|
|
115
|
+
link<K extends MembershipMember<M>>(own: M['key'] | M['doc'], member: K, target: MembershipTarget<E, M, K>): void;
|
|
116
|
+
unlink<K extends MembershipMember<M>>(own: M['key'] | M['doc'], member: K, target: MembershipTarget<E, M, K>): void;
|
|
88
117
|
asNoTracking(): TypedUntrackedReads<E, M>;
|
|
118
|
+
/** The provider contract over this entity's root (MODEL-FORMAT §10.1);
|
|
119
|
+
* the answer is the engine's result shape, value-or-promise (D2). */
|
|
120
|
+
execute<R = unknown>(document: unknown, options?: ExecuteOptions): ValueOrPromise<SequenceResult<R>>;
|
|
121
|
+
explain(document: unknown, options?: ExecuteOptions): Promise<unknown>;
|
|
122
|
+
/** The root expression this set's rows are bound through (`$.<Name>[*]`). */
|
|
123
|
+
readonly root: string;
|
|
124
|
+
/** The identity every entity set of one store shares; it carries every
|
|
125
|
+
* root's relation table. */
|
|
126
|
+
readonly scope: EntityScope;
|
|
127
|
+
/** This entity's relation table (MODEL-FORMAT §10.1): exactly the
|
|
128
|
+
* generated metadata's relation members, as the plain rows a query
|
|
129
|
+
* producer lowers a hop from. */
|
|
130
|
+
readonly relations: Readonly<Record<keyof M['relations'] & string, RelationEntry>>;
|
|
89
131
|
}
|
|
90
132
|
|
|
133
|
+
/** The typed store: every member of `Store` (a typed store is the same
|
|
134
|
+
* object, identity at runtime), with the entity sets typed. */
|
|
91
135
|
export interface TypedStore<E extends MetaMap<E>> {
|
|
92
136
|
readonly capabilities: StoreCapabilities;
|
|
137
|
+
readonly dialect: Dialect;
|
|
93
138
|
stats(): StoreStats;
|
|
94
139
|
collection<T = unknown>(name: string): Collection<T>;
|
|
95
140
|
entity<K extends keyof E & string>(name: K): TypedEntitySet<E, E[K]>;
|
|
96
141
|
execute?<R = unknown>(document: unknown, options?: ExecuteOptions): ValueOrPromise<SequenceResult<R>>;
|
|
142
|
+
explain?(document: unknown, options?: ExecuteOptions): Promise<unknown>;
|
|
143
|
+
/** The entity roots this store-level provider serves (present with entities). */
|
|
144
|
+
readonly roots?: readonly (keyof E & string)[];
|
|
145
|
+
/** The relation tables of every entity, keyed by entity name. */
|
|
146
|
+
readonly relations?: Readonly<Record<keyof E & string, RelationTable>>;
|
|
97
147
|
saveChanges?(): Promise<SaveReport>;
|
|
98
148
|
transaction<R>(fn: (store: Store) => R | Promise<R>): Promise<Awaited<R>>;
|
|
149
|
+
observe(fn: (record: ChangeRecord) => void): () => void;
|
|
150
|
+
changesSince?(after: number): Promise<ChangeRecord[]>;
|
|
151
|
+
dataVersion(): Promise<number>;
|
|
152
|
+
live?(document: unknown, options?: LiveOptions): Promise<LiveQuery>;
|
|
99
153
|
close(options?: { graceMs?: number }): Promise<void>;
|
|
154
|
+
readonly jobs?: JobsApi;
|
|
155
|
+
readonly sync?: SyncStore;
|
|
100
156
|
}
|
|
101
157
|
|
|
102
158
|
/**
|
package/types/wasm.d.ts
CHANGED
|
@@ -3,3 +3,10 @@ import type { Driver } from '@jarenjs/db';
|
|
|
3
3
|
|
|
4
4
|
/** A driver over an injected wasm SQLite handle (possibly async). */
|
|
5
5
|
export declare function wasmDriver(handle: unknown): Driver;
|
|
6
|
+
/** Adapt an `sqlite3.oo1.DB`-shaped database (a loaded sqlite3 module
|
|
7
|
+
* and one of its database objects) to the raw connection contract. */
|
|
8
|
+
export declare function adaptOo1Database(sqlite3: unknown, db: unknown): unknown;
|
|
9
|
+
/** Build the injected HANDLE for `wasmDriver` from a loaded sqlite3
|
|
10
|
+
* module: `DbClass` picks the database class (default `sqlite3.oo1.DB`;
|
|
11
|
+
* the SAH-pool util's `OpfsSAHPoolDb` for OPFS persistence). */
|
|
12
|
+
export declare function sqlite3Handle(sqlite3: unknown, options?: { DbClass?: unknown }): unknown;
|