@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 CHANGED
@@ -10,6 +10,8 @@
10
10
 
11
11
  <!-- END_PACKAGE_OG_IMAGE_PLACEHOLDER -->
12
12
 
13
+ > **Experimental** — this package is outside the Lunora 1.0 stability promise: its API may change in any release, without a major version bump.
14
+
13
15
  <br />
14
16
 
15
17
  <div align="center">
@@ -1,4 +1,4 @@
1
- import { S as SqliteAdapter } from "../packem_shared/types.d-VfJ76cK4.mjs";
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-VfJ76cK4.js";
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-VfJ76cK4.mjs";
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-VfJ76cK4.js";
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-VfJ76cK4.mjs";
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;
@@ -1,4 +1,4 @@
1
- import { S as SqliteAdapter } from "../packem_shared/types.d-VfJ76cK4.js";
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-VfJ76cK4.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-Bp19ueGy.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-Bp19ueGy.mjs";
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&lt;id, row>, posts: Map&lt;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
- /** Options for constructing an {@link EventLogDOClient}. */
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&lt;string, unknown>` constraint — interfaces have no implicit index
250
267
  * signature and aren't assignable to `Record&lt;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-VfJ76cK4.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-GhuZAKgm.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-GhuZAKgm.js";
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&lt;id, row>, posts: Map&lt;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
- /** Options for constructing an {@link EventLogDOClient}. */
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&lt;string, unknown>` constraint — interfaces have no implicit index
250
267
  * signature and aren't assignable to `Record&lt;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-VfJ76cK4.js";
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&lt;"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-VfJ76cK4.mjs";
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&lt;"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-Bp19ueGy.mjs";
2
- import "./packem_shared/types.d-VfJ76cK4.mjs";
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-GhuZAKgm.js";
2
- import "./packem_shared/types.d-VfJ76cK4.js";
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.2",
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",