@ably/ai-transport 0.1.0 → 0.3.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 +93 -111
- package/dist/ably-ai-transport.js +2401 -1387
- package/dist/ably-ai-transport.js.map +1 -1
- package/dist/ably-ai-transport.umd.cjs +1 -1
- package/dist/ably-ai-transport.umd.cjs.map +1 -1
- package/dist/constants.d.ts +116 -42
- package/dist/core/agent.d.ts +44 -0
- package/dist/core/channel-options.d.ts +57 -0
- package/dist/core/codec/codec-event.d.ts +9 -0
- package/dist/core/codec/decoder.d.ts +24 -24
- package/dist/core/codec/define-codec.d.ts +100 -0
- package/dist/core/codec/encoder.d.ts +10 -12
- package/dist/core/codec/field-bag.d.ts +85 -0
- package/dist/core/codec/fields.d.ts +141 -0
- package/dist/core/codec/index.d.ts +8 -2
- package/dist/core/codec/input-descriptor-decoder.d.ts +19 -0
- package/dist/core/codec/input-descriptor-encoder.d.ts +22 -0
- package/dist/core/codec/input-descriptors.d.ts +281 -0
- package/dist/core/codec/lifecycle-tracker.d.ts +10 -9
- package/dist/core/codec/output-descriptor-decoder.d.ts +29 -0
- package/dist/core/codec/output-descriptor-encoder.d.ts +31 -0
- package/dist/core/codec/output-descriptors.d.ts +237 -0
- package/dist/core/codec/types.d.ts +470 -119
- package/dist/core/codec/well-known-inputs.d.ts +52 -0
- package/dist/core/transport/agent-session.d.ts +10 -0
- package/dist/core/transport/agent-view.d.ts +296 -0
- package/dist/core/transport/client-session.d.ts +13 -0
- package/dist/core/transport/decode-fold.d.ts +55 -0
- package/dist/core/transport/headers.d.ts +121 -14
- package/dist/core/transport/index.d.ts +5 -6
- package/dist/core/transport/internal/bounded-map.d.ts +20 -0
- package/dist/core/transport/invocation.d.ts +74 -0
- package/dist/core/transport/load-history-pages.d.ts +71 -0
- package/dist/core/transport/load-history.d.ts +44 -0
- package/dist/core/transport/pipe-stream.d.ts +9 -9
- package/dist/core/transport/run-manager.d.ts +76 -0
- package/dist/core/transport/session-support.d.ts +55 -0
- package/dist/core/transport/tree.d.ts +523 -109
- package/dist/core/transport/types/agent.d.ts +375 -0
- package/dist/core/transport/types/client.d.ts +201 -0
- package/dist/core/transport/types/shared.d.ts +24 -0
- package/dist/core/transport/types/tree.d.ts +357 -0
- package/dist/core/transport/types/view.d.ts +249 -0
- package/dist/core/transport/types.d.ts +13 -553
- package/dist/core/transport/view.d.ts +390 -84
- package/dist/core/transport/wire-log.d.ts +102 -0
- package/dist/errors.d.ts +27 -10
- package/dist/index.d.ts +8 -9
- package/dist/logger.d.ts +12 -0
- package/dist/react/ably-ai-transport-react.js +1365 -1010
- package/dist/react/ably-ai-transport-react.js.map +1 -1
- package/dist/react/ably-ai-transport-react.umd.cjs +1 -1
- package/dist/react/ably-ai-transport-react.umd.cjs.map +1 -1
- package/dist/react/contexts/client-session-context.d.ts +37 -0
- package/dist/react/contexts/client-session-provider.d.ts +56 -0
- package/dist/react/create-session-hooks.d.ts +116 -0
- package/dist/react/index.d.ts +13 -12
- package/dist/react/internal/skipped-session.d.ts +8 -0
- package/dist/react/internal/use-resolved-session.d.ts +36 -0
- package/dist/react/use-ably-messages.d.ts +17 -14
- package/dist/react/use-client-session.d.ts +81 -0
- package/dist/react/use-create-view.d.ts +14 -13
- package/dist/react/use-tree.d.ts +30 -15
- package/dist/react/use-view.d.ts +81 -50
- package/dist/utils.d.ts +48 -71
- package/dist/vercel/ably-ai-transport-vercel.js +3257 -2499
- package/dist/vercel/ably-ai-transport-vercel.js.map +1 -1
- package/dist/vercel/ably-ai-transport-vercel.umd.cjs +1 -1
- package/dist/vercel/ably-ai-transport-vercel.umd.cjs.map +1 -1
- package/dist/vercel/codec/decode-lifecycle.d.ts +9 -0
- package/dist/vercel/codec/events.d.ts +50 -0
- package/dist/vercel/codec/fields.d.ts +44 -0
- package/dist/vercel/codec/fold-content.d.ts +16 -0
- package/dist/vercel/codec/fold-data.d.ts +16 -0
- package/dist/vercel/codec/fold-input.d.ts +67 -0
- package/dist/vercel/codec/fold-lifecycle.d.ts +16 -0
- package/dist/vercel/codec/fold-text.d.ts +16 -0
- package/dist/vercel/codec/fold-tool-input.d.ts +17 -0
- package/dist/vercel/codec/fold-tool-output.d.ts +16 -0
- package/dist/vercel/codec/index.d.ts +7 -20
- package/dist/vercel/codec/inputs.d.ts +11 -0
- package/dist/vercel/codec/outputs.d.ts +11 -0
- package/dist/vercel/codec/reducer-state.d.ts +121 -0
- package/dist/vercel/codec/reducer.d.ts +62 -0
- package/dist/vercel/codec/tool-transitions.d.ts +2 -8
- package/dist/vercel/codec/wire-data.d.ts +34 -0
- package/dist/vercel/index.d.ts +5 -5
- package/dist/vercel/react/ably-ai-transport-vercel-react.js +2859 -9705
- package/dist/vercel/react/ably-ai-transport-vercel-react.js.map +1 -1
- package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs +1 -45
- package/dist/vercel/react/ably-ai-transport-vercel-react.umd.cjs.map +1 -1
- package/dist/vercel/react/contexts/chat-transport-context.d.ts +9 -7
- package/dist/vercel/react/contexts/chat-transport-provider.d.ts +53 -41
- package/dist/vercel/react/index.d.ts +1 -2
- package/dist/vercel/react/use-chat-transport.d.ts +30 -26
- package/dist/vercel/react/use-message-sync.d.ts +17 -30
- package/dist/vercel/run-end-reason.d.ts +84 -0
- package/dist/vercel/tool-part.d.ts +21 -0
- package/dist/vercel/transport/chat-transport.d.ts +41 -24
- package/dist/vercel/transport/index.d.ts +24 -20
- package/dist/vercel/transport/run-output-stream.d.ts +54 -0
- package/dist/version.d.ts +2 -0
- package/package.json +31 -24
- package/src/constants.ts +124 -51
- package/src/core/agent.ts +92 -0
- package/src/core/channel-options.ts +89 -0
- package/src/core/codec/codec-event.ts +27 -0
- package/src/core/codec/decoder.ts +202 -105
- package/src/core/codec/define-codec.ts +432 -0
- package/src/core/codec/encoder.ts +114 -107
- package/src/core/codec/field-bag.ts +142 -0
- package/src/core/codec/fields.ts +193 -0
- package/src/core/codec/index.ts +56 -6
- package/src/core/codec/input-descriptor-decoder.ts +97 -0
- package/src/core/codec/input-descriptor-encoder.ts +150 -0
- package/src/core/codec/input-descriptors.ts +373 -0
- package/src/core/codec/lifecycle-tracker.ts +10 -9
- package/src/core/codec/output-descriptor-decoder.ts +139 -0
- package/src/core/codec/output-descriptor-encoder.ts +101 -0
- package/src/core/codec/output-descriptors.ts +307 -0
- package/src/core/codec/types.ts +505 -126
- package/src/core/codec/well-known-inputs.ts +96 -0
- package/src/core/transport/agent-session.ts +1085 -0
- package/src/core/transport/agent-view.ts +738 -0
- package/src/core/transport/client-session.ts +780 -0
- package/src/core/transport/decode-fold.ts +101 -0
- package/src/core/transport/headers.ts +234 -22
- package/src/core/transport/index.ts +27 -27
- package/src/core/transport/internal/bounded-map.ts +27 -0
- package/src/core/transport/invocation.ts +98 -0
- package/src/core/transport/load-history-pages.ts +220 -0
- package/src/core/transport/load-history.ts +271 -0
- package/src/core/transport/pipe-stream.ts +63 -39
- package/src/core/transport/run-manager.ts +243 -0
- package/src/core/transport/session-support.ts +96 -0
- package/src/core/transport/tree.ts +1293 -308
- package/src/core/transport/types/agent.ts +434 -0
- package/src/core/transport/types/client.ts +247 -0
- package/src/core/transport/types/shared.ts +27 -0
- package/src/core/transport/types/tree.ts +393 -0
- package/src/core/transport/types/view.ts +288 -0
- package/src/core/transport/types.ts +13 -706
- package/src/core/transport/view.ts +1229 -450
- package/src/core/transport/wire-log.ts +189 -0
- package/src/errors.ts +29 -9
- package/src/event-emitter.ts +3 -2
- package/src/index.ts +86 -42
- package/src/logger.ts +14 -1
- package/src/react/contexts/client-session-context.ts +41 -0
- package/src/react/contexts/client-session-provider.tsx +222 -0
- package/src/react/create-session-hooks.ts +141 -0
- package/src/react/index.ts +24 -13
- package/src/react/internal/skipped-session.ts +62 -0
- package/src/react/internal/use-resolved-session.ts +63 -0
- package/src/react/use-ably-messages.ts +32 -22
- package/src/react/use-client-session.ts +178 -0
- package/src/react/use-create-view.ts +33 -29
- package/src/react/use-tree.ts +61 -30
- package/src/react/use-view.ts +138 -96
- package/src/utils.ts +83 -131
- package/src/vercel/codec/decode-lifecycle.ts +70 -0
- package/src/vercel/codec/events.ts +85 -0
- package/src/vercel/codec/fields.ts +58 -0
- package/src/vercel/codec/fold-content.ts +54 -0
- package/src/vercel/codec/fold-data.ts +46 -0
- package/src/vercel/codec/fold-input.ts +255 -0
- package/src/vercel/codec/fold-lifecycle.ts +85 -0
- package/src/vercel/codec/fold-text.ts +55 -0
- package/src/vercel/codec/fold-tool-input.ts +86 -0
- package/src/vercel/codec/fold-tool-output.ts +79 -0
- package/src/vercel/codec/index.ts +28 -21
- package/src/vercel/codec/inputs.ts +116 -0
- package/src/vercel/codec/outputs.ts +207 -0
- package/src/vercel/codec/reducer-state.ts +169 -0
- package/src/vercel/codec/reducer.ts +191 -0
- package/src/vercel/codec/tool-transitions.ts +3 -14
- package/src/vercel/codec/wire-data.ts +64 -0
- package/src/vercel/index.ts +7 -19
- package/src/vercel/react/contexts/chat-transport-context.ts +8 -7
- package/src/vercel/react/contexts/chat-transport-provider.tsx +87 -59
- package/src/vercel/react/index.ts +3 -5
- package/src/vercel/react/use-chat-transport.ts +44 -66
- package/src/vercel/react/use-message-sync.ts +75 -39
- package/src/vercel/run-end-reason.ts +157 -0
- package/src/vercel/tool-part.ts +25 -0
- package/src/vercel/transport/chat-transport.ts +380 -98
- package/src/vercel/transport/index.ts +38 -37
- package/src/vercel/transport/run-output-stream.ts +169 -0
- package/src/version.ts +2 -0
- package/dist/core/transport/client-transport.d.ts +0 -10
- package/dist/core/transport/decode-history.d.ts +0 -43
- package/dist/core/transport/server-transport.d.ts +0 -7
- package/dist/core/transport/stream-router.d.ts +0 -29
- package/dist/core/transport/turn-manager.d.ts +0 -37
- package/dist/react/contexts/transport-context.d.ts +0 -31
- package/dist/react/contexts/transport-provider.d.ts +0 -49
- package/dist/react/create-transport-hooks.d.ts +0 -124
- package/dist/react/use-active-turns.d.ts +0 -12
- package/dist/react/use-client-transport.d.ts +0 -80
- package/dist/vercel/codec/accumulator.d.ts +0 -21
- package/dist/vercel/codec/decoder.d.ts +0 -22
- package/dist/vercel/codec/encoder.d.ts +0 -41
- package/dist/vercel/react/use-staged-add-tool-approval-response.d.ts +0 -30
- package/dist/vercel/tool-approvals.d.ts +0 -124
- package/dist/vercel/tool-events.d.ts +0 -26
- package/src/core/transport/client-transport.ts +0 -977
- package/src/core/transport/decode-history.ts +0 -485
- package/src/core/transport/server-transport.ts +0 -612
- package/src/core/transport/stream-router.ts +0 -136
- package/src/core/transport/turn-manager.ts +0 -165
- package/src/react/contexts/transport-context.ts +0 -37
- package/src/react/contexts/transport-provider.tsx +0 -164
- package/src/react/create-transport-hooks.ts +0 -144
- package/src/react/use-active-turns.ts +0 -72
- package/src/react/use-client-transport.ts +0 -197
- package/src/vercel/codec/accumulator.ts +0 -588
- package/src/vercel/codec/decoder.ts +0 -618
- package/src/vercel/codec/encoder.ts +0 -410
- package/src/vercel/react/use-staged-add-tool-approval-response.ts +0 -87
- package/src/vercel/tool-approvals.ts +0 -380
- package/src/vercel/tool-events.ts +0 -53
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useActiveTurns: reactive view of active turns on the channel,
|
|
3
|
-
* keyed by clientId.
|
|
4
|
-
*
|
|
5
|
-
* Subscribes to transport tree turn lifecycle events and maintains a
|
|
6
|
-
* Map<clientId, Set<turnId>> that updates on every turn start/end.
|
|
7
|
-
*
|
|
8
|
-
* Uses tree (not view) so that all turns are tracked — including remote
|
|
9
|
-
* turns whose messages haven't arrived yet.
|
|
10
|
-
*
|
|
11
|
-
* Generic — works with any codec, not tied to Vercel types.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { useContext, useEffect, useState } from 'react';
|
|
15
|
-
|
|
16
|
-
import { EVENT_TURN_START } from '../constants.js';
|
|
17
|
-
import type { ClientTransport, TurnLifecycleEvent } from '../core/transport/types.js';
|
|
18
|
-
import { NearestTransportContext } from './contexts/transport-context.js';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Returns a reactive Map of all active turns on the channel, keyed by clientId.
|
|
22
|
-
* Updates when turns start or end. When `transport` is omitted, uses the nearest
|
|
23
|
-
* {@link TransportProvider}'s transport via context.
|
|
24
|
-
* @param props - Options including optional `transport`.
|
|
25
|
-
* @param props.transport - Transport to track turns for; defaults to the nearest provider.
|
|
26
|
-
* @returns A Map where keys are clientIds and values are Sets of active turnIds.
|
|
27
|
-
*/
|
|
28
|
-
export const useActiveTurns = <TEvent, TMessage>({
|
|
29
|
-
transport,
|
|
30
|
-
}: { transport?: ClientTransport<TEvent, TMessage> | null } = {}): Map<string, Set<string>> => {
|
|
31
|
-
const nearestSlot = useContext(NearestTransportContext);
|
|
32
|
-
// CAST: NearestTransportContext stores transport with erased generics; types fixed at call site.
|
|
33
|
-
const resolved = (transport ?? nearestSlot?.transport) as ClientTransport<TEvent, TMessage> | undefined;
|
|
34
|
-
|
|
35
|
-
const [turns, setTurns] = useState<Map<string, Set<string>>>(() => new Map());
|
|
36
|
-
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (!resolved) return;
|
|
39
|
-
|
|
40
|
-
// Initialize from current state
|
|
41
|
-
setTurns(resolved.tree.getActiveTurnIds());
|
|
42
|
-
|
|
43
|
-
const unsubscribe = resolved.tree.on('turn', (event: TurnLifecycleEvent) => {
|
|
44
|
-
setTurns((prev) => {
|
|
45
|
-
const next = new Map(prev);
|
|
46
|
-
|
|
47
|
-
if (event.type === EVENT_TURN_START) {
|
|
48
|
-
const set = new Set(next.get(event.clientId));
|
|
49
|
-
set.add(event.turnId);
|
|
50
|
-
next.set(event.clientId, set);
|
|
51
|
-
} else {
|
|
52
|
-
const existing = next.get(event.clientId);
|
|
53
|
-
if (existing) {
|
|
54
|
-
const updated = new Set(existing);
|
|
55
|
-
updated.delete(event.turnId);
|
|
56
|
-
if (updated.size === 0) {
|
|
57
|
-
next.delete(event.clientId);
|
|
58
|
-
} else {
|
|
59
|
-
next.set(event.clientId, updated);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return next;
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
return unsubscribe;
|
|
69
|
-
}, [resolved]);
|
|
70
|
-
|
|
71
|
-
return turns;
|
|
72
|
-
};
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useClientTransport — read a ClientTransport from the nearest TransportProvider.
|
|
3
|
-
*
|
|
4
|
-
* The transport is created by {@link TransportProvider}, which also wraps the subtree
|
|
5
|
-
* with Ably's `ChannelProvider`. This hook is a thin context reader — it does not
|
|
6
|
-
* create or manage transport state.
|
|
7
|
-
*
|
|
8
|
-
* **Provider lookup**
|
|
9
|
-
* - Omit `channelName` to use the innermost `TransportProvider` in the tree.
|
|
10
|
-
* - Pass `channelName` to look up a specific provider by name.
|
|
11
|
-
* - Pass `skip: true` to receive a stub transport that throws on any access —
|
|
12
|
-
* safe to hold in state before auth or other conditions are ready.
|
|
13
|
-
*
|
|
14
|
-
* **Error handling**
|
|
15
|
-
* - When no matching provider is found, or when the provider's `createClientTransport`
|
|
16
|
-
* call threw, `transportError` is set on the returned object instead of throwing.
|
|
17
|
-
* The component can render an error state without an error boundary.
|
|
18
|
-
* - Pass `onError` to receive post-construction transport errors (e.g. send failures,
|
|
19
|
-
* channel continuity loss) without wiring `transport.on('error', ...)` manually.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import * as Ably from 'ably';
|
|
23
|
-
import { useContext, useEffect, useRef } from 'react';
|
|
24
|
-
|
|
25
|
-
import type { ClientTransport, Tree, View } from '../core/transport/types.js';
|
|
26
|
-
import { ErrorCode } from '../errors.js';
|
|
27
|
-
import { NearestTransportContext, TransportContext } from './contexts/transport-context.js';
|
|
28
|
-
|
|
29
|
-
const SKIPPED_TRANSPORT: ClientTransport<unknown, unknown> = {
|
|
30
|
-
get tree(): Tree<unknown> {
|
|
31
|
-
throw new Ably.ErrorInfo('unable to access tree; hook is skipped', ErrorCode.InvalidArgument, 400);
|
|
32
|
-
},
|
|
33
|
-
get view(): View<unknown, unknown> {
|
|
34
|
-
throw new Ably.ErrorInfo('unable to access view; hook is skipped', ErrorCode.InvalidArgument, 400);
|
|
35
|
-
},
|
|
36
|
-
createView: (): View<unknown, unknown> => {
|
|
37
|
-
throw new Ably.ErrorInfo('unable to create view; hook is skipped', ErrorCode.InvalidArgument, 400);
|
|
38
|
-
},
|
|
39
|
-
cancel: () => {
|
|
40
|
-
throw new Ably.ErrorInfo('unable to cancel; hook is skipped', ErrorCode.InvalidArgument, 400);
|
|
41
|
-
},
|
|
42
|
-
stageEvents: () => {
|
|
43
|
-
throw new Ably.ErrorInfo('unable to stage events; hook is skipped', ErrorCode.InvalidArgument, 400);
|
|
44
|
-
},
|
|
45
|
-
stageMessage: () => {
|
|
46
|
-
throw new Ably.ErrorInfo('unable to stage message; hook is skipped', ErrorCode.InvalidArgument, 400);
|
|
47
|
-
},
|
|
48
|
-
waitForTurn: () => {
|
|
49
|
-
throw new Ably.ErrorInfo('unable to wait for turn; hook is skipped', ErrorCode.InvalidArgument, 400);
|
|
50
|
-
},
|
|
51
|
-
on: () => {
|
|
52
|
-
throw new Ably.ErrorInfo('unable to subscribe; hook is skipped', ErrorCode.InvalidArgument, 400);
|
|
53
|
-
},
|
|
54
|
-
close: () => {
|
|
55
|
-
throw new Ably.ErrorInfo('unable to close; hook is skipped', ErrorCode.InvalidArgument, 400);
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Return value of {@link useClientTransport}.
|
|
61
|
-
*
|
|
62
|
-
* `transport` is always a valid object. When `skip` is `true`, when no provider was
|
|
63
|
-
* found, or when the provider's transport construction failed, `transport` is a stub
|
|
64
|
-
* that throws {@link Ably.ErrorInfo} on every access.
|
|
65
|
-
* Check `transportError` before using `transport` to avoid those throws.
|
|
66
|
-
*/
|
|
67
|
-
export interface ClientTransportHandle<TEvent, TMessage> {
|
|
68
|
-
/**
|
|
69
|
-
* The resolved transport.
|
|
70
|
-
*
|
|
71
|
-
* A throwing stub when `skip` is `true`, when no matching {@link TransportProvider}
|
|
72
|
-
* was found in the tree, or when transport construction failed.
|
|
73
|
-
*/
|
|
74
|
-
transport: ClientTransport<TEvent, TMessage>;
|
|
75
|
-
/**
|
|
76
|
-
* Set when no matching {@link TransportProvider} was found, when transport
|
|
77
|
-
* construction failed, and `skip` is `false`.
|
|
78
|
-
* `undefined` when the transport resolved successfully or when `skip` is `true`.
|
|
79
|
-
*/
|
|
80
|
-
transportError?: Ably.ErrorInfo | undefined;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Read a {@link ClientTransport} from the nearest {@link TransportProvider}.
|
|
85
|
-
*
|
|
86
|
-
* Returns `{ transport, transportError }`. When no provider is found or transport
|
|
87
|
-
* construction failed, `transportError` is set and `transport` is a stub that throws
|
|
88
|
-
* on access — the hook never throws during render.
|
|
89
|
-
*
|
|
90
|
-
* Pass `onError` to subscribe to post-construction transport errors
|
|
91
|
-
* (e.g. {@link ErrorCode.TransportSendFailed}, {@link ErrorCode.ChannelContinuityLost})
|
|
92
|
-
* without calling `transport.on('error', …)` manually. The subscription is
|
|
93
|
-
* created when the transport resolves and removed on unmount.
|
|
94
|
-
* @param props - Hook options.
|
|
95
|
-
* @param props.channelName - Look up a specific provider by channel name; omit for the nearest.
|
|
96
|
-
* @param props.skip - When `true`, return the stub transport immediately without reading context.
|
|
97
|
-
* @param props.onError - Called whenever the resolved transport emits an error event.
|
|
98
|
-
* @returns `{ transport, transportError }`.
|
|
99
|
-
*/
|
|
100
|
-
export const useClientTransport = <TEvent, TMessage>({
|
|
101
|
-
channelName,
|
|
102
|
-
skip,
|
|
103
|
-
onError,
|
|
104
|
-
}: {
|
|
105
|
-
/**
|
|
106
|
-
* Channel name passed to the enclosing {@link TransportProvider}.
|
|
107
|
-
* Omit to use the nearest provider in the tree.
|
|
108
|
-
*/
|
|
109
|
-
channelName?: string;
|
|
110
|
-
/**
|
|
111
|
-
* When `true`, skip context lookup and return a stub transport that throws on
|
|
112
|
-
* any access. Use when a condition (auth, feature flag) is not yet resolved.
|
|
113
|
-
*/
|
|
114
|
-
skip?: boolean;
|
|
115
|
-
/**
|
|
116
|
-
* Called whenever the resolved transport emits an error event.
|
|
117
|
-
* The subscription is established once the transport resolves and
|
|
118
|
-
* automatically removed on unmount or when the transport changes.
|
|
119
|
-
*/
|
|
120
|
-
onError?: (error: Ably.ErrorInfo) => void;
|
|
121
|
-
} = {}): ClientTransportHandle<TEvent, TMessage> => {
|
|
122
|
-
const registry = useContext(TransportContext);
|
|
123
|
-
const nearestSlot = useContext(NearestTransportContext);
|
|
124
|
-
const errorCallbackRef = useRef(onError);
|
|
125
|
-
errorCallbackRef.current = onError;
|
|
126
|
-
|
|
127
|
-
// Compute the transport for the onError subscription *before* any conditional
|
|
128
|
-
// returns to satisfy React's rules of hooks (no hooks in branches).
|
|
129
|
-
// Erased generics — this ref is only used in the useEffect below.
|
|
130
|
-
const resolvedForEffect: ClientTransport<unknown, unknown> | undefined = skip
|
|
131
|
-
? undefined
|
|
132
|
-
: channelName === undefined
|
|
133
|
-
? nearestSlot?.transport
|
|
134
|
-
: registry[channelName]?.transport;
|
|
135
|
-
|
|
136
|
-
useEffect(() => {
|
|
137
|
-
if (!resolvedForEffect) return;
|
|
138
|
-
return resolvedForEffect.on('error', (errorInfo) => {
|
|
139
|
-
errorCallbackRef.current?.(errorInfo);
|
|
140
|
-
});
|
|
141
|
-
}, [resolvedForEffect]);
|
|
142
|
-
|
|
143
|
-
if (skip) {
|
|
144
|
-
return {
|
|
145
|
-
transport: SKIPPED_TRANSPORT as unknown as ClientTransport<TEvent, TMessage>,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (channelName !== undefined) {
|
|
150
|
-
const slot = registry[channelName];
|
|
151
|
-
if (slot) {
|
|
152
|
-
if (slot.transport) {
|
|
153
|
-
// CAST: TransportContext stores transports with erased generics.
|
|
154
|
-
// The caller is responsible for using type parameters matching those of the TransportProvider.
|
|
155
|
-
return {
|
|
156
|
-
transport: slot.transport as unknown as ClientTransport<TEvent, TMessage>,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
// Provider exists but construction failed.
|
|
160
|
-
return {
|
|
161
|
-
transport: SKIPPED_TRANSPORT as unknown as ClientTransport<TEvent, TMessage>,
|
|
162
|
-
transportError: slot.error,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
return {
|
|
166
|
-
transport: SKIPPED_TRANSPORT as unknown as ClientTransport<TEvent, TMessage>,
|
|
167
|
-
transportError: new Ably.ErrorInfo(
|
|
168
|
-
`unable to use transport; no TransportProvider found for channelName "${channelName}"`,
|
|
169
|
-
ErrorCode.BadRequest,
|
|
170
|
-
400,
|
|
171
|
-
),
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (nearestSlot) {
|
|
176
|
-
if (nearestSlot.transport) {
|
|
177
|
-
// CAST: NearestTransportContext stores transport with erased generics; types fixed at call site.
|
|
178
|
-
return {
|
|
179
|
-
transport: nearestSlot.transport as unknown as ClientTransport<TEvent, TMessage>,
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
// Nearest provider exists but construction failed.
|
|
183
|
-
return {
|
|
184
|
-
transport: SKIPPED_TRANSPORT as unknown as ClientTransport<TEvent, TMessage>,
|
|
185
|
-
transportError: nearestSlot.error,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return {
|
|
190
|
-
transport: SKIPPED_TRANSPORT as unknown as ClientTransport<TEvent, TMessage>,
|
|
191
|
-
transportError: new Ably.ErrorInfo(
|
|
192
|
-
'unable to use transport; no TransportProvider found in the tree',
|
|
193
|
-
ErrorCode.BadRequest,
|
|
194
|
-
400,
|
|
195
|
-
),
|
|
196
|
-
};
|
|
197
|
-
};
|