@lunora/replica 1.0.0-alpha.2 → 1.0.0-alpha.4
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/README.md +2 -0
- package/dist/adapters/better-sqlite3.d.mts +2 -1
- package/dist/adapters/better-sqlite3.d.ts +2 -1
- package/dist/adapters/sqlite-wasm.d.mts +2 -1
- package/dist/adapters/sqlite-wasm.d.ts +2 -1
- package/dist/adapters/sqljs.d.mts +2 -1
- package/dist/adapters/sqljs.d.ts +2 -1
- package/dist/index.d.mts +49 -4
- package/dist/index.d.ts +49 -4
- package/dist/packem_shared/{local-mirror.d-GhuZAKgm.d.ts → local-mirror.d-BUeOe5KC.d.mts} +28 -1
- package/dist/packem_shared/{local-mirror.d-Bp19ueGy.d.mts → local-mirror.d-Cd8tAg-W.d.ts} +28 -1
- package/dist/packem_shared/{types.d-VfJ76cK4.d.mts → types.d-BuAWjEY5.d.mts} +1 -0
- package/dist/packem_shared/{types.d-VfJ76cK4.d.ts → types.d-BuAWjEY5.d.ts} +1 -0
- package/dist/react.d.mts +4 -2
- package/dist/react.d.ts +4 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SqliteAdapter } from "../packem_shared/types.d-
|
|
1
|
+
import { S as SqliteAdapter } from "../packem_shared/types.d-BuAWjEY5.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* Create a {@link SqliteAdapter} backed by [better-sqlite3](https://github.com/WiseLibs/better-sqlite3)
|
|
4
4
|
* (a synchronous SQLite3 binding for Node.js).
|
|
@@ -11,6 +11,7 @@ import { S as SqliteAdapter } from "../packem_shared/types.d-VfJ76cK4.mjs";
|
|
|
11
11
|
* @param database.exec Execute one or more SQL statements (no params, no results).
|
|
12
12
|
* @param database.prepare Prepare a SQL statement for repeated execution.
|
|
13
13
|
* @param database.transaction Wrap a function so its statements run in a transaction.
|
|
14
|
+
* @experimental
|
|
14
15
|
*/
|
|
15
16
|
declare const createBetterSqlite3Adapter: (database: {
|
|
16
17
|
close: () => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SqliteAdapter } from "../packem_shared/types.d-
|
|
1
|
+
import { S as SqliteAdapter } from "../packem_shared/types.d-BuAWjEY5.js";
|
|
2
2
|
/**
|
|
3
3
|
* Create a {@link SqliteAdapter} backed by [better-sqlite3](https://github.com/WiseLibs/better-sqlite3)
|
|
4
4
|
* (a synchronous SQLite3 binding for Node.js).
|
|
@@ -11,6 +11,7 @@ import { S as SqliteAdapter } from "../packem_shared/types.d-VfJ76cK4.js";
|
|
|
11
11
|
* @param database.exec Execute one or more SQL statements (no params, no results).
|
|
12
12
|
* @param database.prepare Prepare a SQL statement for repeated execution.
|
|
13
13
|
* @param database.transaction Wrap a function so its statements run in a transaction.
|
|
14
|
+
* @experimental
|
|
14
15
|
*/
|
|
15
16
|
declare const createBetterSqlite3Adapter: (database: {
|
|
16
17
|
close: () => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SqliteAdapter } from "../packem_shared/types.d-
|
|
1
|
+
import { S as SqliteAdapter } from "../packem_shared/types.d-BuAWjEY5.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* Create a {@link SqliteAdapter} backed by the [official SQLite Wasm](https://www.npmjs.com/package/@sqlite.org/sqlite-wasm)
|
|
4
4
|
* (a WebAssembly build of SQLite that runs in browsers and Node.js).
|
|
@@ -10,6 +10,7 @@ import { S as SqliteAdapter } from "../packem_shared/types.d-VfJ76cK4.mjs";
|
|
|
10
10
|
* @param database.close Tear down the database connection.
|
|
11
11
|
* @param database.exec Execute SQL with optional bind params and return rows
|
|
12
12
|
* as `{ columns, values }` result objects.
|
|
13
|
+
* @experimental
|
|
13
14
|
*/
|
|
14
15
|
declare const createSqliteWasmAdapter: (database: {
|
|
15
16
|
close: () => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SqliteAdapter } from "../packem_shared/types.d-
|
|
1
|
+
import { S as SqliteAdapter } from "../packem_shared/types.d-BuAWjEY5.js";
|
|
2
2
|
/**
|
|
3
3
|
* Create a {@link SqliteAdapter} backed by the [official SQLite Wasm](https://www.npmjs.com/package/@sqlite.org/sqlite-wasm)
|
|
4
4
|
* (a WebAssembly build of SQLite that runs in browsers and Node.js).
|
|
@@ -10,6 +10,7 @@ import { S as SqliteAdapter } from "../packem_shared/types.d-VfJ76cK4.js";
|
|
|
10
10
|
* @param database.close Tear down the database connection.
|
|
11
11
|
* @param database.exec Execute SQL with optional bind params and return rows
|
|
12
12
|
* as `{ columns, values }` result objects.
|
|
13
|
+
* @experimental
|
|
13
14
|
*/
|
|
14
15
|
declare const createSqliteWasmAdapter: (database: {
|
|
15
16
|
close: () => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SqliteAdapter } from "../packem_shared/types.d-
|
|
1
|
+
import { S as SqliteAdapter } from "../packem_shared/types.d-BuAWjEY5.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* Create a {@link SqliteAdapter} backed by [sql.js](https://sql.js.org)
|
|
4
4
|
* (a WebAssembly build of SQLite that runs in browsers, Node, and
|
|
@@ -7,6 +7,7 @@ import { S as SqliteAdapter } from "../packem_shared/types.d-VfJ76cK4.mjs";
|
|
|
7
7
|
* @param database.run Execute a parameterised SQL statement (no results).
|
|
8
8
|
* @param database.exec Execute SQL and return result rows.
|
|
9
9
|
* @param database.close Tear down the database connection.
|
|
10
|
+
* @experimental
|
|
10
11
|
*/
|
|
11
12
|
declare const createSqlJsAdapter: (database: {
|
|
12
13
|
close: () => void;
|
package/dist/adapters/sqljs.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SqliteAdapter } from "../packem_shared/types.d-
|
|
1
|
+
import { S as SqliteAdapter } from "../packem_shared/types.d-BuAWjEY5.js";
|
|
2
2
|
/**
|
|
3
3
|
* Create a {@link SqliteAdapter} backed by [sql.js](https://sql.js.org)
|
|
4
4
|
* (a WebAssembly build of SQLite that runs in browsers, Node, and
|
|
@@ -7,6 +7,7 @@ import { S as SqliteAdapter } from "../packem_shared/types.d-VfJ76cK4.js";
|
|
|
7
7
|
* @param database.run Execute a parameterised SQL statement (no results).
|
|
8
8
|
* @param database.exec Execute SQL and return result rows.
|
|
9
9
|
* @param database.close Tear down the database connection.
|
|
10
|
+
* @experimental
|
|
10
11
|
*/
|
|
11
12
|
declare const createSqlJsAdapter: (database: {
|
|
12
13
|
close: () => void;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { createBetterSqlite3Adapter } from "./adapters/better-sqlite3.mjs";
|
|
2
2
|
export { createSqliteWasmAdapter } from "./adapters/sqlite-wasm.mjs";
|
|
3
3
|
export { createSqlJsAdapter } from "./adapters/sqljs.mjs";
|
|
4
|
-
import { S as SqliteAdapter } from "./packem_shared/types.d-
|
|
5
|
-
import { T as TableDiff, I as InputEvent, S as Seq, E as EventLogEntry, a as EventLog, A as AppendOptions, L as LocalMirror } from "./packem_shared/local-mirror.d-
|
|
6
|
-
export { type C as ClientSeq, type b as EventLogSnapshot, type G as GlobalSeq, type c as LocalMirrorOptions, type M as MirrorTableDef, type R as RowChange, d as classifyChanges, e as createTableDiff, f as diffSize, i as isClientSeq, g as isDiffEmpty, h as isGlobalSeq, j as isInputEvent, m as mergeDiffs } from "./packem_shared/local-mirror.d-
|
|
4
|
+
import { S as SqliteAdapter } from "./packem_shared/types.d-BuAWjEY5.mjs";
|
|
5
|
+
import { T as TableDiff, I as InputEvent, S as Seq, E as EventLogEntry, a as EventLog, A as AppendOptions, L as LocalMirror } from "./packem_shared/local-mirror.d-BUeOe5KC.mjs";
|
|
6
|
+
export { type C as ClientSeq, type b as EventLogSnapshot, type G as GlobalSeq, type c as LocalMirrorOptions, type M as MirrorTableDef, type R as RowChange, d as classifyChanges, e as createTableDiff, f as diffSize, i as isClientSeq, g as isDiffEmpty, h as isGlobalSeq, j as isInputEvent, m as mergeDiffs } from "./packem_shared/local-mirror.d-BUeOe5KC.mjs";
|
|
7
7
|
/**
|
|
8
8
|
* Apply a single {@link TableDiff} to an in-memory row map and return
|
|
9
9
|
* the updated map.
|
|
@@ -24,6 +24,7 @@ export { type C as ClientSeq, type b as EventLogSnapshot, type G as GlobalSeq, t
|
|
|
24
24
|
* updated.get("id-1")?.name // "alice-updated"
|
|
25
25
|
* updated.get("id-2")?.name // "bob"
|
|
26
26
|
* ```
|
|
27
|
+
* @experimental
|
|
27
28
|
*/
|
|
28
29
|
declare const applyDiff: (current: ReadonlyMap<string, Record<string, unknown>>, diff: TableDiff) => Map<string, Record<string, unknown>>;
|
|
29
30
|
/**
|
|
@@ -31,6 +32,7 @@ declare const applyDiff: (current: ReadonlyMap<string, Record<string, unknown>>,
|
|
|
31
32
|
*
|
|
32
33
|
* This is equivalent to calling {@link applyDiff} repeatedly but avoids
|
|
33
34
|
* intermediate map copies.
|
|
35
|
+
* @experimental
|
|
34
36
|
*/
|
|
35
37
|
declare const applyDiffs: (current: ReadonlyMap<string, Record<string, unknown>>, diffs: ReadonlyArray<TableDiff>) => Map<string, Record<string, unknown>>;
|
|
36
38
|
/**
|
|
@@ -39,6 +41,7 @@ declare const applyDiffs: (current: ReadonlyMap<string, Record<string, unknown>>
|
|
|
39
41
|
* @param snapshot Current snapshot, e.g. `{ users: Map<id, row>, posts: Map<id, row> }`.
|
|
40
42
|
* @param diff Contains the target table name and the row-level changes to merge.
|
|
41
43
|
* @returns A shallow copy of `snapshot` with `diff.table`'s map updated.
|
|
44
|
+
* @experimental
|
|
42
45
|
*/
|
|
43
46
|
declare const applyDiffToSnapshot: (snapshot: ReadonlyMap<string, ReadonlyMap<string, Record<string, unknown>>>, diff: TableDiff) => Map<string, Map<string, Record<string, unknown>>>;
|
|
44
47
|
/** Map a namespace-and-name pair to a qualified event type string. */
|
|
@@ -66,6 +69,7 @@ type EventTypeMap<TDefinition extends Record<string, Record<string, unknown>>> =
|
|
|
66
69
|
*
|
|
67
70
|
* The returned event has no `seq` — it is an optimistic / command payload
|
|
68
71
|
* that the event log will assign a sequence number to on append.
|
|
72
|
+
* @experimental
|
|
69
73
|
*/
|
|
70
74
|
interface EventFactory<Type extends string, Payload> {
|
|
71
75
|
(payload: Payload): InputEvent<Type, Payload>;
|
|
@@ -74,10 +78,12 @@ interface EventFactory<Type extends string, Payload> {
|
|
|
74
78
|
}
|
|
75
79
|
/**
|
|
76
80
|
* The namespace object returned for each group of events.
|
|
81
|
+
* @experimental
|
|
77
82
|
*/
|
|
78
83
|
type EventNamespace<Ns extends string, TDefinition extends Record<string, unknown>> = { [Name in keyof TDefinition & string]: EventFactory<QualifiedType<Ns, Name>, PayloadOf<TDefinition[Name]>> };
|
|
79
84
|
/**
|
|
80
85
|
* The full result of {@link defineEvents}.
|
|
86
|
+
* @experimental
|
|
81
87
|
*/
|
|
82
88
|
type EventsDefinition<TDefinition extends Record<string, Record<string, unknown>>> = { [Ns in keyof TDefinition & string]: EventNamespace<Ns, TDefinition[Ns]> } & {
|
|
83
89
|
/** Type-level map of event type → payload shape. Useful for generic code. */
|
|
@@ -107,12 +113,17 @@ interface DefineEventsOptions {
|
|
|
107
113
|
*/
|
|
108
114
|
readonly version?: string;
|
|
109
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* `defineEvents` is part of the experimental `@lunora/replica` API and may change without a major version bump.
|
|
118
|
+
* @experimental
|
|
119
|
+
*/
|
|
110
120
|
declare const defineEvents: <TDefinition extends Record<string, Record<string, unknown>>>(definition: TDefinition, options?: DefineEventsOptions) => EventsDefinition<TDefinition>;
|
|
111
121
|
/**
|
|
112
122
|
* Shape of the `events[]` items sent in a POST `/append` body.
|
|
113
123
|
*
|
|
114
124
|
* Like {@link InputEvent} but with `timestamp` optional — omit it to
|
|
115
125
|
* let the server assign the timestamp.
|
|
126
|
+
* @experimental
|
|
116
127
|
*/
|
|
117
128
|
interface AppendEventInput {
|
|
118
129
|
/** Globally-unique client identifier (for offline/optimistic support). */
|
|
@@ -128,7 +139,10 @@ interface AppendEventInput {
|
|
|
128
139
|
/** Event type discriminator. */
|
|
129
140
|
readonly type: string;
|
|
130
141
|
}
|
|
131
|
-
/**
|
|
142
|
+
/**
|
|
143
|
+
* Options for constructing an {@link EventLogDOClient}.
|
|
144
|
+
* @experimental
|
|
145
|
+
*/
|
|
132
146
|
interface EventLogDOClientOptions {
|
|
133
147
|
/**
|
|
134
148
|
* A function that dispatches an HTTP request to the target EventLogDO
|
|
@@ -145,6 +159,7 @@ interface EventLogDOClientOptions {
|
|
|
145
159
|
*
|
|
146
160
|
* Each method maps to one of the DO's endpoints, throws on non-OK status,
|
|
147
161
|
* and returns the parsed response body.
|
|
162
|
+
* @experimental
|
|
148
163
|
*/
|
|
149
164
|
declare class EventLogDOClient {
|
|
150
165
|
#private;
|
|
@@ -191,6 +206,7 @@ declare class EventLogDOClient {
|
|
|
191
206
|
* emitter.on("userCreated", (payload) => console.log(payload.name));
|
|
192
207
|
* emitter.emit("userCreated", { id: "1", name: "alice" });
|
|
193
208
|
* ```
|
|
209
|
+
* @experimental
|
|
194
210
|
*/
|
|
195
211
|
declare class EventEmitter<EventMap extends Record<string, unknown>> {
|
|
196
212
|
#private;
|
|
@@ -240,6 +256,7 @@ declare class EventEmitter<EventMap extends Record<string, unknown>> {
|
|
|
240
256
|
* - `"fail"` — throw an error, halting the apply / replay cycle.
|
|
241
257
|
* - A **callback** — invoked with the entry; return truthy to mark it as
|
|
242
258
|
* handled (no warning), falsy to fall through to the configured fallback.
|
|
259
|
+
* @experimental
|
|
243
260
|
*/
|
|
244
261
|
type UnknownEventHandling = "warn" | "ignore" | "fail" | ((entry: EventLogEntry) => boolean);
|
|
245
262
|
/**
|
|
@@ -248,6 +265,7 @@ type UnknownEventHandling = "warn" | "ignore" | "fail" | ((entry: EventLogEntry)
|
|
|
248
265
|
* A `type` (not `interface`) so it satisfies `EventEmitter`'s
|
|
249
266
|
* `Record<string, unknown>` constraint — interfaces have no implicit index
|
|
250
267
|
* signature and aren't assignable to `Record<string, unknown>`.
|
|
268
|
+
* @experimental
|
|
251
269
|
*/
|
|
252
270
|
type EventSourceEvents = {
|
|
253
271
|
/** Fired (once) after the initial replay completes. */
|
|
@@ -270,10 +288,12 @@ type EventSourceEvents = {
|
|
|
270
288
|
*
|
|
271
289
|
* Pure functions are strongly encouraged: given the same event payload
|
|
272
290
|
* and state, they must produce the same next state.
|
|
291
|
+
* @experimental
|
|
273
292
|
*/
|
|
274
293
|
type EventReducer<S> = (state: S, entry: EventLogEntry) => S;
|
|
275
294
|
/**
|
|
276
295
|
* Options for constructing an {@link EventSource}.
|
|
296
|
+
* @experimental
|
|
277
297
|
*/
|
|
278
298
|
interface EventSourceOptions {
|
|
279
299
|
/**
|
|
@@ -295,6 +315,7 @@ interface EventSourceOptions {
|
|
|
295
315
|
* const entry = source.applyEvent("user-created", { id: "1", name: "alice" });
|
|
296
316
|
* console.log(source.state); // updated state
|
|
297
317
|
* ```
|
|
318
|
+
* @experimental
|
|
298
319
|
*/
|
|
299
320
|
declare class EventSource<S extends Record<string, unknown> = Record<string, unknown>> {
|
|
300
321
|
#private;
|
|
@@ -366,6 +387,7 @@ declare class EventSource<S extends Record<string, unknown> = Record<string, unk
|
|
|
366
387
|
* the {@link InMemorySnapshotStore} is used for the offline-first
|
|
367
388
|
* local mirror, while a production client would implement this
|
|
368
389
|
* over IndexedDB or OPFS.
|
|
390
|
+
* @experimental
|
|
369
391
|
*/
|
|
370
392
|
interface SnapshotStore {
|
|
371
393
|
/** Delete all snapshots. */
|
|
@@ -383,6 +405,7 @@ interface SnapshotStore {
|
|
|
383
405
|
* In-memory snapshot store. Useful for testing and for the local
|
|
384
406
|
* offline-first mirror where persistence is handled at a higher
|
|
385
407
|
* layer (IndexedDB adapter).
|
|
408
|
+
* @experimental
|
|
386
409
|
*/
|
|
387
410
|
declare class InMemorySnapshotStore implements SnapshotStore {
|
|
388
411
|
#private;
|
|
@@ -397,10 +420,12 @@ declare class InMemorySnapshotStore implements SnapshotStore {
|
|
|
397
420
|
*
|
|
398
421
|
* Pure functions are strongly encouraged: given the same event and state,
|
|
399
422
|
* they must produce the same next state for deterministic replay.
|
|
423
|
+
* @experimental
|
|
400
424
|
*/
|
|
401
425
|
type MaterializerReducer<S> = (state: S, entry: EventLogEntry) => S;
|
|
402
426
|
/**
|
|
403
427
|
* Options for defining a single materializer.
|
|
428
|
+
* @experimental
|
|
404
429
|
*/
|
|
405
430
|
interface MaterializerDef<S> {
|
|
406
431
|
/**
|
|
@@ -416,6 +441,7 @@ interface MaterializerDef<S> {
|
|
|
416
441
|
}
|
|
417
442
|
/**
|
|
418
443
|
* A constructed materializer ready to be used with a {@link MaterializerRuntime}.
|
|
444
|
+
* @experimental
|
|
419
445
|
*/
|
|
420
446
|
interface Materializer<S> {
|
|
421
447
|
/** Apply a single event entry through the reducer. */
|
|
@@ -433,6 +459,7 @@ interface Materializer<S> {
|
|
|
433
459
|
*
|
|
434
460
|
* The returned {@link Materializer} object can be used standalone or passed
|
|
435
461
|
* to a {@link MaterializerRuntime} for automatic log subscription.
|
|
462
|
+
* @experimental
|
|
436
463
|
*/
|
|
437
464
|
declare const defineMaterializer: <S>(definition: MaterializerDef<S>) => Materializer<S>;
|
|
438
465
|
/**
|
|
@@ -446,6 +473,7 @@ declare const defineMaterializer: <S>(definition: MaterializerDef<S>) => Materia
|
|
|
446
473
|
type AnyMaterializer = Materializer<any>;
|
|
447
474
|
/**
|
|
448
475
|
* Options for constructing a {@link MaterializerRuntime}.
|
|
476
|
+
* @experimental
|
|
449
477
|
*/
|
|
450
478
|
interface MaterializerRuntimeOptions {
|
|
451
479
|
/**
|
|
@@ -472,6 +500,7 @@ interface MaterializerRuntimeOptions {
|
|
|
472
500
|
* - Applying new events as they arrive
|
|
473
501
|
* - Periodic snapshot persistence
|
|
474
502
|
* - Recovery from snapshots (replay only what's missing)
|
|
503
|
+
* @experimental
|
|
475
504
|
*/
|
|
476
505
|
declare class MaterializerRuntime {
|
|
477
506
|
#private;
|
|
@@ -539,6 +568,7 @@ declare class MaterializerRuntime {
|
|
|
539
568
|
* @param database SQLite adapter the statements run against.
|
|
540
569
|
* @param diff The table diff to apply.
|
|
541
570
|
* @param pkColumn Primary key column for DELETE/UPDATE (default `"id"`).
|
|
571
|
+
* @experimental
|
|
542
572
|
*/
|
|
543
573
|
declare const applyDiffToDatabase: (database: SqliteAdapter, diff: TableDiff, pkColumn?: string) => void;
|
|
544
574
|
/**
|
|
@@ -546,6 +576,7 @@ declare const applyDiffToDatabase: (database: SqliteAdapter, diff: TableDiff, pk
|
|
|
546
576
|
*
|
|
547
577
|
* Each diff uses `"id"` as the primary key column. For tables with a custom
|
|
548
578
|
* PK, use {@link applyDiffToDatabase} per-diff and pass the PK explicitly.
|
|
579
|
+
* @experimental
|
|
549
580
|
*/
|
|
550
581
|
declare const applyDiffsToDatabase: (database: SqliteAdapter, diffs: ReadonlyArray<TableDiff>) => void;
|
|
551
582
|
interface EventLogDOState {
|
|
@@ -555,6 +586,10 @@ interface EventLogDOState {
|
|
|
555
586
|
};
|
|
556
587
|
};
|
|
557
588
|
}
|
|
589
|
+
/**
|
|
590
|
+
* `EventLogDO` is part of the experimental `@lunora/replica` API and may change without a major version bump.
|
|
591
|
+
* @experimental
|
|
592
|
+
*/
|
|
558
593
|
declare class EventLogDO {
|
|
559
594
|
#private;
|
|
560
595
|
protected state: EventLogDOState;
|
|
@@ -588,6 +623,7 @@ type Middleware<ContextIn, ContextOut> = (options: {
|
|
|
588
623
|
*
|
|
589
624
|
* Each method delegates to the corresponding {@link EventLogDOClient} method,
|
|
590
625
|
* so handlers never need to import or reference the DO client directly.
|
|
626
|
+
* @experimental
|
|
591
627
|
*/
|
|
592
628
|
interface EventsFacade {
|
|
593
629
|
/**
|
|
@@ -624,6 +660,7 @@ interface EventsFacade {
|
|
|
624
660
|
}
|
|
625
661
|
/**
|
|
626
662
|
* The context shape produced by {@link eventsContext}.
|
|
663
|
+
* @experimental
|
|
627
664
|
*/
|
|
628
665
|
interface EventsContextOutput {
|
|
629
666
|
/** Typed event log facade backed by an {@link EventLogDOClient}. */
|
|
@@ -654,12 +691,14 @@ interface EventsContextOutput {
|
|
|
654
691
|
* return entry;
|
|
655
692
|
* });
|
|
656
693
|
* ```
|
|
694
|
+
* @experimental
|
|
657
695
|
*/
|
|
658
696
|
declare const eventsContext: <Context>(client: EventLogDOClient) => Middleware<Context, Context & EventsContextOutput>;
|
|
659
697
|
/**
|
|
660
698
|
* A dependency-light subscription sink interface that mirrors what
|
|
661
699
|
* `LunoraClient.subscribe` expects, so the mirror helper doesn't
|
|
662
700
|
* need to import `@lunora/client`.
|
|
701
|
+
* @experimental
|
|
663
702
|
*/
|
|
664
703
|
interface SubscriptionClient {
|
|
665
704
|
subscribe: (functionRef: {
|
|
@@ -693,16 +732,19 @@ interface SubscriptionClient {
|
|
|
693
732
|
* // Later:
|
|
694
733
|
* unsub();
|
|
695
734
|
* ```
|
|
735
|
+
* @experimental
|
|
696
736
|
*/
|
|
697
737
|
declare const subscribeToMirror: (client: SubscriptionClient, mirror: LocalMirror, functionRef: {
|
|
698
738
|
__lunoraRef: string;
|
|
699
739
|
}, args: Record<string, unknown>, shardKey?: string) => (() => void);
|
|
700
740
|
/**
|
|
701
741
|
* Callback signature for state-change subscriptions.
|
|
742
|
+
* @experimental
|
|
702
743
|
*/
|
|
703
744
|
type StateChangeCallback = (state: Readonly<Record<string, unknown>>) => void;
|
|
704
745
|
/**
|
|
705
746
|
* Callback signature for event-type subscriptions.
|
|
747
|
+
* @experimental
|
|
706
748
|
*/
|
|
707
749
|
type EventCallback = (entry: EventLogEntry) => void;
|
|
708
750
|
/**
|
|
@@ -730,6 +772,7 @@ type EventCallback = (entry: EventLogEntry) => void;
|
|
|
730
772
|
* unsub1();
|
|
731
773
|
* unsub2();
|
|
732
774
|
* ```
|
|
775
|
+
* @experimental
|
|
733
776
|
*/
|
|
734
777
|
declare class SubscriptionManager {
|
|
735
778
|
#private;
|
|
@@ -764,6 +807,7 @@ declare class SubscriptionManager {
|
|
|
764
807
|
}
|
|
765
808
|
/**
|
|
766
809
|
* Options for constructing an {@link EventsSync}.
|
|
810
|
+
* @experimental
|
|
767
811
|
*/
|
|
768
812
|
interface EventsSyncOptions {
|
|
769
813
|
/**
|
|
@@ -830,6 +874,7 @@ interface EventsSyncOptions {
|
|
|
830
874
|
*
|
|
831
875
|
* The current watermark is exposed via `watermark` and advances
|
|
832
876
|
* monotonically as events are applied.
|
|
877
|
+
* @experimental
|
|
833
878
|
*/
|
|
834
879
|
declare class EventsSync {
|
|
835
880
|
#private;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { createBetterSqlite3Adapter } from "./adapters/better-sqlite3.js";
|
|
2
2
|
export { createSqliteWasmAdapter } from "./adapters/sqlite-wasm.js";
|
|
3
3
|
export { createSqlJsAdapter } from "./adapters/sqljs.js";
|
|
4
|
-
import { S as SqliteAdapter } from "./packem_shared/types.d-
|
|
5
|
-
import { T as TableDiff, I as InputEvent, S as Seq, E as EventLogEntry, a as EventLog, A as AppendOptions, L as LocalMirror } from "./packem_shared/local-mirror.d-
|
|
6
|
-
export { type C as ClientSeq, type b as EventLogSnapshot, type G as GlobalSeq, type c as LocalMirrorOptions, type M as MirrorTableDef, type R as RowChange, d as classifyChanges, e as createTableDiff, f as diffSize, i as isClientSeq, g as isDiffEmpty, h as isGlobalSeq, j as isInputEvent, m as mergeDiffs } from "./packem_shared/local-mirror.d-
|
|
4
|
+
import { S as SqliteAdapter } from "./packem_shared/types.d-BuAWjEY5.js";
|
|
5
|
+
import { T as TableDiff, I as InputEvent, S as Seq, E as EventLogEntry, a as EventLog, A as AppendOptions, L as LocalMirror } from "./packem_shared/local-mirror.d-Cd8tAg-W.js";
|
|
6
|
+
export { type C as ClientSeq, type b as EventLogSnapshot, type G as GlobalSeq, type c as LocalMirrorOptions, type M as MirrorTableDef, type R as RowChange, d as classifyChanges, e as createTableDiff, f as diffSize, i as isClientSeq, g as isDiffEmpty, h as isGlobalSeq, j as isInputEvent, m as mergeDiffs } from "./packem_shared/local-mirror.d-Cd8tAg-W.js";
|
|
7
7
|
/**
|
|
8
8
|
* Apply a single {@link TableDiff} to an in-memory row map and return
|
|
9
9
|
* the updated map.
|
|
@@ -24,6 +24,7 @@ export { type C as ClientSeq, type b as EventLogSnapshot, type G as GlobalSeq, t
|
|
|
24
24
|
* updated.get("id-1")?.name // "alice-updated"
|
|
25
25
|
* updated.get("id-2")?.name // "bob"
|
|
26
26
|
* ```
|
|
27
|
+
* @experimental
|
|
27
28
|
*/
|
|
28
29
|
declare const applyDiff: (current: ReadonlyMap<string, Record<string, unknown>>, diff: TableDiff) => Map<string, Record<string, unknown>>;
|
|
29
30
|
/**
|
|
@@ -31,6 +32,7 @@ declare const applyDiff: (current: ReadonlyMap<string, Record<string, unknown>>,
|
|
|
31
32
|
*
|
|
32
33
|
* This is equivalent to calling {@link applyDiff} repeatedly but avoids
|
|
33
34
|
* intermediate map copies.
|
|
35
|
+
* @experimental
|
|
34
36
|
*/
|
|
35
37
|
declare const applyDiffs: (current: ReadonlyMap<string, Record<string, unknown>>, diffs: ReadonlyArray<TableDiff>) => Map<string, Record<string, unknown>>;
|
|
36
38
|
/**
|
|
@@ -39,6 +41,7 @@ declare const applyDiffs: (current: ReadonlyMap<string, Record<string, unknown>>
|
|
|
39
41
|
* @param snapshot Current snapshot, e.g. `{ users: Map<id, row>, posts: Map<id, row> }`.
|
|
40
42
|
* @param diff Contains the target table name and the row-level changes to merge.
|
|
41
43
|
* @returns A shallow copy of `snapshot` with `diff.table`'s map updated.
|
|
44
|
+
* @experimental
|
|
42
45
|
*/
|
|
43
46
|
declare const applyDiffToSnapshot: (snapshot: ReadonlyMap<string, ReadonlyMap<string, Record<string, unknown>>>, diff: TableDiff) => Map<string, Map<string, Record<string, unknown>>>;
|
|
44
47
|
/** Map a namespace-and-name pair to a qualified event type string. */
|
|
@@ -66,6 +69,7 @@ type EventTypeMap<TDefinition extends Record<string, Record<string, unknown>>> =
|
|
|
66
69
|
*
|
|
67
70
|
* The returned event has no `seq` — it is an optimistic / command payload
|
|
68
71
|
* that the event log will assign a sequence number to on append.
|
|
72
|
+
* @experimental
|
|
69
73
|
*/
|
|
70
74
|
interface EventFactory<Type extends string, Payload> {
|
|
71
75
|
(payload: Payload): InputEvent<Type, Payload>;
|
|
@@ -74,10 +78,12 @@ interface EventFactory<Type extends string, Payload> {
|
|
|
74
78
|
}
|
|
75
79
|
/**
|
|
76
80
|
* The namespace object returned for each group of events.
|
|
81
|
+
* @experimental
|
|
77
82
|
*/
|
|
78
83
|
type EventNamespace<Ns extends string, TDefinition extends Record<string, unknown>> = { [Name in keyof TDefinition & string]: EventFactory<QualifiedType<Ns, Name>, PayloadOf<TDefinition[Name]>> };
|
|
79
84
|
/**
|
|
80
85
|
* The full result of {@link defineEvents}.
|
|
86
|
+
* @experimental
|
|
81
87
|
*/
|
|
82
88
|
type EventsDefinition<TDefinition extends Record<string, Record<string, unknown>>> = { [Ns in keyof TDefinition & string]: EventNamespace<Ns, TDefinition[Ns]> } & {
|
|
83
89
|
/** Type-level map of event type → payload shape. Useful for generic code. */
|
|
@@ -107,12 +113,17 @@ interface DefineEventsOptions {
|
|
|
107
113
|
*/
|
|
108
114
|
readonly version?: string;
|
|
109
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* `defineEvents` is part of the experimental `@lunora/replica` API and may change without a major version bump.
|
|
118
|
+
* @experimental
|
|
119
|
+
*/
|
|
110
120
|
declare const defineEvents: <TDefinition extends Record<string, Record<string, unknown>>>(definition: TDefinition, options?: DefineEventsOptions) => EventsDefinition<TDefinition>;
|
|
111
121
|
/**
|
|
112
122
|
* Shape of the `events[]` items sent in a POST `/append` body.
|
|
113
123
|
*
|
|
114
124
|
* Like {@link InputEvent} but with `timestamp` optional — omit it to
|
|
115
125
|
* let the server assign the timestamp.
|
|
126
|
+
* @experimental
|
|
116
127
|
*/
|
|
117
128
|
interface AppendEventInput {
|
|
118
129
|
/** Globally-unique client identifier (for offline/optimistic support). */
|
|
@@ -128,7 +139,10 @@ interface AppendEventInput {
|
|
|
128
139
|
/** Event type discriminator. */
|
|
129
140
|
readonly type: string;
|
|
130
141
|
}
|
|
131
|
-
/**
|
|
142
|
+
/**
|
|
143
|
+
* Options for constructing an {@link EventLogDOClient}.
|
|
144
|
+
* @experimental
|
|
145
|
+
*/
|
|
132
146
|
interface EventLogDOClientOptions {
|
|
133
147
|
/**
|
|
134
148
|
* A function that dispatches an HTTP request to the target EventLogDO
|
|
@@ -145,6 +159,7 @@ interface EventLogDOClientOptions {
|
|
|
145
159
|
*
|
|
146
160
|
* Each method maps to one of the DO's endpoints, throws on non-OK status,
|
|
147
161
|
* and returns the parsed response body.
|
|
162
|
+
* @experimental
|
|
148
163
|
*/
|
|
149
164
|
declare class EventLogDOClient {
|
|
150
165
|
#private;
|
|
@@ -191,6 +206,7 @@ declare class EventLogDOClient {
|
|
|
191
206
|
* emitter.on("userCreated", (payload) => console.log(payload.name));
|
|
192
207
|
* emitter.emit("userCreated", { id: "1", name: "alice" });
|
|
193
208
|
* ```
|
|
209
|
+
* @experimental
|
|
194
210
|
*/
|
|
195
211
|
declare class EventEmitter<EventMap extends Record<string, unknown>> {
|
|
196
212
|
#private;
|
|
@@ -240,6 +256,7 @@ declare class EventEmitter<EventMap extends Record<string, unknown>> {
|
|
|
240
256
|
* - `"fail"` — throw an error, halting the apply / replay cycle.
|
|
241
257
|
* - A **callback** — invoked with the entry; return truthy to mark it as
|
|
242
258
|
* handled (no warning), falsy to fall through to the configured fallback.
|
|
259
|
+
* @experimental
|
|
243
260
|
*/
|
|
244
261
|
type UnknownEventHandling = "warn" | "ignore" | "fail" | ((entry: EventLogEntry) => boolean);
|
|
245
262
|
/**
|
|
@@ -248,6 +265,7 @@ type UnknownEventHandling = "warn" | "ignore" | "fail" | ((entry: EventLogEntry)
|
|
|
248
265
|
* A `type` (not `interface`) so it satisfies `EventEmitter`'s
|
|
249
266
|
* `Record<string, unknown>` constraint — interfaces have no implicit index
|
|
250
267
|
* signature and aren't assignable to `Record<string, unknown>`.
|
|
268
|
+
* @experimental
|
|
251
269
|
*/
|
|
252
270
|
type EventSourceEvents = {
|
|
253
271
|
/** Fired (once) after the initial replay completes. */
|
|
@@ -270,10 +288,12 @@ type EventSourceEvents = {
|
|
|
270
288
|
*
|
|
271
289
|
* Pure functions are strongly encouraged: given the same event payload
|
|
272
290
|
* and state, they must produce the same next state.
|
|
291
|
+
* @experimental
|
|
273
292
|
*/
|
|
274
293
|
type EventReducer<S> = (state: S, entry: EventLogEntry) => S;
|
|
275
294
|
/**
|
|
276
295
|
* Options for constructing an {@link EventSource}.
|
|
296
|
+
* @experimental
|
|
277
297
|
*/
|
|
278
298
|
interface EventSourceOptions {
|
|
279
299
|
/**
|
|
@@ -295,6 +315,7 @@ interface EventSourceOptions {
|
|
|
295
315
|
* const entry = source.applyEvent("user-created", { id: "1", name: "alice" });
|
|
296
316
|
* console.log(source.state); // updated state
|
|
297
317
|
* ```
|
|
318
|
+
* @experimental
|
|
298
319
|
*/
|
|
299
320
|
declare class EventSource<S extends Record<string, unknown> = Record<string, unknown>> {
|
|
300
321
|
#private;
|
|
@@ -366,6 +387,7 @@ declare class EventSource<S extends Record<string, unknown> = Record<string, unk
|
|
|
366
387
|
* the {@link InMemorySnapshotStore} is used for the offline-first
|
|
367
388
|
* local mirror, while a production client would implement this
|
|
368
389
|
* over IndexedDB or OPFS.
|
|
390
|
+
* @experimental
|
|
369
391
|
*/
|
|
370
392
|
interface SnapshotStore {
|
|
371
393
|
/** Delete all snapshots. */
|
|
@@ -383,6 +405,7 @@ interface SnapshotStore {
|
|
|
383
405
|
* In-memory snapshot store. Useful for testing and for the local
|
|
384
406
|
* offline-first mirror where persistence is handled at a higher
|
|
385
407
|
* layer (IndexedDB adapter).
|
|
408
|
+
* @experimental
|
|
386
409
|
*/
|
|
387
410
|
declare class InMemorySnapshotStore implements SnapshotStore {
|
|
388
411
|
#private;
|
|
@@ -397,10 +420,12 @@ declare class InMemorySnapshotStore implements SnapshotStore {
|
|
|
397
420
|
*
|
|
398
421
|
* Pure functions are strongly encouraged: given the same event and state,
|
|
399
422
|
* they must produce the same next state for deterministic replay.
|
|
423
|
+
* @experimental
|
|
400
424
|
*/
|
|
401
425
|
type MaterializerReducer<S> = (state: S, entry: EventLogEntry) => S;
|
|
402
426
|
/**
|
|
403
427
|
* Options for defining a single materializer.
|
|
428
|
+
* @experimental
|
|
404
429
|
*/
|
|
405
430
|
interface MaterializerDef<S> {
|
|
406
431
|
/**
|
|
@@ -416,6 +441,7 @@ interface MaterializerDef<S> {
|
|
|
416
441
|
}
|
|
417
442
|
/**
|
|
418
443
|
* A constructed materializer ready to be used with a {@link MaterializerRuntime}.
|
|
444
|
+
* @experimental
|
|
419
445
|
*/
|
|
420
446
|
interface Materializer<S> {
|
|
421
447
|
/** Apply a single event entry through the reducer. */
|
|
@@ -433,6 +459,7 @@ interface Materializer<S> {
|
|
|
433
459
|
*
|
|
434
460
|
* The returned {@link Materializer} object can be used standalone or passed
|
|
435
461
|
* to a {@link MaterializerRuntime} for automatic log subscription.
|
|
462
|
+
* @experimental
|
|
436
463
|
*/
|
|
437
464
|
declare const defineMaterializer: <S>(definition: MaterializerDef<S>) => Materializer<S>;
|
|
438
465
|
/**
|
|
@@ -446,6 +473,7 @@ declare const defineMaterializer: <S>(definition: MaterializerDef<S>) => Materia
|
|
|
446
473
|
type AnyMaterializer = Materializer<any>;
|
|
447
474
|
/**
|
|
448
475
|
* Options for constructing a {@link MaterializerRuntime}.
|
|
476
|
+
* @experimental
|
|
449
477
|
*/
|
|
450
478
|
interface MaterializerRuntimeOptions {
|
|
451
479
|
/**
|
|
@@ -472,6 +500,7 @@ interface MaterializerRuntimeOptions {
|
|
|
472
500
|
* - Applying new events as they arrive
|
|
473
501
|
* - Periodic snapshot persistence
|
|
474
502
|
* - Recovery from snapshots (replay only what's missing)
|
|
503
|
+
* @experimental
|
|
475
504
|
*/
|
|
476
505
|
declare class MaterializerRuntime {
|
|
477
506
|
#private;
|
|
@@ -539,6 +568,7 @@ declare class MaterializerRuntime {
|
|
|
539
568
|
* @param database SQLite adapter the statements run against.
|
|
540
569
|
* @param diff The table diff to apply.
|
|
541
570
|
* @param pkColumn Primary key column for DELETE/UPDATE (default `"id"`).
|
|
571
|
+
* @experimental
|
|
542
572
|
*/
|
|
543
573
|
declare const applyDiffToDatabase: (database: SqliteAdapter, diff: TableDiff, pkColumn?: string) => void;
|
|
544
574
|
/**
|
|
@@ -546,6 +576,7 @@ declare const applyDiffToDatabase: (database: SqliteAdapter, diff: TableDiff, pk
|
|
|
546
576
|
*
|
|
547
577
|
* Each diff uses `"id"` as the primary key column. For tables with a custom
|
|
548
578
|
* PK, use {@link applyDiffToDatabase} per-diff and pass the PK explicitly.
|
|
579
|
+
* @experimental
|
|
549
580
|
*/
|
|
550
581
|
declare const applyDiffsToDatabase: (database: SqliteAdapter, diffs: ReadonlyArray<TableDiff>) => void;
|
|
551
582
|
interface EventLogDOState {
|
|
@@ -555,6 +586,10 @@ interface EventLogDOState {
|
|
|
555
586
|
};
|
|
556
587
|
};
|
|
557
588
|
}
|
|
589
|
+
/**
|
|
590
|
+
* `EventLogDO` is part of the experimental `@lunora/replica` API and may change without a major version bump.
|
|
591
|
+
* @experimental
|
|
592
|
+
*/
|
|
558
593
|
declare class EventLogDO {
|
|
559
594
|
#private;
|
|
560
595
|
protected state: EventLogDOState;
|
|
@@ -588,6 +623,7 @@ type Middleware<ContextIn, ContextOut> = (options: {
|
|
|
588
623
|
*
|
|
589
624
|
* Each method delegates to the corresponding {@link EventLogDOClient} method,
|
|
590
625
|
* so handlers never need to import or reference the DO client directly.
|
|
626
|
+
* @experimental
|
|
591
627
|
*/
|
|
592
628
|
interface EventsFacade {
|
|
593
629
|
/**
|
|
@@ -624,6 +660,7 @@ interface EventsFacade {
|
|
|
624
660
|
}
|
|
625
661
|
/**
|
|
626
662
|
* The context shape produced by {@link eventsContext}.
|
|
663
|
+
* @experimental
|
|
627
664
|
*/
|
|
628
665
|
interface EventsContextOutput {
|
|
629
666
|
/** Typed event log facade backed by an {@link EventLogDOClient}. */
|
|
@@ -654,12 +691,14 @@ interface EventsContextOutput {
|
|
|
654
691
|
* return entry;
|
|
655
692
|
* });
|
|
656
693
|
* ```
|
|
694
|
+
* @experimental
|
|
657
695
|
*/
|
|
658
696
|
declare const eventsContext: <Context>(client: EventLogDOClient) => Middleware<Context, Context & EventsContextOutput>;
|
|
659
697
|
/**
|
|
660
698
|
* A dependency-light subscription sink interface that mirrors what
|
|
661
699
|
* `LunoraClient.subscribe` expects, so the mirror helper doesn't
|
|
662
700
|
* need to import `@lunora/client`.
|
|
701
|
+
* @experimental
|
|
663
702
|
*/
|
|
664
703
|
interface SubscriptionClient {
|
|
665
704
|
subscribe: (functionRef: {
|
|
@@ -693,16 +732,19 @@ interface SubscriptionClient {
|
|
|
693
732
|
* // Later:
|
|
694
733
|
* unsub();
|
|
695
734
|
* ```
|
|
735
|
+
* @experimental
|
|
696
736
|
*/
|
|
697
737
|
declare const subscribeToMirror: (client: SubscriptionClient, mirror: LocalMirror, functionRef: {
|
|
698
738
|
__lunoraRef: string;
|
|
699
739
|
}, args: Record<string, unknown>, shardKey?: string) => (() => void);
|
|
700
740
|
/**
|
|
701
741
|
* Callback signature for state-change subscriptions.
|
|
742
|
+
* @experimental
|
|
702
743
|
*/
|
|
703
744
|
type StateChangeCallback = (state: Readonly<Record<string, unknown>>) => void;
|
|
704
745
|
/**
|
|
705
746
|
* Callback signature for event-type subscriptions.
|
|
747
|
+
* @experimental
|
|
706
748
|
*/
|
|
707
749
|
type EventCallback = (entry: EventLogEntry) => void;
|
|
708
750
|
/**
|
|
@@ -730,6 +772,7 @@ type EventCallback = (entry: EventLogEntry) => void;
|
|
|
730
772
|
* unsub1();
|
|
731
773
|
* unsub2();
|
|
732
774
|
* ```
|
|
775
|
+
* @experimental
|
|
733
776
|
*/
|
|
734
777
|
declare class SubscriptionManager {
|
|
735
778
|
#private;
|
|
@@ -764,6 +807,7 @@ declare class SubscriptionManager {
|
|
|
764
807
|
}
|
|
765
808
|
/**
|
|
766
809
|
* Options for constructing an {@link EventsSync}.
|
|
810
|
+
* @experimental
|
|
767
811
|
*/
|
|
768
812
|
interface EventsSyncOptions {
|
|
769
813
|
/**
|
|
@@ -830,6 +874,7 @@ interface EventsSyncOptions {
|
|
|
830
874
|
*
|
|
831
875
|
* The current watermark is exposed via `watermark` and advances
|
|
832
876
|
* monotonically as events are applied.
|
|
877
|
+
* @experimental
|
|
833
878
|
*/
|
|
834
879
|
declare class EventsSync {
|
|
835
880
|
#private;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { S as SqliteAdapter } from "./types.d-
|
|
1
|
+
import { S as SqliteAdapter } from "./types.d-BuAWjEY5.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* Row-level change kind within a TableDiff.
|
|
4
4
|
*
|
|
5
5
|
* Each change represents one row that was inserted, updated, or deleted on
|
|
6
6
|
* the server since the last sync tick.
|
|
7
|
+
* @experimental
|
|
7
8
|
*/
|
|
8
9
|
type RowChange = {
|
|
9
10
|
data: Record<string, unknown>;
|
|
@@ -22,6 +23,7 @@ type RowChange = {
|
|
|
22
23
|
* `TableDiff` is the unit of replication between the server and the local
|
|
23
24
|
* SQLite mirror. The server pushes diffs over the poke protocol; the
|
|
24
25
|
* client applies them via `applyDiff`.
|
|
26
|
+
* @experimental
|
|
25
27
|
*/
|
|
26
28
|
interface TableDiff {
|
|
27
29
|
/** Ordered row changes — insert/update/delete, earliest first. */
|
|
@@ -33,18 +35,22 @@ interface TableDiff {
|
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* Create a {@link TableDiff} with a snapshot of the current time.
|
|
38
|
+
* @experimental
|
|
36
39
|
*/
|
|
37
40
|
declare const createTableDiff: (table: string, changes: ReadonlyArray<RowChange>, timestamp?: number) => TableDiff;
|
|
38
41
|
/**
|
|
39
42
|
* Return `true` when the diff contains no row changes.
|
|
43
|
+
* @experimental
|
|
40
44
|
*/
|
|
41
45
|
declare const isDiffEmpty: (diff: TableDiff) => boolean;
|
|
42
46
|
/**
|
|
43
47
|
* Return the number of rows touched by the diff (inserts + updates + deletes).
|
|
48
|
+
* @experimental
|
|
44
49
|
*/
|
|
45
50
|
declare const diffSize: (diff: TableDiff) => number;
|
|
46
51
|
/**
|
|
47
52
|
* Partition a {@link TableDiff} into three categories for batch processing.
|
|
53
|
+
* @experimental
|
|
48
54
|
*/
|
|
49
55
|
declare const classifyChanges: (diff: TableDiff) => {
|
|
50
56
|
deletes: RowChange[];
|
|
@@ -55,6 +61,7 @@ declare const classifyChanges: (diff: TableDiff) => {
|
|
|
55
61
|
* Merge several diffs for the same table into one (ordering preserved).
|
|
56
62
|
*
|
|
57
63
|
* Returns `null` when the input list is empty.
|
|
64
|
+
* @experimental
|
|
58
65
|
*/
|
|
59
66
|
declare const mergeDiffs: (diffs: ReadonlyArray<TableDiff>) => TableDiff | null;
|
|
60
67
|
/**
|
|
@@ -75,6 +82,7 @@ declare const mergeDiffs: (diffs: ReadonlyArray<TableDiff>) => TableDiff | null;
|
|
|
75
82
|
* Monotonically increasing, assigned by `EventLog` (in-memory) or
|
|
76
83
|
* `EventLogDO` (Durable Object). All confirmed log entries carry a
|
|
77
84
|
* `GlobalSeq`.
|
|
85
|
+
* @experimental
|
|
78
86
|
*/
|
|
79
87
|
type GlobalSeq = number;
|
|
80
88
|
/**
|
|
@@ -83,6 +91,7 @@ type GlobalSeq = number;
|
|
|
83
91
|
* Carries the last-confirmed `global` seq, a monotonically increasing
|
|
84
92
|
* `client` counter, and a `rebaseGeneration` that increments whenever the
|
|
85
93
|
* client's local events are rebased onto a new upstream baseline.
|
|
94
|
+
* @experimental
|
|
86
95
|
*/
|
|
87
96
|
interface ClientSeq {
|
|
88
97
|
/** Client-local monotonically increasing counter. */
|
|
@@ -94,14 +103,17 @@ interface ClientSeq {
|
|
|
94
103
|
}
|
|
95
104
|
/**
|
|
96
105
|
* Discriminated union of all sequence-number types.
|
|
106
|
+
* @experimental
|
|
97
107
|
*/
|
|
98
108
|
type Seq = GlobalSeq | ClientSeq;
|
|
99
109
|
/**
|
|
100
110
|
* Narrow `Seq` to `GlobalSeq`.
|
|
111
|
+
* @experimental
|
|
101
112
|
*/
|
|
102
113
|
declare const isGlobalSeq: (seq: Seq) => seq is GlobalSeq;
|
|
103
114
|
/**
|
|
104
115
|
* Narrow `Seq` to `ClientSeq`.
|
|
116
|
+
* @experimental
|
|
105
117
|
*/
|
|
106
118
|
declare const isClientSeq: (seq: Seq) => seq is ClientSeq;
|
|
107
119
|
/**
|
|
@@ -117,6 +129,7 @@ declare const isClientSeq: (seq: Seq) => seq is ClientSeq;
|
|
|
117
129
|
* const event = events.chat.messageSent({ channelId: "c1", text: "hello" });
|
|
118
130
|
* // event: InputEvent<"chat.messageSent", { channelId: string; text: string }>
|
|
119
131
|
* ```
|
|
132
|
+
* @experimental
|
|
120
133
|
*/
|
|
121
134
|
interface InputEvent<Type extends string = string, Payload = unknown> {
|
|
122
135
|
/** Arbitrary JSON-serialisable payload. */
|
|
@@ -128,6 +141,7 @@ interface InputEvent<Type extends string = string, Payload = unknown> {
|
|
|
128
141
|
}
|
|
129
142
|
/**
|
|
130
143
|
* Type guard: check whether `value` is an {@link InputEvent}.
|
|
144
|
+
* @experimental
|
|
131
145
|
*/
|
|
132
146
|
declare const isInputEvent: (value: unknown) => value is InputEvent;
|
|
133
147
|
/**
|
|
@@ -136,6 +150,7 @@ declare const isInputEvent: (value: unknown) => value is InputEvent;
|
|
|
136
150
|
* Entries are immutable once appended; the `seq` field is assigned
|
|
137
151
|
* monotonically by the log and doubles as a watermark for catch-up
|
|
138
152
|
* replication between tabs or service-worker instances.
|
|
153
|
+
* @experimental
|
|
139
154
|
*/
|
|
140
155
|
interface EventLogEntry {
|
|
141
156
|
/**
|
|
@@ -175,6 +190,7 @@ interface EventLogEntry {
|
|
|
175
190
|
}
|
|
176
191
|
/**
|
|
177
192
|
* Serialised snapshot of the log — used for persistence and transfer.
|
|
193
|
+
* @experimental
|
|
178
194
|
*/
|
|
179
195
|
interface EventLogSnapshot {
|
|
180
196
|
readonly entries: ReadonlyArray<EventLogEntry>;
|
|
@@ -184,6 +200,7 @@ interface EventLogSnapshot {
|
|
|
184
200
|
}
|
|
185
201
|
/**
|
|
186
202
|
* Optional metadata that can accompany an appended event.
|
|
203
|
+
* @experimental
|
|
187
204
|
*/
|
|
188
205
|
interface AppendOptions {
|
|
189
206
|
/** Globally-unique client identifier. */
|
|
@@ -205,6 +222,7 @@ interface AppendOptions {
|
|
|
205
222
|
* @remarks This class is intentionally **not** a full SQLite-backed log.
|
|
206
223
|
* Persistence is the caller's responsibility (write the snapshot
|
|
207
224
|
* to IndexedDB / OPFS via {@link EventLog#snapshot}).
|
|
225
|
+
* @experimental
|
|
208
226
|
*/
|
|
209
227
|
declare class EventLog {
|
|
210
228
|
#private;
|
|
@@ -280,12 +298,17 @@ declare class EventLog {
|
|
|
280
298
|
*/
|
|
281
299
|
events(fromSeq?: number): AsyncGenerator<EventLogEntry>;
|
|
282
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* `MirrorTableDef` is part of the experimental `@lunora/replica` API and may change without a major version bump.
|
|
303
|
+
* @experimental
|
|
304
|
+
*/
|
|
283
305
|
interface MirrorTableDef {
|
|
284
306
|
/** Primary key column name (defaults to `"id"`). */
|
|
285
307
|
readonly primaryKey?: string;
|
|
286
308
|
}
|
|
287
309
|
/**
|
|
288
310
|
* Options for constructing a {@link LocalMirror}.
|
|
311
|
+
* @experimental
|
|
289
312
|
*/
|
|
290
313
|
interface LocalMirrorOptions {
|
|
291
314
|
/** Platform-specific SQLite adapter. */
|
|
@@ -325,6 +348,10 @@ interface LocalMirrorOptions {
|
|
|
325
348
|
* ```
|
|
326
349
|
*/
|
|
327
350
|
type ChangeSubscriber = () => void;
|
|
351
|
+
/**
|
|
352
|
+
* `LocalMirror` is part of the experimental `@lunora/replica` API and may change without a major version bump.
|
|
353
|
+
* @experimental
|
|
354
|
+
*/
|
|
328
355
|
declare class LocalMirror {
|
|
329
356
|
#private;
|
|
330
357
|
/**
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { S as SqliteAdapter } from "./types.d-
|
|
1
|
+
import { S as SqliteAdapter } from "./types.d-BuAWjEY5.js";
|
|
2
2
|
/**
|
|
3
3
|
* Row-level change kind within a TableDiff.
|
|
4
4
|
*
|
|
5
5
|
* Each change represents one row that was inserted, updated, or deleted on
|
|
6
6
|
* the server since the last sync tick.
|
|
7
|
+
* @experimental
|
|
7
8
|
*/
|
|
8
9
|
type RowChange = {
|
|
9
10
|
data: Record<string, unknown>;
|
|
@@ -22,6 +23,7 @@ type RowChange = {
|
|
|
22
23
|
* `TableDiff` is the unit of replication between the server and the local
|
|
23
24
|
* SQLite mirror. The server pushes diffs over the poke protocol; the
|
|
24
25
|
* client applies them via `applyDiff`.
|
|
26
|
+
* @experimental
|
|
25
27
|
*/
|
|
26
28
|
interface TableDiff {
|
|
27
29
|
/** Ordered row changes — insert/update/delete, earliest first. */
|
|
@@ -33,18 +35,22 @@ interface TableDiff {
|
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* Create a {@link TableDiff} with a snapshot of the current time.
|
|
38
|
+
* @experimental
|
|
36
39
|
*/
|
|
37
40
|
declare const createTableDiff: (table: string, changes: ReadonlyArray<RowChange>, timestamp?: number) => TableDiff;
|
|
38
41
|
/**
|
|
39
42
|
* Return `true` when the diff contains no row changes.
|
|
43
|
+
* @experimental
|
|
40
44
|
*/
|
|
41
45
|
declare const isDiffEmpty: (diff: TableDiff) => boolean;
|
|
42
46
|
/**
|
|
43
47
|
* Return the number of rows touched by the diff (inserts + updates + deletes).
|
|
48
|
+
* @experimental
|
|
44
49
|
*/
|
|
45
50
|
declare const diffSize: (diff: TableDiff) => number;
|
|
46
51
|
/**
|
|
47
52
|
* Partition a {@link TableDiff} into three categories for batch processing.
|
|
53
|
+
* @experimental
|
|
48
54
|
*/
|
|
49
55
|
declare const classifyChanges: (diff: TableDiff) => {
|
|
50
56
|
deletes: RowChange[];
|
|
@@ -55,6 +61,7 @@ declare const classifyChanges: (diff: TableDiff) => {
|
|
|
55
61
|
* Merge several diffs for the same table into one (ordering preserved).
|
|
56
62
|
*
|
|
57
63
|
* Returns `null` when the input list is empty.
|
|
64
|
+
* @experimental
|
|
58
65
|
*/
|
|
59
66
|
declare const mergeDiffs: (diffs: ReadonlyArray<TableDiff>) => TableDiff | null;
|
|
60
67
|
/**
|
|
@@ -75,6 +82,7 @@ declare const mergeDiffs: (diffs: ReadonlyArray<TableDiff>) => TableDiff | null;
|
|
|
75
82
|
* Monotonically increasing, assigned by `EventLog` (in-memory) or
|
|
76
83
|
* `EventLogDO` (Durable Object). All confirmed log entries carry a
|
|
77
84
|
* `GlobalSeq`.
|
|
85
|
+
* @experimental
|
|
78
86
|
*/
|
|
79
87
|
type GlobalSeq = number;
|
|
80
88
|
/**
|
|
@@ -83,6 +91,7 @@ type GlobalSeq = number;
|
|
|
83
91
|
* Carries the last-confirmed `global` seq, a monotonically increasing
|
|
84
92
|
* `client` counter, and a `rebaseGeneration` that increments whenever the
|
|
85
93
|
* client's local events are rebased onto a new upstream baseline.
|
|
94
|
+
* @experimental
|
|
86
95
|
*/
|
|
87
96
|
interface ClientSeq {
|
|
88
97
|
/** Client-local monotonically increasing counter. */
|
|
@@ -94,14 +103,17 @@ interface ClientSeq {
|
|
|
94
103
|
}
|
|
95
104
|
/**
|
|
96
105
|
* Discriminated union of all sequence-number types.
|
|
106
|
+
* @experimental
|
|
97
107
|
*/
|
|
98
108
|
type Seq = GlobalSeq | ClientSeq;
|
|
99
109
|
/**
|
|
100
110
|
* Narrow `Seq` to `GlobalSeq`.
|
|
111
|
+
* @experimental
|
|
101
112
|
*/
|
|
102
113
|
declare const isGlobalSeq: (seq: Seq) => seq is GlobalSeq;
|
|
103
114
|
/**
|
|
104
115
|
* Narrow `Seq` to `ClientSeq`.
|
|
116
|
+
* @experimental
|
|
105
117
|
*/
|
|
106
118
|
declare const isClientSeq: (seq: Seq) => seq is ClientSeq;
|
|
107
119
|
/**
|
|
@@ -117,6 +129,7 @@ declare const isClientSeq: (seq: Seq) => seq is ClientSeq;
|
|
|
117
129
|
* const event = events.chat.messageSent({ channelId: "c1", text: "hello" });
|
|
118
130
|
* // event: InputEvent<"chat.messageSent", { channelId: string; text: string }>
|
|
119
131
|
* ```
|
|
132
|
+
* @experimental
|
|
120
133
|
*/
|
|
121
134
|
interface InputEvent<Type extends string = string, Payload = unknown> {
|
|
122
135
|
/** Arbitrary JSON-serialisable payload. */
|
|
@@ -128,6 +141,7 @@ interface InputEvent<Type extends string = string, Payload = unknown> {
|
|
|
128
141
|
}
|
|
129
142
|
/**
|
|
130
143
|
* Type guard: check whether `value` is an {@link InputEvent}.
|
|
144
|
+
* @experimental
|
|
131
145
|
*/
|
|
132
146
|
declare const isInputEvent: (value: unknown) => value is InputEvent;
|
|
133
147
|
/**
|
|
@@ -136,6 +150,7 @@ declare const isInputEvent: (value: unknown) => value is InputEvent;
|
|
|
136
150
|
* Entries are immutable once appended; the `seq` field is assigned
|
|
137
151
|
* monotonically by the log and doubles as a watermark for catch-up
|
|
138
152
|
* replication between tabs or service-worker instances.
|
|
153
|
+
* @experimental
|
|
139
154
|
*/
|
|
140
155
|
interface EventLogEntry {
|
|
141
156
|
/**
|
|
@@ -175,6 +190,7 @@ interface EventLogEntry {
|
|
|
175
190
|
}
|
|
176
191
|
/**
|
|
177
192
|
* Serialised snapshot of the log — used for persistence and transfer.
|
|
193
|
+
* @experimental
|
|
178
194
|
*/
|
|
179
195
|
interface EventLogSnapshot {
|
|
180
196
|
readonly entries: ReadonlyArray<EventLogEntry>;
|
|
@@ -184,6 +200,7 @@ interface EventLogSnapshot {
|
|
|
184
200
|
}
|
|
185
201
|
/**
|
|
186
202
|
* Optional metadata that can accompany an appended event.
|
|
203
|
+
* @experimental
|
|
187
204
|
*/
|
|
188
205
|
interface AppendOptions {
|
|
189
206
|
/** Globally-unique client identifier. */
|
|
@@ -205,6 +222,7 @@ interface AppendOptions {
|
|
|
205
222
|
* @remarks This class is intentionally **not** a full SQLite-backed log.
|
|
206
223
|
* Persistence is the caller's responsibility (write the snapshot
|
|
207
224
|
* to IndexedDB / OPFS via {@link EventLog#snapshot}).
|
|
225
|
+
* @experimental
|
|
208
226
|
*/
|
|
209
227
|
declare class EventLog {
|
|
210
228
|
#private;
|
|
@@ -280,12 +298,17 @@ declare class EventLog {
|
|
|
280
298
|
*/
|
|
281
299
|
events(fromSeq?: number): AsyncGenerator<EventLogEntry>;
|
|
282
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* `MirrorTableDef` is part of the experimental `@lunora/replica` API and may change without a major version bump.
|
|
303
|
+
* @experimental
|
|
304
|
+
*/
|
|
283
305
|
interface MirrorTableDef {
|
|
284
306
|
/** Primary key column name (defaults to `"id"`). */
|
|
285
307
|
readonly primaryKey?: string;
|
|
286
308
|
}
|
|
287
309
|
/**
|
|
288
310
|
* Options for constructing a {@link LocalMirror}.
|
|
311
|
+
* @experimental
|
|
289
312
|
*/
|
|
290
313
|
interface LocalMirrorOptions {
|
|
291
314
|
/** Platform-specific SQLite adapter. */
|
|
@@ -325,6 +348,10 @@ interface LocalMirrorOptions {
|
|
|
325
348
|
* ```
|
|
326
349
|
*/
|
|
327
350
|
type ChangeSubscriber = () => void;
|
|
351
|
+
/**
|
|
352
|
+
* `LocalMirror` is part of the experimental `@lunora/replica` API and may change without a major version bump.
|
|
353
|
+
* @experimental
|
|
354
|
+
*/
|
|
328
355
|
declare class LocalMirror {
|
|
329
356
|
#private;
|
|
330
357
|
/**
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Each runtime (browser via sql.js, React Native via expo-sqlite,
|
|
5
5
|
* Node via better-sqlite3) provides its own adapter implementing this
|
|
6
6
|
* interface so the rest of `@lunora/replica` stays platform-agnostic.
|
|
7
|
+
* @experimental
|
|
7
8
|
*/
|
|
8
9
|
interface SqliteAdapter {
|
|
9
10
|
/** Close the database connection. */
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Each runtime (browser via sql.js, React Native via expo-sqlite,
|
|
5
5
|
* Node via better-sqlite3) provides its own adapter implementing this
|
|
6
6
|
* interface so the rest of `@lunora/replica` stays platform-agnostic.
|
|
7
|
+
* @experimental
|
|
7
8
|
*/
|
|
8
9
|
interface SqliteAdapter {
|
|
9
10
|
/** Close the database connection. */
|
package/dist/react.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { L as LocalMirror } from "./packem_shared/local-mirror.d-
|
|
2
|
-
import "./packem_shared/types.d-
|
|
1
|
+
import { L as LocalMirror } from "./packem_shared/local-mirror.d-BUeOe5KC.mjs";
|
|
2
|
+
import "./packem_shared/types.d-BuAWjEY5.mjs";
|
|
3
3
|
/**
|
|
4
4
|
* Options for the {@link useLocalQuery} hook.
|
|
5
|
+
* @experimental
|
|
5
6
|
*/
|
|
6
7
|
interface UseLocalQueryOptions {
|
|
7
8
|
/**
|
|
@@ -60,6 +61,7 @@ interface UseLocalQueryOptions {
|
|
|
60
61
|
* return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
|
|
61
62
|
* }
|
|
62
63
|
* ```
|
|
64
|
+
* @experimental
|
|
63
65
|
*/
|
|
64
66
|
declare const useLocalQuery: <T = Record<string, unknown>>(mirror: LocalMirror, sql: string, params?: ReadonlyArray<unknown>, _options?: UseLocalQueryOptions) => T[] | undefined;
|
|
65
67
|
export { UseLocalQueryOptions, useLocalQuery };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { L as LocalMirror } from "./packem_shared/local-mirror.d-
|
|
2
|
-
import "./packem_shared/types.d-
|
|
1
|
+
import { L as LocalMirror } from "./packem_shared/local-mirror.d-Cd8tAg-W.js";
|
|
2
|
+
import "./packem_shared/types.d-BuAWjEY5.js";
|
|
3
3
|
/**
|
|
4
4
|
* Options for the {@link useLocalQuery} hook.
|
|
5
|
+
* @experimental
|
|
5
6
|
*/
|
|
6
7
|
interface UseLocalQueryOptions {
|
|
7
8
|
/**
|
|
@@ -60,6 +61,7 @@ interface UseLocalQueryOptions {
|
|
|
60
61
|
* return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
|
|
61
62
|
* }
|
|
62
63
|
* ```
|
|
64
|
+
* @experimental
|
|
63
65
|
*/
|
|
64
66
|
declare const useLocalQuery: <T = Record<string, unknown>>(mirror: LocalMirror, sql: string, params?: ReadonlyArray<unknown>, _options?: UseLocalQueryOptions) => T[] | undefined;
|
|
65
67
|
export { UseLocalQueryOptions, useLocalQuery };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/replica",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.4",
|
|
4
4
|
"description": "Local-first replica runtime + local SQLite mirror for Lunora",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"access": "public"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@lunora/server": "1.0.0-alpha.24",
|
|
65
|
+
"@lunora/server": ">=1.0.0-alpha.24 <2.0.0-0",
|
|
66
66
|
"@sqlite.org/sqlite-wasm": "*",
|
|
67
67
|
"better-sqlite3": "*",
|
|
68
68
|
"react": "^18.0.0 || ^19.0.0",
|