statewire 0.16.0 → 0.17.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 +12 -4
- package/dist/client/connection.d.ts +5 -1
- package/dist/client/connection.d.ts.map +1 -1
- package/dist/client/connection.js +19 -4
- package/dist/client/connection.js.map +1 -1
- package/dist/client/core.d.ts.map +1 -1
- package/dist/client/core.js +2 -0
- package/dist/client/core.js.map +1 -1
- package/dist/client/session.d.ts +15 -4
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/session.js +232 -50
- package/dist/client/session.js.map +1 -1
- package/dist/client/sessionStore.d.ts +5 -1
- package/dist/client/sessionStore.d.ts.map +1 -1
- package/dist/client/sessionStore.js +3 -1
- package/dist/client/sessionStore.js.map +1 -1
- package/dist/host/host.d.ts +1 -0
- package/dist/host/host.d.ts.map +1 -1
- package/dist/host/host.js.map +1 -1
- package/dist/host/http.d.ts.map +1 -1
- package/dist/host/http.js +27 -9
- package/dist/host/http.js.map +1 -1
- package/dist/host/socket.d.ts +10 -3
- package/dist/host/socket.d.ts.map +1 -1
- package/dist/host/socket.js +103 -39
- package/dist/host/socket.js.map +1 -1
- package/dist/host-internal.d.ts +9 -1
- package/dist/host-internal.d.ts.map +1 -1
- package/dist/host-internal.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/statewire.d.ts +33 -2
- package/dist/statewire.d.ts.map +1 -1
- package/dist/statewire.js +34 -3
- package/dist/statewire.js.map +1 -1
- package/dist/transports/fixtures.js +1 -0
- package/dist/transports/fixtures.js.map +1 -1
- package/dist/transports/remote.d.ts.map +1 -1
- package/dist/transports/remote.js +15 -8
- package/dist/transports/remote.js.map +1 -1
- package/dist/transports/sse.d.ts.map +1 -1
- package/dist/transports/sse.js +8 -8
- package/dist/transports/sse.js.map +1 -1
- package/dist/transports/testing.d.ts +1 -1
- package/dist/transports/testing.d.ts.map +1 -1
- package/dist/transports/testing.js +12 -4
- package/dist/transports/testing.js.map +1 -1
- package/dist/transports/ws.js +2 -2
- package/dist/transports/ws.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/wire/documents.d.ts +25 -2
- package/dist/wire/documents.d.ts.map +1 -1
- package/dist/wire/documents.js +27 -7
- package/dist/wire/documents.js.map +1 -1
- package/dist/wire/protocol.d.ts +55 -0
- package/dist/wire/protocol.d.ts.map +1 -0
- package/dist/wire/protocol.js +221 -0
- package/dist/wire/protocol.js.map +1 -0
- package/dist/wire/version.d.ts +1 -3
- package/dist/wire/version.d.ts.map +1 -1
- package/dist/wire/version.js +1 -3
- package/dist/wire/version.js.map +1 -1
- package/package.json +1 -1
- package/src/client/connection.ts +43 -13
- package/src/client/core.ts +6 -0
- package/src/client/session.ts +338 -39
- package/src/client/sessionStore.ts +8 -0
- package/src/host/host.ts +1 -0
- package/src/host/http.ts +36 -7
- package/src/host/socket.ts +141 -50
- package/src/host-internal.ts +12 -1
- package/src/index.ts +3 -0
- package/src/statewire.ts +109 -6
- package/src/transports/fixtures.ts +1 -1
- package/src/transports/remote.ts +16 -7
- package/src/transports/sse.ts +18 -8
- package/src/transports/testing.ts +10 -2
- package/src/transports/ws.ts +1 -1
- package/src/types.ts +11 -0
- package/src/wire/documents.ts +126 -8
- package/src/wire/protocol.ts +327 -0
- package/src/wire/version.ts +0 -2
package/src/client/connection.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
negotiationHeaders,
|
|
3
|
+
validateSelection,
|
|
4
|
+
parseNegotiation,
|
|
5
|
+
} from "../wire/protocol";
|
|
6
|
+
import type { StatewireProtocol } from "../wire/protocol";
|
|
1
7
|
import { useEffect, useRef, useState } from "react";
|
|
2
8
|
import { flushTapSync } from "@assistant-ui/tap";
|
|
3
9
|
import { reviveOps, reviveValue } from "../wire/meta";
|
|
@@ -39,6 +45,8 @@ export type StatewireCmd = {
|
|
|
39
45
|
};
|
|
40
46
|
|
|
41
47
|
export type StatewireSyn = {
|
|
48
|
+
version?: string;
|
|
49
|
+
protocols?: StatewireProtocol.Selection["protocols"];
|
|
42
50
|
seq?: number;
|
|
43
51
|
ctxSeq?: number;
|
|
44
52
|
record?: "ephemeral";
|
|
@@ -95,6 +103,7 @@ const openGate = (g: Gate) => {
|
|
|
95
103
|
export type AttemptOutcome = "stop" | "reattach" | "ended" | "idle";
|
|
96
104
|
|
|
97
105
|
export type Conn = {
|
|
106
|
+
negotiation?: StatewireProtocol.Options;
|
|
98
107
|
connection: StatewireClient.Connection;
|
|
99
108
|
parked: boolean;
|
|
100
109
|
lease: string | null;
|
|
@@ -283,7 +292,6 @@ const cmdsOf = (env: StatewireEnvelope): StatewireCmd[] => {
|
|
|
283
292
|
const snapshotOf = (env: StatewireEnvelope): unknown[] => {
|
|
284
293
|
const ops = env.ops;
|
|
285
294
|
if (ops === undefined) return protocolError("hello missing snapshot");
|
|
286
|
-
if (ops.length === 0) return protocolError("hello missing snapshot");
|
|
287
295
|
return reviveOps(ops);
|
|
288
296
|
};
|
|
289
297
|
|
|
@@ -298,6 +306,7 @@ const helloSynOf = (env: StatewireEnvelope): StatewireSyn => {
|
|
|
298
306
|
|
|
299
307
|
const handleHello = (c: Conn, env: StatewireEnvelope) => {
|
|
300
308
|
const syn = helloSynOf(env);
|
|
309
|
+
if (c.negotiation !== undefined) validateSelection(syn, c.negotiation);
|
|
301
310
|
const ops = snapshotOf(env);
|
|
302
311
|
c.ctx.onHello({
|
|
303
312
|
ops,
|
|
@@ -323,7 +332,12 @@ const warnUnknownSynFact = () => {
|
|
|
323
332
|
const deliverSyn = (c: Conn, value: unknown) => {
|
|
324
333
|
if (!isObject(value)) return protocolError("syn must be an object");
|
|
325
334
|
validateSynScalars(value);
|
|
326
|
-
if (
|
|
335
|
+
if (
|
|
336
|
+
value["version"] !== undefined ||
|
|
337
|
+
value["protocols"] !== undefined ||
|
|
338
|
+
value["record"] !== undefined ||
|
|
339
|
+
value["idle"] !== undefined
|
|
340
|
+
) {
|
|
327
341
|
protocolError("invalid mid-stream syn");
|
|
328
342
|
}
|
|
329
343
|
if (
|
|
@@ -578,6 +592,12 @@ export const attachFrame = async (
|
|
|
578
592
|
headers: StatewireClient.HeadersOption | undefined,
|
|
579
593
|
) => {
|
|
580
594
|
const resolved = await resolveHeaders(headers, c.authStale);
|
|
595
|
+
for (const [name, value] of Object.entries(
|
|
596
|
+
negotiationHeaders(c.negotiation ?? {}),
|
|
597
|
+
)) {
|
|
598
|
+
if (!resolved.has(name)) resolved.set(name, value);
|
|
599
|
+
}
|
|
600
|
+
c.negotiation = parseNegotiation(resolved);
|
|
581
601
|
c.authStale = false;
|
|
582
602
|
const lanes = flushTapSync(() => c.ctx.takeAttachLanes());
|
|
583
603
|
return {
|
|
@@ -589,15 +609,17 @@ export const attachFrame = async (
|
|
|
589
609
|
};
|
|
590
610
|
};
|
|
591
611
|
|
|
592
|
-
export const useLink = (
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
612
|
+
export const useLink = (
|
|
613
|
+
props: StatewireProtocol.Options & {
|
|
614
|
+
url: string;
|
|
615
|
+
isNew?: boolean | undefined;
|
|
616
|
+
onChange?: ((connection: StatewireClient.Connection) => void) | undefined;
|
|
617
|
+
onError?: ((error: StatewireClient.ConnectionError) => void) | undefined;
|
|
618
|
+
ctx: StatewireRemoteProps;
|
|
619
|
+
attemptOnce: (c: Conn, abort: AbortController) => Promise<AttemptOutcome>;
|
|
620
|
+
send: (c: Conn, frame: StatewireFrame) => Promise<StatewireSubmitResult>;
|
|
621
|
+
},
|
|
622
|
+
): RemoteLink => {
|
|
601
623
|
const latest = useRef(props);
|
|
602
624
|
latest.current = props;
|
|
603
625
|
const [, setConnection] = useState<StatewireClient.Connection | null>(null);
|
|
@@ -622,7 +644,10 @@ export const useLink = (props: {
|
|
|
622
644
|
},
|
|
623
645
|
onError: (error) => latest.current.onError?.(error),
|
|
624
646
|
onChange: (connection) => latest.current.onChange?.(connection),
|
|
625
|
-
attemptOnce: (abort) =>
|
|
647
|
+
attemptOnce: (abort) => {
|
|
648
|
+
conn.negotiation = latest.current;
|
|
649
|
+
return latest.current.attemptOnce(conn, abort);
|
|
650
|
+
},
|
|
626
651
|
notify: setConnection,
|
|
627
652
|
reconnect: () => reconnectConn(conn),
|
|
628
653
|
connection: {
|
|
@@ -647,6 +672,11 @@ export const useLink = (props: {
|
|
|
647
672
|
}),
|
|
648
673
|
);
|
|
649
674
|
|
|
675
|
+
const negotiation = JSON.stringify([
|
|
676
|
+
props.protocol,
|
|
677
|
+
props.wireVersion,
|
|
678
|
+
props.applicationProtocols,
|
|
679
|
+
]);
|
|
650
680
|
useEffect(() => {
|
|
651
681
|
c.lease = null;
|
|
652
682
|
c.attempt = 0;
|
|
@@ -671,7 +701,7 @@ export const useLink = (props: {
|
|
|
671
701
|
if (c.lifetime === lifetime) c.lifetime = null;
|
|
672
702
|
openGate(c.gate);
|
|
673
703
|
};
|
|
674
|
-
}, [c, props.url]);
|
|
704
|
+
}, [c, props.url, negotiation]);
|
|
675
705
|
|
|
676
706
|
return link;
|
|
677
707
|
};
|
package/src/client/core.ts
CHANGED
|
@@ -119,6 +119,11 @@ const recompute = (c: Core) => {
|
|
|
119
119
|
for (const overlay of c.overlays) {
|
|
120
120
|
if (overlay.dropped) continue;
|
|
121
121
|
const { inv } = overlay;
|
|
122
|
+
if (
|
|
123
|
+
inv.protocol !== undefined &&
|
|
124
|
+
inv.protocol !== (c.getOptions().protocol ?? "default")
|
|
125
|
+
)
|
|
126
|
+
continue;
|
|
122
127
|
const ctx: StatewireClient.OptimisticContext = {
|
|
123
128
|
ts: inv.ts,
|
|
124
129
|
seq: inv.seq,
|
|
@@ -235,6 +240,7 @@ const note = (
|
|
|
235
240
|
) => {
|
|
236
241
|
if (!c.getOptions().onCommandChange) return;
|
|
237
242
|
c.updates.push({
|
|
243
|
+
...(inv.protocol !== undefined && { protocol: inv.protocol }),
|
|
238
244
|
method: inv.method,
|
|
239
245
|
params: inv.params as never[],
|
|
240
246
|
seq: inv.seq,
|