statewire 0.0.1 → 0.0.3
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 +14 -13
- package/dist/client/changes.d.ts +2 -2
- package/dist/client/changes.d.ts.map +1 -1
- package/dist/client/changes.js +3 -10
- package/dist/client/changes.js.map +1 -1
- package/dist/client/connection.d.ts +18 -39
- package/dist/client/connection.d.ts.map +1 -1
- package/dist/client/connection.js +61 -54
- package/dist/client/connection.js.map +1 -1
- package/dist/client/core.d.ts +7 -11
- package/dist/client/core.d.ts.map +1 -1
- package/dist/client/core.js +58 -55
- package/dist/client/core.js.map +1 -1
- package/dist/client/session.d.ts +12 -26
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/session.js +70 -43
- package/dist/client/session.js.map +1 -1
- package/dist/client/sessionStore.d.ts +1 -1
- package/dist/client/sessionStore.js.map +1 -1
- package/dist/client/timing.d.ts +2 -1
- package/dist/client/timing.d.ts.map +1 -1
- package/dist/client/timing.js +5 -1
- package/dist/client/timing.js.map +1 -1
- package/dist/host/adapter.d.ts +8 -0
- package/dist/host/adapter.d.ts.map +1 -0
- package/dist/host/adapter.js +23 -0
- package/dist/host/adapter.js.map +1 -0
- package/dist/host/draft.d.ts +21 -7
- package/dist/host/draft.d.ts.map +1 -1
- package/dist/host/draft.js +190 -103
- package/dist/host/draft.js.map +1 -1
- package/dist/host/host.d.ts +19 -35
- package/dist/host/host.d.ts.map +1 -1
- package/dist/host/host.js +86 -54
- package/dist/host/host.js.map +1 -1
- package/dist/host/socket.d.ts +14 -0
- package/dist/host/socket.d.ts.map +1 -0
- package/dist/host/socket.js +511 -0
- package/dist/host/socket.js.map +1 -0
- package/dist/host-internal.d.ts +27 -0
- package/dist/host-internal.d.ts.map +1 -0
- package/dist/host-internal.js +3 -0
- package/dist/host.d.ts +54 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +4 -0
- package/dist/index.d.ts +5 -28
- package/dist/index.js +2 -3
- package/dist/statewire.d.ts +97 -10
- package/dist/statewire.d.ts.map +1 -1
- package/dist/statewire.js +32 -36
- package/dist/statewire.js.map +1 -1
- package/dist/transports/fake-sse.d.ts +12 -0
- package/dist/transports/fake-sse.d.ts.map +1 -0
- package/dist/transports/fake-sse.js +39 -0
- package/dist/transports/fake-sse.js.map +1 -0
- package/dist/transports/fixtures.d.ts +33 -0
- package/dist/transports/fixtures.d.ts.map +1 -0
- package/dist/transports/fixtures.js +50 -0
- package/dist/transports/fixtures.js.map +1 -0
- package/dist/transports/remote.d.ts +6 -13
- package/dist/transports/remote.d.ts.map +1 -1
- package/dist/transports/remote.js +7 -25
- package/dist/transports/remote.js.map +1 -1
- package/dist/transports/sse.d.ts +32 -20
- package/dist/transports/sse.d.ts.map +1 -1
- package/dist/transports/sse.js +57 -46
- package/dist/transports/sse.js.map +1 -1
- package/dist/transports/testing.d.ts +8 -6
- package/dist/transports/testing.d.ts.map +1 -1
- package/dist/transports/testing.js +19 -46
- package/dist/transports/testing.js.map +1 -1
- package/dist/transports/ws.d.ts +4 -13
- package/dist/transports/ws.d.ts.map +1 -1
- package/dist/transports/ws.js +59 -63
- package/dist/transports/ws.js.map +1 -1
- package/dist/types.d.ts +55 -100
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/util/draftTraps.d.ts +6 -0
- package/dist/util/draftTraps.d.ts.map +1 -0
- package/dist/util/draftTraps.js +25 -0
- package/dist/util/draftTraps.js.map +1 -0
- package/dist/util/macrotask.d.ts +5 -0
- package/dist/util/macrotask.d.ts.map +1 -0
- package/dist/util/macrotask.js +25 -0
- package/dist/util/macrotask.js.map +1 -0
- package/dist/util/methodProxy.d.ts +5 -0
- package/dist/util/methodProxy.d.ts.map +1 -0
- package/dist/util/methodProxy.js +17 -0
- package/dist/util/methodProxy.js.map +1 -0
- package/dist/util/randomId.d.ts +5 -0
- package/dist/util/randomId.d.ts.map +1 -0
- package/dist/util/randomId.js +6 -0
- package/dist/util/randomId.js.map +1 -0
- package/dist/{client/optimistic.d.ts → util/recordMutations.d.ts} +2 -2
- package/dist/util/recordMutations.d.ts.map +1 -0
- package/dist/{client/optimistic.js → util/recordMutations.js} +5 -24
- package/dist/util/recordMutations.js.map +1 -0
- package/dist/util/statePath.d.ts +14 -0
- package/dist/util/statePath.d.ts.map +1 -0
- package/dist/util/statePath.js +31 -0
- package/dist/util/statePath.js.map +1 -0
- package/dist/wire/meta.d.ts +6 -1
- package/dist/wire/meta.d.ts.map +1 -1
- package/dist/wire/meta.js +30 -28
- package/dist/wire/meta.js.map +1 -1
- package/dist/wire/ops.d.ts +5 -26
- package/dist/wire/ops.d.ts.map +1 -1
- package/dist/wire/ops.js +67 -80
- package/dist/wire/ops.js.map +1 -1
- package/package.json +15 -11
- package/src/client/changes.ts +5 -15
- package/src/client/connection.ts +87 -113
- package/src/client/core.ts +57 -91
- package/src/client/session.ts +129 -90
- package/src/client/sessionStore.ts +1 -1
- package/src/client/timing.ts +6 -0
- package/src/host/adapter.ts +33 -0
- package/src/host/draft.ts +293 -125
- package/src/host/host.ts +122 -110
- package/src/host/socket.ts +618 -0
- package/src/host-internal.ts +28 -0
- package/src/host.ts +72 -0
- package/src/index.ts +2 -62
- package/src/statewire.ts +168 -61
- package/src/transports/fake-sse.ts +51 -0
- package/src/transports/fixtures.ts +60 -0
- package/src/transports/remote.ts +14 -51
- package/src/transports/sse.ts +87 -89
- package/src/transports/testing.ts +33 -63
- package/src/transports/ws.ts +78 -100
- package/src/types.ts +52 -131
- package/src/util/draftTraps.ts +32 -0
- package/src/util/macrotask.ts +25 -0
- package/src/util/methodProxy.ts +16 -0
- package/src/util/randomId.ts +4 -0
- package/src/{client/optimistic.ts → util/recordMutations.ts} +0 -0
- package/src/util/statePath.ts +61 -0
- package/src/wire/meta.ts +42 -47
- package/src/wire/ops.ts +107 -106
- package/LICENSE +0 -21
- package/dist/client/optimistic.d.ts.map +0 -1
- package/dist/client/optimistic.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/server.d.ts +0 -15
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -3
- package/src/server.ts +0 -32
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ type Commands = {
|
|
|
9
9
|
increment(): void;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
const { state,
|
|
12
|
+
const { state, connection, commands } = useStatewire<State, Commands, Event>({
|
|
13
13
|
transport: StatewireSSE({ url: "/api/threads/demo" }),
|
|
14
14
|
optimistic: (draft, command) => {
|
|
15
15
|
if (command.method === "increment") draft.count += 1;
|
|
@@ -24,15 +24,16 @@ const onClick = async () => {
|
|
|
24
24
|
## What you get
|
|
25
25
|
|
|
26
26
|
- **`state`** — `undefined` until the first snapshot, then canonical server state with your pending commands' optimistic effects rebased on top. When the server's ack arrives, the optimistic overlay drops in the same tick: no flicker.
|
|
27
|
-
- **`
|
|
28
|
-
- **`commands`** — a typed proxy over the `Commands` method map: `commands.increment()` submits `{ method: "increment", params: [] }` and resolves with the handler's result only once the stream ack proves the effect is in canonical state. Rejects with `StatewireSendError`, whose `failure.
|
|
27
|
+
- **`connection`** — connection health as a tagged union: `connection.status` is `"connecting" | "live" | "reconnecting" | "gone"`, and each variant carries exactly the data that exists in that situation: `reconnecting` has `cause` (`"dropped"`, `"evicted"`, or `"error"`), `attempt`, `nextRetryAt`, `lastError?`, `message?`; `gone` carries the server's `message?` and `payload?`. `connection.reconnect()` re-attaches manually from `gone`, or "retry now" during backoff.
|
|
28
|
+
- **`commands`** — a typed proxy over the `Commands` method map: `commands.increment()` submits `{ method: "increment", params: [] }` and resolves with the handler's result only once the stream ack proves the effect is in canonical state. Rejects with `StatewireSendError`, whose `failure.fate` carries the verdict; the boundary is definitiveness:
|
|
29
29
|
- `"aborted"` — definitely not applied (never POSTed, or every attempt accounted for); safe to resend
|
|
30
30
|
- `"lost"` — a POST left the machine and never got a definitive answer; whether the server applied it is unknown — check the snapshot for your payload ids
|
|
31
|
-
- `"rejected"` — the server said no; not applied (`message`, optional `payload` from the backend's `
|
|
31
|
+
- `"rejected"` — the server said no; not applied (`message`, optional `payload` from the backend's `StatewireReject`)
|
|
32
|
+
- `"unknown-command"` / `"invalid-params"` — the server does not know the method, or the args failed its schema
|
|
32
33
|
- `"crashed"` — acked, but the processing died before producing a result
|
|
33
|
-
- `"unavailable"` — acked, but the result can no longer be delivered
|
|
34
|
+
- `"result-unavailable"` — acked, but the result can no longer be delivered
|
|
34
35
|
|
|
35
|
-
Every failure also carries `
|
|
36
|
+
Every failure also carries `cause` — which channel settled it: `"server"` = the server's answer, `"stream-gone"` = terminal `finish(gone)`, `"session-lost"` = the server forgot the client id (eviction), `"superseded"` = another attach took the writer lease, `"unmount"` / `"cascade"` are client-side. The taxonomy's single exported type is `StatewireClient.SendFailure`; the `fate` and `cause` unions are reachable as `SendFailure["fate"]` / `SendFailure["cause"]`.
|
|
36
37
|
|
|
37
38
|
Reconnects are not errors: transport drops and server evictions self-heal with exponential backoff while `state` stays renderable. Commands carry a monotonic seq, so retries are deduplicated server-side and a reconnect splices already-applied commands instead of re-running them.
|
|
38
39
|
|
|
@@ -45,13 +46,13 @@ One implementation, three entry points:
|
|
|
45
46
|
```ts
|
|
46
47
|
useStatewire(options) // React hook
|
|
47
48
|
StatewireResource(options) // @assistant-ui/tap resource, for composition
|
|
48
|
-
new
|
|
49
|
+
new StatewireClient(options) // framework-free: .state/.connection/.commands,
|
|
49
50
|
// .subscribe(cb), .dispose()
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
`
|
|
53
|
+
`StatewireClient#subscribe` follows the external-store contract (`useSyncExternalStore`-compatible). `dispose()` settles pending commands like an unmount.
|
|
53
54
|
|
|
54
|
-
Every public type merges onto the class as a namespace — `
|
|
55
|
+
Every public type merges onto the class as a namespace — `StatewireClient.Connection`, `StatewireClient.ConnectionStatus`, `StatewireClient.Options`, `StatewireClient.SendFailure`, … — so one import covers the whole surface.
|
|
55
56
|
|
|
56
57
|
There is no session key: a transport `url` change reattaches in place and the attach snapshot arbitrates identity (an unknown client evicts — pending settles, the client id rotates). For a forced fresh session, key the resource — `withKey(threadId, StatewireResource(options))`; pending commands settle with reason `"unmount"`.
|
|
57
58
|
|
|
@@ -65,20 +66,20 @@ StatewireSSE({
|
|
|
65
66
|
})
|
|
66
67
|
```
|
|
67
68
|
|
|
68
|
-
`StatewireWS({ url, protocols, query, webSocket })` is the full-duplex sibling over `/ws`.
|
|
69
|
+
`StatewireWS({ url, protocols, query, webSocket })` is the full-duplex sibling over `/ws`. A transport is a tap resource producing the `Statewire` value the client consumes; `createMockTransport` from `statewire/testing` is a complete in-memory driver for tests.
|
|
69
70
|
|
|
70
71
|
## Backend
|
|
71
72
|
|
|
72
|
-
Any server speaking the Statewire convention works. The Python implementation lives in this repo (`python/statewire`):
|
|
73
|
+
Any server speaking the Statewire convention works. The Python implementation lives in this repo (`python/statewire/statewire`):
|
|
73
74
|
|
|
74
75
|
```python
|
|
75
|
-
from statewire import Statewire,
|
|
76
|
+
from statewire import Statewire, StatewireReject, command
|
|
76
77
|
|
|
77
78
|
class Counter(Statewire):
|
|
78
79
|
@command
|
|
79
80
|
async def increment(self):
|
|
80
81
|
if self.state["count"] >= 10:
|
|
81
|
-
raise
|
|
82
|
+
raise StatewireReject("counter is full", payload={"max": 10})
|
|
82
83
|
self.state["count"] += 1
|
|
83
84
|
```
|
|
84
85
|
|
package/dist/client/changes.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { Statewire } from "../types.js";
|
|
1
2
|
import { StatewirePath } from "../wire/ops.js";
|
|
2
|
-
import { StatewireChanges } from "../types.js";
|
|
3
3
|
//#region src/client/changes.d.ts
|
|
4
|
-
declare const createChanges: (prev: unknown, next: unknown, changedPaths: readonly StatewirePath[]) =>
|
|
4
|
+
declare const createChanges: (prev: unknown, next: unknown, changedPaths: readonly StatewirePath[]) => Statewire.Changes;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { createChanges };
|
|
7
7
|
//# sourceMappingURL=changes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changes.d.ts","names":[],"sources":["../../src/client/changes.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"changes.d.ts","names":[],"sources":["../../src/client/changes.ts"],"mappings":";;;cAWa,gBACX,eACA,eACA,uBAAuB,oBACtB,UAAU"}
|
package/dist/client/changes.js
CHANGED
|
@@ -1,20 +1,13 @@
|
|
|
1
|
+
import { readAtPath } from "../util/statePath.js";
|
|
1
2
|
//#region src/client/changes.ts
|
|
2
|
-
const lookupValue = (state, path) => {
|
|
3
|
-
let node = state;
|
|
4
|
-
for (const key of path) {
|
|
5
|
-
if (typeof node !== "object" || node === null) return void 0;
|
|
6
|
-
node = Object.hasOwn(node, key) ? node[key] : void 0;
|
|
7
|
-
}
|
|
8
|
-
return node;
|
|
9
|
-
};
|
|
10
3
|
const keysAt = (node) => typeof node === "object" && node !== null ? Object.keys(node) : [];
|
|
11
4
|
const isPrefix = (prefix, path) => prefix.length <= path.length && prefix.every((key, i) => String(key) === String(path[i]));
|
|
12
5
|
const createChanges = (prev, next, changedPaths) => ({
|
|
13
6
|
isChangedAt: (path) => changedPaths.some((p) => isPrefix(p, path) || isPrefix(path, p)),
|
|
14
7
|
getChangedKeys: (path) => {
|
|
15
8
|
if (changedPaths.some((p) => p.length <= path.length && isPrefix(p, path))) {
|
|
16
|
-
const keys = keysAt(
|
|
17
|
-
for (const key of keysAt(
|
|
9
|
+
const keys = keysAt(readAtPath(next, path));
|
|
10
|
+
for (const key of keysAt(readAtPath(prev, path))) if (!keys.includes(key)) keys.push(key);
|
|
18
11
|
return keys;
|
|
19
12
|
}
|
|
20
13
|
const keys = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changes.js","names":["StatewirePath","
|
|
1
|
+
{"version":3,"file":"changes.js","names":["StatewirePath","Statewire","readAtPath","keysAt","node","Object","keys","isPrefix","prefix","path","length","every","key","i","String","createChanges","prev","next","changedPaths","Changes","isChangedAt","some","p","getChangedKeys","wiped","includes","push"],"sources":["../../src/client/changes.ts"],"sourcesContent":["import type { StatewirePath } from \"../wire/ops\";\nimport type { Statewire } from \"../types\";\nimport { readAtPath } from \"../util/statePath\";\n\nconst keysAt = (node: unknown): string[] =>\n typeof node === \"object\" && node !== null ? Object.keys(node) : [];\n\nconst isPrefix = (prefix: StatewirePath, path: StatewirePath): boolean =>\n prefix.length <= path.length &&\n prefix.every((key, i) => String(key) === String(path[i]));\n\nexport const createChanges = (\n prev: unknown,\n next: unknown,\n changedPaths: readonly StatewirePath[],\n): Statewire.Changes => ({\n isChangedAt: (path) =>\n changedPaths.some((p) => isPrefix(p, path) || isPrefix(path, p)),\n getChangedKeys: (path) => {\n const wiped = changedPaths.some(\n (p) => p.length <= path.length && isPrefix(p, path),\n );\n if (wiped) {\n const keys = keysAt(readAtPath(next, path));\n for (const key of keysAt(readAtPath(prev, path))) {\n if (!keys.includes(key)) keys.push(key);\n }\n return keys;\n }\n const keys: string[] = [];\n for (const p of changedPaths) {\n if (p.length <= path.length || !isPrefix(path, p)) continue;\n const key = String(p[path.length]);\n if (!keys.includes(key)) keys.push(key);\n }\n return keys;\n },\n});\n"],"mappings":";;AAIA,MAAMG,UAAUC,SACd,OAAOA,SAAS,YAAYA,SAAS,OAAOC,OAAOC,KAAKF,IAAI,IAAI,CAAA;AAElE,MAAMG,YAAYC,QAAuBC,SACvCD,OAAOE,UAAUD,KAAKC,UACtBF,OAAOG,OAAOC,KAAKC,MAAMC,OAAOF,GAAG,MAAME,OAAOL,KAAKI,EAAE,CAAC;AAE1D,MAAaE,iBACXC,MACAC,MACAC,kBACuB;CACvBE,cAAcX,SACZS,aAAaG,MAAMC,MAAMf,SAASe,GAAGb,IAAI,KAAKF,SAASE,MAAMa,CAAC,CAAC;CACjEC,iBAAiBd,SAAS;EAIxB,IAHcS,aAAaG,MACxBC,MAAMA,EAAEZ,UAAUD,KAAKC,UAAUH,SAASe,GAAGb,IAAI,CAEhDe,GAAO;GACT,MAAMlB,OAAOH,OAAOD,WAAWe,MAAMR,IAAI,CAAC;GAC1C,KAAK,MAAMG,OAAOT,OAAOD,WAAWc,MAAMP,IAAI,CAAC,GAC7C,IAAI,CAACH,KAAKmB,SAASb,GAAG,GAAGN,KAAKoB,KAAKd,GAAG;GAExC,OAAON;EACT;EACA,MAAMA,OAAiB,CAAA;EACvB,KAAK,MAAMgB,KAAKJ,cAAc;GAC5B,IAAII,EAAEZ,UAAUD,KAAKC,UAAU,CAACH,SAASE,MAAMa,CAAC,GAAG;GACnD,MAAMV,MAAME,OAAOQ,EAAEb,KAAKC,OAAO;GACjC,IAAI,CAACJ,KAAKmB,SAASb,GAAG,GAAGN,KAAKoB,KAAKd,GAAG;EACxC;EACA,OAAON;CACT;AACF"}
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StatewireHost } from "../host.js";
|
|
2
|
+
import { StatewireRemoteProps } from "../transports/sse.js";
|
|
3
|
+
import { StatewireClient } from "../statewire.js";
|
|
2
4
|
//#region src/client/connection.d.ts
|
|
3
5
|
type Episode = {
|
|
4
|
-
cause: "dropped" | "
|
|
6
|
+
cause: "dropped" | "evicted" | "error";
|
|
5
7
|
message?: string;
|
|
6
8
|
};
|
|
7
|
-
type StatewireFinish = {
|
|
8
|
-
reason: "ended" | "error" | "gone" | "superseded" | (string & {});
|
|
9
|
-
message?: string;
|
|
10
|
-
payload?: unknown;
|
|
11
|
-
meta?: unknown;
|
|
12
|
-
};
|
|
13
9
|
type StatewireResponse = {
|
|
14
10
|
seq: number;
|
|
15
11
|
type: "accepted" | "rejected" | "pending" | "crashed" | "result-unavailable";
|
|
@@ -27,7 +23,7 @@ type StatewireEnvelope = {
|
|
|
27
23
|
res?: StatewireResponse[];
|
|
28
24
|
ack?: number;
|
|
29
25
|
syn?: StatewireSyn;
|
|
30
|
-
fin?:
|
|
26
|
+
fin?: StatewireHost.Fin;
|
|
31
27
|
};
|
|
32
28
|
declare const createGate: () => {
|
|
33
29
|
take: () => boolean;
|
|
@@ -35,8 +31,8 @@ declare const createGate: () => {
|
|
|
35
31
|
open: () => void;
|
|
36
32
|
};
|
|
37
33
|
type Gate = ReturnType<typeof createGate>;
|
|
38
|
-
type
|
|
39
|
-
connection:
|
|
34
|
+
type Conn = {
|
|
35
|
+
connection: StatewireClient.Connection;
|
|
40
36
|
hasSnapshot: boolean;
|
|
41
37
|
lease: string | null;
|
|
42
38
|
attempt: number;
|
|
@@ -44,41 +40,24 @@ type ConnBase = {
|
|
|
44
40
|
gate: Gate;
|
|
45
41
|
abort: AbortController | null;
|
|
46
42
|
lifetime: AbortController | null;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
options: {
|
|
50
|
-
onChange?: (connection: StatewireConnection) => void;
|
|
51
|
-
};
|
|
52
|
-
ctx: StatewireTransportProps;
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
|
-
notify: (connection: StatewireConnection) => void;
|
|
56
|
-
reconnect: () => void;
|
|
43
|
+
ctx: StatewireRemoteProps;
|
|
44
|
+
onChange: (connection: StatewireClient.Connection) => void;
|
|
57
45
|
attemptOnce: (abort: AbortController) => Promise<"stop" | "reattach" | "ended">;
|
|
46
|
+
notify: (connection: StatewireClient.Connection) => void;
|
|
47
|
+
reconnect: () => void;
|
|
58
48
|
};
|
|
59
|
-
declare const
|
|
60
|
-
declare const
|
|
61
|
-
declare const isTransientFinish: (reason: StatewireFinish["reason"]) => reason is "ended" | "error";
|
|
62
|
-
declare const settleEnvelope: (c: ConnBase, env: StatewireEnvelope) => "stop" | "reattach" | null;
|
|
63
|
-
declare const handleEnvelope: (c: ConnBase, env: StatewireEnvelope, attached: boolean) => "stop" | "reattach" | null;
|
|
64
|
-
declare const scheduleRetry: (c: ConnBase, failure: string | undefined, immediate: boolean, retryAfterMs?: number) => number;
|
|
65
|
-
declare const reconnectConn: (c: ConnBase) => void;
|
|
66
|
-
declare const useStatewireConn: <TOptions extends {
|
|
49
|
+
declare const handleEnvelope: (c: Conn, env: StatewireEnvelope) => "stop" | "reattach" | null;
|
|
50
|
+
declare const useStatewireConn: (props: {
|
|
67
51
|
url: string;
|
|
68
|
-
onChange?: (connection:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
ctx: StatewireTransportProps;
|
|
73
|
-
};
|
|
74
|
-
}, notify: (connection: StatewireConnection) => void) => ConnBase & {
|
|
75
|
-
send: RemoteLink["send"];
|
|
76
|
-
}) => RemoteLink;
|
|
52
|
+
onChange?: ((connection: StatewireClient.Connection) => void) | undefined;
|
|
53
|
+
ctx: StatewireRemoteProps;
|
|
54
|
+
attemptOnce: (c: Conn, abort: AbortController) => Promise<"stop" | "reattach" | "ended">;
|
|
55
|
+
}) => Conn;
|
|
77
56
|
declare const classify: (timeout: AbortSignal) => Error;
|
|
78
57
|
declare const parseRetryAfter: (header: string | null) => number | undefined;
|
|
79
58
|
declare const overloadedError: (retryAfterMs?: number) => Error & {
|
|
80
59
|
retryAfterMs: number | undefined;
|
|
81
60
|
};
|
|
82
61
|
//#endregion
|
|
83
|
-
export {
|
|
62
|
+
export { Conn, Episode, Gate, StatewireEnvelope, StatewireResponse, StatewireSyn, classify, handleEnvelope, overloadedError, parseRetryAfter, useStatewireConn };
|
|
84
63
|
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","names":[],"sources":["../../src/client/connection.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"connection.d.ts","names":[],"sources":["../../src/client/connection.ts"],"mappings":";;;;KAQY;EACV;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA;;KAGU;EACV;EACA,MAAM;EACN;EACA,MAAM;EACN,MAAM,cAAc;;cAGhB;;EASiB,OAAA,uBAAM;;;KA2BjB,OAAO,kBAAkB;KAEzB;EACV,YAAY,gBAAgB;EAC5B;EACA;EACA;EACA,SAAS;EACT,MAAM;EACN,OAAO;EACP,UAAU;EACV,KAAK;EACL,WAAW,YAAY,gBAAgB;EACvC,cACE,OAAO,oBACJ;EACL,SAAS,YAAY,gBAAgB;EACrC;;cAuEW,iBACX,GAAG,MACH,KAAK;cAyEM,mBAAoB;EAC/B;EACA,aAAa,YAAY,gBAAgB;EACzC,KAAK;EACL,cACE,GAAG,MACH,OAAO,oBACJ;MACH;cA8CS,WAAY,SAAS,gBAAW;cAGhC,kBAAmB;cAQnB,kBAAmB,0BAAqB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { reviveOps, reviveResponse, reviveValue } from "../wire/meta.js";
|
|
2
|
-
import {
|
|
2
|
+
import { retryDelay } from "./timing.js";
|
|
3
3
|
import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
|
|
4
4
|
import { flushTapSync } from "@assistant-ui/tap";
|
|
5
5
|
//#region src/client/connection.ts
|
|
@@ -42,25 +42,26 @@ const setStatus = (c, next) => {
|
|
|
42
42
|
reconnect: c.reconnect
|
|
43
43
|
};
|
|
44
44
|
c.notify(c.connection);
|
|
45
|
-
if (changed) c.
|
|
45
|
+
if (changed) c.onChange(c.connection);
|
|
46
46
|
};
|
|
47
|
-
const deliverEnvelope = (c, env
|
|
47
|
+
const deliverEnvelope = (c, env) => {
|
|
48
48
|
if (env.syn?.lease !== void 0) c.lease = env.syn.lease;
|
|
49
|
-
const ctx = c.
|
|
49
|
+
const ctx = c.ctx;
|
|
50
50
|
const ops = env.ops === void 0 ? [] : reviveOps(env.ops);
|
|
51
51
|
const res = env.res?.map(reviveResponse);
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
if (env.syn !== void 0) {
|
|
53
|
+
ctx.onSnapshot({
|
|
54
|
+
ops,
|
|
55
|
+
lastSeq: env.syn.lastSeq
|
|
56
|
+
});
|
|
57
|
+
c.hasSnapshot = true;
|
|
58
|
+
} else if (env.ops !== void 0 || env.res !== void 0 || env.ack !== void 0) ctx.onOps({
|
|
57
59
|
ops,
|
|
58
60
|
...res !== void 0 && { res },
|
|
59
61
|
...env.ack !== void 0 && { ack: env.ack }
|
|
60
62
|
});
|
|
61
|
-
c.hasSnapshot = true;
|
|
62
63
|
};
|
|
63
|
-
const isTransientFinish = (reason) => reason === "
|
|
64
|
+
const isTransientFinish = (reason) => reason === "evicted" || reason === "error";
|
|
64
65
|
const settleEnvelope = (c, env) => {
|
|
65
66
|
let finish = env.fin;
|
|
66
67
|
if (finish) {
|
|
@@ -71,7 +72,7 @@ const settleEnvelope = (c, env) => {
|
|
|
71
72
|
payload: reviveValue(rest.payload, meta)
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
|
-
c.
|
|
75
|
+
c.ctx.onFinish(finish);
|
|
75
76
|
if (isTransientFinish(finish.reason)) {
|
|
76
77
|
c.episode = {
|
|
77
78
|
cause: finish.reason,
|
|
@@ -93,14 +94,14 @@ const settleEnvelope = (c, env) => {
|
|
|
93
94
|
}
|
|
94
95
|
return null;
|
|
95
96
|
};
|
|
96
|
-
const handleEnvelope = (c, env
|
|
97
|
-
deliverEnvelope(c, env
|
|
97
|
+
const handleEnvelope = (c, env) => {
|
|
98
|
+
deliverEnvelope(c, env);
|
|
98
99
|
return settleEnvelope(c, env);
|
|
99
100
|
};
|
|
100
|
-
const scheduleRetry = (c, failure, immediate,
|
|
101
|
+
const scheduleRetry = (c, failure, immediate, cause) => {
|
|
101
102
|
c.attempt += 1;
|
|
102
103
|
c.episode ??= { cause: "dropped" };
|
|
103
|
-
const delay = immediate ? 0 :
|
|
104
|
+
const delay = immediate ? 0 : retryDelay(cause, c.attempt);
|
|
104
105
|
if (c.hasSnapshot) setStatus(c, {
|
|
105
106
|
status: "reconnecting",
|
|
106
107
|
...c.episode,
|
|
@@ -129,14 +130,14 @@ const run = async (c, lifetime, gate) => {
|
|
|
129
130
|
const abort = new AbortController();
|
|
130
131
|
c.abort = abort;
|
|
131
132
|
let failure;
|
|
132
|
-
let
|
|
133
|
+
let cause;
|
|
133
134
|
let gone = false;
|
|
134
135
|
try {
|
|
135
136
|
gone = await c.attemptOnce(abort) === "stop";
|
|
136
137
|
} catch (error) {
|
|
137
138
|
if (!abort.signal.aborted) {
|
|
138
139
|
failure = error instanceof Error && error.message ? error.message : "network";
|
|
139
|
-
|
|
140
|
+
cause = error;
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
143
|
abort.abort();
|
|
@@ -146,48 +147,54 @@ const run = async (c, lifetime, gate) => {
|
|
|
146
147
|
continue;
|
|
147
148
|
}
|
|
148
149
|
const immediate = gate.take();
|
|
149
|
-
const delay = flushTapSync(() => scheduleRetry(c, failure, immediate,
|
|
150
|
+
const delay = flushTapSync(() => scheduleRetry(c, failure, immediate, cause));
|
|
150
151
|
if (delay === 0) continue;
|
|
151
152
|
await gate.wait(delay);
|
|
152
153
|
}
|
|
153
154
|
};
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
c
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const [c] = useState(() => create(latest, setConnection));
|
|
177
|
-
useEffect(() => {
|
|
178
|
-
latest.current = {
|
|
179
|
-
options,
|
|
180
|
-
ctx
|
|
155
|
+
const useStatewireConn = (props) => {
|
|
156
|
+
const latest = useRef(props);
|
|
157
|
+
latest.current = props;
|
|
158
|
+
const [, setConnection] = useState(null);
|
|
159
|
+
const [c] = useState(() => {
|
|
160
|
+
const conn = {
|
|
161
|
+
hasSnapshot: false,
|
|
162
|
+
lease: null,
|
|
163
|
+
attempt: 0,
|
|
164
|
+
episode: null,
|
|
165
|
+
abort: null,
|
|
166
|
+
gate: createGate(),
|
|
167
|
+
lifetime: null,
|
|
168
|
+
ctx: props.ctx,
|
|
169
|
+
onChange: (connection) => latest.current.onChange?.(connection),
|
|
170
|
+
attemptOnce: (abort) => latest.current.attemptOnce(conn, abort),
|
|
171
|
+
notify: setConnection,
|
|
172
|
+
reconnect: () => reconnectConn(conn),
|
|
173
|
+
connection: {
|
|
174
|
+
status: "connecting",
|
|
175
|
+
reconnect: () => conn.reconnect()
|
|
176
|
+
}
|
|
181
177
|
};
|
|
178
|
+
return conn;
|
|
182
179
|
});
|
|
183
180
|
useEffect(() => {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
181
|
+
c.hasSnapshot = false;
|
|
182
|
+
c.lease = null;
|
|
183
|
+
c.attempt = 0;
|
|
184
|
+
c.episode = null;
|
|
185
|
+
if (c.connection.status !== "connecting") setStatus(c, { status: "connecting" });
|
|
186
|
+
const lifetime = new AbortController();
|
|
187
|
+
c.lifetime = lifetime;
|
|
188
|
+
c.gate = createGate();
|
|
189
|
+
run(c, lifetime, c.gate);
|
|
190
|
+
return () => {
|
|
191
|
+
c.abort?.abort();
|
|
192
|
+
lifetime.abort();
|
|
193
|
+
if (c.lifetime === lifetime) c.lifetime = null;
|
|
194
|
+
c.gate.open();
|
|
195
|
+
};
|
|
196
|
+
}, [c, props.url]);
|
|
197
|
+
return c;
|
|
191
198
|
};
|
|
192
199
|
const classify = (timeout) => /* @__PURE__ */ new Error(timeout.aborted ? "timeout" : "network");
|
|
193
200
|
const parseRetryAfter = (header) => {
|
|
@@ -199,6 +206,6 @@ const parseRetryAfter = (header) => {
|
|
|
199
206
|
};
|
|
200
207
|
const overloadedError = (retryAfterMs) => Object.assign(/* @__PURE__ */ new Error("overloaded"), { retryAfterMs });
|
|
201
208
|
//#endregion
|
|
202
|
-
export { classify,
|
|
209
|
+
export { classify, handleEnvelope, overloadedError, parseRetryAfter, useStatewireConn };
|
|
203
210
|
|
|
204
211
|
//# sourceMappingURL=connection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.js","names":["useEffect","useRef","useState","flushTapSync","reviveOps","reviveResponse","reviveValue","backoff","ConnectionState","RemoteLink","StatewireConnection","StatewireTransportProps","Episode","cause","message","StatewireFinish","reason","payload","meta","StatewireResponse","seq","type","code","StatewireSyn","lastSeq","lease","StatewireEnvelope","ops","res","ack","syn","fin","createGate","latched","wake","take","was","wait","timeoutMs","Promise","resolve","timer","undefined","setTimeout","clearTimeout","open","Gate","ReturnType","ConnBase","connection","hasSnapshot","attempt","episode","gate","abort","AbortController","lifetime","latest","current","options","onChange","ctx","notify","reconnect","attemptOnce","setStatus","c","next","changed","status","deliverEnvelope","env","Pick","attached","map","onSnapshot","onOps","isTransientFinish","settleEnvelope","finish","rest","onFinish","handleEnvelope","scheduleRetry","failure","immediate","retryAfterMs","delay","nextRetryAt","Date","now","lastError","reconnectConn","run","alive","gone","error","signal","aborted","Error","startConn","stopConn","useStatewireConn","url","TOptions","create","send","setConnection","classify","timeout","AbortSignal","parseRetryAfter","header","value","trim","test","Number","date","parse","isNaN","Math","max","overloadedError","Object","assign"],"sources":["../../src/client/connection.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\nimport { reviveOps, reviveResponse, reviveValue } from \"../wire/meta\";\nimport { backoff } from \"./timing\";\nimport type {\n ConnectionState,\n RemoteLink,\n StatewireConnection,\n StatewireTransportProps,\n} from \"../transports/sse\";\n\nexport type Episode = {\n cause: \"dropped\" | \"ended\" | \"error\";\n message?: string;\n};\n\nexport type StatewireFinish = {\n reason: \"ended\" | \"error\" | \"gone\" | \"superseded\" | (string & {});\n message?: string;\n payload?: unknown;\n meta?: unknown;\n};\n\nexport type StatewireResponse = {\n seq: number;\n type: \"accepted\" | \"rejected\" | \"pending\" | \"crashed\" | \"result-unavailable\";\n code?: string;\n message?: string;\n payload?: unknown;\n meta?: unknown;\n};\n\nexport type StatewireSyn = {\n lastSeq: number;\n lease?: string;\n};\n\nexport type StatewireEnvelope = {\n ops?: unknown[];\n res?: StatewireResponse[];\n ack?: number;\n syn?: StatewireSyn;\n fin?: StatewireFinish;\n};\n\nexport const createGate = () => {\n let latched = false;\n let wake: (() => void) | undefined;\n return {\n take: () => {\n const was = latched;\n latched = false;\n return was;\n },\n wait: (timeoutMs?: number) => {\n if (latched) {\n latched = false;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n wake = undefined;\n resolve();\n }, timeoutMs);\n wake = () => {\n clearTimeout(timer);\n wake = undefined;\n resolve();\n };\n });\n },\n open: () => {\n if (wake) wake();\n else latched = true;\n },\n };\n};\n\nexport type Gate = ReturnType<typeof createGate>;\n\nexport type ConnBase = {\n connection: StatewireConnection;\n hasSnapshot: boolean;\n lease: string | null;\n attempt: number;\n episode: Episode | null;\n gate: Gate;\n abort: AbortController | null;\n lifetime: AbortController | null;\n latest: {\n readonly current: {\n options: { onChange?: (connection: StatewireConnection) => void };\n ctx: StatewireTransportProps;\n };\n };\n notify: (connection: StatewireConnection) => void;\n reconnect: () => void;\n attemptOnce: (\n abort: AbortController,\n ) => Promise<\"stop\" | \"reattach\" | \"ended\">;\n};\n\nexport const setStatus = (c: ConnBase, next: ConnectionState) => {\n const changed = next.status !== c.connection.status;\n c.connection = { ...next, reconnect: c.reconnect };\n c.notify(c.connection);\n if (changed) c.latest.current.options.onChange?.(c.connection);\n};\n\nexport const deliverEnvelope = (\n c: ConnBase,\n env: Pick<StatewireEnvelope, \"ops\" | \"res\" | \"ack\" | \"syn\">,\n attached: boolean,\n) => {\n if (env.syn?.lease !== undefined) c.lease = env.syn.lease;\n const ctx = c.latest.current.ctx;\n const ops = env.ops === undefined ? [] : reviveOps(env.ops);\n const res = env.res?.map(reviveResponse);\n if (!attached) {\n ctx.onSnapshot({ ops, lastSeq: env.syn?.lastSeq ?? -1 });\n } else if (\n env.ops !== undefined ||\n env.res !== undefined ||\n env.ack !== undefined\n ) {\n ctx.onOps({\n ops,\n ...(res !== undefined && { res }),\n ...(env.ack !== undefined && { ack: env.ack }),\n });\n }\n c.hasSnapshot = true;\n};\n\nexport const isTransientFinish = (\n reason: StatewireFinish[\"reason\"],\n): reason is \"ended\" | \"error\" => reason === \"ended\" || reason === \"error\";\n\nexport const settleEnvelope = (\n c: ConnBase,\n env: StatewireEnvelope,\n): \"stop\" | \"reattach\" | null => {\n let finish = env.fin;\n if (finish) {\n if (finish.meta !== undefined) {\n const { meta, ...rest } = finish;\n finish = { ...rest, payload: reviveValue(rest.payload, meta) };\n }\n c.latest.current.ctx.onFinish(finish);\n if (isTransientFinish(finish.reason)) {\n c.episode = {\n cause: finish.reason,\n ...(finish.message !== undefined && { message: finish.message }),\n };\n return \"reattach\";\n }\n setStatus(c, {\n status: \"gone\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.payload !== undefined && { payload: finish.payload }),\n });\n return \"stop\";\n }\n if (c.connection.status !== \"live\") {\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"live\" });\n }\n return null;\n};\n\nexport const handleEnvelope = (\n c: ConnBase,\n env: StatewireEnvelope,\n attached: boolean,\n): \"stop\" | \"reattach\" | null => {\n deliverEnvelope(c, env, attached);\n return settleEnvelope(c, env);\n};\n\nexport const scheduleRetry = (\n c: ConnBase,\n failure: string | undefined,\n immediate: boolean,\n retryAfterMs?: number,\n) => {\n c.attempt += 1;\n c.episode ??= { cause: \"dropped\" };\n const delay = immediate ? 0 : (retryAfterMs ?? backoff(c.attempt));\n if (c.hasSnapshot) {\n setStatus(c, {\n status: \"reconnecting\",\n ...c.episode,\n attempt: c.attempt,\n nextRetryAt: Date.now() + delay,\n ...(failure !== undefined && { lastError: failure }),\n });\n }\n return delay;\n};\n\nexport const reconnectConn = (c: ConnBase) => {\n if (!c.lifetime) return;\n if (c.connection.status === \"gone\") {\n c.attempt = 0;\n c.episode = { cause: \"dropped\" };\n flushTapSync(() => {\n if (c.hasSnapshot) scheduleRetry(c, undefined, true);\n else setStatus(c, { status: \"connecting\" });\n });\n }\n c.gate.open();\n c.abort?.abort();\n};\n\nconst run = async (c: ConnBase, lifetime: AbortController, gate: Gate) => {\n const alive = () => c.lifetime === lifetime;\n while (alive()) {\n const abort = new AbortController();\n c.abort = abort;\n let failure: string | undefined;\n let retryAfterMs: number | undefined;\n let gone = false;\n try {\n gone = (await c.attemptOnce(abort)) === \"stop\";\n } catch (error) {\n if (!abort.signal.aborted) {\n failure =\n error instanceof Error && error.message ? error.message : \"network\";\n if (\n error instanceof Error &&\n \"retryAfterMs\" in error &&\n typeof error.retryAfterMs === \"number\"\n ) {\n retryAfterMs = error.retryAfterMs;\n }\n }\n }\n abort.abort();\n if (!alive()) return;\n if (gone) {\n await gate.wait();\n continue;\n }\n const immediate = gate.take();\n const delay = flushTapSync(() =>\n scheduleRetry(c, failure, immediate, retryAfterMs),\n );\n if (delay === 0) continue;\n await gate.wait(delay);\n }\n};\n\nconst startConn = (c: ConnBase) => {\n c.hasSnapshot = false;\n c.lease = null;\n c.attempt = 0;\n c.episode = null;\n if (c.connection.status !== \"connecting\") {\n setStatus(c, { status: \"connecting\" });\n }\n c.lifetime = new AbortController();\n c.gate = createGate();\n void run(c, c.lifetime, c.gate);\n};\n\nconst stopConn = (c: ConnBase) => {\n c.abort?.abort();\n c.lifetime?.abort();\n c.lifetime = null;\n c.gate.open();\n};\n\nexport const useStatewireConn = <\n TOptions extends {\n url: string;\n onChange?: (connection: StatewireConnection) => void;\n },\n>(\n options: TOptions,\n ctx: StatewireTransportProps,\n create: (\n latest: {\n readonly current: {\n options: TOptions;\n ctx: StatewireTransportProps;\n };\n },\n notify: (connection: StatewireConnection) => void,\n ) => ConnBase & { send: RemoteLink[\"send\"] },\n): RemoteLink => {\n const latest = useRef({ options, ctx });\n const [connection, setConnection] = useState<StatewireConnection | null>(\n null,\n );\n const [c] = useState(() => create(latest, setConnection));\n\n useEffect(() => {\n latest.current = { options, ctx };\n });\n useEffect(() => {\n startConn(c);\n return () => stopConn(c);\n }, [c, options.url]);\n\n return {\n connection: connection ?? c.connection,\n send: c.send,\n };\n};\n\nexport const classify = (timeout: AbortSignal) =>\n new Error(timeout.aborted ? \"timeout\" : \"network\");\n\nexport const parseRetryAfter = (header: string | null): number | undefined => {\n if (!header) return undefined;\n const value = header.trim();\n if (/^\\d+$/.test(value)) return Number(value) * 1000;\n const date = Date.parse(value);\n return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());\n};\n\nexport const overloadedError = (retryAfterMs?: number) =>\n Object.assign(new Error(\"overloaded\"), { retryAfterMs });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"connection.js","names":["useEffect","useRef","useState","flushTapSync","reviveOps","reviveResponse","reviveValue","retryDelay","ConnectionState","StatewireRemoteProps","StatewireClient","StatewireHost","Episode","cause","message","StatewireResponse","seq","type","code","payload","meta","StatewireSyn","lastSeq","lease","StatewireEnvelope","ops","res","ack","syn","fin","Fin","createGate","latched","wake","take","was","wait","timeoutMs","Promise","resolve","timer","undefined","setTimeout","clearTimeout","open","Gate","ReturnType","Conn","connection","Connection","hasSnapshot","attempt","episode","gate","abort","AbortController","lifetime","ctx","onChange","attemptOnce","notify","reconnect","setStatus","c","next","changed","status","deliverEnvelope","env","Pick","map","onSnapshot","onOps","isTransientFinish","reason","settleEnvelope","finish","rest","onFinish","handleEnvelope","scheduleRetry","failure","immediate","delay","nextRetryAt","Date","now","lastError","reconnectConn","run","alive","gone","error","signal","aborted","Error","useStatewireConn","props","url","latest","current","setConnection","conn","classify","timeout","AbortSignal","parseRetryAfter","header","value","trim","test","Number","date","parse","isNaN","Math","max","overloadedError","retryAfterMs","Object","assign"],"sources":["../../src/client/connection.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\nimport { reviveOps, reviveResponse, reviveValue } from \"../wire/meta\";\nimport { retryDelay } from \"./timing\";\nimport type { ConnectionState, StatewireRemoteProps } from \"../transports/sse\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\n\nexport type Episode = {\n cause: \"dropped\" | \"evicted\" | \"error\";\n message?: string;\n};\n\nexport type StatewireResponse = {\n seq: number;\n type: \"accepted\" | \"rejected\" | \"pending\" | \"crashed\" | \"result-unavailable\";\n code?: string;\n message?: string;\n payload?: unknown;\n meta?: unknown;\n};\n\nexport type StatewireSyn = {\n lastSeq: number;\n lease?: string;\n};\n\nexport type StatewireEnvelope = {\n ops?: unknown[];\n res?: StatewireResponse[];\n ack?: number;\n syn?: StatewireSyn;\n fin?: StatewireHost.Fin;\n};\n\nconst createGate = () => {\n let latched = false;\n let wake: (() => void) | undefined;\n return {\n take: () => {\n const was = latched;\n latched = false;\n return was;\n },\n wait: (timeoutMs?: number) => {\n if (latched) {\n latched = false;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n wake = undefined;\n resolve();\n }, timeoutMs);\n wake = () => {\n clearTimeout(timer);\n wake = undefined;\n resolve();\n };\n });\n },\n open: () => {\n if (wake) wake();\n else latched = true;\n },\n };\n};\n\nexport type Gate = ReturnType<typeof createGate>;\n\nexport type Conn = {\n connection: StatewireClient.Connection;\n hasSnapshot: boolean;\n lease: string | null;\n attempt: number;\n episode: Episode | null;\n gate: Gate;\n abort: AbortController | null;\n lifetime: AbortController | null;\n ctx: StatewireRemoteProps;\n onChange: (connection: StatewireClient.Connection) => void;\n attemptOnce: (\n abort: AbortController,\n ) => Promise<\"stop\" | \"reattach\" | \"ended\">;\n notify: (connection: StatewireClient.Connection) => void;\n reconnect: () => void;\n};\n\nconst setStatus = (c: Conn, next: ConnectionState) => {\n const changed = next.status !== c.connection.status;\n c.connection = { ...next, reconnect: c.reconnect };\n c.notify(c.connection);\n if (changed) c.onChange(c.connection);\n};\n\nconst deliverEnvelope = (\n c: Conn,\n env: Pick<StatewireEnvelope, \"ops\" | \"res\" | \"ack\" | \"syn\">,\n) => {\n if (env.syn?.lease !== undefined) c.lease = env.syn.lease;\n const ctx = c.ctx;\n const ops = env.ops === undefined ? [] : reviveOps(env.ops);\n const res = env.res?.map(reviveResponse);\n if (env.syn !== undefined) {\n ctx.onSnapshot({ ops, lastSeq: env.syn.lastSeq });\n c.hasSnapshot = true;\n } else if (\n env.ops !== undefined ||\n env.res !== undefined ||\n env.ack !== undefined\n ) {\n ctx.onOps({\n ops,\n ...(res !== undefined && { res }),\n ...(env.ack !== undefined && { ack: env.ack }),\n });\n }\n};\n\nconst isTransientFinish = (\n reason: StatewireHost.Fin[\"reason\"],\n): reason is \"evicted\" | \"error\" => reason === \"evicted\" || reason === \"error\";\n\nconst settleEnvelope = (\n c: Conn,\n env: StatewireEnvelope,\n): \"stop\" | \"reattach\" | null => {\n let finish = env.fin;\n if (finish) {\n if (finish.meta !== undefined) {\n const { meta, ...rest } = finish;\n finish = { ...rest, payload: reviveValue(rest.payload, meta) };\n }\n c.ctx.onFinish(finish);\n if (isTransientFinish(finish.reason)) {\n c.episode = {\n cause: finish.reason,\n ...(finish.message !== undefined && { message: finish.message }),\n };\n return \"reattach\";\n }\n setStatus(c, {\n status: \"gone\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.payload !== undefined && { payload: finish.payload }),\n });\n return \"stop\";\n }\n if (c.connection.status !== \"live\") {\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"live\" });\n }\n return null;\n};\n\nexport const handleEnvelope = (\n c: Conn,\n env: StatewireEnvelope,\n): \"stop\" | \"reattach\" | null => {\n deliverEnvelope(c, env);\n return settleEnvelope(c, env);\n};\n\nconst scheduleRetry = (\n c: Conn,\n failure: string | undefined,\n immediate: boolean,\n cause?: unknown,\n) => {\n c.attempt += 1;\n c.episode ??= { cause: \"dropped\" };\n const delay = immediate ? 0 : retryDelay(cause, c.attempt);\n if (c.hasSnapshot) {\n setStatus(c, {\n status: \"reconnecting\",\n ...c.episode,\n attempt: c.attempt,\n nextRetryAt: Date.now() + delay,\n ...(failure !== undefined && { lastError: failure }),\n });\n }\n return delay;\n};\n\nconst reconnectConn = (c: Conn) => {\n if (!c.lifetime) return;\n if (c.connection.status === \"gone\") {\n c.attempt = 0;\n c.episode = { cause: \"dropped\" };\n flushTapSync(() => {\n if (c.hasSnapshot) scheduleRetry(c, undefined, true);\n else setStatus(c, { status: \"connecting\" });\n });\n }\n c.gate.open();\n c.abort?.abort();\n};\n\nconst run = async (c: Conn, lifetime: AbortController, gate: Gate) => {\n const alive = () => c.lifetime === lifetime;\n while (alive()) {\n const abort = new AbortController();\n c.abort = abort;\n let failure: string | undefined;\n let cause: unknown;\n let gone = false;\n try {\n gone = (await c.attemptOnce(abort)) === \"stop\";\n } catch (error) {\n if (!abort.signal.aborted) {\n failure =\n error instanceof Error && error.message ? error.message : \"network\";\n cause = error;\n }\n }\n abort.abort();\n if (!alive()) return;\n if (gone) {\n await gate.wait();\n continue;\n }\n const immediate = gate.take();\n const delay = flushTapSync(() =>\n scheduleRetry(c, failure, immediate, cause),\n );\n if (delay === 0) continue;\n await gate.wait(delay);\n }\n};\n\nexport const useStatewireConn = (props: {\n url: string;\n onChange?: ((connection: StatewireClient.Connection) => void) | undefined;\n ctx: StatewireRemoteProps;\n attemptOnce: (\n c: Conn,\n abort: AbortController,\n ) => Promise<\"stop\" | \"reattach\" | \"ended\">;\n}): Conn => {\n const latest = useRef(props);\n latest.current = props;\n const [, setConnection] = useState<StatewireClient.Connection | null>(null);\n const [c] = useState((): Conn => {\n const conn: Conn = {\n hasSnapshot: false,\n lease: null,\n attempt: 0,\n episode: null,\n abort: null,\n gate: createGate(),\n lifetime: null,\n ctx: props.ctx,\n onChange: (connection) => latest.current.onChange?.(connection),\n attemptOnce: (abort) => latest.current.attemptOnce(conn, abort),\n notify: setConnection,\n reconnect: () => reconnectConn(conn),\n connection: { status: \"connecting\", reconnect: () => conn.reconnect() },\n };\n return conn;\n });\n\n useEffect(() => {\n c.hasSnapshot = false;\n c.lease = null;\n c.attempt = 0;\n c.episode = null;\n if (c.connection.status !== \"connecting\") {\n setStatus(c, { status: \"connecting\" });\n }\n const lifetime = new AbortController();\n c.lifetime = lifetime;\n c.gate = createGate();\n void run(c, lifetime, c.gate);\n return () => {\n c.abort?.abort();\n lifetime.abort();\n if (c.lifetime === lifetime) c.lifetime = null;\n c.gate.open();\n };\n }, [c, props.url]);\n\n return c;\n};\n\nexport const classify = (timeout: AbortSignal) =>\n new Error(timeout.aborted ? \"timeout\" : \"network\");\n\nexport const parseRetryAfter = (header: string | null): number | undefined => {\n if (!header) return undefined;\n const value = header.trim();\n if (/^\\d+$/.test(value)) return Number(value) * 1000;\n const date = Date.parse(value);\n return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());\n};\n\nexport const overloadedError = (retryAfterMs?: number) =>\n Object.assign(new Error(\"overloaded\"), { retryAfterMs });\n"],"mappings":";;;;;AAmCA,MAAM+B,mBAAmB;CACvB,IAAIC,UAAU;CACd,IAAIC;CACJ,OAAO;EACLC,YAAY;GACV,MAAMC,MAAMH;GACZA,UAAU;GACV,OAAOG;EACT;EACAC,OAAOC,cAAuB;GAC5B,IAAIL,SAAS;IACXA,UAAU;IACV,OAAOM,QAAQC,QAAQ;GACzB;GACA,OAAO,IAAID,SAAeC,YAAY;IACpC,MAAMC,QACJH,cAAcI,KAAAA,IACVA,KAAAA,IACAC,iBAAiB;KACfT,OAAOQ,KAAAA;KACPF,QAAQ;IACV,GAAGF,SAAS;IAClBJ,aAAa;KACXU,aAAaH,KAAK;KAClBP,OAAOQ,KAAAA;KACPF,QAAQ;IACV;GACF,CAAC;EACH;EACAK,YAAY;GACV,IAAIX,MAAMA,KAAK;QACVD,UAAU;EACjB;CACF;AACF;AAsBA,MAAM8B,aAAaC,GAASC,SAA0B;CACpD,MAAMC,UAAUD,KAAKE,WAAWH,EAAEf,WAAWkB;CAC7CH,EAAEf,aAAa;EAAE,GAAGgB;EAAMH,WAAWE,EAAEF;CAAU;CACjDE,EAAEH,OAAOG,EAAEf,UAAU;CACrB,IAAIiB,SAASF,EAAEL,SAASK,EAAEf,UAAU;AACtC;AAEA,MAAMmB,mBACJJ,GACAK,QACG;CACH,IAAIA,IAAIxC,KAAKL,UAAUkB,KAAAA,GAAWsB,EAAExC,QAAQ6C,IAAIxC,IAAIL;CACpD,MAAMkC,MAAMM,EAAEN;CACd,MAAMhC,MAAM2C,IAAI3C,QAAQgB,KAAAA,IAAY,CAAA,IAAKrC,UAAUgE,IAAI3C,GAAG;CAC1D,MAAMC,MAAM0C,IAAI1C,KAAK4C,IAAIjE,cAAc;CACvC,IAAI+D,IAAIxC,QAAQa,KAAAA,GAAW;EACzBgB,IAAIc,WAAW;GAAE9C;GAAKH,SAAS8C,IAAIxC,IAAIN;EAAQ,CAAC;EAChDyC,EAAEb,cAAc;CAClB,OAAO,IACLkB,IAAI3C,QAAQgB,KAAAA,KACZ2B,IAAI1C,QAAQe,KAAAA,KACZ2B,IAAIzC,QAAQc,KAAAA,GAEZgB,IAAIe,MAAM;EACR/C;EACA,GAAIC,QAAQe,KAAAA,KAAa,EAAEf,IAAI;EAC/B,GAAI0C,IAAIzC,QAAQc,KAAAA,KAAa,EAAEd,KAAKyC,IAAIzC,IAAI;CAC9C,CAAC;AAEL;AAEA,MAAM8C,qBACJC,WACkCA,WAAW,aAAaA,WAAW;AAEvE,MAAMC,kBACJZ,GACAK,QAC+B;CAC/B,IAAIQ,SAASR,IAAIvC;CACjB,IAAI+C,QAAQ;EACV,IAAIA,OAAOxD,SAASqB,KAAAA,GAAW;GAC7B,MAAM,EAAErB,MAAM,GAAGyD,SAASD;GAC1BA,SAAS;IAAE,GAAGC;IAAM1D,SAASb,YAAYuE,KAAK1D,SAASC,IAAI;GAAE;EAC/D;EACA2C,EAAEN,IAAIqB,SAASF,MAAM;EACrB,IAAIH,kBAAkBG,OAAOF,MAAM,GAAG;GACpCX,EAAEX,UAAU;IACVvC,OAAO+D,OAAOF;IACd,GAAIE,OAAO9D,YAAY2B,KAAAA,KAAa,EAAE3B,SAAS8D,OAAO9D,QAAQ;GAChE;GACA,OAAO;EACT;EACAgD,UAAUC,GAAG;GACXG,QAAQ;GACR,GAAIU,OAAO9D,YAAY2B,KAAAA,KAAa,EAAE3B,SAAS8D,OAAO9D,QAAQ;GAC9D,GAAI8D,OAAOzD,YAAYsB,KAAAA,KAAa,EAAEtB,SAASyD,OAAOzD,QAAQ;EAChE,CAAC;EACD,OAAO;CACT;CACA,IAAI4C,EAAEf,WAAWkB,WAAW,QAAQ;EAClCH,EAAEZ,UAAU;EACZY,EAAEX,UAAU;EACZU,UAAUC,GAAG,EAAEG,QAAQ,OAAO,CAAC;CACjC;CACA,OAAO;AACT;AAEA,MAAaa,kBACXhB,GACAK,QAC+B;CAC/BD,gBAAgBJ,GAAGK,GAAG;CACtB,OAAOO,eAAeZ,GAAGK,GAAG;AAC9B;AAEA,MAAMY,iBACJjB,GACAkB,SACAC,WACArE,UACG;CACHkD,EAAEZ,WAAW;CACbY,EAAEX,YAAY,EAAEvC,OAAO,UAAU;CACjC,MAAMsE,QAAQD,YAAY,IAAI3E,WAAWM,OAAOkD,EAAEZ,OAAO;CACzD,IAAIY,EAAEb,aACJY,UAAUC,GAAG;EACXG,QAAQ;EACR,GAAGH,EAAEX;EACLD,SAASY,EAAEZ;EACXiC,aAAaC,KAAKC,IAAI,IAAIH;EAC1B,GAAIF,YAAYxC,KAAAA,KAAa,EAAE8C,WAAWN,QAAQ;CACpD,CAAC;CAEH,OAAOE;AACT;AAEA,MAAMK,iBAAiBzB,MAAY;CACjC,IAAI,CAACA,EAAEP,UAAU;CACjB,IAAIO,EAAEf,WAAWkB,WAAW,QAAQ;EAClCH,EAAEZ,UAAU;EACZY,EAAEX,UAAU,EAAEvC,OAAO,UAAU;EAC/BV,mBAAmB;GACjB,IAAI4D,EAAEb,aAAa8B,cAAcjB,GAAGtB,KAAAA,GAAW,IAAI;QAC9CqB,UAAUC,GAAG,EAAEG,QAAQ,aAAa,CAAC;EAC5C,CAAC;CACH;CACAH,EAAEV,KAAKT,KAAK;CACZmB,EAAET,OAAOA,MAAM;AACjB;AAEA,MAAMmC,MAAM,OAAO1B,GAASP,UAA2BH,SAAe;CACpE,MAAMqC,cAAc3B,EAAEP,aAAaA;CACnC,OAAOkC,MAAM,GAAG;EACd,MAAMpC,QAAQ,IAAIC,gBAAgB;EAClCQ,EAAET,QAAQA;EACV,IAAI2B;EACJ,IAAIpE;EACJ,IAAI8E,OAAO;EACX,IAAI;GACFA,OAAQ,MAAM5B,EAAEJ,YAAYL,KAAK,MAAO;EAC1C,SAASsC,OAAO;GACd,IAAI,CAACtC,MAAMuC,OAAOC,SAAS;IACzBb,UACEW,iBAAiBG,SAASH,MAAM9E,UAAU8E,MAAM9E,UAAU;IAC5DD,QAAQ+E;GACV;EACF;EACAtC,MAAMA,MAAM;EACZ,IAAI,CAACoC,MAAM,GAAG;EACd,IAAIC,MAAM;GACR,MAAMtC,KAAKjB,KAAK;GAChB;EACF;EACA,MAAM8C,YAAY7B,KAAKnB,KAAK;EAC5B,MAAMiD,QAAQhF,mBACZ6E,cAAcjB,GAAGkB,SAASC,WAAWrE,KAAK,CAC5C;EACA,IAAIsE,UAAU,GAAG;EACjB,MAAM9B,KAAKjB,KAAK+C,KAAK;CACvB;AACF;AAEA,MAAaa,oBAAoBC,UAQrB;CACV,MAAME,SAASlG,OAAOgG,KAAK;CAC3BE,OAAOC,UAAUH;CACjB,MAAM,GAAGI,iBAAiBnG,SAA4C,IAAI;CAC1E,MAAM,CAAC6D,KAAK7D,eAAqB;EAC/B,MAAMoG,OAAa;GACjBpD,aAAa;GACb3B,OAAO;GACP4B,SAAS;GACTC,SAAS;GACTE,OAAO;GACPD,MAAMtB,WAAW;GACjByB,UAAU;GACVC,KAAKwC,MAAMxC;GACXC,WAAWV,eAAemD,OAAOC,QAAQ1C,WAAWV,UAAU;GAC9DW,cAAcL,UAAU6C,OAAOC,QAAQzC,YAAY2C,MAAMhD,KAAK;GAC9DM,QAAQyC;GACRxC,iBAAiB2B,cAAcc,IAAI;GACnCtD,YAAY;IAAEkB,QAAQ;IAAcL,iBAAiByC,KAAKzC,UAAU;GAAE;EACxE;EACA,OAAOyC;CACT,CAAC;CAEDtG,gBAAgB;EACd+D,EAAEb,cAAc;EAChBa,EAAExC,QAAQ;EACVwC,EAAEZ,UAAU;EACZY,EAAEX,UAAU;EACZ,IAAIW,EAAEf,WAAWkB,WAAW,cAC1BJ,UAAUC,GAAG,EAAEG,QAAQ,aAAa,CAAC;EAEvC,MAAMV,WAAW,IAAID,gBAAgB;EACrCQ,EAAEP,WAAWA;EACbO,EAAEV,OAAOtB,WAAW;EACpB,IAASgC,GAAGP,UAAUO,EAAEV,IAAI;EAC5B,aAAa;GACXU,EAAET,OAAOA,MAAM;GACfE,SAASF,MAAM;GACf,IAAIS,EAAEP,aAAaA,UAAUO,EAAEP,WAAW;GAC1CO,EAAEV,KAAKT,KAAK;EACd;CACF,GAAG,CAACmB,GAAGkC,MAAMC,GAAG,CAAC;CAEjB,OAAOnC;AACT;AAEA,MAAawC,YAAYC,4BACvB,IAAIT,MAAMS,QAAQV,UAAU,YAAY,SAAS;AAEnD,MAAaY,mBAAmBC,WAA8C;CAC5E,IAAI,CAACA,QAAQ,OAAOlE,KAAAA;CACpB,MAAMmE,QAAQD,OAAOE,KAAK;CAC1B,IAAI,QAAQC,KAAKF,KAAK,GAAG,OAAOG,OAAOH,KAAK,IAAI;CAChD,MAAMI,OAAO3B,KAAK4B,MAAML,KAAK;CAC7B,OAAOG,OAAOG,MAAMF,IAAI,IAAIvE,KAAAA,IAAY0E,KAAKC,IAAI,GAAGJ,OAAO3B,KAAKC,IAAI,CAAC;AACvE;AAEA,MAAa+B,mBAAmBC,iBAC9BC,OAAOC,uBAAO,IAAIzB,MAAM,YAAY,GAAG,EAAEuB,aAAa,CAAC"}
|
package/dist/client/core.d.ts
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { StatewireClient } from "../statewire.js";
|
|
2
|
+
import { Statewire } from "../types.js";
|
|
3
3
|
//#region src/client/core.d.ts
|
|
4
|
-
declare const LIVE_CONNECTION:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
attach: (next: StatewireTransport<unknown>) => void;
|
|
4
|
+
declare const LIVE_CONNECTION: StatewireClient.Connection;
|
|
5
|
+
declare const useStatewireCore: (getOptions: () => StatewireClient.Options<any, any, any>, value: Statewire<unknown>) => {
|
|
6
|
+
attach: (next: Statewire<unknown>) => void;
|
|
8
7
|
detach: () => void;
|
|
9
|
-
dispose: () => void;
|
|
10
8
|
getState: () => unknown;
|
|
11
|
-
|
|
12
|
-
commands: StatewireCommandsProxy<any>;
|
|
13
|
-
flush: () => void;
|
|
9
|
+
commands: Statewire.CommandsProxy<any>;
|
|
14
10
|
subscribe: (listener: () => void) => () => void;
|
|
15
11
|
};
|
|
16
12
|
//#endregion
|
|
17
|
-
export { LIVE_CONNECTION,
|
|
13
|
+
export { LIVE_CONNECTION, useStatewireCore };
|
|
18
14
|
//# sourceMappingURL=core.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","names":[],"sources":["../../src/client/core.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"core.d.ts","names":[],"sources":["../../src/client/core.ts"],"mappings":";;;cAYa,iBAAiB,gBAAgB;cA6RjC,mBACX,kBAAkB,gBAAgB,wBAClC,OAAO;EAjFe,SAAA,MAAA;;;;EAsEE,YAAA"}
|