@doync/client 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/adapter.cjs +1 -1
- package/dist/adapter.d.cts +1 -1
- package/dist/adapter.d.ts +1 -1
- package/dist/adapter.js +1 -1
- package/dist/{client-CR5SoP5D.cjs → client-AGRXHAJy.cjs} +6 -6
- package/dist/{client-OAVaC3pt.d.ts → client-BZWglwNl.d.cts} +42 -7
- package/dist/{client-OPt8Axyp.d.cts.map → client-BZWglwNl.d.cts.map} +1 -1
- package/dist/client-Dphx71Qk.js +16 -0
- package/dist/client-Dphx71Qk.js.map +1 -0
- package/dist/{client-OPt8Axyp.d.cts → client-tAY8RnNM.d.ts} +42 -7
- package/dist/{client-OAVaC3pt.d.ts.map → client-tAY8RnNM.d.ts.map} +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/internal.cjs +1 -1
- package/dist/internal.d.cts +2 -2
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +1 -1
- package/dist/internal.js.map +1 -1
- package/package.json +3 -3
- package/src/engine.ts +91 -6
- package/src/index.ts +2 -0
- package/src/internal.ts +4 -0
- package/dist/client-C97IzM56.js +0 -16
- package/dist/client-C97IzM56.js.map +0 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ The package splits its public surface by **audience** (same lockstep semver —
|
|
|
20
20
|
|
|
21
21
|
`@doync/client` is the engine half of every doync client:
|
|
22
22
|
|
|
23
|
-
- **`DoyncClient` + View handles** — the call surface adapters wrap (`subscribe` / `once` / `local` / `mutate`, connection + schema status, preload); shared reactive reads with `retain` / `release` ownership.
|
|
23
|
+
- **`DoyncClient` + View handles** — the call surface adapters wrap (`subscribe` / `once` / `local` / `mutate`, connection + schema status, preload, warmup); shared reactive reads with `retain` / `release` ownership.
|
|
24
24
|
- **OnceView** — per-call cache-and-network reads.
|
|
25
25
|
- **Mutation invocation types** — `MutationResult` / `MutationOptions`; definitions themselves come from `@doync/core` and are the registry entries on both ends.
|
|
26
26
|
- **Host seams + reconnect + `createClient`** — on [`@doync/client/adapter`](#writing-a-host--framework-adapter); environment packages implement `LocalDb` / `SyncSocket` and construct clients there.
|
|
@@ -35,7 +35,7 @@ The main entry exports **types only** — the symbols apps meet through `@doync/
|
|
|
35
35
|
| --- | --- |
|
|
36
36
|
| `DoyncClient` | The call surface adapters wrap |
|
|
37
37
|
| `View` / `OnceView` / `ViewStatus` / `QueryStatus` | Reactive + once handle types |
|
|
38
|
-
| `SubscribeOptions` / `PreloadHandle` / `PreloadOptions` / `FalsyQuery` | Subscribe / preload options |
|
|
38
|
+
| `SubscribeOptions` / `PreloadHandle` / `PreloadOptions` / `WarmupHandle` / `WarmupOptions` / `FalsyQuery` | Subscribe / preload / warmup options |
|
|
39
39
|
| `MutationResult` / `MutationOptions` | `mutate()` return + options |
|
|
40
40
|
| `ConnectionStatus` / `SchemaEvent` / `SchemaEventKind` | Connection + schema status |
|
|
41
41
|
| `LogoutBehavior` | `'keep' \| 'forget'` durable logout policy (here only — `/adapter` references it, no double-listing) |
|
|
@@ -79,6 +79,7 @@ interface DoyncClient {
|
|
|
79
79
|
mutate(mutation, args, options?): MutationResult // { client, server }
|
|
80
80
|
|
|
81
81
|
preload(bound | FalsyQuery, options?): PreloadHandle
|
|
82
|
+
warmup(bound | FalsyQuery, options?): WarmupHandle // held ahead of a mount
|
|
82
83
|
|
|
83
84
|
readonly userId: string | null
|
|
84
85
|
readonly connectionStatus: ConnectionStatus
|
package/dist/adapter.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./client-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./client-AGRXHAJy.cjs");let t=require("@doync/core/internal");function n(e){let n=e.schedule??((e,t)=>{let n=setTimeout(e,t);return()=>clearTimeout(n)}),r=e.scheduleInterval??((e,t)=>{let n=setInterval(e,t);return()=>clearInterval(n)}),i=e.backoffBaseMs??250,a=e.backoffMaxMs??1e4,o=e.pingIntervalMs??3e4,s=e.random??Math.random,c=null,l=[],u=!1,d=0,f=!1,p=!1,m=null,h=!1;function g(){let e=null;return{arm(t,r){e?.();let i=!0,a=n(()=>{i&&(i=!1,e=null,t())},r);e=()=>{i=!1,typeof a==`function`&&a()}},clear(){e?.(),e=null}}}let _=g(),v=g(),y=g(),b=g();function x(){v.clear(),y.clear()}function S(){m?.(),m=null,_.clear()}function C(t,n){c===t&&(c=null,x(),S(),u||e.onDisconnected?.({code:n,wasError:p}),u||j())}function w(e){e.onclose=null,e.onerror=null,e.onopen=null,e.onmessage=null}function T(e){c===e&&(w(e),e.close(),C(e,void 0))}function E(e){_.arm(()=>{c!==e||e.readyState!==`open`||T(e)},5e3)}function D(){S(),m=r(()=>{let e=c;e?.readyState===`open`&&(E(e),e.send(t.PING_FRAME))},o)}function O(e){v.clear(),e.readyState===`connecting`&&v.arm(()=>{c!==e||e.readyState!==`connecting`||T(e)},3e4)}function k(e){y.arm(()=>{c!==e||e.readyState!==`open`||(d=0)},5e3)}function A(){if(!(!c||c.readyState!==`open`))for(;l.length>0;){let e=l.shift();e!==void 0&&c.send(e)}}function j(){if(h)return;let e=Math.min(i*2**d,a),t=Math.min(1,Math.max(0,s())),n=e/2+e/2*t;d++,b.arm(()=>{u||h||M()},n)}function M(){if(h||c&&c.readyState!==`closed`)return;x(),S(),e.onConnecting?.();let t=e.connect();c=t,p=!1,t.onopen=()=>{c===t&&(v.clear(),k(t),f&&(l.length=0),f=!0,e.onReconnect(),A(),D())},t.onmessage=n=>{c===t&&(_.clear(),e.onMessage?.(n))},t.onerror=()=>{c===t&&(p=!0)},t.onclose=e=>{C(t,e)},O(t)}return{get isConnected(){return c?.readyState===`open`},open(){h||(u=!1,M())},close(){u=!0,S(),x(),b.clear(),c?.close(),c=null},reconnect(){if(h||c===null)return;u=!1;let t=c;c=null,S(),x(),w(t),e.onDisconnected?.({}),j(),t.close()},reconnectNow(){h||c&&c.readyState!==`closed`||(u=!1,b.clear(),M())},__simulateDisconnect(){h=!0,b.clear(),c!==null&&(u=!1,T(c))},__simulateReconnect(){h=!1,u=!1,b.clear(),M()},send(e){l.push(e),A()}}}exports.createClient=e.t,exports.createReconnectingSocket=n;
|
package/dist/adapter.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as SyncSocket, H as LocalDb, U as LocalRow, V as SyncSocketHandlers, n as createClient, t as CreateClientOptions, z as SeamStatus } from "./client-BZWglwNl.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/socket-reconnect.d.ts
|
|
4
4
|
/**
|
package/dist/adapter.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as SyncSocket, H as LocalDb, U as LocalRow, V as SyncSocketHandlers, n as createClient, t as CreateClientOptions, z as SeamStatus } from "./client-tAY8RnNM.js";
|
|
2
2
|
|
|
3
3
|
//#region src/socket-reconnect.d.ts
|
|
4
4
|
/**
|
package/dist/adapter.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./client-
|
|
1
|
+
import{t as e}from"./client-Dphx71Qk.js";import{PING_FRAME as t}from"@doync/core/internal";function n(e){let n=e.schedule??((e,t)=>{let n=setTimeout(e,t);return()=>clearTimeout(n)}),r=e.scheduleInterval??((e,t)=>{let n=setInterval(e,t);return()=>clearInterval(n)}),i=e.backoffBaseMs??250,a=e.backoffMaxMs??1e4,o=e.pingIntervalMs??3e4,s=e.random??Math.random,c=null,l=[],u=!1,d=0,f=!1,p=!1,m=null,h=!1;function g(){let e=null;return{arm(t,r){e?.();let i=!0,a=n(()=>{i&&(i=!1,e=null,t())},r);e=()=>{i=!1,typeof a==`function`&&a()}},clear(){e?.(),e=null}}}let _=g(),v=g(),y=g(),b=g();function x(){v.clear(),y.clear()}function S(){m?.(),m=null,_.clear()}function C(t,n){c===t&&(c=null,x(),S(),u||e.onDisconnected?.({code:n,wasError:p}),u||j())}function w(e){e.onclose=null,e.onerror=null,e.onopen=null,e.onmessage=null}function T(e){c===e&&(w(e),e.close(),C(e,void 0))}function E(e){_.arm(()=>{c!==e||e.readyState!==`open`||T(e)},5e3)}function D(){S(),m=r(()=>{let e=c;e?.readyState===`open`&&(E(e),e.send(t))},o)}function O(e){v.clear(),e.readyState===`connecting`&&v.arm(()=>{c!==e||e.readyState!==`connecting`||T(e)},3e4)}function k(e){y.arm(()=>{c!==e||e.readyState!==`open`||(d=0)},5e3)}function A(){if(!(!c||c.readyState!==`open`))for(;l.length>0;){let e=l.shift();e!==void 0&&c.send(e)}}function j(){if(h)return;let e=Math.min(i*2**d,a),t=Math.min(1,Math.max(0,s())),n=e/2+e/2*t;d++,b.arm(()=>{u||h||M()},n)}function M(){if(h||c&&c.readyState!==`closed`)return;x(),S(),e.onConnecting?.();let t=e.connect();c=t,p=!1,t.onopen=()=>{c===t&&(v.clear(),k(t),f&&(l.length=0),f=!0,e.onReconnect(),A(),D())},t.onmessage=n=>{c===t&&(_.clear(),e.onMessage?.(n))},t.onerror=()=>{c===t&&(p=!0)},t.onclose=e=>{C(t,e)},O(t)}return{get isConnected(){return c?.readyState===`open`},open(){h||(u=!1,M())},close(){u=!0,S(),x(),b.clear(),c?.close(),c=null},reconnect(){if(h||c===null)return;u=!1;let t=c;c=null,S(),x(),w(t),e.onDisconnected?.({}),j(),t.close()},reconnectNow(){h||c&&c.readyState!==`closed`||(u=!1,b.clear(),M())},__simulateDisconnect(){h=!0,b.clear(),c!==null&&(u=!1,T(c))},__simulateReconnect(){h=!1,u=!1,b.clear(),M()},send(e){l.push(e),A()}}}export{e as createClient,n as createReconnectingSocket};
|
|
2
2
|
//# sourceMappingURL=adapter.js.map
|
|
@@ -3,13 +3,13 @@ let e=require("@doync/core/internal"),t=require("@doync/sqlite-parser");var n=cl
|
|
|
3
3
|
ON CONFLICT (k) DO UPDATE SET v = excluded.v`,t,n)}var ee="CREATE TABLE `__doync_membership` (\n `instance` text NOT NULL,\n `level` integer NOT NULL,\n `tbl` text NOT NULL,\n `pk` text NOT NULL,\n PRIMARY KEY(`instance`, `level`, `pk`)\n) WITHOUT ROWID;\n--> statement-breakpoint\nCREATE INDEX `__doync_membership_by_row` ON `__doync_membership` (`tbl`,`pk`);--> statement-breakpoint\nCREATE TABLE `__doync_meta` (\n `k` text PRIMARY KEY NOT NULL,\n `v` blob\n) WITHOUT ROWID;\n--> statement-breakpoint\nCREATE TABLE `__doync_pending` (\n `mutation_id` integer PRIMARY KEY NOT NULL,\n `name` text NOT NULL,\n `args` text NOT NULL,\n `idem_key` text\n);\n",te="CREATE TABLE `__doync_release_stamp` (\n `instance` text PRIMARY KEY NOT NULL,\n `cookie` integer NOT NULL,\n `released_at` integer NOT NULL,\n `ttl_ms` integer NOT NULL\n) WITHOUT ROWID;\n",ne="CREATE TABLE `__doync_prefs` (\n `k` text PRIMARY KEY NOT NULL,\n `v` blob\n) WITHOUT ROWID;\n--> statement-breakpoint\nINSERT INTO `__doync_prefs` (`k`, `v`)\n SELECT `k`, `v` FROM `__doync_meta` WHERE `k` = 'logout_behavior';\n--> statement-breakpoint\nDELETE FROM `__doync_meta` WHERE `k` = 'logout_behavior';\n",re=[{idx:0,version:`6`,when:1784031358638,tag:`0000_replica_engine_v0`,breakpoints:!0},{idx:1,version:`6`,when:1784450022155,tag:`0001_release_stamps`,breakpoints:!0},{idx:2,version:`6`,when:1785060176159,tag:`0002_prefs_table`,breakpoints:!0}];const ie={"0000_replica_engine_v0":ee,"0001_release_stamps":te,"0002_prefs_table":ne},_=re.slice().sort((e,t)=>e.idx-t.idx).map(e=>{let t=ie[e.tag];if(t===void 0)throw Error(`doync: replica engine track missing sql for journal tag ${JSON.stringify(e.tag)}`);return t.split(/-->\s*statement-breakpoint/).map(e=>e.trim()).filter(e=>e.length>0)});function v(e){e.exec(`CREATE TABLE IF NOT EXISTS __doync_engine (
|
|
4
4
|
k TEXT PRIMARY KEY,
|
|
5
5
|
v
|
|
6
|
-
) WITHOUT ROWID`)}function
|
|
7
|
-
ON CONFLICT (k) DO UPDATE SET v = excluded.v`,r),n=r}}function
|
|
6
|
+
) WITHOUT ROWID`)}function ae(e,t){let n=t;for(;n<_.length;){let t=_[n];if(t===void 0)break;let r=n+1;for(let n of t)e.exec(n);e.exec(`INSERT INTO __doync_engine (k, v) VALUES ('track_version', ?)
|
|
7
|
+
ON CONFLICT (k) DO UPDATE SET v = excluded.v`,r),n=r}}function oe(e){v(e);let t=e.exec(`SELECT v FROM __doync_engine WHERE k = 'track_version'`),n=t.length===0?0:Number(t[0]?.v);if((!Number.isFinite(n)||n<0)&&(n=0),n>_.length)return console.warn(`doync: replica engine track_version ${n} is above bundled track length ${_.length} — wiping engine tables and rebuilding (code rollback against a newer database). Consumer state will resync through wipe-and-resync.`),y(e),{rolledBack:!0};try{ae(e,n)}catch(t){return console.warn(`doync: replica engine track failed at version ${n} — wiping engine tables and rebuilding (code rollback against a newer database). Consumer state will resync through wipe-and-resync.`,t),y(e),{rolledBack:!0}}return{rolledBack:!1}}function y(e){let t=null;try{t=h(e,`logout_behavior`)}catch{}e.exec(`DROP TABLE IF EXISTS __doync_release_stamp`),e.exec(`DROP TABLE IF EXISTS __doync_membership`),e.exec(`DROP TABLE IF EXISTS __doync_prefs`),e.exec(`DROP TABLE IF EXISTS __doync_meta`),e.exec(`DROP TABLE IF EXISTS __doync_pending`),e.exec(`DROP TABLE IF EXISTS __doync_engine`),v(e),ae(e,0),t!==null&&g(e,`logout_behavior`,t)}function se(e){return e===void 0?18e5:e}function ce(e,t){e.exec(`INSERT INTO __doync_release_stamp (instance, cookie, released_at, ttl_ms)
|
|
8
8
|
VALUES (?, ?, ?, ?)
|
|
9
9
|
ON CONFLICT (instance) DO UPDATE SET
|
|
10
10
|
cookie = excluded.cookie,
|
|
11
11
|
released_at = excluded.released_at,
|
|
12
|
-
ttl_ms = excluded.ttl_ms`,t.instance,t.cookie,t.releasedAt,t.ttlMs)}function
|
|
13
|
-
FROM __doync_release_stamp WHERE instance = ?`,t)[0];return n===void 0?null:S(n)}function w(e){return e.exec(`SELECT instance, cookie, released_at, ttl_ms FROM __doync_release_stamp`).map(S)}function T(t){if(!(0,e.isSqlIdentifier)(t))throw Error(`doync: refusing to quote non-identifier ${JSON.stringify(t)}`);return`"${t}"`}function E(t,n){let r=JSON.parse(t),i=(0,e.tablePrimaryKey)(n);if(!Array.isArray(r)||r.length!==i.length)throw Error(`doync: malformed pk ${t} for table ${n.name} (expected ${i.length} key part(s))`);return r.map(t=>(0,e.decodePkValue)(t))}function D(t){return(0,e.tablePrimaryKey)(t).map(e=>`${T(e)} = ?`).join(` AND `)}function le(t,n){let r=Object.keys(n);for(let n of r)if(!(0,e.isSqlIdentifier)(n))throw Error(`doync: patch image for table ${t.name} has an invalid column name ${JSON.stringify(n)}`);return{columns:r,values:r.map(t=>(0,e.decodeImageValue)(n[t]))}}function O(e,t){let n=e.tables.find(e=>e.name===t);if(n===void 0)throw Error(`doync: no synced table named ${JSON.stringify(t)} in the client schema`);return n}function k(e){return ae(e)}function A(t,n){p(t,`schema_version`)===null&&j(t,n,0,(0,e.declaredSchemaVersion)(n))}function j(e,t,n,r){for(let i of f(t,n,r))e.execBatch(i);m(e,`schema_version`,String(r))}function M(e,t){for(let n of t.tables)e.exec(`DROP TABLE IF EXISTS ${T(n.name)}`)}function ue(t){for(let n of t.tables)if((0,e.isInternalTable)(n.name))throw Error(`doync: synced table ${n.name} uses the reserved __doync_ prefix`)}const N=`logout_behavior`,P=`connected_clock`,F=`doync_optimistic`,I=`doync_body`;var L=class{lifecycle;decode;one;#e=!1;#t=null;#n=new Set;#r=J;#i=Y;#a=!1;#o=null;constructor(e,t,n){this.lifecycle=e,this.decode=t,this.one=n}#s(e){if(this.#o?.read!==e||this.#o.generation!==e.generation){let t=e.rawRows();this.#r=this.decode?this.decode(t):t,this.#o={read:e,generation:e.generation}}return this.#r}#c(){if(this.#a)return;this.#a=!0;let e=this.lifecycle.peek();if(e!==null)this.#s(e),this.#i=e.status();else{let e=this.lifecycle.compute();this.#r=e.rows,this.#i=e.status}}current(){let e=this.lifecycle.peek();return e!==null&&e.generation>0?(this.#a=!0,this.#s(e)):(this.#c(),this.#r)}status(){let e=this.lifecycle.peek();return e===null?(this.#c(),this.#i):(this.#a=!0,this.#i=e.status(),this.#i)}onChange(e){return this.#n.add(e),()=>this.#n.delete(e)}retain(){if(this.#e)return;this.#e=!0,this.#a=!0;let e=this.lifecycle.retain();if(this.#t=e.onChange(()=>{this.#s(e),this.#i=e.status();for(let e of this.#n)e()}),e.generation>0&&(this.#o?.read!==e||this.#o.generation!==e.generation)||e.status()!==this.#i){e.generation>0&&this.#s(e),this.#i=e.status();for(let e of this.#n)e()}}release(){this.#e&&(this.#e=!1,this.#t?.(),this.#t=null,this.lifecycle.release())}},R=class{#e;#t;#n;#r;#i;#a;#o=null;#s;#c;#l=1;#u=null;#d=!1;#f=0;#p=null;#m;#h=!1;#g=null;#_=!1;#v=new Set;#y=0;#b=0;#x=null;#S;#C=new Set;#w=!1;#T=[];#E=new Map;#D=new Map;#O=new Set;#k=new Set;#A=new Map;#j=new Map;#M=new Map;#N=new Map;#P=new Map;#F=1;#I=new Map;#L=new Map;#R=new Set;#z=null;#B=[];#V=!1;#H=[];#U=new Set;constructor(e){this.#e=e.db,this.#t=e.schema,this.#n=e.mutations,this.#r=e.socket,this.#i=e.ctx??null,this.#a=e.token,this.#o=e.userId??null,this.#S=e.onSchemaEvent,this.#c=e.generateId??ve,this.#m=e.now??Date.now,this.#W(e),this.#r.setHandlers({message:e=>this.#Ee(e),open:()=>this.#xe(),close:()=>{this.#p=null,this.#rt(!1)},status:e=>this.#it(e)})}get connectedClock(){return this.#f}releaseStamp(e){return C(this.#e,e)}releaseStamps(){return w(this.#e)}get clientId(){return this.#s}get userId(){return this.#o}get cookie(){return this.#u}get errors(){return this.#B}get recoveredKeys(){return this.#O}get schemaVersion(){return this.#y}get schemaStatus(){return this.#x}#W(t){let n=this.#e;n.exec(`PRAGMA foreign_keys = OFF`),ue(this.#t);let{rolledBack:r}=k(n);r?(this.#Ge(n,(0,e.declaredSchemaVersion)(this.#t)),this.#u=null):A(n,this.#t),this.#y=(0,e.declaredSchemaVersion)(this.#t);let i=be(n);i!==null&&(console.error(`doync: durable meta "${i}" is corrupt — healing by FORGETTING the local store (fresh identity, full re-hydration). A corrupt mutation counter makes the pending queue untrustworthy, so unsynced writes are discarded rather than risk double-apply.`),this.#Ke(n)),this.#b=this.#G(n,`schema_version`)??0;let a=p(n,`client_id`);this.#s=a??t.clientId??this.#c(),a===null&&m(n,`client_id`,this.#s),this.#l=this.#G(n,`next_mutation_id`)??1,this.#u=this.#G(n,`cookie`);let o=Number(p(n,P));Number.isInteger(o)&&o>=0?this.#f=o:(p(n,`connected_clock`)!==null&&console.warn(`doync: durable connected-clock reading is corrupt — resetting to 0 (clock runs slow; GC defers, server full-hydrates)`),this.#f=0),this.#p=null,i!==null&&this.#$e(`forget`,`corrupt durable meta "${i}" — forgot the local store and reset to a fresh identity`),this.#T=n.exec(`SELECT mutation_id, name, args, idem_key FROM __doync_pending ORDER BY mutation_id ASC`).map(t=>{let n=JSON.parse(String(t.args));return{mutationId:Number(t.mutation_id),name:String(t.name),wireArgs:n,args:(0,e.decodeArgs)(n,`mutation args`),key:t.idem_key===null?void 0:String(t.idem_key)}});for(let e of this.#T){let t=this.#ut(e.mutationId,!0);e.key!==void 0&&(this.#D.set(e.key,t.pair),this.#O.add(e.key))}this.#ge({includeStampless:!1}),n.drainWrittenTables();let s=this.#Q();z(s)&&(this.#V=!0,s.then(()=>this.#J(),()=>this.#J()))}#G(e,t){let n=p(e,t);if(n===null)return null;let r=Number(n);if(!Number.isInteger(r))throw Error(`doync: durable meta "${t}" is corrupt (${JSON.stringify(n)} → ${r}) — a non-integer must never ride the wire (ADR-0019 next-id trap); the boot-time corrupt-meta heal should have caught this`);return r}#K(e){if(this.#V){this.#H.push(e);return}this.#V=!0,this.#q(e)}#q(e){let t;try{t=e()}catch(e){throw this.#V=!1,this.#Y(),e}z(t)?t.then(()=>this.#J(),e=>{this.#B.push(`doync: exclusive-chain step rejected — ${K(e)}`),this.#J()}):this.#J()}#J(){this.#V=!1,this.#Y()}#Y(){let e=this.#H.shift();if(e!==void 0){this.#V=!0,this.#q(e);return}this.#X()}#X(){if(this.#U.size===0)return;let e=[...this.#U];this.#U.clear();for(let t of e)t.recompute()&&t.notify()}#Z(e){this.#V?this.#U.add(e):e.recompute()}#Q(){return this.#e.drainWrittenTables(),this.#e.exec(`SAVEPOINT ${F}`),this.#_=!0,this.#A.clear(),B(this.#$(0),()=>{this.#R=W(this.#e.drainWrittenTables())})}#$(e){for(let t=e;t<this.#T.length;t++){let e=this.#ne(this.#T[t]);if(z(e))return e.then(()=>this.#$(t+1))}}#ee(){this.#_&&=(this.#e.exec(`ROLLBACK TO ${F}`),this.#e.exec(`RELEASE ${F}`),!1)}#te(e){let t=this.#R;this.#ee(),this.#e.drainWrittenTables(),this.#e.exec(`BEGIN`);try{e(),this.#e.exec(`COMMIT`)}catch(e){return this.#e.exec(`ROLLBACK`),B(this.#Q(),()=>{throw e})}let n=W(this.#e.drainWrittenTables());return B(this.#Q(),()=>new Set([...t,...n,...this.#R]))}#ne(e){this.#e.exec(`SAVEPOINT ${I}`);let t;try{let n=this.#n[e.name];if(n===void 0)throw Error(`unknown mutation "${e.name}"`);t=n.body({args:e.args,ctx:this.#i,sql:this.#ae()})}catch(t){this.#ie(e.mutationId,t);return}if(z(t))return t.then(()=>this.#re(e.mutationId),t=>this.#ie(e.mutationId,t));this.#re(e.mutationId)}#re(e){this.#e.exec(`RELEASE ${I}`),this.#A.delete(e)}#ie(e,t){this.#e.exec(`ROLLBACK TO ${I}`),this.#e.exec(`RELEASE ${I}`),this.#A.set(e,t)}#ae(){return{exec:(e,...t)=>this.#e.exec(e,...t.map(e=>typeof e==`boolean`?+!!e:e))}}#oe(e){this.#r.send({type:`push`,clientId:this.#s,mutationId:e.mutationId,name:e.name,args:e.wireArgs})}mutate(t,n,r){let i=r?.key;if(i!==void 0){let e=this.#D.get(i);if(e!==void 0)return e}let a=t.name;if(a===void 0||a===``)return G(Error(`doync: mutate requires a registered mutation — wrap it in defineMutations(...) so it carries a dotted name`));let o=this.#n[a];if(o===void 0)return G(Error(`doync: unknown mutation "${a}"`));let s,c;try{s=(0,e.prepareArgs)(o.args,n,`mutation args`),c=(0,e.encodeArgs)(s,`mutation args`)}catch(e){return G(e)}let l=this.#dt(!1);return i!==void 0&&this.#D.set(i,l.pair),this.#K(()=>this.#se({name:a,args:s,wireArgs:c,key:i,promise:l})),l.pair}#se(e){let t=this.#e,n=this.#l;this.#E.set(n,e.promise);let r={mutationId:n,name:e.name,args:e.args,wireArgs:e.wireArgs,key:e.key};return B(this.#te(()=>{t.exec(`INSERT INTO __doync_pending (mutation_id, name, args, idem_key) VALUES (?, ?, ?, ?)`,n,r.name,JSON.stringify(r.wireArgs??null),r.key??null),this.#l=n+1,m(t,`next_mutation_id`,String(this.#l)),this.#T.push(r)}),e=>this.#ce(r,e))}#ce(e,t){let n=e.mutationId;if(!this.#A.has(n)){this.#ft(n,null),this.#st(t),this.#d&&this.#oe(e);return}let r=this.#A.get(n),i=this.#E.get(n)?.pair;return e.key!==void 0&&this.#D.delete(e.key),B(this.#le(n,!0),e=>{this.#ft(n,r),this.#pt(n,r),i?.client.catch(()=>{}),i?.server.catch(()=>{}),this.#st(new Set([...t,...e]))})}#le(e,t=!1){let n=this.#e;return this.#te(()=>{n.exec(`DELETE FROM __doync_pending WHERE mutation_id = ?`,e),this.#T=this.#T.filter(t=>t.mutationId!==e),t&&(this.#l=e,m(n,`next_mutation_id`,String(e)))})}updateAuth(e,t,n){this.#a=e??void 0,n!==void 0&&(this.#o=n),t!==void 0&&(this.#i=t),this.#d&&!this.#w&&typeof e==`string`&&e!==``&&this.#r.send({type:`updateAuth`,jwt:e})}subscribe(e,t){if(H(e))return new V;let{query:n,args:r,options:i}=U(`subscribe`,e,t);if(i?.skip)return new V;let a=n.name,o=n.resolve({args:r,ctx:this.#i}),s={sql:o.sql,params:o.params},c=o.identity,l={name:a,args:r,ttl:i?.ttl,statement:s},u=o.decode;return new L({peek:()=>this.#M.get(c)?.read??null,retain:()=>this.#de(c,l),release:()=>this.#pe(c),compute:()=>{if(this.#V)return{rows:J,status:Y};let e=this.#e.exec(s.sql,...s.params),t=this.#M.get(c);return{rows:u?u(e):e,status:Z(t?.phase??`pending`,t?.error)}}},u,o.one??!1)}preload(e,t){if(H(e))return ge;let{query:n,args:r,options:i}=U(`preload`,e,t),a=n.name,o=n.resolve({args:r,ctx:this.#i}),s=o.identity;this.#fe(s,{name:a,args:r,ttl:i?.ttl,statement:{sql:o.sql,params:o.params}});let c=!1;return{cleanup:()=>{c||(c=!0,this.#pe(s))}}}#ue(e,t){let n=this.#M.get(e);if(n===void 0){let r=this.#Te(e);n={name:t.name,args:t.args,ttl:t.ttl,count:0,read:null,phase:`pending`,error:void 0},this.#M.set(e,n),this.#We(()=>x(this.#e,e)),this.#d&&this.#r.send({type:`subscribe`,queries:[this.#we(e,{heldAt:r})]})}else n.phase===`error`&&this.#d?(this.#lt(e,`pending`),this.#r.send({type:`subscribe`,queries:[this.#we(e)]})):t.ttl!==void 0&&(n.ttl===void 0||t.ttl>n.ttl)&&(n.ttl=t.ttl,this.#d&&this.#r.send({type:`subscribe`,queries:[this.#we(e)]}));return n.count+=1,n}#de(e,t){let r=this.#ue(e,t);if(r.read===null){let i=this.#L.get(e);if(i!==void 0)clearTimeout(i.timer),this.#L.delete(e),r.read=i.read,this.#Z(i.read);else{let i=new n({run:e=>this.#e.exec(e.sql,...e.params),readSet:()=>{let t=this.#j.get(e);return t===void 0?void 0:new Set(t.readSet)}},t.statement,e,Z(r.phase,r.error));r.read=i,this.#Z(i)}}return r.read}#fe(e,t){this.#ue(e,t)}#pe(t){let n=this.#M.get(t);n===void 0||--n.count>0||(this.#M.delete(t),this.#d&&this.#r.send({type:`unsubscribe`,queries:[{name:n.name,args:n.args===void 0?void 0:(0,e.encodeArgs)(n.args,`query args`)}]}),this.#me(t,n.ttl),n.read!==null&&this.#ve(t,n.read))}#me(e,t){let n=this.#u;if(n===null)return;let r={instance:e,cookie:n,releasedAt:this.#f,ttlMs:oe(t)};this.#K(()=>B(this.#te(()=>{se(this.#e,r),this.#ge({includeStampless:!0}),this.#he()}),e=>this.#st(e)))}#he(){m(this.#e,P,String(this.#f))}#ge(e){let t=this.#_e(e.includeStampless);if(t.length!==0){for(let e of t)this.#Le(e);this.#he()}}#_e(e){let t=this.#M,n=w(this.#e),r=new Set(n.map(e=>e.instance)),i=[];if(e){let e=this.#e.exec(`SELECT DISTINCT instance FROM __doync_membership`);for(let n of e){let e=String(n.instance);t.has(e)||r.has(e)||i.push(e)}}let a=this.#f;for(let e of n)t.has(e.instance)||(e.ttlMs<=0||a-e.releasedAt>e.ttlMs)&&i.push(e.instance);return i}#ve(e,t){let n=this.#L.get(e);n!==void 0&&clearTimeout(n.timer),this.#L.set(e,{read:t,timer:setTimeout(()=>{let n=this.#L.get(e);n===void 0||n.read!==t||(this.#L.delete(e),this.#U.delete(t))},q)})}once(t){if(H(t))return new he;let{query:n,args:r}=U(`once`,t),i=n.name,a=n.resolve({args:r,ctx:this.#i}),o;if(this.#V)o=[];else{let e=this.#e.exec(a.sql,...a.params);o=a.decode?a.decode(e):e}let s=`once-${this.#F++}`,c=r===void 0?void 0:(0,e.encodeArgs)(r,`query args`),l=new fe(o,a.decode,{start:()=>{this.#N.set(s,{view:l,name:i,args:c}),this.#d&&this.#r.send({type:`once`,id:s,name:i,args:c})},drop:()=>{this.#N.delete(s),this.#P.delete(s)}});return l}local(e,...t){let n=`local:${e}\u0000${JSON.stringify(t)}`,r={sql:e,params:t};return new L({peek:()=>this.#I.get(n)?.read??null,retain:()=>this.#ye(n,r),release:()=>this.#be(n),compute:()=>this.#V?{rows:J,status:Y}:{rows:this.#e.exec(r.sql,...r.params),status:X}},void 0,void 0)}#ye(e,t){let r=this.#I.get(e);if(r===void 0&&(r={count:0,read:null},this.#I.set(e,r)),r.count+=1,r.read===null){let i=this.#L.get(e);if(i!==void 0)clearTimeout(i.timer),this.#L.delete(e),r.read=i.read,this.#Z(i.read);else{let e=new n({run:e=>this.#e.exec(e.sql,...e.params),readSet:()=>void 0},t,void 0,X);r.read=e,this.#Z(e)}}return r.read}#be(e){let t=this.#I.get(e);t===void 0||--t.count>0||(this.#I.delete(e),t.read!==null&&this.#ve(e,t.read))}#xe(){this.#w||(this.#p=null,this.#rt(!0),this.#Ce())}#Se(){let e=this.#m();if(this.#p!==null){let t=e-this.#p;t>0&&(this.#f+=t)}this.#p=e}#Ce(){for(let e of this.#M.keys())this.#lt(e,`pending`);this.#r.send({type:`connect`,clientId:this.#s,...this.#a===void 0?{}:{jwt:this.#a},cookie:this.#u,desiredQueries:[...this.#M.keys()].map(e=>this.#we(e)),schemaVersion:this.#y});for(let e of this.#T)this.#oe(e);for(let[e,t]of this.#N)this.#r.send({type:`once`,id:e,name:t.name,args:t.args})}#we(t,n){let r=this.#M.get(t),i=n===void 0?this.#Te(t):n.heldAt;return{name:r?.name??t,args:r?.args===void 0?void 0:(0,e.encodeArgs)(r.args,`query args`),...r?.ttl===void 0?{}:{ttl:r.ttl},...i===void 0?{}:{heldAt:i}}}#Te(e){if(!(this.#e.exec(`SELECT 1 FROM __doync_membership WHERE instance = ? LIMIT 1`,e).length>0))return;if(this.#M.has(e))return this.#u??void 0;let t=C(this.#e,e);if(t!==null)return t.cookie}#Ee(e){if(this.#w){e.type===`error`&&this.#B.push(e.message);return}if(e.type===`pong`){this.#Se();return}if(e.type===`unauthorized`){this.#B.push(e.message),this.#at(!0);return}if(e.type===`pokeStart`&&e.clientId!==this.#s){this.#B.push(`doync: pokeStart addressed to client ${e.clientId}, this engine is ${this.#s}`);return}switch(this.#h&&e.type!==`error`&&this.#at(!1),e.type){case`schemaSkew`:this.#Be(e);break;case`schema`:this.#Ve(e);break;case`subscribeAck`:this.#et();for(let t of e.instances){this.#j.set(t.instance,t);let e=this.#M.get(t.instance);e!==void 0&&e.phase!==`complete`&&this.#lt(t.instance,`acked`)}break;case`pokeStart`:this.#et(),this.#z=[];break;case`pokePart`:if(this.#z===null)this.#B.push(`doync: pokePart arrived with no open poke`);else for(let t of e.patches)this.#z.push(t);break;case`pokeEnd`:this.#z===null?this.#B.push(`doync: pokeEnd arrived with no open poke`):this.#Ae(e.cookie,e.lastMutationId,e.confirms);break;case`pokeReject`:this.#ze(e.mutationId,e.error,e.reason);break;case`onceStart`:this.#P.set(e.id,[]);break;case`oncePart`:{let t=this.#P.get(e.id);if(t===void 0)this.#B.push(`doync: oncePart arrived with no open once`);else for(let n of e.rows)t.push(n);break}case`onceEnd`:this.#ke(e);break;case`resyncRequired`:this.#B.push(e.message),this.#K(()=>this.#Ze(`heldAt ahead of vouched baseline (instance ${e.instance}: heldAt=${e.heldAt} baseline=${e.baseline}) — ${e.message}`));break;case`error`:if(this.#B.push(e.message),xe(e.message)){this.#K(()=>this.#Ze(`cookie above the Origin head (server reset) — ${e.message}`));break}e.instances===void 0?this.#Oe(e.message):this.#De(e.instances,e.message);break;default:this.#B.push(`doync: unknown ServerMessage type ${String(e.type)}`)}}#De(e,t){let n=Error(t);for(let t of e){let e=this.#M.get(t);e!==void 0&&(e.phase===`pending`||e.phase===`acked`)&&this.#lt(t,`error`,n)}}#Oe(e){let t=Error(e);for(let[e,n]of this.#M)(n.phase===`pending`||n.phase===`acked`)&&this.#lt(e,`error`,t)}#ke(e){let t=this.#P.get(e.id)??[];this.#P.delete(e.id);let n=this.#N.get(e.id);if(n!==void 0){if(this.#N.delete(e.id),e.error!==void 0){n.view.settleError(Error(e.error));return}n.view.deliver(t.map(_e))}}#Ae(e,t,n){let r=this.#z??[];this.#z=null,this.#K(()=>this.#je(r,e,t,n))}#je(e,t,n,r){let i=this.#e,a=[];return B(this.#te(()=>{for(let t of e)t.op===`put`&&this.#Ne(t);for(let t of e)t.op===`del`&&this.#Pe(t);for(let t of e)t.op===`pks`&&this.#Fe(t);if(n!==null){for(let e of this.#T)e.mutationId<=n&&!this.#k.has(e.mutationId)&&a.push(e.mutationId);for(let e of a)i.exec(`DELETE FROM __doync_pending WHERE mutation_id = ?`,e)}this.#u=t,m(i,`cookie`,String(t)),this.#he(),this.#T=this.#T.filter(e=>!a.includes(e.mutationId))}),e=>{for(let e of a)this.#pt(e,null);for(let e of a)this.#k.delete(e);this.#st(e),this.#Me(r)})}#Me(e){if(e!==void 0)for(let t of e){let e=this.#M.get(t);e!==void 0&&e.phase===`acked`&&this.#lt(t,`complete`)}}#Ne(e){let t=this.#e,n=this.#Re(e.instance,e.level);t.exec(`INSERT INTO __doync_membership (instance, level, tbl, pk) VALUES (?, ?, ?, ?)
|
|
14
|
-
ON CONFLICT (instance, level, pk) DO UPDATE SET tbl = excluded.tbl`,e.instance,e.level,n.name,e.pk);let r=
|
|
15
|
-
VALUES (${i.map(()=>`?`).join(`, `)})`,...a)}#Pe(e){this.#Ie(e.instance,e.level,e.pk)}#Fe(e){let t=new Set(e.pks),n=this.#e.exec(`SELECT pk FROM __doync_membership WHERE instance = ? AND level = ?`,e.instance,e.level);for(let r of n){let n=String(r.pk);t.has(n)||this.#Ie(e.instance,e.level,n)}}#Ie(e,t,n){let r=this.#e,i=this.#Re(e,t);r.exec(`DELETE FROM __doync_membership WHERE instance = ? AND level = ? AND pk = ?`,e,t,n);let a=r.exec(`SELECT DISTINCT instance FROM __doync_membership WHERE tbl = ? AND pk = ?`,i.name,n);if(!a.some(e=>this.#M.has(String(e.instance)))){r.exec(`DELETE FROM ${T(i.name)} WHERE ${D(i)}`,...E(n,i));for(let e of a)this.#Le(String(e.instance))}}#Le(e){let t=this.#e,n=t.exec(`SELECT DISTINCT tbl, pk FROM __doync_membership WHERE instance = ?`,e);t.exec(`DELETE FROM __doync_membership WHERE instance = ?`,e),x(t,e);for(let e of n){let n=String(e.tbl),r=String(e.pk);if(t.exec(`SELECT 1 FROM __doync_membership WHERE tbl = ? AND pk = ? LIMIT 1`,n,r).length===0){let e=O(this.#t,n);t.exec(`DELETE FROM ${T(e.name)} WHERE ${D(e)}`,...E(r,e))}}}#Re(e,t){let n=this.#j.get(e);if(n===void 0)throw Error(`doync: patch for unknown instance ${e} — a subscribeAck must precede its hydration poke`);let r=n.levels.find(e=>e.level===t);if(r===void 0)throw Error(`doync: instance ${e} has no Level ${t} in its subscribeAck`);return O(this.#t,r.table)}#ze(e,t,n){if(this.#k.add(e),n===`reaped`){let e=this.#T.length;this.#B.push(t),this.#K(()=>this.#Ze(`server forgot this client (reaped) — dropped ${e} pending write${e===1?``:`s`} — ${t}`,`reaped`));return}this.#K(()=>B(this.#le(e),n=>{this.#pt(e,Error(t)),this.#st(n)}))}#Be(e){let t=e.serverVersion===void 0?``:` (server v${e.serverVersion})`;e.reason===`client-stale`?(this.#$e(`reload`,`schema client-stale: bundle v${this.#y} is behind the Mirror${t} — reload for the new bundle`),this.#nt()):(this.#$e(`server-behind`,`schema client-ahead: bundle v${this.#y} is ahead of the Mirror${t} — backing off until it deploys`),this.#rt(!1),this.#r.reconnect())}#Ve(e){let t=e.version;if(t>this.#y){this.#$e(`reload`,`schema directive v${t} is above the bundled track v${this.#y} — reload for the new bundle`),this.#nt();return}t<=this.#b||this.#K(()=>this.#He(t))}#He(e){let t=t=>`local migration to schema v${e} failed: ${K(t)}`,n;try{n=this.#te(()=>{j(this.#e,this.#t,this.#b,e)})}catch(e){return this.#Ze(t(e))}return de(n,t=>{this.#b=e,this.#st(new Set([...t,...this.#Qe()]))},e=>this.#Ze(t(e)))}resync(){this.#K(()=>this.#Ze(`resync() requested by the consumer`))}forget(){this.#K(()=>this.#Je(`forget() requested by the consumer`))}setLogoutBehavior(e){this.#Ue(N,e)}#Ue(e,t){this.#We(()=>g(this.#e,e,t))}#We(e){this.#K(()=>B(this.#te(e),()=>{}))}#Ge(e,t=this.#y){M(e,this.#t),e.exec(`DELETE FROM __doync_membership`),ce(e),e.exec(`DELETE FROM __doync_pending`),e.exec(`DELETE FROM __doync_meta`),j(e,this.#t,0,t)}#Ke(e){this.#Ge(e),e.exec(`DELETE FROM __doync_prefs`)}#qe(e){let t=this.#e;this.#Xe(e),this.#s=this.#c(),m(t,`client_id`,this.#s),this.#u=null,this.#l=1,this.#f=0,this.#p=null,this.#T=[]}#Je(e){let t=this.#e,n=this.#te(()=>{this.#Ke(t),this.#qe(Error(`doync: ${e} — pending writes were forgotten`))});return this.#Ye(n,`forget`,`forgot the local store — ${e}`)}#Ye(e,t,n){return B(e,e=>{this.#b=this.#y,this.#j.clear(),this.#$e(t,n),this.#d&&(this.#rt(!1),this.#r.reconnect()),this.#st(new Set([...e,...this.#Qe()]))})}#Xe(e){for(let t of this.#E.keys())this.#ft(t,e),this.#pt(t,e);this.#D.clear(),this.#O.clear(),this.#k.clear(),this.#A.clear()}#Ze(e,t=`resync`){let n=this.#e,r=this.#te(()=>{this.#Ge(n),this.#qe(Error(`doync: ${e} — pending writes were dropped`))});return this.#Ye(r,t,t===`reaped`?`client state was reaped — ${e}`:`wiped and resyncing — ${e}`)}#Qe(){return this.#t.tables.map(e=>e.name)}onSchemaChange(e){return this.#C.add(e),()=>this.#C.delete(e)}#$e(e,t){let n={kind:e,message:t};this.#x=n,this.#S?.(n),this.#tt()}#et(){let e=this.#x?.kind;(e===`server-behind`||e===`resync`||e===`reaped`||e===`forget`)&&(this.#x=null,this.#tt())}#tt(){for(let e of this.#C)e()}#nt(){this.#w=!0,this.#rt(!1)}get connectionStatus(){return this.#h?`needs-auth`:this.#d?`connected`:this.#g??`disconnected`}onConnectionChange(e){return this.#v.add(e),()=>this.#v.delete(e)}#rt(e){this.#ot(()=>{this.#d=e,e&&(this.#g=null)})}#it(e){this.#ot(()=>{this.#g=e})}#at(e){this.#ot(()=>{this.#h=e})}#ot(e){let t=this.connectionStatus;if(e(),this.connectionStatus!==t)for(let e of this.#v)e()}#st(e){let t=W(e),n=new Set(this.#U);this.#U.clear();for(let e of this.#ct()){let r=e.readSet;(n.has(e)||r===void 0||[...r].some(e=>t.has(e)))&&e.recompute()&&e.notify()}}*#ct(){for(let e of this.#M.values())e.read!==null&&(yield e.read);for(let e of this.#I.values())e.read!==null&&(yield e.read)}#lt(e,t,n){let r=this.#M.get(e);if(r===void 0)return;r.phase=t,r.error=n;let i=Z(t,n);r.read!==null&&r.read.updateStatus(i)&&r.read.notify()}#ut(e,t){let n=this.#E.get(e);if(n!==void 0)return n;let r=this.#dt(t);return this.#E.set(e,r),r}#dt(e){let t,n,r,i,a=new Promise((e,r)=>{t=e,n=r}),o=new Promise((e,t)=>{r=e,i=t});return e&&(a.catch(()=>{}),o.catch(()=>{})),{pair:{client:a,server:o},resolveClient:t,rejectClient:n,resolveServer:r,rejectServer:i,clientSettled:!1,serverSettled:!1}}#ft(e,t){let n=this.#E.get(e);if(n===void 0){this.#B.push(`doync: settleClient for unknown mutation ${e} — no pending promise (a mutate() awaiting it would hang)`);return}n.clientSettled||(n.clientSettled=!0,t===null?n.resolveClient():n.rejectClient(t))}#pt(e,t){let n=this.#E.get(e);if(n===void 0){this.#B.push(`doync: settleServer for unknown mutation ${e} — no pending promise (a mutate() awaiting it would hang)`);return}n.serverSettled||(n.serverSettled=!0,t===null?n.resolveServer():n.rejectServer(t),n.clientSettled&&this.#E.delete(e))}};function z(e){return e instanceof Promise}function B(e,t){return e instanceof Promise?e.then(t):t(e)}function de(e,t,n){return e instanceof Promise?e.then(t,n):t(e)}var V=class{current(){return J}status(){return Y}onChange(){return()=>{}}retain(){}release(){}},fe=class{#e;#t=new Set;#n=!1;#r=!1;#i=Promise.withResolvers();#a=null;#o;#s;#c;constructor(e,t,n){this.#e=e,this.#o=t,this.#s=n.start,this.#c=n.drop}current(){return this.#l(),this.#e}onChange(e){return this.#l(),this.#t.add(e),()=>this.#t.delete(e)}get server(){return this.#l(),this.#i.promise}deliver(e){if(this.#r)return;let t=this.#o?this.#o(e):e;this.#e=t,this.#i.resolve(t);for(let e of this.#t)e()}settleError(e){this.#r||this.#i.reject(e)}dispose(){this.#r||this.#a===null&&(this.#a=setTimeout(()=>{this.#a=null,!this.#r&&(this.#r=!0,this.#t.clear(),this.#c())},q))}#l(){this.#r||(this.#a!==null&&(clearTimeout(this.#a),this.#a=null),!this.#n&&(this.#n=!0,this.#i=Promise.withResolvers(),this.#i.promise.catch(()=>{}),this.#s()))}};function H(e){return e===!1||e==null}function U(t,n,r){if((0,e.isBoundQuery)(n))return{query:n.query,args:n.args,options:r};throw pe(t,n)}function pe(e,t){return Error(typeof t==`function`?`doync: client.${e} expected a BoundQuery — received a function; did you forget to call it?`:`doync: client.${e} expected a BoundQuery, got ${me(t)}`)}function me(e){if(e===null)return`null`;if(Array.isArray(e))return`an array`;let t=typeof e;if(t===`object`){let t=e.kind;return typeof t==`string`?`an object with kind "${t}"`:`an object`}return t}var he=class{current(){return J}onChange(){return()=>{}}get server(){return new Promise(()=>{})}dispose(){}};const ge={cleanup(){}};function _e(t){let n={};for(let[r,i]of Object.entries(t))n[r]=(0,e.decodeImageValue)(i);return n}function W(t){return new Set([...t].filter(t=>!(0,e.isInternalTable)(t)))}function G(e){let t=Promise.reject(e),n=Promise.reject(e);return t.catch(()=>{}),n.catch(()=>{}),{client:t,server:n}}function K(e){return e instanceof Error?e.message:String(e)}const q=0,J=Object.freeze([]),Y=Object.freeze({status:`unknown`}),X=Object.freeze({status:`complete`});function Z(e,t){return e===`complete`?X:e===`error`?t===void 0?{status:`error`}:{status:`error`,error:t}:Y}const ve=()=>{let e=globalThis.crypto?.randomUUID?.();return e===void 0?`client-${Math.random().toString(16).slice(2)}-${Date.now().toString(16)}`:e},ye=[`schema_version`,`next_mutation_id`,`cookie`];function be(e){for(let t of ye){let n=p(e,t);if(n!==null&&!Number.isInteger(Number(n)))return t}return null}function xe(e){return e.includes(`above the Origin head`)}function Se(e){return Q(e)}function Q(t){t.logoutBehavior!==void 0&&(k(t.db),g(t.db,N,t.logoutBehavior));let n=$(t.authData,t.ctxValidationSchema);return new R({db:t.db,schema:t.schema,mutations:(0,e.flattenMutations)(t.mutations),socket:t.socket,ctx:n.ctx,token:n.token,userId:n.userId,clientId:t.clientId,onSchemaEvent:t.onSchemaEvent})}function $(t,n){if(t===null)return{userId:null,token:void 0,ctx:null};let r=t.ctx;return n!==void 0&&(r=(0,e.validateStandardSchema)(n,t.ctx,`auth context`)),{userId:t.userId,token:t.token,ctx:r}}Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return P}}),Object.defineProperty(exports,"b",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return U}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return G}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return Q}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return $}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return Se}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,"v",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"y",{enumerable:!0,get:function(){return d}});
|
|
12
|
+
ttl_ms = excluded.ttl_ms`,t.instance,t.cookie,t.releasedAt,t.ttlMs)}function b(e,t){e.exec(`DELETE FROM __doync_release_stamp WHERE instance = ?`,t)}function le(e){e.exec(`DELETE FROM __doync_release_stamp`)}function x(e){return{instance:String(e.instance),cookie:Number(e.cookie),releasedAt:Number(e.released_at),ttlMs:Number(e.ttl_ms)}}function S(e,t){let n=e.exec(`SELECT instance, cookie, released_at, ttl_ms
|
|
13
|
+
FROM __doync_release_stamp WHERE instance = ?`,t)[0];return n===void 0?null:x(n)}function C(e){return e.exec(`SELECT instance, cookie, released_at, ttl_ms FROM __doync_release_stamp`).map(x)}function w(t){if(!(0,e.isSqlIdentifier)(t))throw Error(`doync: refusing to quote non-identifier ${JSON.stringify(t)}`);return`"${t}"`}function T(t,n){let r=JSON.parse(t),i=(0,e.tablePrimaryKey)(n);if(!Array.isArray(r)||r.length!==i.length)throw Error(`doync: malformed pk ${t} for table ${n.name} (expected ${i.length} key part(s))`);return r.map(t=>(0,e.decodePkValue)(t))}function E(t){return(0,e.tablePrimaryKey)(t).map(e=>`${w(e)} = ?`).join(` AND `)}function ue(t,n){let r=Object.keys(n);for(let n of r)if(!(0,e.isSqlIdentifier)(n))throw Error(`doync: patch image for table ${t.name} has an invalid column name ${JSON.stringify(n)}`);return{columns:r,values:r.map(t=>(0,e.decodeImageValue)(n[t]))}}function D(e,t){let n=e.tables.find(e=>e.name===t);if(n===void 0)throw Error(`doync: no synced table named ${JSON.stringify(t)} in the client schema`);return n}function O(e){return oe(e)}function k(t,n){p(t,`schema_version`)===null&&A(t,n,0,(0,e.declaredSchemaVersion)(n))}function A(e,t,n,r){for(let i of f(t,n,r))e.execBatch(i);m(e,`schema_version`,String(r))}function j(e,t){for(let n of t.tables)e.exec(`DROP TABLE IF EXISTS ${w(n.name)}`)}function de(t){for(let n of t.tables)if((0,e.isInternalTable)(n.name))throw Error(`doync: synced table ${n.name} uses the reserved __doync_ prefix`)}const M=`logout_behavior`,N=`connected_clock`,P=`doync_optimistic`,F=`doync_body`;var I=class{lifecycle;decode;one;#e=!1;#t=null;#n=new Set;#r=Y;#i=X;#a=!1;#o=null;constructor(e,t,n){this.lifecycle=e,this.decode=t,this.one=n}#s(e){if(this.#o?.read!==e||this.#o.generation!==e.generation){let t=e.rawRows();this.#r=this.decode?this.decode(t):t,this.#o={read:e,generation:e.generation}}return this.#r}#c(){if(this.#a)return;this.#a=!0;let e=this.lifecycle.peek();if(e!==null)this.#s(e),this.#i=e.status();else{let e=this.lifecycle.compute();this.#r=e.rows,this.#i=e.status}}current(){let e=this.lifecycle.peek();return e!==null&&e.generation>0?(this.#a=!0,this.#s(e)):(this.#c(),this.#r)}status(){let e=this.lifecycle.peek();return e===null?(this.#c(),this.#i):(this.#a=!0,this.#i=e.status(),this.#i)}onChange(e){return this.#n.add(e),()=>this.#n.delete(e)}retain(){if(this.#e)return;this.#e=!0,this.#a=!0;let e=this.lifecycle.retain();if(this.#t=e.onChange(()=>{this.#s(e),this.#i=e.status();for(let e of this.#n)e()}),e.generation>0&&(this.#o?.read!==e||this.#o.generation!==e.generation)||e.status()!==this.#i){e.generation>0&&this.#s(e),this.#i=e.status();for(let e of this.#n)e()}}release(){this.#e&&(this.#e=!1,this.#t?.(),this.#t=null,this.lifecycle.release())}},L=class{#e;#t;#n;#r;#i;#a;#o=null;#s;#c;#l=1;#u=null;#d=!1;#f=0;#p=null;#m;#h=!1;#g=null;#_=!1;#v=new Set;#y=0;#b=0;#x=null;#S;#C=new Set;#w=!1;#T=[];#E=new Map;#D=new Map;#O=new Set;#k=new Set;#A=new Map;#j=new Map;#M=new Map;#N=new Map;#P=new Map;#F=1;#I=new Map;#L=new Map;#R=new Set;#z=null;#B=[];#V=!1;#H=[];#U=new Set;constructor(e){this.#e=e.db,this.#t=e.schema,this.#n=e.mutations,this.#r=e.socket,this.#i=e.ctx??null,this.#a=e.token,this.#o=e.userId??null,this.#S=e.onSchemaEvent,this.#c=e.generateId??xe,this.#m=e.now??Date.now,this.#W(e),this.#r.setHandlers({message:e=>this.#Ee(e),open:()=>this.#xe(),close:()=>{this.#p=null,this.#rt(!1)},status:e=>this.#it(e)})}get connectedClock(){return this.#f}releaseStamp(e){return S(this.#e,e)}releaseStamps(){return C(this.#e)}get clientId(){return this.#s}get userId(){return this.#o}get cookie(){return this.#u}get errors(){return this.#B}get recoveredKeys(){return this.#O}get schemaVersion(){return this.#y}get schemaStatus(){return this.#x}#W(t){let n=this.#e;n.exec(`PRAGMA foreign_keys = OFF`),de(this.#t);let{rolledBack:r}=O(n);r?(this.#Ge(n,(0,e.declaredSchemaVersion)(this.#t)),this.#u=null):k(n,this.#t),this.#y=(0,e.declaredSchemaVersion)(this.#t);let i=Ce(n);i!==null&&(console.error(`doync: durable meta "${i}" is corrupt — healing by FORGETTING the local store (fresh identity, full re-hydration). A corrupt mutation counter makes the pending queue untrustworthy, so unsynced writes are discarded rather than risk double-apply.`),this.#Ke(n)),this.#b=this.#G(n,`schema_version`)??0;let a=p(n,`client_id`);this.#s=a??t.clientId??this.#c(),a===null&&m(n,`client_id`,this.#s),this.#l=this.#G(n,`next_mutation_id`)??1,this.#u=this.#G(n,`cookie`);let o=Number(p(n,N));Number.isInteger(o)&&o>=0?this.#f=o:(p(n,`connected_clock`)!==null&&console.warn(`doync: durable connected-clock reading is corrupt — resetting to 0 (clock runs slow; GC defers, server full-hydrates)`),this.#f=0),this.#p=null,i!==null&&this.#$e(`forget`,`corrupt durable meta "${i}" — forgot the local store and reset to a fresh identity`),this.#T=n.exec(`SELECT mutation_id, name, args, idem_key FROM __doync_pending ORDER BY mutation_id ASC`).map(t=>{let n=JSON.parse(String(t.args));return{mutationId:Number(t.mutation_id),name:String(t.name),wireArgs:n,args:(0,e.decodeArgs)(n,`mutation args`),key:t.idem_key===null?void 0:String(t.idem_key)}});for(let e of this.#T){let t=this.#ut(e.mutationId,!0);e.key!==void 0&&(this.#D.set(e.key,t.pair),this.#O.add(e.key))}this.#ge({includeStampless:!1}),n.drainWrittenTables();let s=this.#Q();R(s)&&(this.#V=!0,s.then(()=>this.#J(),()=>this.#J()))}#G(e,t){let n=p(e,t);if(n===null)return null;let r=Number(n);if(!Number.isInteger(r))throw Error(`doync: durable meta "${t}" is corrupt (${JSON.stringify(n)} → ${r}) — a non-integer must never ride the wire (ADR-0019 next-id trap); the boot-time corrupt-meta heal should have caught this`);return r}#K(e){if(this.#V){this.#H.push(e);return}this.#V=!0,this.#q(e)}#q(e){let t;try{t=e()}catch(e){throw this.#V=!1,this.#Y(),e}R(t)?t.then(()=>this.#J(),e=>{this.#B.push(`doync: exclusive-chain step rejected — ${q(e)}`),this.#J()}):this.#J()}#J(){this.#V=!1,this.#Y()}#Y(){let e=this.#H.shift();if(e!==void 0){this.#V=!0,this.#q(e);return}this.#X()}#X(){if(this.#U.size===0)return;let e=[...this.#U];this.#U.clear();for(let t of e)t.recompute()&&t.notify()}#Z(e){this.#V?this.#U.add(e):e.recompute()}#Q(){return this.#e.drainWrittenTables(),this.#e.exec(`SAVEPOINT ${P}`),this.#_=!0,this.#A.clear(),z(this.#$(0),()=>{this.#R=G(this.#e.drainWrittenTables())})}#$(e){for(let t=e;t<this.#T.length;t++){let e=this.#ne(this.#T[t]);if(R(e))return e.then(()=>this.#$(t+1))}}#ee(){this.#_&&=(this.#e.exec(`ROLLBACK TO ${P}`),this.#e.exec(`RELEASE ${P}`),!1)}#te(e){let t=this.#R;this.#ee(),this.#e.drainWrittenTables(),this.#e.exec(`BEGIN`);try{e(),this.#e.exec(`COMMIT`)}catch(e){return this.#e.exec(`ROLLBACK`),z(this.#Q(),()=>{throw e})}let n=G(this.#e.drainWrittenTables());return z(this.#Q(),()=>new Set([...t,...n,...this.#R]))}#ne(e){this.#e.exec(`SAVEPOINT ${F}`);let t;try{let n=this.#n[e.name];if(n===void 0)throw Error(`unknown mutation "${e.name}"`);t=n.body({args:e.args,ctx:this.#i,sql:this.#ae()})}catch(t){this.#ie(e.mutationId,t);return}if(R(t))return t.then(()=>this.#re(e.mutationId),t=>this.#ie(e.mutationId,t));this.#re(e.mutationId)}#re(e){this.#e.exec(`RELEASE ${F}`),this.#A.delete(e)}#ie(e,t){this.#e.exec(`ROLLBACK TO ${F}`),this.#e.exec(`RELEASE ${F}`),this.#A.set(e,t)}#ae(){return{exec:(e,...t)=>this.#e.exec(e,...t.map(e=>typeof e==`boolean`?+!!e:e))}}#oe(e){this.#r.send({type:`push`,clientId:this.#s,mutationId:e.mutationId,name:e.name,args:e.wireArgs})}mutate(t,n,r){let i=r?.key;if(i!==void 0){let e=this.#D.get(i);if(e!==void 0)return e}let a=t.name;if(a===void 0||a===``)return K(Error(`doync: mutate requires a registered mutation — wrap it in defineMutations(...) so it carries a dotted name`));let o=this.#n[a];if(o===void 0)return K(Error(`doync: unknown mutation "${a}"`));let s,c;try{s=(0,e.prepareArgs)(o.args,n,`mutation args`),c=(0,e.encodeArgs)(s,`mutation args`)}catch(e){return K(e)}let l=this.#dt(!1);return i!==void 0&&this.#D.set(i,l.pair),this.#K(()=>this.#se({name:a,args:s,wireArgs:c,key:i,promise:l})),l.pair}#se(e){let t=this.#e,n=this.#l;this.#E.set(n,e.promise);let r={mutationId:n,name:e.name,args:e.args,wireArgs:e.wireArgs,key:e.key};return z(this.#te(()=>{t.exec(`INSERT INTO __doync_pending (mutation_id, name, args, idem_key) VALUES (?, ?, ?, ?)`,n,r.name,JSON.stringify(r.wireArgs??null),r.key??null),this.#l=n+1,m(t,`next_mutation_id`,String(this.#l)),this.#T.push(r)}),e=>this.#ce(r,e))}#ce(e,t){let n=e.mutationId;if(!this.#A.has(n)){this.#ft(n,null),this.#st(t),this.#d&&this.#oe(e);return}let r=this.#A.get(n),i=this.#E.get(n)?.pair;return e.key!==void 0&&this.#D.delete(e.key),z(this.#le(n,!0),e=>{this.#ft(n,r),this.#pt(n,r),i?.client.catch(()=>{}),i?.server.catch(()=>{}),this.#st(new Set([...t,...e]))})}#le(e,t=!1){let n=this.#e;return this.#te(()=>{n.exec(`DELETE FROM __doync_pending WHERE mutation_id = ?`,e),this.#T=this.#T.filter(t=>t.mutationId!==e),t&&(this.#l=e,m(n,`next_mutation_id`,String(e)))})}updateAuth(e,t,n){this.#a=e??void 0,n!==void 0&&(this.#o=n),t!==void 0&&(this.#i=t),this.#d&&!this.#w&&typeof e==`string`&&e!==``&&this.#r.send({type:`updateAuth`,jwt:e})}subscribe(e,t){if(V(e))return new B;let{query:n,args:r,options:i}=H(`subscribe`,e,t);if(i?.skip)return new B;let a=n.name,o=n.resolve({args:r,ctx:this.#i}),s={sql:o.sql,params:o.params},c=o.identity,l={name:a,args:r,ttl:i?.ttl,statement:s},u=o.decode;return new I({peek:()=>this.#M.get(c)?.read??null,retain:()=>this.#de(c,l),release:()=>this.#pe(c),compute:()=>{if(this.#V)return{rows:Y,status:X};let e=this.#e.exec(s.sql,...s.params),t=this.#M.get(c);return{rows:u?u(e):e,status:Q(t?.phase??`pending`,t?.error)}}},u,o.one??!1)}warmup(e,t){return V(e)||t?.signal?.aborted?U:W(this.subscribe(e,t===void 0?void 0:{ttl:t.ttl}),t?.signal)}preload(e,t){if(V(e))return _e;let{query:n,args:r,options:i}=H(`preload`,e,t),a=n.name,o=n.resolve({args:r,ctx:this.#i}),s=o.identity;this.#fe(s,{name:a,args:r,ttl:i?.ttl,statement:{sql:o.sql,params:o.params}});let c=!1;return{cleanup:()=>{c||(c=!0,this.#pe(s))}}}#ue(e,t){let n=this.#M.get(e);if(n===void 0){let r=this.#Te(e);n={name:t.name,args:t.args,ttl:t.ttl,count:0,read:null,phase:`pending`,error:void 0},this.#M.set(e,n),this.#We(()=>b(this.#e,e)),this.#d&&this.#r.send({type:`subscribe`,queries:[this.#we(e,{heldAt:r})]})}else n.phase===`error`&&this.#d?(this.#lt(e,`pending`),this.#r.send({type:`subscribe`,queries:[this.#we(e)]})):t.ttl!==void 0&&(n.ttl===void 0||t.ttl>n.ttl)&&(n.ttl=t.ttl,this.#d&&this.#r.send({type:`subscribe`,queries:[this.#we(e)]}));return n.count+=1,n}#de(e,t){let r=this.#ue(e,t);if(r.read===null){let i=this.#L.get(e);if(i!==void 0)clearTimeout(i.timer),this.#L.delete(e),r.read=i.read,this.#Z(i.read);else{let i=new n({run:e=>this.#e.exec(e.sql,...e.params),readSet:()=>{let t=this.#j.get(e);return t===void 0?void 0:new Set(t.readSet)}},t.statement,e,Q(r.phase,r.error));r.read=i,this.#Z(i)}}return r.read}#fe(e,t){this.#ue(e,t)}#pe(t){let n=this.#M.get(t);n===void 0||--n.count>0||(this.#M.delete(t),this.#d&&this.#r.send({type:`unsubscribe`,queries:[{name:n.name,args:n.args===void 0?void 0:(0,e.encodeArgs)(n.args,`query args`)}]}),this.#me(t,n.ttl),n.read!==null&&this.#ve(t,n.read))}#me(e,t){let n=this.#u;if(n===null)return;let r={instance:e,cookie:n,releasedAt:this.#f,ttlMs:se(t)};this.#K(()=>z(this.#te(()=>{ce(this.#e,r),this.#ge({includeStampless:!0}),this.#he()}),e=>this.#st(e)))}#he(){m(this.#e,N,String(this.#f))}#ge(e){let t=this.#_e(e.includeStampless);if(t.length!==0){for(let e of t)this.#Le(e);this.#he()}}#_e(e){let t=this.#M,n=C(this.#e),r=new Set(n.map(e=>e.instance)),i=[];if(e){let e=this.#e.exec(`SELECT DISTINCT instance FROM __doync_membership`);for(let n of e){let e=String(n.instance);t.has(e)||r.has(e)||i.push(e)}}let a=this.#f;for(let e of n)t.has(e.instance)||(e.ttlMs<=0||a-e.releasedAt>e.ttlMs)&&i.push(e.instance);return i}#ve(e,t){let n=this.#L.get(e);n!==void 0&&clearTimeout(n.timer),this.#L.set(e,{read:t,timer:setTimeout(()=>{let n=this.#L.get(e);n===void 0||n.read!==t||(this.#L.delete(e),this.#U.delete(t))},J)})}once(t){if(V(t))return new ge;let{query:n,args:r}=H(`once`,t),i=n.name,a=n.resolve({args:r,ctx:this.#i}),o;if(this.#V)o=[];else{let e=this.#e.exec(a.sql,...a.params);o=a.decode?a.decode(e):e}let s=`once-${this.#F++}`,c=r===void 0?void 0:(0,e.encodeArgs)(r,`query args`),l=new pe(o,a.decode,{start:()=>{this.#N.set(s,{view:l,name:i,args:c}),this.#d&&this.#r.send({type:`once`,id:s,name:i,args:c})},drop:()=>{this.#N.delete(s),this.#P.delete(s)}});return l}local(e,...t){let n=`local:${e}\u0000${JSON.stringify(t)}`,r={sql:e,params:t};return new I({peek:()=>this.#I.get(n)?.read??null,retain:()=>this.#ye(n,r),release:()=>this.#be(n),compute:()=>this.#V?{rows:Y,status:X}:{rows:this.#e.exec(r.sql,...r.params),status:Z}},void 0,void 0)}#ye(e,t){let r=this.#I.get(e);if(r===void 0&&(r={count:0,read:null},this.#I.set(e,r)),r.count+=1,r.read===null){let i=this.#L.get(e);if(i!==void 0)clearTimeout(i.timer),this.#L.delete(e),r.read=i.read,this.#Z(i.read);else{let e=new n({run:e=>this.#e.exec(e.sql,...e.params),readSet:()=>void 0},t,void 0,Z);r.read=e,this.#Z(e)}}return r.read}#be(e){let t=this.#I.get(e);t===void 0||--t.count>0||(this.#I.delete(e),t.read!==null&&this.#ve(e,t.read))}#xe(){this.#w||(this.#p=null,this.#rt(!0),this.#Ce())}#Se(){let e=this.#m();if(this.#p!==null){let t=e-this.#p;t>0&&(this.#f+=t)}this.#p=e}#Ce(){for(let e of this.#M.keys())this.#lt(e,`pending`);this.#r.send({type:`connect`,clientId:this.#s,...this.#a===void 0?{}:{jwt:this.#a},cookie:this.#u,desiredQueries:[...this.#M.keys()].map(e=>this.#we(e)),schemaVersion:this.#y});for(let e of this.#T)this.#oe(e);for(let[e,t]of this.#N)this.#r.send({type:`once`,id:e,name:t.name,args:t.args})}#we(t,n){let r=this.#M.get(t),i=n===void 0?this.#Te(t):n.heldAt;return{name:r?.name??t,args:r?.args===void 0?void 0:(0,e.encodeArgs)(r.args,`query args`),...r?.ttl===void 0?{}:{ttl:r.ttl},...i===void 0?{}:{heldAt:i}}}#Te(e){if(!(this.#e.exec(`SELECT 1 FROM __doync_membership WHERE instance = ? LIMIT 1`,e).length>0))return;if(this.#M.has(e))return this.#u??void 0;let t=S(this.#e,e);if(t!==null)return t.cookie}#Ee(e){if(this.#w){e.type===`error`&&this.#B.push(e.message);return}if(e.type===`pong`){this.#Se();return}if(e.type===`unauthorized`){this.#B.push(e.message),this.#at(!0);return}if(e.type===`pokeStart`&&e.clientId!==this.#s){this.#B.push(`doync: pokeStart addressed to client ${e.clientId}, this engine is ${this.#s}`);return}switch(this.#h&&e.type!==`error`&&this.#at(!1),e.type){case`schemaSkew`:this.#Be(e);break;case`schema`:this.#Ve(e);break;case`subscribeAck`:this.#et();for(let t of e.instances){this.#j.set(t.instance,t);let e=this.#M.get(t.instance);e!==void 0&&e.phase!==`complete`&&this.#lt(t.instance,`acked`)}break;case`pokeStart`:this.#et(),this.#z=[];break;case`pokePart`:if(this.#z===null)this.#B.push(`doync: pokePart arrived with no open poke`);else for(let t of e.patches)this.#z.push(t);break;case`pokeEnd`:this.#z===null?this.#B.push(`doync: pokeEnd arrived with no open poke`):this.#Ae(e.cookie,e.lastMutationId,e.confirms);break;case`pokeReject`:this.#ze(e.mutationId,e.error,e.reason);break;case`onceStart`:this.#P.set(e.id,[]);break;case`oncePart`:{let t=this.#P.get(e.id);if(t===void 0)this.#B.push(`doync: oncePart arrived with no open once`);else for(let n of e.rows)t.push(n);break}case`onceEnd`:this.#ke(e);break;case`resyncRequired`:this.#B.push(e.message),this.#K(()=>this.#Ze(`heldAt ahead of vouched baseline (instance ${e.instance}: heldAt=${e.heldAt} baseline=${e.baseline}) — ${e.message}`));break;case`error`:if(this.#B.push(e.message),we(e.message)){this.#K(()=>this.#Ze(`cookie above the Origin head (server reset) — ${e.message}`));break}e.instances===void 0?this.#Oe(e.message):this.#De(e.instances,e.message);break;default:this.#B.push(`doync: unknown ServerMessage type ${String(e.type)}`)}}#De(e,t){let n=Error(t);for(let t of e){let e=this.#M.get(t);e!==void 0&&(e.phase===`pending`||e.phase===`acked`)&&this.#lt(t,`error`,n)}}#Oe(e){let t=Error(e);for(let[e,n]of this.#M)(n.phase===`pending`||n.phase===`acked`)&&this.#lt(e,`error`,t)}#ke(e){let t=this.#P.get(e.id)??[];this.#P.delete(e.id);let n=this.#N.get(e.id);if(n!==void 0){if(this.#N.delete(e.id),e.error!==void 0){n.view.settleError(Error(e.error));return}n.view.deliver(t.map(ve))}}#Ae(e,t,n){let r=this.#z??[];this.#z=null,this.#K(()=>this.#je(r,e,t,n))}#je(e,t,n,r){let i=this.#e,a=[];return z(this.#te(()=>{for(let t of e)t.op===`put`&&this.#Ne(t);for(let t of e)t.op===`del`&&this.#Pe(t);for(let t of e)t.op===`pks`&&this.#Fe(t);if(n!==null){for(let e of this.#T)e.mutationId<=n&&!this.#k.has(e.mutationId)&&a.push(e.mutationId);for(let e of a)i.exec(`DELETE FROM __doync_pending WHERE mutation_id = ?`,e)}this.#u=t,m(i,`cookie`,String(t)),this.#he(),this.#T=this.#T.filter(e=>!a.includes(e.mutationId))}),e=>{for(let e of a)this.#pt(e,null);for(let e of a)this.#k.delete(e);this.#st(e),this.#Me(r)})}#Me(e){if(e!==void 0)for(let t of e){let e=this.#M.get(t);e!==void 0&&e.phase===`acked`&&this.#lt(t,`complete`)}}#Ne(e){let t=this.#e,n=this.#Re(e.instance,e.level);t.exec(`INSERT INTO __doync_membership (instance, level, tbl, pk) VALUES (?, ?, ?, ?)
|
|
14
|
+
ON CONFLICT (instance, level, pk) DO UPDATE SET tbl = excluded.tbl`,e.instance,e.level,n.name,e.pk);let r=T(e.pk,n);t.exec(`DELETE FROM ${w(n.name)} WHERE ${E(n)}`,...r);let{columns:i,values:a}=ue(n,e.image);t.exec(`INSERT INTO ${w(n.name)} (${i.map(w).join(`, `)})
|
|
15
|
+
VALUES (${i.map(()=>`?`).join(`, `)})`,...a)}#Pe(e){this.#Ie(e.instance,e.level,e.pk)}#Fe(e){let t=new Set(e.pks),n=this.#e.exec(`SELECT pk FROM __doync_membership WHERE instance = ? AND level = ?`,e.instance,e.level);for(let r of n){let n=String(r.pk);t.has(n)||this.#Ie(e.instance,e.level,n)}}#Ie(e,t,n){let r=this.#e,i=this.#Re(e,t);r.exec(`DELETE FROM __doync_membership WHERE instance = ? AND level = ? AND pk = ?`,e,t,n);let a=r.exec(`SELECT DISTINCT instance FROM __doync_membership WHERE tbl = ? AND pk = ?`,i.name,n);if(!a.some(e=>this.#M.has(String(e.instance)))){r.exec(`DELETE FROM ${w(i.name)} WHERE ${E(i)}`,...T(n,i));for(let e of a)this.#Le(String(e.instance))}}#Le(e){let t=this.#e,n=t.exec(`SELECT DISTINCT tbl, pk FROM __doync_membership WHERE instance = ?`,e);t.exec(`DELETE FROM __doync_membership WHERE instance = ?`,e),b(t,e);for(let e of n){let n=String(e.tbl),r=String(e.pk);if(t.exec(`SELECT 1 FROM __doync_membership WHERE tbl = ? AND pk = ? LIMIT 1`,n,r).length===0){let e=D(this.#t,n);t.exec(`DELETE FROM ${w(e.name)} WHERE ${E(e)}`,...T(r,e))}}}#Re(e,t){let n=this.#j.get(e);if(n===void 0)throw Error(`doync: patch for unknown instance ${e} — a subscribeAck must precede its hydration poke`);let r=n.levels.find(e=>e.level===t);if(r===void 0)throw Error(`doync: instance ${e} has no Level ${t} in its subscribeAck`);return D(this.#t,r.table)}#ze(e,t,n){if(this.#k.add(e),n===`reaped`){let e=this.#T.length;this.#B.push(t),this.#K(()=>this.#Ze(`server forgot this client (reaped) — dropped ${e} pending write${e===1?``:`s`} — ${t}`,`reaped`));return}this.#K(()=>z(this.#le(e),n=>{this.#pt(e,Error(t)),this.#st(n)}))}#Be(e){let t=e.serverVersion===void 0?``:` (server v${e.serverVersion})`;e.reason===`client-stale`?(this.#$e(`reload`,`schema client-stale: bundle v${this.#y} is behind the Mirror${t} — reload for the new bundle`),this.#nt()):(this.#$e(`server-behind`,`schema client-ahead: bundle v${this.#y} is ahead of the Mirror${t} — backing off until it deploys`),this.#rt(!1),this.#r.reconnect())}#Ve(e){let t=e.version;if(t>this.#y){this.#$e(`reload`,`schema directive v${t} is above the bundled track v${this.#y} — reload for the new bundle`),this.#nt();return}t<=this.#b||this.#K(()=>this.#He(t))}#He(e){let t=t=>`local migration to schema v${e} failed: ${q(t)}`,n;try{n=this.#te(()=>{A(this.#e,this.#t,this.#b,e)})}catch(e){return this.#Ze(t(e))}return fe(n,t=>{this.#b=e,this.#st(new Set([...t,...this.#Qe()]))},e=>this.#Ze(t(e)))}resync(){this.#K(()=>this.#Ze(`resync() requested by the consumer`))}forget(){this.#K(()=>this.#Je(`forget() requested by the consumer`))}setLogoutBehavior(e){this.#Ue(M,e)}#Ue(e,t){this.#We(()=>g(this.#e,e,t))}#We(e){this.#K(()=>z(this.#te(e),()=>{}))}#Ge(e,t=this.#y){j(e,this.#t),e.exec(`DELETE FROM __doync_membership`),le(e),e.exec(`DELETE FROM __doync_pending`),e.exec(`DELETE FROM __doync_meta`),A(e,this.#t,0,t)}#Ke(e){this.#Ge(e),e.exec(`DELETE FROM __doync_prefs`)}#qe(e){let t=this.#e;this.#Xe(e),this.#s=this.#c(),m(t,`client_id`,this.#s),this.#u=null,this.#l=1,this.#f=0,this.#p=null,this.#T=[]}#Je(e){let t=this.#e,n=this.#te(()=>{this.#Ke(t),this.#qe(Error(`doync: ${e} — pending writes were forgotten`))});return this.#Ye(n,`forget`,`forgot the local store — ${e}`)}#Ye(e,t,n){return z(e,e=>{this.#b=this.#y,this.#j.clear(),this.#$e(t,n),this.#d&&(this.#rt(!1),this.#r.reconnect()),this.#st(new Set([...e,...this.#Qe()]))})}#Xe(e){for(let t of this.#E.keys())this.#ft(t,e),this.#pt(t,e);this.#D.clear(),this.#O.clear(),this.#k.clear(),this.#A.clear()}#Ze(e,t=`resync`){let n=this.#e,r=this.#te(()=>{this.#Ge(n),this.#qe(Error(`doync: ${e} — pending writes were dropped`))});return this.#Ye(r,t,t===`reaped`?`client state was reaped — ${e}`:`wiped and resyncing — ${e}`)}#Qe(){return this.#t.tables.map(e=>e.name)}onSchemaChange(e){return this.#C.add(e),()=>this.#C.delete(e)}#$e(e,t){let n={kind:e,message:t};this.#x=n,this.#S?.(n),this.#tt()}#et(){let e=this.#x?.kind;(e===`server-behind`||e===`resync`||e===`reaped`||e===`forget`)&&(this.#x=null,this.#tt())}#tt(){for(let e of this.#C)e()}#nt(){this.#w=!0,this.#rt(!1)}get connectionStatus(){return this.#h?`needs-auth`:this.#d?`connected`:this.#g??`disconnected`}onConnectionChange(e){return this.#v.add(e),()=>this.#v.delete(e)}#rt(e){this.#ot(()=>{this.#d=e,e&&(this.#g=null)})}#it(e){this.#ot(()=>{this.#g=e})}#at(e){this.#ot(()=>{this.#h=e})}#ot(e){let t=this.connectionStatus;if(e(),this.connectionStatus!==t)for(let e of this.#v)e()}#st(e){let t=G(e),n=new Set(this.#U);this.#U.clear();for(let e of this.#ct()){let r=e.readSet;(n.has(e)||r===void 0||[...r].some(e=>t.has(e)))&&e.recompute()&&e.notify()}}*#ct(){for(let e of this.#M.values())e.read!==null&&(yield e.read);for(let e of this.#I.values())e.read!==null&&(yield e.read)}#lt(e,t,n){let r=this.#M.get(e);if(r===void 0)return;r.phase=t,r.error=n;let i=Q(t,n);r.read!==null&&r.read.updateStatus(i)&&r.read.notify()}#ut(e,t){let n=this.#E.get(e);if(n!==void 0)return n;let r=this.#dt(t);return this.#E.set(e,r),r}#dt(e){let t,n,r,i,a=new Promise((e,r)=>{t=e,n=r}),o=new Promise((e,t)=>{r=e,i=t});return e&&(a.catch(()=>{}),o.catch(()=>{})),{pair:{client:a,server:o},resolveClient:t,rejectClient:n,resolveServer:r,rejectServer:i,clientSettled:!1,serverSettled:!1}}#ft(e,t){let n=this.#E.get(e);if(n===void 0){this.#B.push(`doync: settleClient for unknown mutation ${e} — no pending promise (a mutate() awaiting it would hang)`);return}n.clientSettled||(n.clientSettled=!0,t===null?n.resolveClient():n.rejectClient(t))}#pt(e,t){let n=this.#E.get(e);if(n===void 0){this.#B.push(`doync: settleServer for unknown mutation ${e} — no pending promise (a mutate() awaiting it would hang)`);return}n.serverSettled||(n.serverSettled=!0,t===null?n.resolveServer():n.rejectServer(t),n.clientSettled&&this.#E.delete(e))}};function R(e){return e instanceof Promise}function z(e,t){return e instanceof Promise?e.then(t):t(e)}function fe(e,t,n){return e instanceof Promise?e.then(t,n):t(e)}var B=class{current(){return Y}status(){return X}onChange(){return()=>{}}retain(){}release(){}},pe=class{#e;#t=new Set;#n=!1;#r=!1;#i=Promise.withResolvers();#a=null;#o;#s;#c;constructor(e,t,n){this.#e=e,this.#o=t,this.#s=n.start,this.#c=n.drop}current(){return this.#l(),this.#e}onChange(e){return this.#l(),this.#t.add(e),()=>this.#t.delete(e)}get server(){return this.#l(),this.#i.promise}deliver(e){if(this.#r)return;let t=this.#o?this.#o(e):e;this.#e=t,this.#i.resolve(t);for(let e of this.#t)e()}settleError(e){this.#r||this.#i.reject(e)}dispose(){this.#r||this.#a===null&&(this.#a=setTimeout(()=>{this.#a=null,!this.#r&&(this.#r=!0,this.#t.clear(),this.#c())},J))}#l(){this.#r||(this.#a!==null&&(clearTimeout(this.#a),this.#a=null),!this.#n&&(this.#n=!0,this.#i=Promise.withResolvers(),this.#i.promise.catch(()=>{}),this.#s()))}};function V(e){return e===!1||e==null}function H(t,n,r){if((0,e.isBoundQuery)(n))return{query:n.query,args:n.args,options:r};throw me(t,n)}function me(e,t){return Error(typeof t==`function`?`doync: client.${e} expected a BoundQuery — received a function; did you forget to call it?`:`doync: client.${e} expected a BoundQuery, got ${he(t)}`)}function he(e){if(e===null)return`null`;if(Array.isArray(e))return`an array`;let t=typeof e;if(t===`object`){let t=e.kind;return typeof t==`string`?`an object with kind "${t}"`:`an object`}return t}var ge=class{current(){return Y}onChange(){return()=>{}}get server(){return new Promise(()=>{})}dispose(){}};const U={release(){}};function W(e,t){e.retain();let n,r=!1,i=()=>{r||(r=!0,clearTimeout(n),t?.removeEventListener(`abort`,i),e.release())};return n=setTimeout(i,ye),be(n),t?.addEventListener(`abort`,i,{once:!0}),{release:i}}const _e={cleanup(){}};function ve(t){let n={};for(let[r,i]of Object.entries(t))n[r]=(0,e.decodeImageValue)(i);return n}function G(t){return new Set([...t].filter(t=>!(0,e.isInternalTable)(t)))}function K(e){let t=Promise.reject(e),n=Promise.reject(e);return t.catch(()=>{}),n.catch(()=>{}),{client:t,server:n}}function q(e){return e instanceof Error?e.message:String(e)}const J=0,ye=15e3;function be(e){typeof e==`object`&&e&&`unref`in e&&e.unref?.call(e)}const Y=Object.freeze([]),X=Object.freeze({status:`unknown`}),Z=Object.freeze({status:`complete`});function Q(e,t){return e===`complete`?Z:e===`error`?t===void 0?{status:`error`}:{status:`error`,error:t}:X}const xe=()=>{let e=globalThis.crypto?.randomUUID?.();return e===void 0?`client-${Math.random().toString(16).slice(2)}-${Date.now().toString(16)}`:e},Se=[`schema_version`,`next_mutation_id`,`cookie`];function Ce(e){for(let t of Se){let n=p(e,t);if(n!==null&&!Number.isInteger(Number(n)))return t}return null}function we(e){return e.includes(`above the Origin head`)}function Te(e){return Ee(e)}function Ee(t){t.logoutBehavior!==void 0&&(O(t.db),g(t.db,M,t.logoutBehavior));let n=$(t.authData,t.ctxValidationSchema);return new L({db:t.db,schema:t.schema,mutations:(0,e.flattenMutations)(t.mutations),socket:t.socket,ctx:n.ctx,token:n.token,userId:n.userId,clientId:t.clientId,onSchemaEvent:t.onSchemaEvent})}function $(t,n){if(t===null)return{userId:null,token:void 0,ctx:null};let r=t.ctx;return n!==void 0&&(r=(0,e.validateStandardSchema)(n,t.ctx,`auth context`)),{userId:t.userId,token:t.token,ctx:r}}Object.defineProperty(exports,"S",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return U}}),Object.defineProperty(exports,"b",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return Ee}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return $}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return Te}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return K}}),Object.defineProperty(exports,"v",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"x",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"y",{enumerable:!0,get:function(){return g}});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ClientMessage, ServerMessage } from "@doync/core/internal";
|
|
2
1
|
import { AuthContext, AuthData, BoundQuery, DoyncSchema, MutationDefinition, MutationTree, SqlValue } from "@doync/core";
|
|
2
|
+
import { ClientMessage, ServerMessage } from "@doync/core/internal";
|
|
3
3
|
|
|
4
4
|
//#region ../../node_modules/.pnpm/@standard-schema+spec@1.1.0/node_modules/@standard-schema/spec/dist/index.d.ts
|
|
5
5
|
/** The Standard Typed interface. This is a base type extended by other specs. */
|
|
@@ -419,6 +419,13 @@ interface DoyncClient {
|
|
|
419
419
|
*/
|
|
420
420
|
local<Row extends Record<string, unknown> = Record<string, SqlValue>>(sql: string, ...params: SqlValue[]): View<Row>;
|
|
421
421
|
/**
|
|
422
|
+
* Start a subscription and hold its view before a component needs it. The
|
|
423
|
+
* hold is released automatically after a short grace window, when its signal
|
|
424
|
+
* aborts, or when the returned handle is released. An already-aborted signal
|
|
425
|
+
* returns an inert handle without starting the query.
|
|
426
|
+
*/
|
|
427
|
+
warmup<Row extends Record<string, unknown> = Record<string, SqlValue>>(query: BoundQuery<Row, boolean> | FalsyQuery, options?: WarmupOptions): WarmupHandle;
|
|
428
|
+
/**
|
|
422
429
|
* Apply a registered mutation optimistically and push it to the Origin. Pass
|
|
423
430
|
* the {@link MutationDefinition} from your mutations tree; args are
|
|
424
431
|
* type-checked from the definition. Returns {@link MutationResult}.
|
|
@@ -459,15 +466,16 @@ interface DoyncClient {
|
|
|
459
466
|
* for other queries that read the same tables. Falsy yields a no-op handle.
|
|
460
467
|
* Call `cleanup()` to release (often never, for a session-long preload).
|
|
461
468
|
*/
|
|
462
|
-
preload(query: BoundQuery | FalsyQuery, options?: PreloadOptions): PreloadHandle;
|
|
469
|
+
preload<Row extends Record<string, unknown> = Record<string, SqlValue>>(query: BoundQuery<Row, boolean> | FalsyQuery, options?: PreloadOptions): PreloadHandle;
|
|
463
470
|
/** Current {@link ConnectionStatus} to the Mirror. */
|
|
464
471
|
readonly connectionStatus: ConnectionStatus;
|
|
465
472
|
/** Subscribe to connection-status transitions. Returns the unsubscribe. */
|
|
466
473
|
onConnectionChange(listener: () => void): () => void;
|
|
467
474
|
}
|
|
468
475
|
/**
|
|
469
|
-
* Falsy "no query" on subscribe / once / preload: `false | null |
|
|
470
|
-
* Lets `cond && query(args)` and optional-prop patterns
|
|
476
|
+
* Falsy "no query" on subscribe / once / preload / warmup: `false | null |
|
|
477
|
+
* undefined`. Lets `cond && query(args)` and optional-prop patterns
|
|
478
|
+
* type-check.
|
|
471
479
|
*/
|
|
472
480
|
type FalsyQuery = false | null | undefined;
|
|
473
481
|
/** Per-subscribe options. */
|
|
@@ -491,6 +499,18 @@ interface PreloadOptions {
|
|
|
491
499
|
*/
|
|
492
500
|
readonly ttl?: number;
|
|
493
501
|
}
|
|
502
|
+
/** Options accepted by `warmup()`. */
|
|
503
|
+
interface WarmupOptions {
|
|
504
|
+
/** Connected-time grace after the query is released. */
|
|
505
|
+
readonly ttl?: number;
|
|
506
|
+
/** Release the warmup hold when the signal aborts. */
|
|
507
|
+
readonly signal?: AbortSignal;
|
|
508
|
+
}
|
|
509
|
+
/** Handle returned by `warmup()`. */
|
|
510
|
+
interface WarmupHandle {
|
|
511
|
+
/** Release the warmup hold. Idempotent. */
|
|
512
|
+
release(): void;
|
|
513
|
+
}
|
|
494
514
|
/** Handle returned by {@link DoyncClient.preload}. */
|
|
495
515
|
interface PreloadHandle {
|
|
496
516
|
/**
|
|
@@ -633,13 +653,20 @@ declare class ClientEngine implements DoyncClient {
|
|
|
633
653
|
*/
|
|
634
654
|
subscribe<Row extends Record<string, unknown> = Record<string, SqlValue>>(query: BoundQuery<Row, boolean> | FalsyQuery, options?: SubscribeOptions): View<Row>;
|
|
635
655
|
/**
|
|
656
|
+
* Start a subscription and hold its view before a component needs it. The
|
|
657
|
+
* hold is released automatically after a short grace window, when its signal
|
|
658
|
+
* aborts, or when the returned handle is released. An already-aborted signal
|
|
659
|
+
* returns an inert handle without starting the query.
|
|
660
|
+
*/
|
|
661
|
+
warmup<Row extends Record<string, unknown> = Record<string, SqlValue>>(query: BoundQuery<Row, boolean> | FalsyQuery, options?: WarmupOptions): WarmupHandle;
|
|
662
|
+
/**
|
|
636
663
|
* Warm the replica without materializing a View (#104, ADR-0019/0021):
|
|
637
664
|
* register upstream so pokes hydrate rows other queries read, at zero local
|
|
638
665
|
* recompute of the preload statement. Refcounts the same desired instance as
|
|
639
666
|
* a live subscribe (byte-identical statement). `{cleanup}` releases into TTL
|
|
640
667
|
* grace (ADR-0014). Bound form only (ADR-0027 / #200); falsy → no-op handle.
|
|
641
668
|
*/
|
|
642
|
-
preload(query: BoundQuery | FalsyQuery, options?: PreloadOptions): PreloadHandle;
|
|
669
|
+
preload<Row extends Record<string, unknown> = Record<string, SqlValue>>(query: BoundQuery<Row, boolean> | FalsyQuery, options?: PreloadOptions): PreloadHandle;
|
|
643
670
|
/**
|
|
644
671
|
* Once (ADR-0012 / ADR-0021): cache-and-network. Local replica first (real
|
|
645
672
|
* SQL `[]` when empty); Mirror executes once under its ctx. Local
|
|
@@ -718,6 +745,14 @@ declare function normalizeQuerySurface<Options = never>(surface: "subscribe" | "
|
|
|
718
745
|
args: unknown;
|
|
719
746
|
options: Options | undefined;
|
|
720
747
|
};
|
|
748
|
+
/** No-op {@link WarmupHandle} for warmup(falsy) (ADR-0027). */
|
|
749
|
+
declare const NOOP_WARMUP: WarmupHandle;
|
|
750
|
+
/**
|
|
751
|
+
* Retain `view` as a warmup hold: released by the grace lapse, `signal` abort,
|
|
752
|
+
* or the handle — idempotent, first wins. Shared by every client's `warmup` so
|
|
753
|
+
* the three release paths cannot drift per platform.
|
|
754
|
+
*/
|
|
755
|
+
declare function warmupHold(view: View<Record<string, unknown>>, signal?: AbortSignal): WarmupHandle;
|
|
721
756
|
/**
|
|
722
757
|
* A `mutate()` whose failure is known synchronously (unknown name, bad args).
|
|
723
758
|
* Exported for the web topology's tab-side `mutate`, which shares the
|
|
@@ -796,5 +831,5 @@ declare function resolveClientAuthData<TAuthContext extends AuthContext>(authDat
|
|
|
796
831
|
ctx: AuthContext;
|
|
797
832
|
};
|
|
798
833
|
//#endregion
|
|
799
|
-
export {
|
|
800
|
-
//# sourceMappingURL=client-
|
|
834
|
+
export { warmupHold as A, SyncSocket as B, WarmupHandle as C, isFalsyQuery as D, __LOGOUT_BEHAVIOR_PREF_KEY as E, readMeta as F, LocalDb as H, readPref as I, writeMeta as L, createEngineTables as M, dropConsumerTables as N, normalizeQuerySurface as O, replayMigrations as P, writePref as R, ViewStatus as S, __CONNECTED_CLOCK_META_KEY as T, LocalRow as U, SyncSocketHandlers as V, extractWriteTable as W, QueryStatus as _, ClientEngine as a, SubscribeOptions as b, DoyncClient as c, MutationOptions as d, MutationResult as f, PreloadOptions as g, PreloadHandle as h, resolveClientAuthData as i, applyBundledMigrations as j, settledRejection as k, FalsyQuery as l, OnceView as m, createClient as n, ClientEngineConfig as o, NOOP_WARMUP as p, createClientEngine as r, ConnectionStatus as s, CreateClientOptions as t, LogoutBehavior as u, SchemaEvent as v, WarmupOptions as w, View as x, SchemaEventKind as y, SeamStatus as z };
|
|
835
|
+
//# sourceMappingURL=client-BZWglwNl.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-
|
|
1
|
+
{"version":3,"file":"client-BZWglwNl.d.cts","names":["Input","Output","StandardTypedV1","Props","version","vendor","types","Types","input","output","InferInput","Schema","NonNullable","InferOutput","StandardSchemaV1","validate","value","Options","options","Result","Promise","SuccessResult","FailureResult","issues","libraryOptions","Record","ReadonlyArray","Issue","message","path","PropertyKey","PathSegment","key","StandardJSONSchemaV1","jsonSchema","Converter","Target","target"],"sources":["../../../node_modules/.pnpm/@standard-schema+spec@1.1.0/node_modules/@standard-schema/spec/dist/index.d.ts","../src/port.ts","../src/socket.ts","../src/replica/meta.ts","../src/replica/stamps.ts","../src/replica/index.ts","../src/engine.ts","../src/client.ts"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import{declaredSchemaVersion as e,decodeArgs as t,decodeImageValue as n,decodePkValue as r,encodeArgs as i,flattenMutations as a,isBoundQuery as o,isInternalTable as s,isSqlIdentifier as c,prepareArgs as l,tablePrimaryKey as u,validateStandardSchema as ee}from"@doync/core/internal";import{SQLiteParserError as te,parse as ne,parseAll as re,unparse as ie}from"@doync/sqlite-parser";var d=class{host;statement;identity;#e=[];#t=0;#n=new Set;#r;constructor(e,t,n,r){this.host=e,this.statement=t,this.identity=n,this.#r=r}get readSet(){return this.identity===void 0?void 0:this.host.readSet()}status(){return this.#r}updateStatus(e){return this.#r.status===e.status&&this.#r.error===e.error?!1:(this.#r=e,!0)}recompute(){let e=this.host.run(this.statement);return ae(e,this.#e)?!1:(this.#e=e,this.#t+=1,!0)}rawRows(){return this.#e}get generation(){return this.#t}onChange(e){return this.#n.add(e),()=>this.#n.delete(e)}notify(){for(let e of this.#n)e()}};function ae(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++){let r=e[n],i=t[n],a=Object.keys(r);if(a.length!==Object.keys(i).length)return!1;for(let e of a)if(!oe(r[e]??null,i[e]??null))return!1}return!0}function oe(e,t){if(e===t)return!0;if(e instanceof ArrayBuffer&&t instanceof ArrayBuffer){if(e.byteLength!==t.byteLength)return!1;let n=new Uint8Array(e),r=new Uint8Array(t);for(let e=0;e<n.length;e++)if(n[e]!==r[e])return!1;return!0}return!1}const se=new Set([`STMT_CREATE_TABLE`,`STMT_CREATE_INDEX`,`STMT_CREATE_VIEW`,`STMT_CREATE_VTABLE`,`STMT_DROP`,`STMT_ALTER`]),ce=new Set([`STMT_INSERT`,`STMT_UPDATE`,`STMT_DELETE`,`STMT_SELECT`,`COMPOUND_SELECT`]);function le(e){try{return ne(e)}catch(e){if(e instanceof te)return null;throw e}}function ue(e){try{return re(e)}catch(e){if(e instanceof te)return null;throw e}}function de(e){return e.kind===`STMT_CREATE_TRIGGER`||e.kind===`STMT_DROP`&&e.target===`TRIGGER`?`trigger`:e.kind===`STMT_PRAGMA`?`pragma`:se.has(e.kind)?`ddl`:ce.has(e.kind)?`dml`:`other`}function f(e){let t=ue(e);if(t===null)throw Error(`could not parse the SQL — a statement has a syntax error; fix it and retry`);return t.map(e=>ie(e))}function p(e){let t=le(e);return t===null?`other`:de(t)}function m(e,t,n){let r=[];for(let i=t;i<n;i+=1){let a=e.migrations[i];if(a===void 0)throw Error(`doync: bundled migration track has a hole at version ${i} (requested range ${t}..${n}, but the track holds ${e.migrations.length}) — the schema is corrupt or truncated`);for(let e of f(a.sql))p(e)===`ddl`&&r.push(e)}return r}function h(e,t){let n=e.exec(`SELECT v FROM __doync_meta WHERE k = ?`,t)[0];return n===void 0||n.v===null?null:String(n.v)}function g(e,t,n){e.exec(`INSERT INTO __doync_meta (k, v) VALUES (?, ?)
|
|
2
|
+
ON CONFLICT (k) DO UPDATE SET v = excluded.v`,t,n)}function fe(e,t){let n=e.exec(`SELECT v FROM __doync_prefs WHERE k = ?`,t)[0];return n===void 0||n.v===null?null:String(n.v)}function _(e,t,n){e.exec(`INSERT INTO __doync_prefs (k, v) VALUES (?, ?)
|
|
3
|
+
ON CONFLICT (k) DO UPDATE SET v = excluded.v`,t,n)}var pe="CREATE TABLE `__doync_membership` (\n `instance` text NOT NULL,\n `level` integer NOT NULL,\n `tbl` text NOT NULL,\n `pk` text NOT NULL,\n PRIMARY KEY(`instance`, `level`, `pk`)\n) WITHOUT ROWID;\n--> statement-breakpoint\nCREATE INDEX `__doync_membership_by_row` ON `__doync_membership` (`tbl`,`pk`);--> statement-breakpoint\nCREATE TABLE `__doync_meta` (\n `k` text PRIMARY KEY NOT NULL,\n `v` blob\n) WITHOUT ROWID;\n--> statement-breakpoint\nCREATE TABLE `__doync_pending` (\n `mutation_id` integer PRIMARY KEY NOT NULL,\n `name` text NOT NULL,\n `args` text NOT NULL,\n `idem_key` text\n);\n",me="CREATE TABLE `__doync_release_stamp` (\n `instance` text PRIMARY KEY NOT NULL,\n `cookie` integer NOT NULL,\n `released_at` integer NOT NULL,\n `ttl_ms` integer NOT NULL\n) WITHOUT ROWID;\n",he="CREATE TABLE `__doync_prefs` (\n `k` text PRIMARY KEY NOT NULL,\n `v` blob\n) WITHOUT ROWID;\n--> statement-breakpoint\nINSERT INTO `__doync_prefs` (`k`, `v`)\n SELECT `k`, `v` FROM `__doync_meta` WHERE `k` = 'logout_behavior';\n--> statement-breakpoint\nDELETE FROM `__doync_meta` WHERE `k` = 'logout_behavior';\n",ge=[{idx:0,version:`6`,when:1784031358638,tag:`0000_replica_engine_v0`,breakpoints:!0},{idx:1,version:`6`,when:1784450022155,tag:`0001_release_stamps`,breakpoints:!0},{idx:2,version:`6`,when:1785060176159,tag:`0002_prefs_table`,breakpoints:!0}];const _e={"0000_replica_engine_v0":pe,"0001_release_stamps":me,"0002_prefs_table":he},v=ge.slice().sort((e,t)=>e.idx-t.idx).map(e=>{let t=_e[e.tag];if(t===void 0)throw Error(`doync: replica engine track missing sql for journal tag ${JSON.stringify(e.tag)}`);return t.split(/-->\s*statement-breakpoint/).map(e=>e.trim()).filter(e=>e.length>0)});function y(e){e.exec(`CREATE TABLE IF NOT EXISTS __doync_engine (
|
|
4
|
+
k TEXT PRIMARY KEY,
|
|
5
|
+
v
|
|
6
|
+
) WITHOUT ROWID`)}function b(e,t){let n=t;for(;n<v.length;){let t=v[n];if(t===void 0)break;let r=n+1;for(let n of t)e.exec(n);e.exec(`INSERT INTO __doync_engine (k, v) VALUES ('track_version', ?)
|
|
7
|
+
ON CONFLICT (k) DO UPDATE SET v = excluded.v`,r),n=r}}function ve(e){y(e);let t=e.exec(`SELECT v FROM __doync_engine WHERE k = 'track_version'`),n=t.length===0?0:Number(t[0]?.v);if((!Number.isFinite(n)||n<0)&&(n=0),n>v.length)return console.warn(`doync: replica engine track_version ${n} is above bundled track length ${v.length} — wiping engine tables and rebuilding (code rollback against a newer database). Consumer state will resync through wipe-and-resync.`),x(e),{rolledBack:!0};try{b(e,n)}catch(t){return console.warn(`doync: replica engine track failed at version ${n} — wiping engine tables and rebuilding (code rollback against a newer database). Consumer state will resync through wipe-and-resync.`,t),x(e),{rolledBack:!0}}return{rolledBack:!1}}function x(e){let t=null;try{t=fe(e,`logout_behavior`)}catch{}e.exec(`DROP TABLE IF EXISTS __doync_release_stamp`),e.exec(`DROP TABLE IF EXISTS __doync_membership`),e.exec(`DROP TABLE IF EXISTS __doync_prefs`),e.exec(`DROP TABLE IF EXISTS __doync_meta`),e.exec(`DROP TABLE IF EXISTS __doync_pending`),e.exec(`DROP TABLE IF EXISTS __doync_engine`),y(e),b(e,0),t!==null&&_(e,`logout_behavior`,t)}function ye(e){return e===void 0?18e5:e}function be(e,t){e.exec(`INSERT INTO __doync_release_stamp (instance, cookie, released_at, ttl_ms)
|
|
8
|
+
VALUES (?, ?, ?, ?)
|
|
9
|
+
ON CONFLICT (instance) DO UPDATE SET
|
|
10
|
+
cookie = excluded.cookie,
|
|
11
|
+
released_at = excluded.released_at,
|
|
12
|
+
ttl_ms = excluded.ttl_ms`,t.instance,t.cookie,t.releasedAt,t.ttlMs)}function S(e,t){e.exec(`DELETE FROM __doync_release_stamp WHERE instance = ?`,t)}function xe(e){e.exec(`DELETE FROM __doync_release_stamp`)}function C(e){return{instance:String(e.instance),cookie:Number(e.cookie),releasedAt:Number(e.released_at),ttlMs:Number(e.ttl_ms)}}function w(e,t){let n=e.exec(`SELECT instance, cookie, released_at, ttl_ms
|
|
13
|
+
FROM __doync_release_stamp WHERE instance = ?`,t)[0];return n===void 0?null:C(n)}function T(e){return e.exec(`SELECT instance, cookie, released_at, ttl_ms FROM __doync_release_stamp`).map(C)}function E(e){if(!c(e))throw Error(`doync: refusing to quote non-identifier ${JSON.stringify(e)}`);return`"${e}"`}function D(e,t){let n=JSON.parse(e),i=u(t);if(!Array.isArray(n)||n.length!==i.length)throw Error(`doync: malformed pk ${e} for table ${t.name} (expected ${i.length} key part(s))`);return n.map(e=>r(e))}function O(e){return u(e).map(e=>`${E(e)} = ?`).join(` AND `)}function Se(e,t){let r=Object.keys(t);for(let t of r)if(!c(t))throw Error(`doync: patch image for table ${e.name} has an invalid column name ${JSON.stringify(t)}`);return{columns:r,values:r.map(e=>n(t[e]))}}function k(e,t){let n=e.tables.find(e=>e.name===t);if(n===void 0)throw Error(`doync: no synced table named ${JSON.stringify(t)} in the client schema`);return n}function A(e){return ve(e)}function j(t,n){h(t,`schema_version`)===null&&M(t,n,0,e(n))}function M(e,t,n,r){for(let i of m(t,n,r))e.execBatch(i);g(e,`schema_version`,String(r))}function N(e,t){for(let n of t.tables)e.exec(`DROP TABLE IF EXISTS ${E(n.name)}`)}function Ce(e){for(let t of e.tables)if(s(t.name))throw Error(`doync: synced table ${t.name} uses the reserved __doync_ prefix`)}const P=`logout_behavior`,F=`connected_clock`,I=`doync_optimistic`,L=`doync_body`;var R=class{lifecycle;decode;one;#e=!1;#t=null;#n=new Set;#r=Y;#i=X;#a=!1;#o=null;constructor(e,t,n){this.lifecycle=e,this.decode=t,this.one=n}#s(e){if(this.#o?.read!==e||this.#o.generation!==e.generation){let t=e.rawRows();this.#r=this.decode?this.decode(t):t,this.#o={read:e,generation:e.generation}}return this.#r}#c(){if(this.#a)return;this.#a=!0;let e=this.lifecycle.peek();if(e!==null)this.#s(e),this.#i=e.status();else{let e=this.lifecycle.compute();this.#r=e.rows,this.#i=e.status}}current(){let e=this.lifecycle.peek();return e!==null&&e.generation>0?(this.#a=!0,this.#s(e)):(this.#c(),this.#r)}status(){let e=this.lifecycle.peek();return e===null?(this.#c(),this.#i):(this.#a=!0,this.#i=e.status(),this.#i)}onChange(e){return this.#n.add(e),()=>this.#n.delete(e)}retain(){if(this.#e)return;this.#e=!0,this.#a=!0;let e=this.lifecycle.retain();if(this.#t=e.onChange(()=>{this.#s(e),this.#i=e.status();for(let e of this.#n)e()}),e.generation>0&&(this.#o?.read!==e||this.#o.generation!==e.generation)||e.status()!==this.#i){e.generation>0&&this.#s(e),this.#i=e.status();for(let e of this.#n)e()}}release(){this.#e&&(this.#e=!1,this.#t?.(),this.#t=null,this.lifecycle.release())}},z=class{#e;#t;#n;#r;#i;#a;#o=null;#s;#c;#l=1;#u=null;#d=!1;#f=0;#p=null;#m;#h=!1;#g=null;#_=!1;#v=new Set;#y=0;#b=0;#x=null;#S;#C=new Set;#w=!1;#T=[];#E=new Map;#D=new Map;#O=new Set;#k=new Set;#A=new Map;#j=new Map;#M=new Map;#N=new Map;#P=new Map;#F=1;#I=new Map;#L=new Map;#R=new Set;#z=null;#B=[];#V=!1;#H=[];#U=new Set;constructor(e){this.#e=e.db,this.#t=e.schema,this.#n=e.mutations,this.#r=e.socket,this.#i=e.ctx??null,this.#a=e.token,this.#o=e.userId??null,this.#S=e.onSchemaEvent,this.#c=e.generateId??Fe,this.#m=e.now??Date.now,this.#W(e),this.#r.setHandlers({message:e=>this.#Ee(e),open:()=>this.#xe(),close:()=>{this.#p=null,this.#rt(!1)},status:e=>this.#it(e)})}get connectedClock(){return this.#f}releaseStamp(e){return w(this.#e,e)}releaseStamps(){return T(this.#e)}get clientId(){return this.#s}get userId(){return this.#o}get cookie(){return this.#u}get errors(){return this.#B}get recoveredKeys(){return this.#O}get schemaVersion(){return this.#y}get schemaStatus(){return this.#x}#W(n){let r=this.#e;r.exec(`PRAGMA foreign_keys = OFF`),Ce(this.#t);let{rolledBack:i}=A(r);i?(this.#Ge(r,e(this.#t)),this.#u=null):j(r,this.#t),this.#y=e(this.#t);let a=Le(r);a!==null&&(console.error(`doync: durable meta "${a}" is corrupt — healing by FORGETTING the local store (fresh identity, full re-hydration). A corrupt mutation counter makes the pending queue untrustworthy, so unsynced writes are discarded rather than risk double-apply.`),this.#Ke(r)),this.#b=this.#G(r,`schema_version`)??0;let o=h(r,`client_id`);this.#s=o??n.clientId??this.#c(),o===null&&g(r,`client_id`,this.#s),this.#l=this.#G(r,`next_mutation_id`)??1,this.#u=this.#G(r,`cookie`);let s=Number(h(r,F));Number.isInteger(s)&&s>=0?this.#f=s:(h(r,`connected_clock`)!==null&&console.warn(`doync: durable connected-clock reading is corrupt — resetting to 0 (clock runs slow; GC defers, server full-hydrates)`),this.#f=0),this.#p=null,a!==null&&this.#$e(`forget`,`corrupt durable meta "${a}" — forgot the local store and reset to a fresh identity`),this.#T=r.exec(`SELECT mutation_id, name, args, idem_key FROM __doync_pending ORDER BY mutation_id ASC`).map(e=>{let n=JSON.parse(String(e.args));return{mutationId:Number(e.mutation_id),name:String(e.name),wireArgs:n,args:t(n,`mutation args`),key:e.idem_key===null?void 0:String(e.idem_key)}});for(let e of this.#T){let t=this.#ut(e.mutationId,!0);e.key!==void 0&&(this.#D.set(e.key,t.pair),this.#O.add(e.key))}this.#ge({includeStampless:!1}),r.drainWrittenTables();let c=this.#Q();B(c)&&(this.#V=!0,c.then(()=>this.#J(),()=>this.#J()))}#G(e,t){let n=h(e,t);if(n===null)return null;let r=Number(n);if(!Number.isInteger(r))throw Error(`doync: durable meta "${t}" is corrupt (${JSON.stringify(n)} → ${r}) — a non-integer must never ride the wire (ADR-0019 next-id trap); the boot-time corrupt-meta heal should have caught this`);return r}#K(e){if(this.#V){this.#H.push(e);return}this.#V=!0,this.#q(e)}#q(e){let t;try{t=e()}catch(e){throw this.#V=!1,this.#Y(),e}B(t)?t.then(()=>this.#J(),e=>{this.#B.push(`doync: exclusive-chain step rejected — ${Me(e)}`),this.#J()}):this.#J()}#J(){this.#V=!1,this.#Y()}#Y(){let e=this.#H.shift();if(e!==void 0){this.#V=!0,this.#q(e);return}this.#X()}#X(){if(this.#U.size===0)return;let e=[...this.#U];this.#U.clear();for(let t of e)t.recompute()&&t.notify()}#Z(e){this.#V?this.#U.add(e):e.recompute()}#Q(){return this.#e.drainWrittenTables(),this.#e.exec(`SAVEPOINT ${I}`),this.#_=!0,this.#A.clear(),V(this.#$(0),()=>{this.#R=K(this.#e.drainWrittenTables())})}#$(e){for(let t=e;t<this.#T.length;t++){let e=this.#ne(this.#T[t]);if(B(e))return e.then(()=>this.#$(t+1))}}#ee(){this.#_&&=(this.#e.exec(`ROLLBACK TO ${I}`),this.#e.exec(`RELEASE ${I}`),!1)}#te(e){let t=this.#R;this.#ee(),this.#e.drainWrittenTables(),this.#e.exec(`BEGIN`);try{e(),this.#e.exec(`COMMIT`)}catch(e){return this.#e.exec(`ROLLBACK`),V(this.#Q(),()=>{throw e})}let n=K(this.#e.drainWrittenTables());return V(this.#Q(),()=>new Set([...t,...n,...this.#R]))}#ne(e){this.#e.exec(`SAVEPOINT ${L}`);let t;try{let n=this.#n[e.name];if(n===void 0)throw Error(`unknown mutation "${e.name}"`);t=n.body({args:e.args,ctx:this.#i,sql:this.#ae()})}catch(t){this.#ie(e.mutationId,t);return}if(B(t))return t.then(()=>this.#re(e.mutationId),t=>this.#ie(e.mutationId,t));this.#re(e.mutationId)}#re(e){this.#e.exec(`RELEASE ${L}`),this.#A.delete(e)}#ie(e,t){this.#e.exec(`ROLLBACK TO ${L}`),this.#e.exec(`RELEASE ${L}`),this.#A.set(e,t)}#ae(){return{exec:(e,...t)=>this.#e.exec(e,...t.map(e=>typeof e==`boolean`?+!!e:e))}}#oe(e){this.#r.send({type:`push`,clientId:this.#s,mutationId:e.mutationId,name:e.name,args:e.wireArgs})}mutate(e,t,n){let r=n?.key;if(r!==void 0){let e=this.#D.get(r);if(e!==void 0)return e}let a=e.name;if(a===void 0||a===``)return q(Error(`doync: mutate requires a registered mutation — wrap it in defineMutations(...) so it carries a dotted name`));let o=this.#n[a];if(o===void 0)return q(Error(`doync: unknown mutation "${a}"`));let s,c;try{s=l(o.args,t,`mutation args`),c=i(s,`mutation args`)}catch(e){return q(e)}let u=this.#dt(!1);return r!==void 0&&this.#D.set(r,u.pair),this.#K(()=>this.#se({name:a,args:s,wireArgs:c,key:r,promise:u})),u.pair}#se(e){let t=this.#e,n=this.#l;this.#E.set(n,e.promise);let r={mutationId:n,name:e.name,args:e.args,wireArgs:e.wireArgs,key:e.key};return V(this.#te(()=>{t.exec(`INSERT INTO __doync_pending (mutation_id, name, args, idem_key) VALUES (?, ?, ?, ?)`,n,r.name,JSON.stringify(r.wireArgs??null),r.key??null),this.#l=n+1,g(t,`next_mutation_id`,String(this.#l)),this.#T.push(r)}),e=>this.#ce(r,e))}#ce(e,t){let n=e.mutationId;if(!this.#A.has(n)){this.#ft(n,null),this.#st(t),this.#d&&this.#oe(e);return}let r=this.#A.get(n),i=this.#E.get(n)?.pair;return e.key!==void 0&&this.#D.delete(e.key),V(this.#le(n,!0),e=>{this.#ft(n,r),this.#pt(n,r),i?.client.catch(()=>{}),i?.server.catch(()=>{}),this.#st(new Set([...t,...e]))})}#le(e,t=!1){let n=this.#e;return this.#te(()=>{n.exec(`DELETE FROM __doync_pending WHERE mutation_id = ?`,e),this.#T=this.#T.filter(t=>t.mutationId!==e),t&&(this.#l=e,g(n,`next_mutation_id`,String(e)))})}updateAuth(e,t,n){this.#a=e??void 0,n!==void 0&&(this.#o=n),t!==void 0&&(this.#i=t),this.#d&&!this.#w&&typeof e==`string`&&e!==``&&this.#r.send({type:`updateAuth`,jwt:e})}subscribe(e,t){if(U(e))return new H;let{query:n,args:r,options:i}=W(`subscribe`,e,t);if(i?.skip)return new H;let a=n.name,o=n.resolve({args:r,ctx:this.#i}),s={sql:o.sql,params:o.params},c=o.identity,l={name:a,args:r,ttl:i?.ttl,statement:s},u=o.decode;return new R({peek:()=>this.#M.get(c)?.read??null,retain:()=>this.#de(c,l),release:()=>this.#pe(c),compute:()=>{if(this.#V)return{rows:Y,status:X};let e=this.#e.exec(s.sql,...s.params),t=this.#M.get(c);return{rows:u?u(e):e,status:Q(t?.phase??`pending`,t?.error)}}},u,o.one??!1)}warmup(e,t){return U(e)||t?.signal?.aborted?G:ke(this.subscribe(e,t===void 0?void 0:{ttl:t.ttl}),t?.signal)}preload(e,t){if(U(e))return Ae;let{query:n,args:r,options:i}=W(`preload`,e,t),a=n.name,o=n.resolve({args:r,ctx:this.#i}),s=o.identity;this.#fe(s,{name:a,args:r,ttl:i?.ttl,statement:{sql:o.sql,params:o.params}});let c=!1;return{cleanup:()=>{c||(c=!0,this.#pe(s))}}}#ue(e,t){let n=this.#M.get(e);if(n===void 0){let r=this.#Te(e);n={name:t.name,args:t.args,ttl:t.ttl,count:0,read:null,phase:`pending`,error:void 0},this.#M.set(e,n),this.#We(()=>S(this.#e,e)),this.#d&&this.#r.send({type:`subscribe`,queries:[this.#we(e,{heldAt:r})]})}else n.phase===`error`&&this.#d?(this.#lt(e,`pending`),this.#r.send({type:`subscribe`,queries:[this.#we(e)]})):t.ttl!==void 0&&(n.ttl===void 0||t.ttl>n.ttl)&&(n.ttl=t.ttl,this.#d&&this.#r.send({type:`subscribe`,queries:[this.#we(e)]}));return n.count+=1,n}#de(e,t){let n=this.#ue(e,t);if(n.read===null){let r=this.#L.get(e);if(r!==void 0)clearTimeout(r.timer),this.#L.delete(e),n.read=r.read,this.#Z(r.read);else{let r=new d({run:e=>this.#e.exec(e.sql,...e.params),readSet:()=>{let t=this.#j.get(e);return t===void 0?void 0:new Set(t.readSet)}},t.statement,e,Q(n.phase,n.error));n.read=r,this.#Z(r)}}return n.read}#fe(e,t){this.#ue(e,t)}#pe(e){let t=this.#M.get(e);t===void 0||--t.count>0||(this.#M.delete(e),this.#d&&this.#r.send({type:`unsubscribe`,queries:[{name:t.name,args:t.args===void 0?void 0:i(t.args,`query args`)}]}),this.#me(e,t.ttl),t.read!==null&&this.#ve(e,t.read))}#me(e,t){let n=this.#u;if(n===null)return;let r={instance:e,cookie:n,releasedAt:this.#f,ttlMs:ye(t)};this.#K(()=>V(this.#te(()=>{be(this.#e,r),this.#ge({includeStampless:!0}),this.#he()}),e=>this.#st(e)))}#he(){g(this.#e,F,String(this.#f))}#ge(e){let t=this.#_e(e.includeStampless);if(t.length!==0){for(let e of t)this.#Le(e);this.#he()}}#_e(e){let t=this.#M,n=T(this.#e),r=new Set(n.map(e=>e.instance)),i=[];if(e){let e=this.#e.exec(`SELECT DISTINCT instance FROM __doync_membership`);for(let n of e){let e=String(n.instance);t.has(e)||r.has(e)||i.push(e)}}let a=this.#f;for(let e of n)t.has(e.instance)||(e.ttlMs<=0||a-e.releasedAt>e.ttlMs)&&i.push(e.instance);return i}#ve(e,t){let n=this.#L.get(e);n!==void 0&&clearTimeout(n.timer),this.#L.set(e,{read:t,timer:setTimeout(()=>{let n=this.#L.get(e);n===void 0||n.read!==t||(this.#L.delete(e),this.#U.delete(t))},J)})}once(e){if(U(e))return new Oe;let{query:t,args:n}=W(`once`,e),r=t.name,a=t.resolve({args:n,ctx:this.#i}),o;if(this.#V)o=[];else{let e=this.#e.exec(a.sql,...a.params);o=a.decode?a.decode(e):e}let s=`once-${this.#F++}`,c=n===void 0?void 0:i(n,`query args`),l=new Te(o,a.decode,{start:()=>{this.#N.set(s,{view:l,name:r,args:c}),this.#d&&this.#r.send({type:`once`,id:s,name:r,args:c})},drop:()=>{this.#N.delete(s),this.#P.delete(s)}});return l}local(e,...t){let n=`local:${e}\u0000${JSON.stringify(t)}`,r={sql:e,params:t};return new R({peek:()=>this.#I.get(n)?.read??null,retain:()=>this.#ye(n,r),release:()=>this.#be(n),compute:()=>this.#V?{rows:Y,status:X}:{rows:this.#e.exec(r.sql,...r.params),status:Z}},void 0,void 0)}#ye(e,t){let n=this.#I.get(e);if(n===void 0&&(n={count:0,read:null},this.#I.set(e,n)),n.count+=1,n.read===null){let r=this.#L.get(e);if(r!==void 0)clearTimeout(r.timer),this.#L.delete(e),n.read=r.read,this.#Z(r.read);else{let e=new d({run:e=>this.#e.exec(e.sql,...e.params),readSet:()=>void 0},t,void 0,Z);n.read=e,this.#Z(e)}}return n.read}#be(e){let t=this.#I.get(e);t===void 0||--t.count>0||(this.#I.delete(e),t.read!==null&&this.#ve(e,t.read))}#xe(){this.#w||(this.#p=null,this.#rt(!0),this.#Ce())}#Se(){let e=this.#m();if(this.#p!==null){let t=e-this.#p;t>0&&(this.#f+=t)}this.#p=e}#Ce(){for(let e of this.#M.keys())this.#lt(e,`pending`);this.#r.send({type:`connect`,clientId:this.#s,...this.#a===void 0?{}:{jwt:this.#a},cookie:this.#u,desiredQueries:[...this.#M.keys()].map(e=>this.#we(e)),schemaVersion:this.#y});for(let e of this.#T)this.#oe(e);for(let[e,t]of this.#N)this.#r.send({type:`once`,id:e,name:t.name,args:t.args})}#we(e,t){let n=this.#M.get(e),r=t===void 0?this.#Te(e):t.heldAt;return{name:n?.name??e,args:n?.args===void 0?void 0:i(n.args,`query args`),...n?.ttl===void 0?{}:{ttl:n.ttl},...r===void 0?{}:{heldAt:r}}}#Te(e){if(!(this.#e.exec(`SELECT 1 FROM __doync_membership WHERE instance = ? LIMIT 1`,e).length>0))return;if(this.#M.has(e))return this.#u??void 0;let t=w(this.#e,e);if(t!==null)return t.cookie}#Ee(e){if(this.#w){e.type===`error`&&this.#B.push(e.message);return}if(e.type===`pong`){this.#Se();return}if(e.type===`unauthorized`){this.#B.push(e.message),this.#at(!0);return}if(e.type===`pokeStart`&&e.clientId!==this.#s){this.#B.push(`doync: pokeStart addressed to client ${e.clientId}, this engine is ${this.#s}`);return}switch(this.#h&&e.type!==`error`&&this.#at(!1),e.type){case`schemaSkew`:this.#Be(e);break;case`schema`:this.#Ve(e);break;case`subscribeAck`:this.#et();for(let t of e.instances){this.#j.set(t.instance,t);let e=this.#M.get(t.instance);e!==void 0&&e.phase!==`complete`&&this.#lt(t.instance,`acked`)}break;case`pokeStart`:this.#et(),this.#z=[];break;case`pokePart`:if(this.#z===null)this.#B.push(`doync: pokePart arrived with no open poke`);else for(let t of e.patches)this.#z.push(t);break;case`pokeEnd`:this.#z===null?this.#B.push(`doync: pokeEnd arrived with no open poke`):this.#Ae(e.cookie,e.lastMutationId,e.confirms);break;case`pokeReject`:this.#ze(e.mutationId,e.error,e.reason);break;case`onceStart`:this.#P.set(e.id,[]);break;case`oncePart`:{let t=this.#P.get(e.id);if(t===void 0)this.#B.push(`doync: oncePart arrived with no open once`);else for(let n of e.rows)t.push(n);break}case`onceEnd`:this.#ke(e);break;case`resyncRequired`:this.#B.push(e.message),this.#K(()=>this.#Ze(`heldAt ahead of vouched baseline (instance ${e.instance}: heldAt=${e.heldAt} baseline=${e.baseline}) — ${e.message}`));break;case`error`:if(this.#B.push(e.message),Re(e.message)){this.#K(()=>this.#Ze(`cookie above the Origin head (server reset) — ${e.message}`));break}e.instances===void 0?this.#Oe(e.message):this.#De(e.instances,e.message);break;default:this.#B.push(`doync: unknown ServerMessage type ${String(e.type)}`)}}#De(e,t){let n=Error(t);for(let t of e){let e=this.#M.get(t);e!==void 0&&(e.phase===`pending`||e.phase===`acked`)&&this.#lt(t,`error`,n)}}#Oe(e){let t=Error(e);for(let[e,n]of this.#M)(n.phase===`pending`||n.phase===`acked`)&&this.#lt(e,`error`,t)}#ke(e){let t=this.#P.get(e.id)??[];this.#P.delete(e.id);let n=this.#N.get(e.id);if(n!==void 0){if(this.#N.delete(e.id),e.error!==void 0){n.view.settleError(Error(e.error));return}n.view.deliver(t.map(je))}}#Ae(e,t,n){let r=this.#z??[];this.#z=null,this.#K(()=>this.#je(r,e,t,n))}#je(e,t,n,r){let i=this.#e,a=[];return V(this.#te(()=>{for(let t of e)t.op===`put`&&this.#Ne(t);for(let t of e)t.op===`del`&&this.#Pe(t);for(let t of e)t.op===`pks`&&this.#Fe(t);if(n!==null){for(let e of this.#T)e.mutationId<=n&&!this.#k.has(e.mutationId)&&a.push(e.mutationId);for(let e of a)i.exec(`DELETE FROM __doync_pending WHERE mutation_id = ?`,e)}this.#u=t,g(i,`cookie`,String(t)),this.#he(),this.#T=this.#T.filter(e=>!a.includes(e.mutationId))}),e=>{for(let e of a)this.#pt(e,null);for(let e of a)this.#k.delete(e);this.#st(e),this.#Me(r)})}#Me(e){if(e!==void 0)for(let t of e){let e=this.#M.get(t);e!==void 0&&e.phase===`acked`&&this.#lt(t,`complete`)}}#Ne(e){let t=this.#e,n=this.#Re(e.instance,e.level);t.exec(`INSERT INTO __doync_membership (instance, level, tbl, pk) VALUES (?, ?, ?, ?)
|
|
14
|
+
ON CONFLICT (instance, level, pk) DO UPDATE SET tbl = excluded.tbl`,e.instance,e.level,n.name,e.pk);let r=D(e.pk,n);t.exec(`DELETE FROM ${E(n.name)} WHERE ${O(n)}`,...r);let{columns:i,values:a}=Se(n,e.image);t.exec(`INSERT INTO ${E(n.name)} (${i.map(E).join(`, `)})
|
|
15
|
+
VALUES (${i.map(()=>`?`).join(`, `)})`,...a)}#Pe(e){this.#Ie(e.instance,e.level,e.pk)}#Fe(e){let t=new Set(e.pks),n=this.#e.exec(`SELECT pk FROM __doync_membership WHERE instance = ? AND level = ?`,e.instance,e.level);for(let r of n){let n=String(r.pk);t.has(n)||this.#Ie(e.instance,e.level,n)}}#Ie(e,t,n){let r=this.#e,i=this.#Re(e,t);r.exec(`DELETE FROM __doync_membership WHERE instance = ? AND level = ? AND pk = ?`,e,t,n);let a=r.exec(`SELECT DISTINCT instance FROM __doync_membership WHERE tbl = ? AND pk = ?`,i.name,n);if(!a.some(e=>this.#M.has(String(e.instance)))){r.exec(`DELETE FROM ${E(i.name)} WHERE ${O(i)}`,...D(n,i));for(let e of a)this.#Le(String(e.instance))}}#Le(e){let t=this.#e,n=t.exec(`SELECT DISTINCT tbl, pk FROM __doync_membership WHERE instance = ?`,e);t.exec(`DELETE FROM __doync_membership WHERE instance = ?`,e),S(t,e);for(let e of n){let n=String(e.tbl),r=String(e.pk);if(t.exec(`SELECT 1 FROM __doync_membership WHERE tbl = ? AND pk = ? LIMIT 1`,n,r).length===0){let e=k(this.#t,n);t.exec(`DELETE FROM ${E(e.name)} WHERE ${O(e)}`,...D(r,e))}}}#Re(e,t){let n=this.#j.get(e);if(n===void 0)throw Error(`doync: patch for unknown instance ${e} — a subscribeAck must precede its hydration poke`);let r=n.levels.find(e=>e.level===t);if(r===void 0)throw Error(`doync: instance ${e} has no Level ${t} in its subscribeAck`);return k(this.#t,r.table)}#ze(e,t,n){if(this.#k.add(e),n===`reaped`){let e=this.#T.length;this.#B.push(t),this.#K(()=>this.#Ze(`server forgot this client (reaped) — dropped ${e} pending write${e===1?``:`s`} — ${t}`,`reaped`));return}this.#K(()=>V(this.#le(e),n=>{this.#pt(e,Error(t)),this.#st(n)}))}#Be(e){let t=e.serverVersion===void 0?``:` (server v${e.serverVersion})`;e.reason===`client-stale`?(this.#$e(`reload`,`schema client-stale: bundle v${this.#y} is behind the Mirror${t} — reload for the new bundle`),this.#nt()):(this.#$e(`server-behind`,`schema client-ahead: bundle v${this.#y} is ahead of the Mirror${t} — backing off until it deploys`),this.#rt(!1),this.#r.reconnect())}#Ve(e){let t=e.version;if(t>this.#y){this.#$e(`reload`,`schema directive v${t} is above the bundled track v${this.#y} — reload for the new bundle`),this.#nt();return}t<=this.#b||this.#K(()=>this.#He(t))}#He(e){let t=t=>`local migration to schema v${e} failed: ${Me(t)}`,n;try{n=this.#te(()=>{M(this.#e,this.#t,this.#b,e)})}catch(e){return this.#Ze(t(e))}return we(n,t=>{this.#b=e,this.#st(new Set([...t,...this.#Qe()]))},e=>this.#Ze(t(e)))}resync(){this.#K(()=>this.#Ze(`resync() requested by the consumer`))}forget(){this.#K(()=>this.#Je(`forget() requested by the consumer`))}setLogoutBehavior(e){this.#Ue(P,e)}#Ue(e,t){this.#We(()=>_(this.#e,e,t))}#We(e){this.#K(()=>V(this.#te(e),()=>{}))}#Ge(e,t=this.#y){N(e,this.#t),e.exec(`DELETE FROM __doync_membership`),xe(e),e.exec(`DELETE FROM __doync_pending`),e.exec(`DELETE FROM __doync_meta`),M(e,this.#t,0,t)}#Ke(e){this.#Ge(e),e.exec(`DELETE FROM __doync_prefs`)}#qe(e){let t=this.#e;this.#Xe(e),this.#s=this.#c(),g(t,`client_id`,this.#s),this.#u=null,this.#l=1,this.#f=0,this.#p=null,this.#T=[]}#Je(e){let t=this.#e,n=this.#te(()=>{this.#Ke(t),this.#qe(Error(`doync: ${e} — pending writes were forgotten`))});return this.#Ye(n,`forget`,`forgot the local store — ${e}`)}#Ye(e,t,n){return V(e,e=>{this.#b=this.#y,this.#j.clear(),this.#$e(t,n),this.#d&&(this.#rt(!1),this.#r.reconnect()),this.#st(new Set([...e,...this.#Qe()]))})}#Xe(e){for(let t of this.#E.keys())this.#ft(t,e),this.#pt(t,e);this.#D.clear(),this.#O.clear(),this.#k.clear(),this.#A.clear()}#Ze(e,t=`resync`){let n=this.#e,r=this.#te(()=>{this.#Ge(n),this.#qe(Error(`doync: ${e} — pending writes were dropped`))});return this.#Ye(r,t,t===`reaped`?`client state was reaped — ${e}`:`wiped and resyncing — ${e}`)}#Qe(){return this.#t.tables.map(e=>e.name)}onSchemaChange(e){return this.#C.add(e),()=>this.#C.delete(e)}#$e(e,t){let n={kind:e,message:t};this.#x=n,this.#S?.(n),this.#tt()}#et(){let e=this.#x?.kind;(e===`server-behind`||e===`resync`||e===`reaped`||e===`forget`)&&(this.#x=null,this.#tt())}#tt(){for(let e of this.#C)e()}#nt(){this.#w=!0,this.#rt(!1)}get connectionStatus(){return this.#h?`needs-auth`:this.#d?`connected`:this.#g??`disconnected`}onConnectionChange(e){return this.#v.add(e),()=>this.#v.delete(e)}#rt(e){this.#ot(()=>{this.#d=e,e&&(this.#g=null)})}#it(e){this.#ot(()=>{this.#g=e})}#at(e){this.#ot(()=>{this.#h=e})}#ot(e){let t=this.connectionStatus;if(e(),this.connectionStatus!==t)for(let e of this.#v)e()}#st(e){let t=K(e),n=new Set(this.#U);this.#U.clear();for(let e of this.#ct()){let r=e.readSet;(n.has(e)||r===void 0||[...r].some(e=>t.has(e)))&&e.recompute()&&e.notify()}}*#ct(){for(let e of this.#M.values())e.read!==null&&(yield e.read);for(let e of this.#I.values())e.read!==null&&(yield e.read)}#lt(e,t,n){let r=this.#M.get(e);if(r===void 0)return;r.phase=t,r.error=n;let i=Q(t,n);r.read!==null&&r.read.updateStatus(i)&&r.read.notify()}#ut(e,t){let n=this.#E.get(e);if(n!==void 0)return n;let r=this.#dt(t);return this.#E.set(e,r),r}#dt(e){let t,n,r,i,a=new Promise((e,r)=>{t=e,n=r}),o=new Promise((e,t)=>{r=e,i=t});return e&&(a.catch(()=>{}),o.catch(()=>{})),{pair:{client:a,server:o},resolveClient:t,rejectClient:n,resolveServer:r,rejectServer:i,clientSettled:!1,serverSettled:!1}}#ft(e,t){let n=this.#E.get(e);if(n===void 0){this.#B.push(`doync: settleClient for unknown mutation ${e} — no pending promise (a mutate() awaiting it would hang)`);return}n.clientSettled||(n.clientSettled=!0,t===null?n.resolveClient():n.rejectClient(t))}#pt(e,t){let n=this.#E.get(e);if(n===void 0){this.#B.push(`doync: settleServer for unknown mutation ${e} — no pending promise (a mutate() awaiting it would hang)`);return}n.serverSettled||(n.serverSettled=!0,t===null?n.resolveServer():n.rejectServer(t),n.clientSettled&&this.#E.delete(e))}};function B(e){return e instanceof Promise}function V(e,t){return e instanceof Promise?e.then(t):t(e)}function we(e,t,n){return e instanceof Promise?e.then(t,n):t(e)}var H=class{current(){return Y}status(){return X}onChange(){return()=>{}}retain(){}release(){}},Te=class{#e;#t=new Set;#n=!1;#r=!1;#i=Promise.withResolvers();#a=null;#o;#s;#c;constructor(e,t,n){this.#e=e,this.#o=t,this.#s=n.start,this.#c=n.drop}current(){return this.#l(),this.#e}onChange(e){return this.#l(),this.#t.add(e),()=>this.#t.delete(e)}get server(){return this.#l(),this.#i.promise}deliver(e){if(this.#r)return;let t=this.#o?this.#o(e):e;this.#e=t,this.#i.resolve(t);for(let e of this.#t)e()}settleError(e){this.#r||this.#i.reject(e)}dispose(){this.#r||this.#a===null&&(this.#a=setTimeout(()=>{this.#a=null,!this.#r&&(this.#r=!0,this.#t.clear(),this.#c())},J))}#l(){this.#r||(this.#a!==null&&(clearTimeout(this.#a),this.#a=null),!this.#n&&(this.#n=!0,this.#i=Promise.withResolvers(),this.#i.promise.catch(()=>{}),this.#s()))}};function U(e){return e===!1||e==null}function W(e,t,n){if(o(t))return{query:t.query,args:t.args,options:n};throw Ee(e,t)}function Ee(e,t){return Error(typeof t==`function`?`doync: client.${e} expected a BoundQuery — received a function; did you forget to call it?`:`doync: client.${e} expected a BoundQuery, got ${De(t)}`)}function De(e){if(e===null)return`null`;if(Array.isArray(e))return`an array`;let t=typeof e;if(t===`object`){let t=e.kind;return typeof t==`string`?`an object with kind "${t}"`:`an object`}return t}var Oe=class{current(){return Y}onChange(){return()=>{}}get server(){return new Promise(()=>{})}dispose(){}};const G={release(){}};function ke(e,t){e.retain();let n,r=!1,i=()=>{r||(r=!0,clearTimeout(n),t?.removeEventListener(`abort`,i),e.release())};return n=setTimeout(i,Ne),Pe(n),t?.addEventListener(`abort`,i,{once:!0}),{release:i}}const Ae={cleanup(){}};function je(e){let t={};for(let[r,i]of Object.entries(e))t[r]=n(i);return t}function K(e){return new Set([...e].filter(e=>!s(e)))}function q(e){let t=Promise.reject(e),n=Promise.reject(e);return t.catch(()=>{}),n.catch(()=>{}),{client:t,server:n}}function Me(e){return e instanceof Error?e.message:String(e)}const J=0,Ne=15e3;function Pe(e){typeof e==`object`&&e&&`unref`in e&&e.unref?.call(e)}const Y=Object.freeze([]),X=Object.freeze({status:`unknown`}),Z=Object.freeze({status:`complete`});function Q(e,t){return e===`complete`?Z:e===`error`?t===void 0?{status:`error`}:{status:`error`,error:t}:X}const Fe=()=>{let e=globalThis.crypto?.randomUUID?.();return e===void 0?`client-${Math.random().toString(16).slice(2)}-${Date.now().toString(16)}`:e},Ie=[`schema_version`,`next_mutation_id`,`cookie`];function Le(e){for(let t of Ie){let n=h(e,t);if(n!==null&&!Number.isInteger(Number(n)))return t}return null}function Re(e){return e.includes(`above the Origin head`)}function ze(e){return Be(e)}function Be(e){e.logoutBehavior!==void 0&&(A(e.db),_(e.db,P,e.logoutBehavior));let t=$(e.authData,e.ctxValidationSchema);return new z({db:e.db,schema:e.schema,mutations:a(e.mutations),socket:e.socket,ctx:t.ctx,token:t.token,userId:t.userId,clientId:e.clientId,onSchemaEvent:e.onSchemaEvent})}function $(e,t){if(e===null)return{userId:null,token:void 0,ctx:null};let n=e.ctx;return t!==void 0&&(n=ee(t,e.ctx,`auth context`)),{userId:e.userId,token:e.token,ctx:n}}export{f as S,fe as _,G as a,m as b,U as c,ke as d,M as f,h as g,j as h,z as i,W as l,N as m,Be as n,F as o,A as p,$ as r,P as s,ze as t,q as u,g as v,p as x,_ as y};
|
|
16
|
+
//# sourceMappingURL=client-Dphx71Qk.js.map
|