@rindle/optimistic 0.4.2 → 0.4.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 +30 -61
- package/dist/backend.d.ts +29 -16
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +77 -21
- package/dist/backend.js.map +1 -1
- package/dist/client.d.ts +9 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +22 -5
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/local-persist.d.ts +102 -0
- package/dist/local-persist.d.ts.map +1 -0
- package/dist/local-persist.js +957 -0
- package/dist/local-persist.js.map +1 -0
- package/package.json +6 -5
- package/src/backend.ts +93 -30
- package/src/client.ts +31 -5
- package/src/index.ts +15 -0
- package/src/local-persist.ts +1129 -0
package/dist/client.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Transport } from "@rindle/remote";
|
|
|
3
3
|
import type { OptimisticBackend } from "./backend.ts";
|
|
4
4
|
import type { ClientRegistry, MutationTx } from "./backend.ts";
|
|
5
5
|
import { type MutateFn } from "./index.ts";
|
|
6
|
+
import { type PersistLocalOptions } from "./local-persist.ts";
|
|
6
7
|
import type { Store } from "@rindle/client";
|
|
7
8
|
export type HeadersInit = Record<string, string>;
|
|
8
9
|
export interface RindleClientOptions<S extends ColsMap, R extends ClientRegistry> {
|
|
@@ -43,6 +44,14 @@ export interface RindleClientOptions<S extends ColsMap, R extends ClientRegistry
|
|
|
43
44
|
clientID?: string;
|
|
44
45
|
/** A policy rejection's reason (the prediction's snap-back rides the lmid release). */
|
|
45
46
|
onRejected?: (envelope: MutationEnvelope, reason: string) => void;
|
|
47
|
+
/** Persist `local: true` tables across reloads and keep them live-coherent across tabs
|
|
48
|
+
* (`207-LOCAL-TABLE-PERSISTENCE-DESIGN.md`). `user` is the storage identity (§3.2) — one IDB
|
|
49
|
+
* database per (origin, user); pass a sentinel like `"anon"` for a signed-out mode. When set,
|
|
50
|
+
* `createRindleClient` awaits the initial restore before returning, so the first render never
|
|
51
|
+
* flashes empty local state (§5.2). Logout is `deleteLocalPersistence(user)` — never implicit.
|
|
52
|
+
* Per-table opt-out: declare `table(name, { local: "session" })` for local state that must stay
|
|
53
|
+
* ephemeral and per-tab (e.g. selection) even with persistence on (§5.4). */
|
|
54
|
+
persistLocal?: PersistLocalOptions;
|
|
46
55
|
queue?: {
|
|
47
56
|
maxBatch?: number;
|
|
48
57
|
retryDelayMs?: (attempt: number) => number;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAMxE,OAAO,KAAK,EAA2C,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGzF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAM5C,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEjD,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,cAAc;IAC9E,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAClB,qFAAqF;IACrF,QAAQ,EAAE,CAAC,CAAC;IACZ;;qGAEiG;IACjG,IAAI,CAAC,EAAE,MAAM,MAAM,CAAC;IACpB,qFAAqF;IACrF,GAAG,EAAE;QACH,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7C,6EAA6E;QAC7E,OAAO,CAAC,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;QACnE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;KACtB,CAAC;IACF;;;;;;+FAM2F;IAC3F,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,SAAS,EAAE,SAAS,CAAA;KAAE,CAAC;IACtD;;;uBAGmB;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAClE,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;KAAE,CAAC;IAC1E;yEACqE;IACrE,GAAG,CAAC,EAAE;QACJ;0FACkF;QAClF,kBAAkB,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;CACH;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,cAAc;IACvE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAChB,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC9B;gFAC4E;IAC5E,MAAM,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAAE,CAAC;IAC1D;kFAC8E;IAC9E,UAAU,IAAI,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAsB,kBAAkB,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,cAAc,EAClF,IAAI,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC9B,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAMxE,OAAO,KAAK,EAA2C,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGzF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAiD,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC7G,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAM5C,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEjD,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,cAAc;IAC9E,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAClB,qFAAqF;IACrF,QAAQ,EAAE,CAAC,CAAC;IACZ;;qGAEiG;IACjG,IAAI,CAAC,EAAE,MAAM,MAAM,CAAC;IACpB,qFAAqF;IACrF,GAAG,EAAE;QACH,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7C,6EAA6E;QAC7E,OAAO,CAAC,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;QACnE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;KACtB,CAAC;IACF;;;;;;+FAM2F;IAC3F,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,SAAS,EAAE,SAAS,CAAA;KAAE,CAAC;IACtD;;;uBAGmB;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAClE;;;;;;kFAM8E;IAC9E,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;KAAE,CAAC;IAC1E;yEACqE;IACrE,GAAG,CAAC,EAAE;QACJ;0FACkF;QAClF,kBAAkB,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;CACH;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,cAAc;IACvE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAChB,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC9B;gFAC4E;IAC5E,MAAM,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAAE,CAAC;IAC1D;kFAC8E;IAC9E,UAAU,IAAI,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAsB,kBAAkB,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,cAAc,EAClF,IAAI,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC9B,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAuG7B;AAED,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC;AAC3C,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/client.js
CHANGED
|
@@ -12,6 +12,7 @@ import { RemoteOptimisticSource, WsTransport, createQueuedMutationSender, } from
|
|
|
12
12
|
import { initWasm } from "@rindle/wasm";
|
|
13
13
|
import { resetStableClientID, stableClientID } from "./client-id.js";
|
|
14
14
|
import { createOptimisticStore } from "./index.js";
|
|
15
|
+
import { attachLocalPersistence } from "./local-persist.js";
|
|
15
16
|
/** Must mirror `DEFAULT_RINDLE_API_ROUTES` in `@rindle/api-server` (the app-wire contract;
|
|
16
17
|
* duplicated so the browser bundle doesn't import the server package). */
|
|
17
18
|
const DEFAULT_ROUTES = { query: "/api/rindle/query", mutate: "/api/rindle/mutate" };
|
|
@@ -67,15 +68,30 @@ export async function createRindleClient(opts) {
|
|
|
67
68
|
clientID,
|
|
68
69
|
user: opts.user,
|
|
69
70
|
});
|
|
71
|
+
// Local-table persistence (207 §5.2): attach immediately after the store exists — before any
|
|
72
|
+
// app write can reach `writeLocal` — and AWAIT the initial restore (one `getAll` over small
|
|
73
|
+
// tables) so the first render never flashes empty local state. Restored rows arrive as ordinary
|
|
74
|
+
// deltas, so correctness never needed the gate — only UX does.
|
|
75
|
+
let persistence;
|
|
76
|
+
if (opts.persistLocal) {
|
|
77
|
+
persistence = attachLocalPersistence(backend, opts.schema, opts.persistLocal);
|
|
78
|
+
await persistence.ready;
|
|
79
|
+
}
|
|
70
80
|
// Drain folds before the tab goes away (FOLDED-MUTATIONS-DESIGN §0.1/§3): a fold deliberately
|
|
71
81
|
// holds its server write through the debounce window, so an unclean navigation would otherwise
|
|
72
82
|
// lose the applied-locally tail. `pagehide`/`beforeunload` is the last-chance flush; `close`
|
|
73
|
-
// also drains.
|
|
83
|
+
// also drains. The same hook is the persistence layer's best-effort final forward/persist
|
|
84
|
+
// (207 §9 — bounds the unacked-tail loss). (Best-effort: an unclean crash still loses the
|
|
85
|
+
// tail — an accepted cost, §0.1.)
|
|
74
86
|
const flushFolds = () => backend.flushFolds();
|
|
87
|
+
const onPageHide = () => {
|
|
88
|
+
flushFolds();
|
|
89
|
+
void persistence?.flush();
|
|
90
|
+
};
|
|
75
91
|
// Structural typing — this package has no DOM lib, but the browser global carries these.
|
|
76
92
|
const target = globalThis;
|
|
77
|
-
target.addEventListener?.("pagehide",
|
|
78
|
-
target.addEventListener?.("beforeunload",
|
|
93
|
+
target.addEventListener?.("pagehide", onPageHide);
|
|
94
|
+
target.addEventListener?.("beforeunload", onPageHide);
|
|
79
95
|
return {
|
|
80
96
|
store,
|
|
81
97
|
backend,
|
|
@@ -84,8 +100,9 @@ export async function createRindleClient(opts) {
|
|
|
84
100
|
clientID,
|
|
85
101
|
close: () => {
|
|
86
102
|
flushFolds();
|
|
87
|
-
target.removeEventListener?.("pagehide",
|
|
88
|
-
target.removeEventListener?.("beforeunload",
|
|
103
|
+
target.removeEventListener?.("pagehide", onPageHide);
|
|
104
|
+
target.removeEventListener?.("beforeunload", onPageHide);
|
|
105
|
+
persistence?.close(); // releases leadership + the channel + the IDB handle (207 P10)
|
|
89
106
|
source.close();
|
|
90
107
|
},
|
|
91
108
|
};
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,iGAAiG;AACjG,6DAA6D;AAC7D,8DAA8D;AAC9D,EAAE;AACF,oGAAoG;AACpG,yFAAyF;AACzF,sFAAsF;AACtF,gDAAgD;AAGhD,OAAO,EACL,sBAAsB,EACtB,WAAW,EACX,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAiB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export type { IsoTx, MutationGen, MutatorCtx, SharedMutator, YieldEffect } from
|
|
|
15
15
|
export { createRindleClient } from "./client.ts";
|
|
16
16
|
export type { RindleClient, RindleClientOptions } from "./client.ts";
|
|
17
17
|
export { resetStableClientID, stableClientID } from "./client-id.ts";
|
|
18
|
+
export { attachLocalPersistence, deleteLocalPersistence } from "./local-persist.ts";
|
|
19
|
+
export type { LocalPersistence, PersistChannel, PersistDb, PersistEnv, PersistLocalOptions, PersistMeta, RowState, StoredRow, } from "./local-persist.ts";
|
|
18
20
|
/** A {@link Store} over an {@link OptimisticBackend}, plus the named-mutator entry
|
|
19
21
|
* (`mutate.createIssue(args)` — the §9 dream shape) and the §6 lifecycle surface. */
|
|
20
22
|
export declare function createOptimisticStore<S extends ColsMap, R extends ClientRegistry>(schema: Schema<S>, source: OptimisticSource, registry: R, opts: OptimisticBackendOptions): {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAExE,OAAO,EACL,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAC;AAEtB;;mGAEmG;AACnG,MAAM,MAAM,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,GAAG;IACtD,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,GAAG,UAAU,CAAC;CACnD,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EACV,aAAa,EACb,cAAc,EACd,SAAS,EACT,UAAU,EACV,WAAW,EACX,WAAW,EACX,QAAQ,EACR,UAAU,EACV,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,QAAQ,EACR,cAAc,EACd,UAAU,GACX,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGxF,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGjG,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAExE,OAAO,EACL,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAC;AAEtB;;mGAEmG;AACnG,MAAM,MAAM,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,GAAG;IACtD,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,GAAG,UAAU,CAAC;CACnD,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EACV,aAAa,EACb,cAAc,EACd,SAAS,EACT,UAAU,EACV,WAAW,EACX,WAAW,EACX,QAAQ,EACR,UAAU,EACV,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,QAAQ,EACR,cAAc,EACd,UAAU,GACX,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGxF,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGjG,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAKrE,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACpF,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,QAAQ,EACR,SAAS,GACV,MAAM,oBAAoB,CAAC;AAE5B;sFACsF;AACtF,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,cAAc,EAC/E,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EACjB,MAAM,EAAE,gBAAgB,EACxB,QAAQ,EAAE,CAAC,EACX,IAAI,EAAE,wBAAwB,GAC7B;IACD,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAChB,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAAE,CAAC;CAC3D,CAcA"}
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,10 @@ export { isoTx } from "@rindle/client";
|
|
|
11
11
|
// The one-call client for the daemon/serverless topology (API server + daemon ws).
|
|
12
12
|
export { createRindleClient } from "./client.js";
|
|
13
13
|
export { resetStableClientID, stableClientID } from "./client-id.js";
|
|
14
|
+
// Local-table persistence (207-LOCAL-TABLE-PERSISTENCE-DESIGN.md): durable, cross-tab `local: true`
|
|
15
|
+
// tables. `createRindleClient` wires it via the `persistLocal` option; a standalone backend attaches
|
|
16
|
+
// with `attachLocalPersistence`; `deleteLocalPersistence` is the sanctioned logout hook (§3.2).
|
|
17
|
+
export { attachLocalPersistence, deleteLocalPersistence } from "./local-persist.js";
|
|
14
18
|
/** A {@link Store} over an {@link OptimisticBackend}, plus the named-mutator entry
|
|
15
19
|
* (`mutate.createIssue(args)` — the §9 dream shape) and the §6 lifecycle surface. */
|
|
16
20
|
export function createOptimisticStore(schema, source, registry, opts) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,gFAAgF;AAChF,gFAAgF;AAChF,qFAAqF;AAErF,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,OAAO,EACL,iBAAiB,GAKlB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAkBjD,sGAAsG;AACtG,wGAAwG;AACxG,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,mFAAmF;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErE;sFACsF;AACtF,MAAM,UAAU,qBAAqB,CACnC,MAAiB,EACjB,MAAwB,EACxB,QAAW,EACX,IAA8B;IAM9B,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,KAAK,CACtB,EAAE,EACF;QACE,GAAG,EAAE,CAAC,EAAE,EAAE,IAAY,EAAE,EAAE;YACxB,MAAM,EAAE,GAAG,CAAC,CAAC,IAAa,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAsB,CAAC;YAChF,EAAE,CAAC,MAAM,GAAG,CAAC,QAAqB,EAAE,IAAa,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YACjG,OAAO,EAAE,CAAC;QACZ,CAAC;KACF,CACmD,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AACpC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,gFAAgF;AAChF,gFAAgF;AAChF,qFAAqF;AAErF,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,OAAO,EACL,iBAAiB,GAKlB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAkBjD,sGAAsG;AACtG,wGAAwG;AACxG,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,mFAAmF;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErE,oGAAoG;AACpG,qGAAqG;AACrG,gGAAgG;AAChG,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAYpF;sFACsF;AACtF,MAAM,UAAU,qBAAqB,CACnC,MAAiB,EACjB,MAAwB,EACxB,QAAW,EACX,IAA8B;IAM9B,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,KAAK,CACtB,EAAE,EACF;QACE,GAAG,EAAE,CAAC,EAAE,EAAE,IAAY,EAAE,EAAE;YACxB,MAAM,EAAE,GAAG,CAAC,CAAC,IAAa,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAsB,CAAC;YAChF,EAAE,CAAC,MAAM,GAAG,CAAC,QAAqB,EAAE,IAAa,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YACjG,OAAO,EAAE,CAAC;QACZ,CAAC;KACF,CACmD,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { ColsMap, Schema, WireValue } from "@rindle/client";
|
|
2
|
+
import type { OptimisticBackend } from "./backend.ts";
|
|
3
|
+
export interface PersistLocalOptions {
|
|
4
|
+
/** The storage identity (§3.2): one IDB database per (origin, user). NOT the mutator principal —
|
|
5
|
+
* this is fixed for the client's lifetime; an anonymous mode passes its own sentinel (`"anon"`). */
|
|
6
|
+
user: string;
|
|
7
|
+
/** Call `navigator.storage.persist()` to resist eviction (§3.2). Default false — it can prompt. */
|
|
8
|
+
requestPersistentStorage?: boolean;
|
|
9
|
+
/** IDB/channel failures surface here (P9 — durability degrades, the write path never throws).
|
|
10
|
+
* Default `console.error`. */
|
|
11
|
+
onError?: (e: Error) => void;
|
|
12
|
+
/** Test seam: a fake IDB/locks/channel environment. Defaults to the browser globals. */
|
|
13
|
+
env?: PersistEnv;
|
|
14
|
+
}
|
|
15
|
+
/** The attached layer's handle. `createRindleClient` awaits {@link ready} before returning (§5.2). */
|
|
16
|
+
export interface LocalPersistence {
|
|
17
|
+
/** Resolves when the initial restore (§4.6 steps 1–5) has completed and the layer is live. */
|
|
18
|
+
readonly ready: Promise<void>;
|
|
19
|
+
/** Best-effort final persist/forward (the `pagehide` hook, §9): re-posts unacked ops (any
|
|
20
|
+
* role), then a leader drains its persist queue and retries P9-degraded batches. */
|
|
21
|
+
flush(): Promise<void>;
|
|
22
|
+
/** Release leadership (or abandon the queued lock request), close the channel + IDB (P10).
|
|
23
|
+
* A leader DRAINS its queued persist steps first (they carry already-committed writes) and
|
|
24
|
+
* releases the lock only after the last one lands; a follower re-posts its unacked ops. */
|
|
25
|
+
close(): void;
|
|
26
|
+
/** Introspection for tests/devtools: current role. */
|
|
27
|
+
role(): "leader" | "follower";
|
|
28
|
+
}
|
|
29
|
+
/** Delete a user's local-persistence database — the sanctioned LOGOUT hook (§3.2). Never called
|
|
30
|
+
* implicitly; the old database otherwise remains on disk (fast re-login, and a privacy decision
|
|
31
|
+
* the app owns). Close this tab's live client for `user` first; a SIBLING tab's connection is
|
|
32
|
+
* released automatically (it closes on `versionchange` and degrades to broadcast-only), so a
|
|
33
|
+
* multi-tab logout completes instead of parking behind the other tab forever. */
|
|
34
|
+
export declare function deleteLocalPersistence(user: string, env?: PersistEnv): Promise<void>;
|
|
35
|
+
/** Attach the persistence layer to a backend (standalone form — `createRindleClient` calls this
|
|
36
|
+
* for you). The observer is wired SYNCHRONOUSLY, but the mirror starts empty: attach before the
|
|
37
|
+
* first `writeLocal` (§5.2, a v1 constraint `createRindleClient` satisfies by construction).
|
|
38
|
+
* Await `handle.ready` before first render if the app wants restored rows at first paint. */
|
|
39
|
+
export declare function attachLocalPersistence<S extends ColsMap>(backend: OptimisticBackend<S>, schema: Schema<S>, opts: PersistLocalOptions): LocalPersistence;
|
|
40
|
+
/** The narrow storage surface the layer needs (§3.1): two fixed stores, `rows` + `meta`. Each
|
|
41
|
+
* method is one atomic IDB transaction; a resolved promise means the txn COMPLETED — the P1
|
|
42
|
+
* ("persist-then-broadcast") anchor. */
|
|
43
|
+
export interface PersistDb {
|
|
44
|
+
getMeta(): Promise<PersistMeta | undefined>;
|
|
45
|
+
putMeta(meta: PersistMeta): Promise<void>;
|
|
46
|
+
getAllRows(): Promise<StoredRow[]>;
|
|
47
|
+
/** Apply one commit batch atomically: `row === null` deletes, else puts. */
|
|
48
|
+
putBatch(batch: RowState[]): Promise<void>;
|
|
49
|
+
/** The P7 gate: clear `rows` and write `meta` in ONE transaction (never a half state). */
|
|
50
|
+
reset(meta: PersistMeta): Promise<void>;
|
|
51
|
+
/** Delete specific records (the leader's stale-table sweep, §3.1). */
|
|
52
|
+
deleteRows(keys: Array<{
|
|
53
|
+
table: string;
|
|
54
|
+
pkKey: string;
|
|
55
|
+
}>): Promise<void>;
|
|
56
|
+
close(): void;
|
|
57
|
+
}
|
|
58
|
+
export interface PersistChannel {
|
|
59
|
+
post(msg: unknown): void;
|
|
60
|
+
onMessage(handler: (msg: unknown) => void): void;
|
|
61
|
+
close(): void;
|
|
62
|
+
}
|
|
63
|
+
export interface PersistEnv {
|
|
64
|
+
/** Open (creating if needed) the database. Resolves `null` when storage is unavailable —
|
|
65
|
+
* the layer degrades to broadcast-only (§3.2). */
|
|
66
|
+
openDatabase(name: string): Promise<PersistDb | null>;
|
|
67
|
+
deleteDatabase(name: string): Promise<void>;
|
|
68
|
+
/** Open the tab-coherence channel; `null` when BroadcastChannel is unavailable (single-tab). */
|
|
69
|
+
createChannel(name: string): PersistChannel | null;
|
|
70
|
+
/** Queue for the exclusive leadership lock (§4.1): `onAcquired`'s promise HOLDS the lock until
|
|
71
|
+
* it resolves; `signal` aborts a still-queued request. When Web Locks are unavailable, grant
|
|
72
|
+
* immediately ONLY if the runtime is provably single-context (no channel) — see
|
|
73
|
+
* {@link leaderElectionUnavailable}. */
|
|
74
|
+
requestLock(name: string, signal: AbortSignal, onAcquired: () => Promise<void>): void;
|
|
75
|
+
/** The runtime has tabs (a channel) but NO exclusive lock (Firefox <96, Safari 15.1–15.3,
|
|
76
|
+
* Node): every context would self-promote into concurrent leaders over one database — P2
|
|
77
|
+
* violated, permanent divergence. When set, the layer runs INERT: local tables still work,
|
|
78
|
+
* session-scoped (the 201 baseline), with no persistence and no cross-tab replication. */
|
|
79
|
+
leaderElectionUnavailable?: boolean;
|
|
80
|
+
/** `navigator.storage.persist()` (§3.2), best-effort. */
|
|
81
|
+
requestPersistentStorage?(): void;
|
|
82
|
+
}
|
|
83
|
+
export interface PersistMeta {
|
|
84
|
+
schemaHash: string;
|
|
85
|
+
epoch: number;
|
|
86
|
+
}
|
|
87
|
+
export interface StoredRow {
|
|
88
|
+
table: string;
|
|
89
|
+
pkKey: string;
|
|
90
|
+
row: WireValue[];
|
|
91
|
+
}
|
|
92
|
+
/** The replication unit everywhere (§4.3): idempotent full-row state. `row: null` = tombstone
|
|
93
|
+
* (live protocol only — removes DELETE the IDB record; there are no persisted tombstones). */
|
|
94
|
+
export interface RowState {
|
|
95
|
+
table: string;
|
|
96
|
+
pkKey: string;
|
|
97
|
+
row: WireValue[] | null;
|
|
98
|
+
}
|
|
99
|
+
/** The real-browser environment: IndexedDB + BroadcastChannel + `navigator.locks`, each reached
|
|
100
|
+
* structurally and each degrading gracefully when absent (§3.2). */
|
|
101
|
+
export declare function defaultEnv(): PersistEnv;
|
|
102
|
+
//# sourceMappingURL=local-persist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-persist.d.ts","sourceRoot":"","sources":["../src/local-persist.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAMtD,MAAM,WAAW,mBAAmB;IAClC;yGACqG;IACrG,IAAI,EAAE,MAAM,CAAC;IACb,mGAAmG;IACnG,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;mCAC+B;IAC/B,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;IAC7B,wFAAwF;IACxF,GAAG,CAAC,EAAE,UAAU,CAAC;CAClB;AAED,sGAAsG;AACtG,MAAM,WAAW,gBAAgB;IAC/B,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B;yFACqF;IACrF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB;;gGAE4F;IAC5F,KAAK,IAAI,IAAI,CAAC;IACd,sDAAsD;IACtD,IAAI,IAAI,QAAQ,GAAG,UAAU,CAAC;CAC/B;AAED;;;;kFAIkF;AAClF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpF;AAED;;;8FAG8F;AAC9F,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,OAAO,EACtD,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC7B,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EACjB,IAAI,EAAE,mBAAmB,GACxB,gBAAgB,CAElB;AAMD;;yCAEyC;AACzC,MAAM,WAAW,SAAS;IACxB,OAAO,IAAI,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACnC,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,0FAA0F;IAC1F,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,sEAAsE;IACtE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IACjD,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB;uDACmD;IACnD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACtD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,gGAAgG;IAChG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;IACnD;;;6CAGyC;IACzC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACtF;;;+FAG2F;IAC3F,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,yDAAyD;IACzD,wBAAwB,CAAC,IAAI,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,SAAS,EAAE,CAAC;CAClB;AAED;+FAC+F;AAC/F,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;CACzB;AAy3BD;qEACqE;AACrE,wBAAgB,UAAU,IAAI,UAAU,CA8FvC"}
|