iterate 0.3.0 → 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 +164 -82
- package/dist/{next/api.d.ts → api.d.ts} +197 -33
- package/dist/{next/app-server.d.ts → app-server.d.ts} +7 -0
- package/dist/{next/app-server.mjs → app-server.mjs} +17 -15
- package/dist/app-server.mjs.map +1 -0
- package/dist/{next/app-session.mjs → app-session.mjs} +12 -15
- package/dist/app-session.mjs.map +1 -0
- package/dist/{next/app.mjs → app.mjs} +53 -14
- package/dist/app.mjs.map +1 -0
- package/dist/{next/client → client}/live-state.d.ts +11 -11
- package/dist/client/oauth.d.ts +17 -0
- package/dist/{next/client → client}/react.d.ts +10 -42
- package/dist/{next/client → client}/socket.d.ts +1 -0
- package/dist/client.mjs +156 -4
- package/dist/client.mjs.map +1 -0
- package/dist/{next/expression.d.ts → expression.d.ts} +11 -69
- package/dist/{next/expression.mjs → expression.mjs} +11 -109
- package/dist/expression.mjs.map +1 -0
- package/dist/lib-BWr-5mFO.mjs +36 -0
- package/dist/lib-BWr-5mFO.mjs.map +1 -0
- package/dist/{next/lib.d.ts → lib.d.ts} +16 -2
- package/dist/{next/lib.mjs → lib.mjs} +32 -3
- package/dist/lib.mjs.map +1 -0
- package/dist/node.d.ts +15 -3
- package/dist/node.mjs +36 -174
- package/dist/node.mjs.map +1 -1
- package/dist/{next/oauth-scopes.mjs → oauth-scopes.mjs} +1 -1
- package/dist/oauth-scopes.mjs.map +1 -0
- package/dist/{next/oauth.mjs → oauth.mjs} +14 -2
- package/dist/oauth.mjs.map +1 -0
- package/dist/principal.d.ts +8 -0
- package/dist/principal.mjs +8 -0
- package/dist/principal.mjs.map +1 -0
- package/dist/project-ingress.d.ts +58 -0
- package/dist/project-ingress.mjs +104 -0
- package/dist/project-ingress.mjs.map +1 -0
- package/dist/{next/react.mjs → react.mjs} +12 -12
- package/dist/react.mjs.map +1 -0
- package/dist/sdk/auth.d.ts +25 -0
- package/dist/sdk/index.d.ts +155 -0
- package/dist/sdk/record-pipelined-steps.d.ts +19 -0
- package/dist/sdk.mjs +245 -2
- package/dist/sdk.mjs.map +1 -0
- package/dist/{next/stream → stream}/processor.d.ts +28 -23
- package/dist/{next/stream → stream}/processor.mjs +48 -25
- package/dist/stream/processor.mjs.map +1 -0
- package/dist/{next/stream → stream}/run.d.ts +9 -6
- package/dist/{next/stream → stream}/run.mjs +13 -8
- package/dist/stream/run.mjs.map +1 -0
- package/dist/stream/test-support.d.ts +45 -0
- package/dist/stream/test-support.mjs +196 -0
- package/dist/stream/test-support.mjs.map +1 -0
- package/package.json +65 -219
- package/THIRD_PARTY_NOTICES.md +0 -55
- package/bin/iterate.js +0 -94
- package/dist/api-url-B6404M82.mjs +0 -17
- package/dist/api-url-B6404M82.mjs.map +0 -1
- package/dist/app-ref-BipL0feU.mjs +0 -35
- package/dist/app-ref-BipL0feU.mjs.map +0 -1
- package/dist/app-ref-C1CrgXqX.mjs +0 -7
- package/dist/app-ref-C1CrgXqX.mjs.map +0 -1
- package/dist/app-ref-DYai_om1.mjs +0 -7
- package/dist/app-ref-DYai_om1.mjs.map +0 -1
- package/dist/cli-D0c-pDL_.mjs +0 -1010
- package/dist/cli-D0c-pDL_.mjs.map +0 -1
- package/dist/client.d.ts +0 -3
- package/dist/cloudflare-BTm90gQ4.mjs +0 -951
- package/dist/cloudflare-BTm90gQ4.mjs.map +0 -1
- package/dist/contract-s4FW4eES.mjs +0 -309
- package/dist/contract-s4FW4eES.mjs.map +0 -1
- package/dist/document-review/index.d.ts +0 -5
- package/dist/document-review/types.d.ts +0 -107
- package/dist/document-review.mjs +0 -7015
- package/dist/document-review.mjs.map +0 -1
- package/dist/durable-object-processor-durability-CNsTjAJS.mjs +0 -205
- package/dist/durable-object-processor-durability-CNsTjAJS.mjs.map +0 -1
- package/dist/idempotency-DleloJNt.mjs +0 -28
- package/dist/idempotency-DleloJNt.mjs.map +0 -1
- package/dist/index.d.mts +0 -5
- package/dist/index.mjs +0 -8
- package/dist/index.mjs.map +0 -1
- package/dist/itx/api-url.d.ts +0 -6
- package/dist/itx/itx-node-client.d.ts +0 -65
- package/dist/itx/itx-session.d.ts +0 -215
- package/dist/itx/owned-rpc-session.d.ts +0 -14
- package/dist/itx/query-client.d.ts +0 -10
- package/dist/itx-api.generated.d.ts +0 -6195
- package/dist/itx-session-sjud8GiT.mjs +0 -534
- package/dist/itx-session-sjud8GiT.mjs.map +0 -1
- package/dist/live-state-BJNqOwFw.mjs +0 -299
- package/dist/live-state-BJNqOwFw.mjs.map +0 -1
- package/dist/next/app-server.mjs.map +0 -1
- package/dist/next/app-session.mjs.map +0 -1
- package/dist/next/app.mjs.map +0 -1
- package/dist/next/client/oauth.d.ts +0 -12
- package/dist/next/client.mjs +0 -156
- package/dist/next/client.mjs.map +0 -1
- package/dist/next/expression.mjs.map +0 -1
- package/dist/next/lib.mjs.map +0 -1
- package/dist/next/oauth-scopes.mjs.map +0 -1
- package/dist/next/oauth.mjs.map +0 -1
- package/dist/next/principal.d.ts +0 -64
- package/dist/next/principal.mjs +0 -98
- package/dist/next/principal.mjs.map +0 -1
- package/dist/next/project-ingress.d.ts +0 -37
- package/dist/next/project-ingress.mjs +0 -75
- package/dist/next/project-ingress.mjs.map +0 -1
- package/dist/next/react.mjs.map +0 -1
- package/dist/next/sdk/auth.d.ts +0 -5
- package/dist/next/sdk/index.d.ts +0 -112
- package/dist/next/sdk.mjs +0 -139
- package/dist/next/sdk.mjs.map +0 -1
- package/dist/next/stream/processor.mjs.map +0 -1
- package/dist/next/stream/run.mjs.map +0 -1
- package/dist/next-node.d.ts +0 -15
- package/dist/next-node.mjs +0 -51
- package/dist/next-node.mjs.map +0 -1
- package/dist/processor-host-capabilities-BMFH3KTM.mjs +0 -56
- package/dist/processor-host-capabilities-BMFH3KTM.mjs.map +0 -1
- package/dist/processors/cloudflare.d.ts +0 -3
- package/dist/processors/durable-object-processor-durability.d.ts +0 -79
- package/dist/processors/event-consumption-metrics.d.ts +0 -82
- package/dist/processors/idempotency.d.ts +0 -13
- package/dist/processors/index.d.ts +0 -12
- package/dist/processors/processor-contracts.d.ts +0 -342
- package/dist/processors/processor-facet.d.ts +0 -186
- package/dist/processors/processor-host-capabilities.d.ts +0 -60
- package/dist/processors/prompt-sections.d.ts +0 -17
- package/dist/processors/rpc-types.d.ts +0 -515
- package/dist/processors/schemas.d.ts +0 -102
- package/dist/processors/stream-handle.d.ts +0 -45
- package/dist/processors/stream-processor-keepalive.d.ts +0 -95
- package/dist/processors/stream-processor-registry.d.ts +0 -233
- package/dist/processors/stream-processor-runner.d.ts +0 -289
- package/dist/processors/stream-processor.d.ts +0 -339
- package/dist/processors/stream-runtime-metrics.d.ts +0 -107
- package/dist/processors/testing.d.ts +0 -302
- package/dist/processors-BoNyeBfQ.mjs +0 -10
- package/dist/processors-BoNyeBfQ.mjs.map +0 -1
- package/dist/processors-cloudflare.mjs +0 -3
- package/dist/processors-testing.mjs +0 -435
- package/dist/processors-testing.mjs.map +0 -1
- package/dist/processors.mjs +0 -52
- package/dist/processors.mjs.map +0 -1
- package/dist/protocol-DnK_f2m6.mjs +0 -251
- package/dist/protocol-DnK_f2m6.mjs.map +0 -1
- package/dist/sdk/capnweb/index.d.ts +0 -2
- package/dist/sdk/capnweb/live-state/compact.d.ts +0 -5
- package/dist/sdk/capnweb/live-state/diff.d.ts +0 -41
- package/dist/sdk/capnweb/live-state/engine.d.ts +0 -44
- package/dist/sdk/capnweb/live-state/index.d.ts +0 -41
- package/dist/sdk/capnweb/live-state/protocol.d.ts +0 -87
- package/dist/sdk/capnweb/live-state/retain.d.ts +0 -23
- package/dist/sdk/capnweb/live-state/store.d.ts +0 -20
- package/dist/sdk/capnweb/live-state/types.d.ts +0 -11
- package/dist/sdk/capnweb/react.d.ts +0 -45
- package/dist/sdk/capnweb/react.mjs +0 -316
- package/dist/sdk/capnweb/react.mjs.map +0 -1
- package/dist/sdk/capnweb.mjs +0 -4
- package/dist/sdk/itx/react.d.ts +0 -191
- package/dist/sdk/itx/react.mjs +0 -383
- package/dist/sdk/itx/react.mjs.map +0 -1
- package/dist/sdk-DMB-IM11.mjs +0 -933
- package/dist/sdk-DMB-IM11.mjs.map +0 -1
- package/dist/sdk.d.ts +0 -339
- package/dist/serve-itx.d.ts +0 -46
- package/dist/starter-apps/flake-dashboard/app-ref.d.ts +0 -31
- package/dist/starter-apps/flake-dashboard/configured-worker.mjs +0 -1055
- package/dist/starter-apps/flake-dashboard/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/flake-dashboard/contract.d.ts +0 -4839
- package/dist/starter-apps/flake-dashboard/contract.mjs +0 -2
- package/dist/starter-apps/flake-dashboard/index.d.ts +0 -17
- package/dist/starter-apps/flake-dashboard/index.mjs +0 -56
- package/dist/starter-apps/flake-dashboard/index.mjs.map +0 -1
- package/dist/starter-apps/flake-dashboard/worker.d.ts +0 -4607
- package/dist/starter-apps/github-ai-linter/ai-linter.d.ts +0 -8914
- package/dist/starter-apps/github-ai-linter/configured-worker.mjs +0 -17987
- package/dist/starter-apps/github-ai-linter/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/github-ai-linter/contract.d.ts +0 -9193
- package/dist/starter-apps/github-ai-linter/index.d.ts +0 -10
- package/dist/starter-apps/github-ai-linter/index.mjs +0 -36
- package/dist/starter-apps/github-ai-linter/index.mjs.map +0 -1
- package/dist/starter-apps/github-ai-linter/prompt.d.ts +0 -13
- package/dist/starter-apps/github-ai-linter/review-bot.d.ts +0 -808
- package/dist/starter-apps/github-ai-linter/rules.d.ts +0 -34
- package/dist/starter-apps/github-ai-linter/worker-ref.d.ts +0 -19
- package/dist/starter-apps/github-ai-linter/worker.d.ts +0 -19
- package/dist/starter-apps/github-ai-linter/worker.mjs +0 -947
- package/dist/starter-apps/github-ai-linter/worker.mjs.map +0 -1
- package/dist/starter-apps/guestbook/app-ref.d.ts +0 -27
- package/dist/starter-apps/guestbook/client.d.ts +0 -7
- package/dist/starter-apps/guestbook/client.mjs +0 -59
- package/dist/starter-apps/guestbook/configured-worker.mjs +0 -205
- package/dist/starter-apps/guestbook/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/guestbook/index.d.ts +0 -9
- package/dist/starter-apps/guestbook/index.mjs +0 -31
- package/dist/starter-apps/guestbook/index.mjs.map +0 -1
- package/dist/starter-apps/guestbook/processor.d.ts +0 -2267
- package/dist/starter-apps/guestbook/worker.d.ts +0 -26
- package/dist/starter-apps/guestbook/worker.mjs +0 -191
- package/dist/starter-apps/guestbook/worker.mjs.map +0 -1
- package/dist/starter-apps/media/configured-worker.mjs +0 -577
- package/dist/starter-apps/media/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/media/index.mjs +0 -36
- package/dist/starter-apps/media/index.mjs.map +0 -1
- package/dist/starter-apps/media/ref.mjs +0 -20
- package/dist/starter-apps/media/ref.mjs.map +0 -1
- package/dist/starter-apps/media/worker.mjs +0 -579
- package/dist/starter-apps/media/worker.mjs.map +0 -1
- package/dist/starter-apps/notes/configured-worker.mjs +0 -6134
- package/dist/starter-apps/notes/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/notes/index.mjs +0 -23
- package/dist/starter-apps/notes/index.mjs.map +0 -1
- package/dist/starter-apps/notes/ref.mjs +0 -21
- package/dist/starter-apps/notes/ref.mjs.map +0 -1
- package/dist/starter-apps/notes/worker.mjs +0 -427
- package/dist/starter-apps/notes/worker.mjs.map +0 -1
- package/dist/starter-apps/todo/client.mjs +0 -59
- package/dist/starter-apps/todo/configured-worker.mjs +0 -2864
- package/dist/starter-apps/todo/configured-worker.mjs.map +0 -1
- package/dist/starter-apps/todo/index.d.ts +0 -8
- package/dist/starter-apps/todo/index.mjs +0 -29
- package/dist/starter-apps/todo/index.mjs.map +0 -1
- package/dist/stream-processor-keepalive-DAQTP6m3.mjs +0 -2082
- package/dist/stream-processor-keepalive-DAQTP6m3.mjs.map +0 -1
- package/dist/usingCtx-mZx5nsAW.mjs +0 -11800
- package/dist/usingCtx-mZx5nsAW.mjs.map +0 -1
- package/dist/worker-ref-DZxPDmb_.mjs +0 -390
- package/dist/worker-ref-DZxPDmb_.mjs.map +0 -1
- package/dist/worker.d.mts +0 -33
- package/dist/worker.mjs +0 -18
- package/dist/worker.mjs.map +0 -1
- package/menubar/Iterate.entitlements +0 -12
- package/menubar/Iterate.swift +0 -914
- package/menubar/IterateIcon.swift +0 -145
- package/menubar/README.md +0 -28
- package/menubar/build-menubar-app.sh +0 -59
- /package/dist/{next/api.mjs → api.mjs} +0 -0
- /package/dist/{next/app-session.d.ts → app-session.d.ts} +0 -0
- /package/dist/{next/app.d.ts → app.d.ts} +0 -0
- /package/dist/{next/oauth-scopes.d.ts → oauth-scopes.d.ts} +0 -0
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
import { r as createLiveStateStore, t as isLiveStateSnapshot } from "../../protocol-DnK_f2m6.mjs";
|
|
2
|
-
import { createContext, createElement, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
3
|
-
//#region src/sdk/capnweb/react.tsx
|
|
4
|
-
const CapnWebContext = createContext(void 0);
|
|
5
|
-
const CONNECTION_STABLE_MS = 3e4;
|
|
6
|
-
const CONNECTION_RETRY_MAX_MS = 1e4;
|
|
7
|
-
const SUBSCRIBE_RETRY_MS = 1e4;
|
|
8
|
-
const MAX_SUBSCRIBE_RETRIES = 2;
|
|
9
|
-
const SUBSCRIBE_TIMEOUT_MS = 15e3;
|
|
10
|
-
const PING_INTERVAL_MS = 45e3;
|
|
11
|
-
const PING_TIMEOUT_MS = 1e4;
|
|
12
|
-
function releaseLiveStateSubscription(handle) {
|
|
13
|
-
Promise.resolve().then(() => handle.unsubscribe()).catch(() => {}).finally(() => handle[Symbol.dispose]?.());
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Own one reconnectable Cap'n Web root for a React subtree. The factory is the
|
|
17
|
-
* only transport policy: it can dial a WebSocket directly or duplicate a root
|
|
18
|
-
* from a lower-level shared connection keeper. Broken roots are disposed and
|
|
19
|
-
* replaced with bounded exponential backoff.
|
|
20
|
-
*/
|
|
21
|
-
function CapnWebProvider({ children, makeConnection }) {
|
|
22
|
-
return createElement(CapnWebContext, { value: useCapnWebConnection(makeConnection) }, children);
|
|
23
|
-
}
|
|
24
|
-
function useCapnWebConnection(makeConnection, enabled = true) {
|
|
25
|
-
const [epoch, setEpoch] = useState(0);
|
|
26
|
-
const failures = useRef(0);
|
|
27
|
-
const failureSource = useRef(makeConnection);
|
|
28
|
-
const reconnect = useCallback(() => setEpoch((current) => current + 1), []);
|
|
29
|
-
const [snapshot, setSnapshot] = useState({
|
|
30
|
-
enabled,
|
|
31
|
-
generation: 0,
|
|
32
|
-
reconnect,
|
|
33
|
-
source: makeConnection,
|
|
34
|
-
status: "connecting"
|
|
35
|
-
});
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
let disposed = false;
|
|
38
|
-
let root;
|
|
39
|
-
let retry;
|
|
40
|
-
let stable;
|
|
41
|
-
if (failureSource.current !== makeConnection) {
|
|
42
|
-
failureSource.current = makeConnection;
|
|
43
|
-
failures.current = 0;
|
|
44
|
-
}
|
|
45
|
-
if (!enabled || makeConnection === void 0) {
|
|
46
|
-
failures.current = 0;
|
|
47
|
-
setSnapshot((current) => ({
|
|
48
|
-
enabled,
|
|
49
|
-
generation: current.generation,
|
|
50
|
-
reconnect,
|
|
51
|
-
source: makeConnection,
|
|
52
|
-
status: "connecting"
|
|
53
|
-
}));
|
|
54
|
-
} else {
|
|
55
|
-
const scheduleReconnect = () => {
|
|
56
|
-
const nextFailures = failures.current += 1;
|
|
57
|
-
retry = setTimeout(reconnect, Math.min(250 * 2 ** (nextFailures - 1), CONNECTION_RETRY_MAX_MS));
|
|
58
|
-
};
|
|
59
|
-
setSnapshot((current) => ({
|
|
60
|
-
enabled,
|
|
61
|
-
generation: current.generation,
|
|
62
|
-
reconnect,
|
|
63
|
-
source: makeConnection,
|
|
64
|
-
status: "connecting"
|
|
65
|
-
}));
|
|
66
|
-
Promise.resolve(makeConnection()).then((connected) => {
|
|
67
|
-
if (disposed) {
|
|
68
|
-
connected[Symbol.dispose]?.();
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
root = connected;
|
|
72
|
-
setSnapshot((current) => ({
|
|
73
|
-
enabled,
|
|
74
|
-
generation: current.generation + 1,
|
|
75
|
-
reconnect,
|
|
76
|
-
root: connected,
|
|
77
|
-
source: makeConnection,
|
|
78
|
-
status: "connected"
|
|
79
|
-
}));
|
|
80
|
-
stable = setTimeout(() => {
|
|
81
|
-
if (!disposed && root === connected) failures.current = 0;
|
|
82
|
-
}, CONNECTION_STABLE_MS);
|
|
83
|
-
connected.onRpcBroken?.(() => {
|
|
84
|
-
if (disposed || root !== connected) return;
|
|
85
|
-
clearTimeout(stable);
|
|
86
|
-
root = void 0;
|
|
87
|
-
connected[Symbol.dispose]?.();
|
|
88
|
-
setSnapshot((current) => ({
|
|
89
|
-
enabled,
|
|
90
|
-
generation: current.generation,
|
|
91
|
-
reconnect,
|
|
92
|
-
source: makeConnection,
|
|
93
|
-
status: "connecting"
|
|
94
|
-
}));
|
|
95
|
-
scheduleReconnect();
|
|
96
|
-
});
|
|
97
|
-
}, (cause) => {
|
|
98
|
-
if (disposed) return;
|
|
99
|
-
setSnapshot((current) => ({
|
|
100
|
-
enabled,
|
|
101
|
-
error: cause instanceof Error ? cause.message : String(cause),
|
|
102
|
-
generation: current.generation,
|
|
103
|
-
reconnect,
|
|
104
|
-
source: makeConnection,
|
|
105
|
-
status: "error"
|
|
106
|
-
}));
|
|
107
|
-
scheduleReconnect();
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
return () => {
|
|
111
|
-
disposed = true;
|
|
112
|
-
clearTimeout(retry);
|
|
113
|
-
clearTimeout(stable);
|
|
114
|
-
root?.[Symbol.dispose]?.();
|
|
115
|
-
};
|
|
116
|
-
}, [
|
|
117
|
-
enabled,
|
|
118
|
-
epoch,
|
|
119
|
-
makeConnection,
|
|
120
|
-
reconnect
|
|
121
|
-
]);
|
|
122
|
-
if (snapshot.enabled !== enabled || snapshot.source !== makeConnection) return {
|
|
123
|
-
generation: snapshot.generation,
|
|
124
|
-
reconnect,
|
|
125
|
-
scope: makeConnection,
|
|
126
|
-
status: "connecting"
|
|
127
|
-
};
|
|
128
|
-
const { enabled: _enabled, source: _source, ...connection } = snapshot;
|
|
129
|
-
return {
|
|
130
|
-
...connection,
|
|
131
|
-
scope: makeConnection
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
/** The current provider root, undefined while its connection is being replaced. */
|
|
135
|
-
function useCapnWebRoot() {
|
|
136
|
-
const connection = useContext(CapnWebContext);
|
|
137
|
-
if (connection === void 0) throw new Error("useCapnWebRoot must be rendered under <CapnWebProvider>.");
|
|
138
|
-
return connection.root;
|
|
139
|
-
}
|
|
140
|
-
/** Resolve provider, owned connection, or borrowed root with one logical scope. */
|
|
141
|
-
function useLiveStateConnection(options) {
|
|
142
|
-
const provider = useContext(CapnWebContext);
|
|
143
|
-
const hasRootOverride = options !== void 0 && Object.hasOwn(options, "root");
|
|
144
|
-
const connectionFactory = hasRootOverride ? void 0 : options?.makeConnection;
|
|
145
|
-
const owned = useCapnWebConnection(connectionFactory, !hasRootOverride && (options?.enabled ?? true));
|
|
146
|
-
if (!hasRootOverride && !connectionFactory && !provider) throw new Error("useLiveState needs <CapnWebProvider>, a makeConnection option, or an explicit { root } override.");
|
|
147
|
-
const connection = hasRootOverride ? void 0 : connectionFactory ? owned : provider;
|
|
148
|
-
const root = (hasRootOverride ? options.root : connection?.root) ?? void 0;
|
|
149
|
-
return {
|
|
150
|
-
connection,
|
|
151
|
-
root,
|
|
152
|
-
scope: hasRootOverride ? root : connectionFactory ?? connection?.scope
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Render a selected slice of any LiveStateRpc reachable from the provider root.
|
|
157
|
-
* Pass `{ root }` to borrow an explicit root instead; borrowed roots are never
|
|
158
|
-
* disposed or reconnected by this hook.
|
|
159
|
-
*/
|
|
160
|
-
function useLiveState(live, selector = (state) => state, deps = [], options) {
|
|
161
|
-
const { connection, root, scope } = useLiveStateConnection(options);
|
|
162
|
-
const enabled = options?.enabled ?? true;
|
|
163
|
-
const [epoch, setEpoch] = useState(0);
|
|
164
|
-
const liveRef = useRef(live);
|
|
165
|
-
const selectorRef = useRef(selector);
|
|
166
|
-
useEffect(() => {
|
|
167
|
-
liveRef.current = live;
|
|
168
|
-
selectorRef.current = selector;
|
|
169
|
-
});
|
|
170
|
-
const store = useMemo(() => createLiveStateStore(), [scope, ...deps]);
|
|
171
|
-
const subscribeRetries = useMemo(() => ({
|
|
172
|
-
count: 0,
|
|
173
|
-
resyncs: 0
|
|
174
|
-
}), [store]);
|
|
175
|
-
const refresh = useCallback(() => {
|
|
176
|
-
subscribeRetries.count = 0;
|
|
177
|
-
subscribeRetries.resyncs = 0;
|
|
178
|
-
setEpoch((current) => current + 1);
|
|
179
|
-
}, [subscribeRetries]);
|
|
180
|
-
const [subscriptionState, setSubscriptionState] = useState({
|
|
181
|
-
epoch,
|
|
182
|
-
generation: connection?.generation,
|
|
183
|
-
status: "connecting",
|
|
184
|
-
store
|
|
185
|
-
});
|
|
186
|
-
useEffect(() => {
|
|
187
|
-
let disposed = false;
|
|
188
|
-
let stale = false;
|
|
189
|
-
let handle;
|
|
190
|
-
let pingTimeout;
|
|
191
|
-
let retry;
|
|
192
|
-
let timeout;
|
|
193
|
-
let watchdog;
|
|
194
|
-
const release = () => {
|
|
195
|
-
stale = true;
|
|
196
|
-
if (handle === void 0) return;
|
|
197
|
-
releaseLiveStateSubscription(handle);
|
|
198
|
-
handle = void 0;
|
|
199
|
-
};
|
|
200
|
-
setSubscriptionState({
|
|
201
|
-
epoch,
|
|
202
|
-
generation: connection?.generation,
|
|
203
|
-
status: "connecting",
|
|
204
|
-
store
|
|
205
|
-
});
|
|
206
|
-
if (enabled && root !== void 0) {
|
|
207
|
-
const report = (cause, shouldRetry = false) => {
|
|
208
|
-
if (disposed || stale) return;
|
|
209
|
-
release();
|
|
210
|
-
setSubscriptionState({
|
|
211
|
-
error: cause instanceof Error ? cause.message : String(cause),
|
|
212
|
-
epoch,
|
|
213
|
-
generation: connection?.generation,
|
|
214
|
-
status: "error",
|
|
215
|
-
store
|
|
216
|
-
});
|
|
217
|
-
if (shouldRetry && subscribeRetries.count < MAX_SUBSCRIBE_RETRIES) {
|
|
218
|
-
subscribeRetries.count += 1;
|
|
219
|
-
retry = setTimeout(() => setEpoch((current) => current + 1), SUBSCRIBE_RETRY_MS);
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
try {
|
|
223
|
-
const pending = liveRef.current(root).subscribe((update) => {
|
|
224
|
-
if (disposed || stale) return;
|
|
225
|
-
try {
|
|
226
|
-
store.apply(update, () => {
|
|
227
|
-
throw new Error("Live-state revision gap");
|
|
228
|
-
});
|
|
229
|
-
if (!isLiveStateSnapshot(update)) subscribeRetries.resyncs = 0;
|
|
230
|
-
} catch (error) {
|
|
231
|
-
const shouldResync = subscribeRetries.resyncs < MAX_SUBSCRIBE_RETRIES;
|
|
232
|
-
if (shouldResync) subscribeRetries.resyncs += 1;
|
|
233
|
-
report(error, shouldResync);
|
|
234
|
-
}
|
|
235
|
-
}, { patchVersion: 3 });
|
|
236
|
-
timeout = setTimeout(() => report(/* @__PURE__ */ new Error(`live-state subscription timed out after ${SUBSCRIBE_TIMEOUT_MS}ms`), true), SUBSCRIBE_TIMEOUT_MS);
|
|
237
|
-
Promise.resolve(pending).then((subscription) => {
|
|
238
|
-
clearTimeout(timeout);
|
|
239
|
-
if (disposed || stale) {
|
|
240
|
-
releaseLiveStateSubscription(subscription);
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
handle = subscription;
|
|
244
|
-
subscribeRetries.count = 0;
|
|
245
|
-
setSubscriptionState({
|
|
246
|
-
epoch,
|
|
247
|
-
generation: connection?.generation,
|
|
248
|
-
status: "live",
|
|
249
|
-
store
|
|
250
|
-
});
|
|
251
|
-
watchdog = setInterval(() => {
|
|
252
|
-
if (handle === void 0) return;
|
|
253
|
-
Promise.race([Promise.resolve(handle.ping()), new Promise((resolve) => {
|
|
254
|
-
pingTimeout = setTimeout(() => resolve(false), PING_TIMEOUT_MS);
|
|
255
|
-
})]).then((alive) => {
|
|
256
|
-
if (!disposed && !alive) refresh();
|
|
257
|
-
}, (cause) => report(cause, true)).finally(() => clearTimeout(pingTimeout));
|
|
258
|
-
}, PING_INTERVAL_MS);
|
|
259
|
-
}, (cause) => {
|
|
260
|
-
clearTimeout(timeout);
|
|
261
|
-
report(cause, true);
|
|
262
|
-
});
|
|
263
|
-
} catch (cause) {
|
|
264
|
-
report(cause, true);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return () => {
|
|
268
|
-
disposed = true;
|
|
269
|
-
clearTimeout(pingTimeout);
|
|
270
|
-
clearTimeout(timeout);
|
|
271
|
-
clearTimeout(retry);
|
|
272
|
-
clearInterval(watchdog);
|
|
273
|
-
release();
|
|
274
|
-
};
|
|
275
|
-
}, [
|
|
276
|
-
connection?.generation,
|
|
277
|
-
enabled,
|
|
278
|
-
epoch,
|
|
279
|
-
root,
|
|
280
|
-
store,
|
|
281
|
-
...deps
|
|
282
|
-
]);
|
|
283
|
-
const selected = useRef({
|
|
284
|
-
state: void 0,
|
|
285
|
-
value: void 0
|
|
286
|
-
});
|
|
287
|
-
const getSelected = () => {
|
|
288
|
-
const state = store.getState();
|
|
289
|
-
if (Object.is(selected.current.state, state)) return selected.current.value;
|
|
290
|
-
const value = state === void 0 ? void 0 : selectorRef.current(state);
|
|
291
|
-
selected.current = {
|
|
292
|
-
state,
|
|
293
|
-
value
|
|
294
|
-
};
|
|
295
|
-
return value;
|
|
296
|
-
};
|
|
297
|
-
const value = useSyncExternalStore(store.subscribe, getSelected, () => void 0);
|
|
298
|
-
const providerError = connection?.status === "error" ? connection.error : void 0;
|
|
299
|
-
const activeSubscriptionState = subscriptionState.store === store && subscriptionState.epoch === epoch && subscriptionState.generation === connection?.generation ? subscriptionState : {
|
|
300
|
-
epoch,
|
|
301
|
-
generation: connection?.generation,
|
|
302
|
-
status: "connecting",
|
|
303
|
-
store
|
|
304
|
-
};
|
|
305
|
-
const connectionIsConnecting = connection?.status === "connecting";
|
|
306
|
-
return {
|
|
307
|
-
error: providerError ?? (connectionIsConnecting || !enabled ? void 0 : activeSubscriptionState.error),
|
|
308
|
-
refresh: connection?.status === "error" ? connection.reconnect : refresh,
|
|
309
|
-
status: providerError !== void 0 ? "error" : connectionIsConnecting || !enabled ? "connecting" : activeSubscriptionState.status,
|
|
310
|
-
value
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
//#endregion
|
|
314
|
-
export { CapnWebProvider, useCapnWebRoot, useLiveState };
|
|
315
|
-
|
|
316
|
-
//# sourceMappingURL=react.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"react.mjs","names":[],"sources":["../../../src/sdk/capnweb/react.tsx"],"sourcesContent":["// oxlint-disable react/only-export-components -- this public entry deliberately colocates its provider with the hooks that consume it.\nimport {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\";\nimport { createLiveStateStore } from \"./live-state/store.ts\";\nimport { isLiveStateSnapshot } from \"./live-state/protocol.ts\";\nimport type { LiveStateRpc, LiveStateSubscriptionHandle } from \"./live-state/types.ts\";\n\nexport type CapnWebRoot = object &\n Partial<Disposable> & {\n onRpcBroken?(callback: (error?: unknown) => void): void;\n };\n\nexport type MakeCapnWebConnection<Root extends CapnWebRoot> = () => Root | PromiseLike<Root>;\nexport type LiveStateStatus = \"connecting\" | \"live\" | \"error\";\n\ntype ConnectionSnapshot = {\n error?: string;\n generation: number;\n reconnect: () => void;\n root?: CapnWebRoot;\n /** Stable for one connection factory, across all of that factory's reconnects. */\n scope: object | undefined;\n status: \"connecting\" | \"connected\" | \"error\";\n};\n\nconst CapnWebContext = createContext<ConnectionSnapshot | undefined>(undefined);\nconst CONNECTION_STABLE_MS = 30_000;\nconst CONNECTION_RETRY_MAX_MS = 10_000;\nconst SUBSCRIBE_RETRY_MS = 10_000;\nconst MAX_SUBSCRIBE_RETRIES = 2;\nconst SUBSCRIBE_TIMEOUT_MS = 15_000;\nconst PING_INTERVAL_MS = 45_000;\nconst PING_TIMEOUT_MS = 10_000;\n\nfunction releaseLiveStateSubscription(handle: LiveStateSubscriptionHandle): void {\n // Teardown commonly races a dead transport: the remote unsubscribe may\n // reject, but the local capability must still leave Cap'n Web's import table.\n void Promise.resolve()\n .then(() => handle.unsubscribe())\n .catch(() => {})\n .finally(() => handle[Symbol.dispose]?.());\n}\n\n/**\n * Own one reconnectable Cap'n Web root for a React subtree. The factory is the\n * only transport policy: it can dial a WebSocket directly or duplicate a root\n * from a lower-level shared connection keeper. Broken roots are disposed and\n * replaced with bounded exponential backoff.\n */\nexport function CapnWebProvider<Root extends CapnWebRoot>({\n children,\n makeConnection,\n}: {\n children?: ReactNode;\n makeConnection: MakeCapnWebConnection<Root>;\n}) {\n const snapshot = useCapnWebConnection(makeConnection);\n\n return createElement(CapnWebContext, { value: snapshot }, children);\n}\n\nfunction useCapnWebConnection<Root extends CapnWebRoot>(\n makeConnection: MakeCapnWebConnection<Root> | undefined,\n enabled = true,\n): ConnectionSnapshot {\n const [epoch, setEpoch] = useState(0);\n const failures = useRef(0);\n const failureSource = useRef(makeConnection);\n const reconnect = useCallback(() => setEpoch((current) => current + 1), []);\n const [snapshot, setSnapshot] = useState<InternalConnectionSnapshot<Root>>({\n enabled,\n generation: 0,\n reconnect,\n source: makeConnection,\n status: \"connecting\",\n });\n\n // react-doctor-disable-next-line effect-needs-cleanup -- the unconditional cleanup below owns both timers assigned by async connection callbacks and the root\n useEffect(() => {\n let disposed = false;\n let root: Root | undefined;\n let retry: ReturnType<typeof setTimeout> | undefined;\n let stable: ReturnType<typeof setTimeout> | undefined;\n if (failureSource.current !== makeConnection) {\n failureSource.current = makeConnection;\n failures.current = 0;\n }\n if (!enabled || makeConnection === undefined) {\n failures.current = 0;\n setSnapshot((current) => ({\n enabled,\n generation: current.generation,\n reconnect,\n source: makeConnection,\n status: \"connecting\",\n }));\n } else {\n const scheduleReconnect = () => {\n const nextFailures = (failures.current += 1);\n retry = setTimeout(\n reconnect,\n Math.min(250 * 2 ** (nextFailures - 1), CONNECTION_RETRY_MAX_MS),\n );\n };\n setSnapshot((current) => ({\n enabled,\n generation: current.generation,\n reconnect,\n source: makeConnection,\n status: \"connecting\",\n }));\n\n void Promise.resolve(makeConnection()).then(\n (connected) => {\n if (disposed) {\n connected[Symbol.dispose]?.();\n return;\n }\n root = connected;\n setSnapshot((current) => ({\n enabled,\n generation: current.generation + 1,\n reconnect,\n root: connected,\n source: makeConnection,\n status: \"connected\",\n }));\n stable = setTimeout(() => {\n if (!disposed && root === connected) failures.current = 0;\n }, CONNECTION_STABLE_MS);\n connected.onRpcBroken?.(() => {\n if (disposed || root !== connected) return;\n clearTimeout(stable);\n root = undefined;\n connected[Symbol.dispose]?.();\n setSnapshot((current) => ({\n enabled,\n generation: current.generation,\n reconnect,\n source: makeConnection,\n status: \"connecting\",\n }));\n scheduleReconnect();\n });\n },\n (cause: unknown) => {\n if (disposed) return;\n setSnapshot((current) => ({\n enabled,\n error: cause instanceof Error ? cause.message : String(cause),\n generation: current.generation,\n reconnect,\n source: makeConnection,\n status: \"error\",\n }));\n scheduleReconnect();\n },\n );\n }\n\n return () => {\n disposed = true;\n clearTimeout(retry);\n clearTimeout(stable);\n root?.[Symbol.dispose]?.();\n };\n }, [enabled, epoch, makeConnection, reconnect]);\n\n if (snapshot.enabled !== enabled || snapshot.source !== makeConnection) {\n return {\n generation: snapshot.generation,\n reconnect,\n scope: makeConnection,\n status: \"connecting\",\n };\n }\n const { enabled: _enabled, source: _source, ...connection } = snapshot;\n return { ...connection, scope: makeConnection };\n}\n\ntype InternalConnectionSnapshot<Root extends CapnWebRoot> = Omit<ConnectionSnapshot, \"scope\"> & {\n enabled: boolean;\n source: MakeCapnWebConnection<Root> | undefined;\n};\n\n/** The current provider root, undefined while its connection is being replaced. */\nexport function useCapnWebRoot<Root extends CapnWebRoot>(): Root | undefined {\n const connection = useContext(CapnWebContext);\n if (connection === undefined) {\n throw new Error(\"useCapnWebRoot must be rendered under <CapnWebProvider>.\");\n }\n return connection.root as Root | undefined;\n}\n\ntype LiveStateOptions<Root extends CapnWebRoot> = {\n enabled?: boolean;\n makeConnection?: MakeCapnWebConnection<Root>;\n root?: Root | null;\n};\n\n/** Resolve provider, owned connection, or borrowed root with one logical scope. */\nfunction useLiveStateConnection<Root extends CapnWebRoot>(options?: LiveStateOptions<Root>) {\n const provider = useContext(CapnWebContext);\n const hasRootOverride = options !== undefined && Object.hasOwn(options, \"root\");\n const connectionFactory = hasRootOverride ? undefined : options?.makeConnection;\n const owned = useCapnWebConnection(\n connectionFactory,\n !hasRootOverride && (options?.enabled ?? true),\n );\n if (!hasRootOverride && !connectionFactory && !provider) {\n throw new Error(\n \"useLiveState needs <CapnWebProvider>, a makeConnection option, or an explicit { root } override.\",\n );\n }\n const connection = hasRootOverride ? undefined : connectionFactory ? owned : provider;\n const root = (hasRootOverride ? options.root : connection?.root) ?? undefined;\n const scope = hasRootOverride ? root : (connectionFactory ?? connection?.scope);\n return { connection, root, scope };\n}\n\n/**\n * Render a selected slice of any LiveStateRpc reachable from the provider root.\n * Pass `{ root }` to borrow an explicit root instead; borrowed roots are never\n * disposed or reconnected by this hook.\n */\nexport function useLiveState<Root extends CapnWebRoot, State, Selected = State>(\n live: (root: Root) => LiveStateRpc<State>,\n selector: (state: State) => Selected = (state) => state as unknown as Selected,\n deps: unknown[] = [],\n options?: LiveStateOptions<Root>,\n): {\n error?: string;\n refresh: () => void;\n status: LiveStateStatus;\n value: Selected | undefined;\n} {\n const { connection, root, scope } = useLiveStateConnection(options);\n const enabled = options?.enabled ?? true;\n const [epoch, setEpoch] = useState(0);\n const liveRef = useRef(live);\n const selectorRef = useRef(selector);\n useEffect(() => {\n liveRef.current = live;\n selectorRef.current = selector;\n });\n\n // A different provider/factory, explicit borrowed root, or logical node gets\n // an empty store synchronously. A new transport generation within the same\n // connection scope keeps the last value visible while it re-subscribes.\n // oxlint-disable-next-line react-hooks/exhaustive-deps -- this memo is intentionally keyed; deps complete the caller's logical-node identity\n const store = useMemo(() => createLiveStateStore<State>(), [scope, ...deps]);\n // oxlint-disable-next-line react-hooks/exhaustive-deps -- store is the logical subscription identity; its replacement must reset the retry budget\n const subscribeRetries = useMemo(() => ({ count: 0, resyncs: 0 }), [store]);\n const refresh = useCallback(() => {\n subscribeRetries.count = 0;\n subscribeRetries.resyncs = 0;\n setEpoch((current) => current + 1);\n }, [subscribeRetries]);\n const [subscriptionState, setSubscriptionState] = useState<{\n error?: string;\n epoch: number;\n generation: number | undefined;\n status: LiveStateStatus;\n store: typeof store;\n }>({ epoch, generation: connection?.generation, status: \"connecting\", store });\n\n // react-doctor-disable-next-line effect-needs-cleanup -- the unconditional cleanup below owns subscribe/retry/ping timers and the subscription handle\n useEffect(() => {\n let disposed = false;\n let stale = false;\n let handle: LiveStateSubscriptionHandle | undefined;\n let pingTimeout: ReturnType<typeof setTimeout> | undefined;\n let retry: ReturnType<typeof setTimeout> | undefined;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let watchdog: ReturnType<typeof setInterval> | undefined;\n const release = () => {\n stale = true;\n if (handle === undefined) return;\n releaseLiveStateSubscription(handle);\n handle = undefined;\n };\n setSubscriptionState({\n epoch,\n generation: connection?.generation,\n status: \"connecting\",\n store,\n });\n if (enabled && root !== undefined) {\n const report = (cause: unknown, shouldRetry = false) => {\n if (disposed || stale) return;\n release();\n setSubscriptionState({\n error: cause instanceof Error ? cause.message : String(cause),\n epoch,\n generation: connection?.generation,\n status: \"error\",\n store,\n });\n if (shouldRetry && subscribeRetries.count < MAX_SUBSCRIBE_RETRIES) {\n subscribeRetries.count += 1;\n retry = setTimeout(() => setEpoch((current) => current + 1), SUBSCRIBE_RETRY_MS);\n }\n };\n\n // The context erases its root parameter; this hook's provider/factory/root\n // inputs are the only sources, so restoring the caller's Root is safe.\n try {\n const pending = liveRef.current(root as Root).subscribe(\n (update) => {\n if (disposed || stale) return;\n try {\n store.apply(update, () => {\n throw new Error(\"Live-state revision gap\");\n });\n if (!isLiveStateSnapshot(update)) subscribeRetries.resyncs = 0;\n } catch (error) {\n // A successful subscribe alone cannot reset this budget: a host\n // could repeatedly seed a valid snapshot followed by a bad patch.\n const shouldResync = subscribeRetries.resyncs < MAX_SUBSCRIBE_RETRIES;\n if (shouldResync) subscribeRetries.resyncs += 1;\n report(error, shouldResync);\n }\n },\n { patchVersion: 3 },\n );\n timeout = setTimeout(\n () =>\n report(\n new Error(`live-state subscription timed out after ${SUBSCRIBE_TIMEOUT_MS}ms`),\n true,\n ),\n SUBSCRIBE_TIMEOUT_MS,\n );\n void Promise.resolve(pending).then(\n (subscription) => {\n clearTimeout(timeout);\n if (disposed || stale) {\n releaseLiveStateSubscription(subscription);\n return;\n }\n handle = subscription;\n subscribeRetries.count = 0;\n setSubscriptionState({\n epoch,\n generation: connection?.generation,\n status: \"live\",\n store,\n });\n watchdog = setInterval(() => {\n if (handle === undefined) return;\n void Promise.race([\n Promise.resolve(handle.ping()),\n new Promise<boolean>((resolve) => {\n pingTimeout = setTimeout(() => resolve(false), PING_TIMEOUT_MS);\n }),\n ])\n .then(\n (alive) => {\n if (!disposed && !alive) refresh();\n },\n (cause: unknown) => report(cause, true),\n )\n .finally(() => clearTimeout(pingTimeout));\n }, PING_INTERVAL_MS);\n },\n (cause: unknown) => {\n clearTimeout(timeout);\n report(cause, true);\n },\n );\n } catch (cause) {\n report(cause, true);\n }\n }\n\n return () => {\n disposed = true;\n clearTimeout(pingTimeout);\n clearTimeout(timeout);\n clearTimeout(retry);\n clearInterval(watchdog);\n release();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- deps define the caller's logical node\n }, [connection?.generation, enabled, epoch, root, store, ...deps]);\n\n const selected = useRef<{ state: State | undefined; value: Selected | undefined }>({\n state: undefined,\n value: undefined,\n });\n const getSelected = () => {\n const state = store.getState();\n if (Object.is(selected.current.state, state)) return selected.current.value;\n const value = state === undefined ? undefined : selectorRef.current(state);\n selected.current = { state, value };\n return value;\n };\n const value = useSyncExternalStore(store.subscribe, getSelected, () => undefined);\n const providerError = connection?.status === \"error\" ? connection.error : undefined;\n const activeSubscriptionState =\n subscriptionState.store === store &&\n subscriptionState.epoch === epoch &&\n subscriptionState.generation === connection?.generation\n ? subscriptionState\n : {\n epoch,\n generation: connection?.generation,\n status: \"connecting\" as const,\n store,\n };\n const connectionIsConnecting = connection?.status === \"connecting\";\n return {\n error:\n providerError ??\n (connectionIsConnecting || !enabled ? undefined : activeSubscriptionState.error),\n refresh: connection?.status === \"error\" ? connection.reconnect : refresh,\n status:\n providerError !== undefined\n ? \"error\"\n : connectionIsConnecting || !enabled\n ? \"connecting\"\n : activeSubscriptionState.status,\n value,\n };\n}\n"],"mappings":"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"}
|
package/dist/sdk/capnweb.mjs
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { a as isThenable, i as disposeIgnoredRpcResult, n as LiveStateSubscriptionRpcTarget, o as retainCallback, r as LiveState, t as LiveStateRpcTarget } from "../live-state-BJNqOwFw.mjs";
|
|
2
|
-
import { a as compactPatch, i as applyCompactPatch, n as liveStateRevision, o as applyPatch, r as createLiveStateStore, s as diff, t as isLiveStateSnapshot } from "../protocol-DnK_f2m6.mjs";
|
|
3
|
-
export * from "@iterate-com/capnweb";
|
|
4
|
-
export { LiveState, LiveStateRpcTarget, LiveStateSubscriptionRpcTarget, applyCompactPatch, applyPatch, compactPatch, createLiveStateStore, diff, disposeIgnoredRpcResult, isLiveStateSnapshot, isThenable, liveStateRevision, retainCallback };
|
package/dist/sdk/itx/react.d.ts
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `iterate/sdk/itx/react` — hooks over the framework-free session keeper in
|
|
3
|
-
* ../../itx/itx-session.ts (one WebSocket per tab, generations, invisible
|
|
4
|
-
* reconnect — the session model lives there) plus TanStack Query for reads.
|
|
5
|
-
*
|
|
6
|
-
* Renderer-agnostic on purpose: nothing here touches the DOM, so the same
|
|
7
|
-
* hooks run under react-dom (the OS dashboard), @opentui/react (the chat TUI),
|
|
8
|
-
* and React Native — TanStack Query itself only uses React primitives. The
|
|
9
|
-
* browser-specific pieces (cookie auth, window-derived URL, visibility/online
|
|
10
|
-
* wake probes) live in the keeper behind runtime guards; non-browser apps
|
|
11
|
-
* point the keeper at a deployment with `configureIterateSession`.
|
|
12
|
-
*
|
|
13
|
-
* ───────────────────────────────────────────────────────────────────────────
|
|
14
|
-
* THE PRIMITIVES
|
|
15
|
-
* ───────────────────────────────────────────────────────────────────────────
|
|
16
|
-
*
|
|
17
|
-
* SESSION (the catalog authenticate() returned)
|
|
18
|
-
* useIterateSession() in render; suspends once on first connect
|
|
19
|
-
* connectIterateSession() imperative (handlers/closures); a Promise
|
|
20
|
-
*
|
|
21
|
-
* ITX (a project capability handle — session.projects.get(slug))
|
|
22
|
-
* useItx(slug?) in render; slug (or prj_ id) from the arg or <ProjectScope>
|
|
23
|
-
* connectItx(slug) imperative; a Promise
|
|
24
|
-
*
|
|
25
|
-
* READ ONCE useItxQuery({ key, query }) project read; SUSPENDS
|
|
26
|
-
* useIterateSessionQuery({ key, query }) session read; NON-suspending (shell)
|
|
27
|
-
* LIVE STATE useLiveState((itx) => itx.liveState, selector) project snapshot + diffs
|
|
28
|
-
* useIterateSessionLiveState(...) session snapshot + diffs
|
|
29
|
-
* CONNECT useStreamConnection((itx) => handle, deps) raw event batches (escape hatch)
|
|
30
|
-
* MOUNT <ProjectScope slug> ambient project + reconnectable Cap'n Web provider
|
|
31
|
-
*
|
|
32
|
-
* ACTIONS (mutations) — imperative on the handle, no extra primitive:
|
|
33
|
-
* const itx = useItx();
|
|
34
|
-
* <button onClick={() => itx.chat.sendMessage(text)} />
|
|
35
|
-
*
|
|
36
|
-
* RECONNECT, AS REACT SEES IT: components read an immutable Snapshot via
|
|
37
|
-
* `useSyncExternalStore`; `snapshot.session` holds the LAST live session and is
|
|
38
|
-
* kept across a transport gap. So `useIterateSession()` suspends exactly once —
|
|
39
|
-
* first load, on the stable first-connect promise — and never again: when the
|
|
40
|
-
* socket dies we keep showing the last session while a fresh generation connects
|
|
41
|
-
* in the background, then swap when it establishes. TanStack keeps cached read
|
|
42
|
-
* data through a reconnect (no re-suspend, no spinner); only an in-flight read
|
|
43
|
-
* retries, on the transport-only policy — see useItxQuery. A stray action fired
|
|
44
|
-
* during the sub-second gap rides the dead stub and rejects — the one accepted
|
|
45
|
-
* edge.
|
|
46
|
-
*
|
|
47
|
-
* CONNECTING THROWS ON THE SERVER (never SSRs): a forever-pending `use()`
|
|
48
|
-
* during streaming SSR would hang the response. Render itx consumers under an
|
|
49
|
-
* `ssr: false` route or `<ClientOnly>` + `<Suspense>`.
|
|
50
|
-
*/
|
|
51
|
-
import { type ReactNode } from "react";
|
|
52
|
-
import { type QueryKey, type UseQueryResult } from "@tanstack/react-query";
|
|
53
|
-
import type { LiveStateRpc } from "../../itx-api.generated.ts";
|
|
54
|
-
import { type LiveStateStatus } from "../capnweb/react.tsx";
|
|
55
|
-
import { type ItxRecoverableConnectionHandle, type ProjectStub, type SessionStub } from "../../itx/itx-session.ts";
|
|
56
|
-
export { configureIterateSession, connectIterateSession, connectItx, disconnectIterateSession, isItxTransportError, reconnectIterateSession, retryFailedIterateSession, reportTransportSuspicion, type Itx, type ItxRecoverableConnectionHandle, type IterateSessionConfig, type ProjectStub, type SessionStub, } from "../../itx/itx-session.ts";
|
|
57
|
-
export { createIterateQueryClient } from "../../itx/query-client.ts";
|
|
58
|
-
export type * from "../../itx-api.generated.ts";
|
|
59
|
-
/**
|
|
60
|
-
* The Session — the catalog `authenticate()` returned (`projects.list/create`,
|
|
61
|
-
* admin `streams`). Suspends exactly ONCE, on first connect; a later reconnect
|
|
62
|
-
* keeps returning the last session (no re-suspend — see module header).
|
|
63
|
-
*/
|
|
64
|
-
export declare function useIterateSession(): SessionStub;
|
|
65
|
-
/**
|
|
66
|
-
* The project itx for `slug` — `session.projects.get(slug)`, the real capnweb
|
|
67
|
-
* stub. `slug` comes from the argument or the nearest <ProjectScope>; an
|
|
68
|
-
* explicit argument wins. The returned stub's identity is stable within a socket
|
|
69
|
-
* and changes once per reconnect (which re-runs effects/memos keyed on it).
|
|
70
|
-
*
|
|
71
|
-
* const itx = useItx(); // ambient project (under <ProjectScope>)
|
|
72
|
-
* const itx = useItx("other-slug"); // a specific project
|
|
73
|
-
* const onSend = () => itx.chat.sendMessage(text);
|
|
74
|
-
*/
|
|
75
|
-
export declare function useItx(explicitSlug?: string): ProjectStub;
|
|
76
|
-
/**
|
|
77
|
-
* Set the ambient project for a subtree and provide its reconnectable Cap'n Web
|
|
78
|
-
* root. The project-specific layer is deliberately only a connection factory;
|
|
79
|
-
* live-state ownership and recovery live in `iterate/sdk/capnweb/react`.
|
|
80
|
-
*
|
|
81
|
-
* The provider dials in an effect, never during render, so this context remains
|
|
82
|
-
* safe to render on the server. The duplicate belongs to the provider; the
|
|
83
|
-
* lower-level session keeper keeps owning and reconnecting the shared socket
|
|
84
|
-
* beneath it.
|
|
85
|
-
*/
|
|
86
|
-
export declare function ProjectScope({ slug, children }: {
|
|
87
|
-
slug: string;
|
|
88
|
-
children?: ReactNode;
|
|
89
|
-
}): import("react").FunctionComponentElement<import("react").ProviderProps<string | undefined>>;
|
|
90
|
-
/**
|
|
91
|
-
* Read once through a project itx, suspending until it resolves. A thin adapter
|
|
92
|
-
* over TanStack Query's `useSuspenseQuery`. `key` (prefixed with "itx"
|
|
93
|
-
* internally) is the cache key — it must encode what the result is scoped to,
|
|
94
|
-
* INCLUDING the project, so two projects' data can't collide: a per-project read
|
|
95
|
-
* keys by the project, e.g. `["repo-files", projectId, repoPath]`. (The ambient
|
|
96
|
-
* slug drives the CONNECTION, not the key — so a mutation invalidates with the
|
|
97
|
-
* same `["itx", ...key]` it was written under.)
|
|
98
|
-
*
|
|
99
|
-
* const files = useItxQuery({
|
|
100
|
-
* key: ["repo-files", projectId, repoPath],
|
|
101
|
-
* query: (itx) => itx.repos.get(repoPath).listFiles(),
|
|
102
|
-
* });
|
|
103
|
-
*
|
|
104
|
-
* The connection is resolved PER FETCH (never a render-captured stub — that
|
|
105
|
-
* would pin a dead socket after a reconnect), and the per-fetch project stub is
|
|
106
|
-
* disposed once the read resolves. A resolved query keeps its cached data across
|
|
107
|
-
* a reconnect (no re-suspend, no spinner); only an in-flight read retries, on a
|
|
108
|
-
* finite transport-only policy. Errors with no cached data throw to the nearest
|
|
109
|
-
* error boundary; refetch after a mutation with
|
|
110
|
-
* `queryClient.invalidateQueries({ queryKey: ["itx", ...key] })`.
|
|
111
|
-
*/
|
|
112
|
-
export declare function useItxQuery<T>({ key, query, }: {
|
|
113
|
-
key: QueryKey;
|
|
114
|
-
query: (itx: ProjectStub) => Promise<T>;
|
|
115
|
-
}): T;
|
|
116
|
-
/**
|
|
117
|
-
* Read once through the SESSION (the catalog — `projects.list`, admin `streams`),
|
|
118
|
-
* the session-scoped sibling of {@link useItxQuery}. NON-suspending: session
|
|
119
|
-
* reads live in the always-mounted shell (sidebar, ⌘K, admin) which must not
|
|
120
|
-
* suspend on the socket, so this returns the full TanStack result (`data`,
|
|
121
|
-
* `isPending`, …) and accepts the usual options (`enabled`, `staleTime`). Same
|
|
122
|
-
* `["itx", ...key]` namespace and the same transport-only retry as useItxQuery,
|
|
123
|
-
* resolved per fetch (never a render-captured session stub).
|
|
124
|
-
*
|
|
125
|
-
* const { data } = useIterateSessionQuery({ key: ["projects"], query: (s) => s.projects.list() });
|
|
126
|
-
*/
|
|
127
|
-
export declare function useIterateSessionQuery<T>({ key, query, enabled, staleTime, }: {
|
|
128
|
-
key: QueryKey;
|
|
129
|
-
query: (session: SessionStub) => Promise<T>;
|
|
130
|
-
enabled?: boolean;
|
|
131
|
-
staleTime?: number;
|
|
132
|
-
}): UseQueryResult<T>;
|
|
133
|
-
export type ItxConnectionStatus = LiveStateStatus;
|
|
134
|
-
/**
|
|
135
|
-
* Hold one raw stream callback connection for the component's lifetime.
|
|
136
|
-
* Reconnects, silent connection death, and transport-failed open attempts recover
|
|
137
|
-
* through the shared watchdog; permanent failures remain in `"error"` until
|
|
138
|
-
* `refresh()` or a reconnect. Reopening replays the first push, so callbacks
|
|
139
|
-
* must be replay-tolerant. Teardown closes and disposes the handle.
|
|
140
|
-
*
|
|
141
|
-
* `enabled: false` is inert; `deps` reopen on change. `opts.slug` targets
|
|
142
|
-
* a project outside the ambient {@link ProjectScope} without suspending.
|
|
143
|
-
*/
|
|
144
|
-
export declare function useStreamConnection(open: (itx: ProjectStub) => Promise<ItxRecoverableConnectionHandle>, deps: unknown[], opts?: {
|
|
145
|
-
enabled?: boolean;
|
|
146
|
-
slug?: string;
|
|
147
|
-
}): {
|
|
148
|
-
status: ItxConnectionStatus;
|
|
149
|
-
error?: string;
|
|
150
|
-
refresh: () => void;
|
|
151
|
-
};
|
|
152
|
-
/**
|
|
153
|
-
* THE live-state primitive: subscribe to any `.liveState` node, render the slice
|
|
154
|
-
* you pick. The server pushes a snapshot then minimal diffs; this hook
|
|
155
|
-
* reassembles them and hands back `selector(state)`.
|
|
156
|
-
*
|
|
157
|
-
* const streams = useLiveState((itx) => itx.liveState, (s) => s.streamsIndex);
|
|
158
|
-
*
|
|
159
|
-
* THE SELECTOR CONTRACT — a pure function of the state, nothing else:
|
|
160
|
-
* - Return a STABLE slice (`s => s.rows`), not a fresh object; map downstream.
|
|
161
|
-
* - Do NOT close over props/state (`s => s.rows[props.id]`): selection is cached
|
|
162
|
-
* by STATE identity, so a closure-captured value going stale is invisible until
|
|
163
|
-
* the next push. Select the broader slice and index in render, or route the
|
|
164
|
-
* changing input through `deps`.
|
|
165
|
-
*
|
|
166
|
-
* `value` is `undefined` between mount and the first snapshot (one round trip);
|
|
167
|
-
* render a loading row for that window. It never suspends — a reconnect keeps the
|
|
168
|
-
* last value while the subscription silently re-establishes. `deps` (or a changed
|
|
169
|
-
* `opts.slug`) re-point the hook at a different node, and the held value drops to
|
|
170
|
-
* `undefined` immediately — the previous node's state is never shown against the
|
|
171
|
-
* new one. To read a DIFFERENT project's live state from OUTSIDE its scope (⌘K in
|
|
172
|
-
* the app shell), pass `opts.slug`.
|
|
173
|
-
*/
|
|
174
|
-
export declare function useLiveState<State, Selected = State>(live: (itx: ProjectStub) => LiveStateRpc<State>, selector: (state: State) => Selected, deps?: unknown[], opts?: {
|
|
175
|
-
slug?: string;
|
|
176
|
-
enabled?: boolean;
|
|
177
|
-
}): {
|
|
178
|
-
value: Selected | undefined;
|
|
179
|
-
status: ItxConnectionStatus;
|
|
180
|
-
error?: string;
|
|
181
|
-
refresh: () => void;
|
|
182
|
-
};
|
|
183
|
-
/** Session-scoped sibling of {@link useLiveState}, for deployment-wide live nodes. */
|
|
184
|
-
export declare function useIterateSessionLiveState<State, Selected = State>(live: (session: SessionStub) => LiveStateRpc<State>, selector: (state: State) => Selected, deps?: unknown[], opts?: {
|
|
185
|
-
enabled?: boolean;
|
|
186
|
-
}): {
|
|
187
|
-
value: Selected | undefined;
|
|
188
|
-
status: ItxConnectionStatus;
|
|
189
|
-
error?: string;
|
|
190
|
-
refresh: () => void;
|
|
191
|
-
};
|