@salesforce/sf-embedding-bridge 2.2.2 → 2.2.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/dist/bootstrap-session.d.ts +44 -11
- package/dist/index.cjs.js +546 -38
- package/dist/index.d.ts +666 -13
- package/dist/index.esm.js +521 -34
- package/package.json +10 -3
- package/dist/bootstrap-envelope.d.ts.map +0 -1
- package/dist/bootstrap-listener.d.ts.map +0 -1
- package/dist/bootstrap-session.d.ts.map +0 -1
- package/dist/embedding-info.d.ts.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/host-meta-data.d.ts.map +0 -1
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.esm.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,199 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/** Wire identifier for this protocol. Carried verbatim on every bootstrap envelope. */
|
|
2
|
+
declare const PROTOCOL_NAME: "sf-embedding";
|
|
3
|
+
/** Discriminator for the host → embedding bootstrap envelope. */
|
|
4
|
+
declare const BOOTSTRAP_ENVELOPE_TYPE: "sf-embedding.bootstrap";
|
|
5
|
+
/** Discriminator for the embedding → host content-free heartbeat. */
|
|
6
|
+
declare const HEARTBEAT_TYPE: "sf-embedding/ready";
|
|
7
|
+
/**
|
|
8
|
+
* Discriminator for the embedding → host fail-closed shutdown signal
|
|
9
|
+
* (e.g., duplicate-transfer detection). Posted via window-level postMessage,
|
|
10
|
+
* not over the JSON-RPC port.
|
|
11
|
+
*/
|
|
12
|
+
declare const SHUTDOWN_TYPE: "sf-embedding/shutdown";
|
|
13
|
+
/** Bootstrap envelope the host transfers to the embedding alongside `port1`. */
|
|
14
|
+
interface BootstrapEnvelope {
|
|
15
|
+
type: typeof BOOTSTRAP_ENVELOPE_TYPE;
|
|
16
|
+
protocol: typeof PROTOCOL_NAME;
|
|
17
|
+
/** Host-minted; byte-for-byte identical to `hostMetaData.instanceId` (MC-10). */
|
|
18
|
+
instanceId: string;
|
|
19
|
+
/** Origins the host expects its wrapper chrome to load on; embedding reverse-checks. */
|
|
20
|
+
allowedOrigins: string[];
|
|
21
|
+
}
|
|
22
|
+
/** Heartbeat the embedding posts to `window.parent` before the port is transferred. */
|
|
23
|
+
interface HeartbeatEnvelope {
|
|
24
|
+
type: typeof HEARTBEAT_TYPE;
|
|
25
|
+
/** Mirrors the URL-supplied `hostMetaData.instanceId`; binds the heartbeat to this iframe instance. */
|
|
26
|
+
instanceId: string;
|
|
27
|
+
/** SemVer protocol version the bridge speaks; host validates against its supported set. */
|
|
28
|
+
protocolVersion: string;
|
|
29
|
+
}
|
|
30
|
+
/** Embedding-initiated fail-closed shutdown payload (sibling-race detected, etc.). */
|
|
31
|
+
interface ShutdownEnvelope {
|
|
32
|
+
type: typeof SHUTDOWN_TYPE;
|
|
33
|
+
/** Free-form; common values: `"DUPLICATE_PORT_TRANSFER"`. */
|
|
34
|
+
reason?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** sf-embedding protocol-specific error codes (§8.2 numeric assignments). */
|
|
38
|
+
declare const SfEmbeddingErrorCode: {
|
|
39
|
+
/** Method exists at selected version but is not granted (§6.5). */
|
|
40
|
+
readonly CAPABILITY_NOT_ALLOWED: -32010;
|
|
41
|
+
/** In-flight request gated on a capability that was just revoked (§6.6). */
|
|
42
|
+
readonly CAPABILITY_REVOKED: -32011;
|
|
43
|
+
/** Frame arrived before the required handshake step completed (§5.2, §4.2). */
|
|
44
|
+
readonly NOT_INITIALIZED: -32012;
|
|
45
|
+
/** Embedding's protocol version is not supported by the host (§4.2, §3.1.2). */
|
|
46
|
+
readonly PROTOCOL_VERSION_MISMATCH: -32013;
|
|
47
|
+
/** Frame's origin does not match the bound peer origin (§3.1). */
|
|
48
|
+
readonly ORIGIN_MISMATCH: -32014;
|
|
49
|
+
/** Catch-all — duplicate ui/select-version, duplicate ui/discover-capabilities, etc. */
|
|
50
|
+
readonly PROTOCOL_VIOLATION: -32020;
|
|
51
|
+
/** Embedding observed a second valid bootstrap envelope and shut down (§3.1.2). */
|
|
52
|
+
readonly BOOTSTRAP_DUPLICATE_TRANSFER: -32023;
|
|
53
|
+
};
|
|
54
|
+
/** Numeric type of any value in `SfEmbeddingErrorCode`. */
|
|
55
|
+
type SfEmbeddingErrorCodeValue = (typeof SfEmbeddingErrorCode)[keyof typeof SfEmbeddingErrorCode];
|
|
56
|
+
/**
|
|
57
|
+
* Codes that are non-retryable by default (§8.4). Consumers building error
|
|
58
|
+
* payloads SHOULD set `retryable: false` automatically for these.
|
|
59
|
+
*/
|
|
60
|
+
declare const NON_RETRYABLE_CODES: ReadonlySet<number>;
|
|
61
|
+
|
|
62
|
+
declare const EVENTS_DISPATCH_METHOD: "ui/events/dispatch";
|
|
63
|
+
declare const EVENTS_SUBSCRIBE_METHOD: "ui/events/subscribe";
|
|
64
|
+
declare const EVENTS_UNSUBSCRIBE_METHOD: "ui/events/unsubscribe";
|
|
65
|
+
interface EventsDispatchParams {
|
|
66
|
+
eventType: string;
|
|
67
|
+
detail: unknown;
|
|
68
|
+
/** Whether the dispatched DOM event bubbles. Default: true. */
|
|
69
|
+
bubbles?: boolean;
|
|
70
|
+
/** Whether the dispatched DOM event crosses shadow-DOM boundaries. Default: true. */
|
|
71
|
+
composed?: boolean;
|
|
72
|
+
/** Whether the dispatched DOM event is cancelable via `preventDefault()`. Default: false. */
|
|
73
|
+
cancelable?: boolean;
|
|
74
|
+
}
|
|
75
|
+
interface EventsSubscribeParams {
|
|
76
|
+
}
|
|
77
|
+
interface EventsSubscribeResult {
|
|
78
|
+
subscriptionId: string;
|
|
79
|
+
}
|
|
80
|
+
interface EventsUnsubscribeParams {
|
|
81
|
+
subscriptionId: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Event names the host LWC dispatches on its own element. Reserved by the protocol. */
|
|
85
|
+
declare const HostLwcEvent: {
|
|
86
|
+
/** Synchronous with `ui/discover-capabilities` response; session reaches READY. */
|
|
87
|
+
readonly READY: "sf-embedding.component.ready";
|
|
88
|
+
/** Misconfiguration, bootstrap failure, embedding-reported fatal, or protocol violation. */
|
|
89
|
+
readonly ERROR: "sf-embedding.component.error";
|
|
90
|
+
};
|
|
91
|
+
/** Type-level union of the reserved event names. */
|
|
92
|
+
type HostLwcEventName = (typeof HostLwcEvent)[keyof typeof HostLwcEvent];
|
|
93
|
+
/** Detail of `sf-embedding.component.ready`. */
|
|
94
|
+
interface HostReadyEventDetail {
|
|
95
|
+
instanceId: string;
|
|
96
|
+
}
|
|
97
|
+
/** Detail of `sf-embedding.component.error` (§12.3). */
|
|
98
|
+
interface HostErrorEventDetail {
|
|
99
|
+
instanceId?: string;
|
|
100
|
+
/** Failure category — drives consumer reaction. */
|
|
101
|
+
phase: "configuration" | "bootstrap" | "session";
|
|
102
|
+
/** ErrorCode constant or a configuration-error string (e.g. `"SAME_ORIGIN_SRC"`). */
|
|
103
|
+
code: string;
|
|
104
|
+
message: string;
|
|
105
|
+
/**
|
|
106
|
+
* Whether remount is plausibly fruitful (per spec §12.3).
|
|
107
|
+
* `true` — transient failures where a fresh attempt may succeed: bootstrap
|
|
108
|
+
* handshake timeout, embedding-reported runtime error.
|
|
109
|
+
* `false` — fix the underlying problem first: configuration errors
|
|
110
|
+
* (same-origin src, allow-scripts stripped, malformed src) and protocol
|
|
111
|
+
* violations (duplicate port transfer).
|
|
112
|
+
*/
|
|
113
|
+
retryable: boolean;
|
|
114
|
+
cause?: unknown;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** URL query-parameter name carrying the JSON-encoded `HostMetaData`. */
|
|
118
|
+
declare const HOST_META_DATA_PARAM: "hostMetaData";
|
|
119
|
+
/**
|
|
120
|
+
* Shape of the JSON-encoded `hostMetaData` query parameter on the iframe URL.
|
|
121
|
+
*
|
|
122
|
+
* The host MUST write this onto `iframe.src` when assigning it; the embedding
|
|
123
|
+
* MUST read it before emitting the heartbeat. `hostAppOrigin` is the trust
|
|
124
|
+
* root for the embedding's inbound bootstrap envelope (MC-8). `instanceId`
|
|
125
|
+
* binds the inbound bootstrap envelope to this iframe instance (MC-10).
|
|
126
|
+
*/
|
|
127
|
+
interface HostMetaData {
|
|
128
|
+
hostAppOrigin: string;
|
|
129
|
+
instanceId: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Throw from a request handler to surface a specific JSON-RPC error code. */
|
|
133
|
+
declare class JsonRpcHandlerError extends Error {
|
|
134
|
+
readonly code: number;
|
|
135
|
+
constructor(code: number, message: string);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Host announces session identity to the embedding over the port. */
|
|
139
|
+
declare const HOST_INITIALIZED_METHOD: "ui/notifications/host-initialized";
|
|
140
|
+
/** Embedding acknowledges receipt of `host-initialized`. Fire-and-forget. */
|
|
141
|
+
declare const EMBEDDING_INITIALIZED_METHOD: "ui/notifications/embedding-initialized";
|
|
142
|
+
/** Identity of the host or embedding product. */
|
|
143
|
+
interface PeerInfo {
|
|
144
|
+
name: string;
|
|
145
|
+
version: string;
|
|
146
|
+
}
|
|
147
|
+
/** Params for `ui/notifications/host-initialized`. */
|
|
148
|
+
interface HostInitializedParams {
|
|
149
|
+
instanceId: string;
|
|
150
|
+
hostInfo: PeerInfo;
|
|
151
|
+
}
|
|
152
|
+
/** Params for `ui/notifications/embedding-initialized`. */
|
|
153
|
+
interface EmbeddingInitializedParams {
|
|
154
|
+
embeddingInfo: PeerInfo;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
declare const RESIZE_METHOD: "ui/notifications/resize";
|
|
158
|
+
interface ResizeParams {
|
|
159
|
+
width?: number;
|
|
160
|
+
height: number;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
declare const UI_STATE_SUBSCRIBE_METHOD: "ui/subscribe/ui-state";
|
|
164
|
+
declare const UI_STATE_UNSUBSCRIBE_METHOD: "ui/unsubscribe/ui-state";
|
|
165
|
+
declare const UI_STATE_CHANGED_METHOD: "ui/notifications/ui-state-changed";
|
|
166
|
+
/** Styling hints the host wants the embedding to mirror. */
|
|
167
|
+
interface HostStyles {
|
|
168
|
+
/** CSS custom properties (`--*`) read from the host element's inline style. */
|
|
169
|
+
variables?: Record<string, string>;
|
|
170
|
+
/** Mirrored a11y/i18n/input attributes from the host LWC element. */
|
|
171
|
+
attributes?: Record<string, string>;
|
|
172
|
+
}
|
|
173
|
+
/** Host → embedding rendering snapshot. */
|
|
174
|
+
interface UiState {
|
|
175
|
+
props: Record<string, unknown>;
|
|
176
|
+
styles: HostStyles;
|
|
177
|
+
theme: string;
|
|
178
|
+
locale: {
|
|
179
|
+
tag: string;
|
|
180
|
+
dir: "ltr" | "rtl";
|
|
181
|
+
};
|
|
182
|
+
formFactor: "Small" | "Medium" | "Large";
|
|
183
|
+
}
|
|
184
|
+
interface UiStateSubscribeParams {
|
|
185
|
+
}
|
|
186
|
+
interface UiStateSubscribeResult {
|
|
187
|
+
subscriptionId: string;
|
|
188
|
+
current: UiState;
|
|
189
|
+
}
|
|
190
|
+
interface UiStateUnsubscribeParams {
|
|
191
|
+
subscriptionId: string;
|
|
192
|
+
}
|
|
193
|
+
interface UiStateChangedParams {
|
|
194
|
+
subscriptionId: string;
|
|
195
|
+
current: UiState;
|
|
196
|
+
}
|
|
3
197
|
|
|
4
198
|
type BootstrapEnvelopeValidationFailure = "INVALID_SHAPE" | "WRONG_SOURCE" | "ORIGIN_NOT_ALLOWED" | "WRONG_PORT_COUNT" | "INSTANCE_ID_MISMATCH" | "DUPLICATE_TRANSFER";
|
|
5
199
|
type BootstrapEnvelopeValidationResult = {
|
|
@@ -31,9 +225,436 @@ declare class BootstrapFailureError extends Error {
|
|
|
31
225
|
constructor(reason: BootstrapFailureReason);
|
|
32
226
|
}
|
|
33
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
230
|
+
* All rights reserved.
|
|
231
|
+
* For full license text, see the LICENSE.txt file
|
|
232
|
+
*/
|
|
233
|
+
/**
|
|
234
|
+
* JSON-RPC 2.0 Protocol Types
|
|
235
|
+
*
|
|
236
|
+
* This module provides TypeScript types and runtime guards for implementing
|
|
237
|
+
* JSON-RPC 2.0 as specified in https://www.jsonrpc.org/specification.
|
|
238
|
+
*
|
|
239
|
+
* JSON-RPC 2.0 is a stateless, light-weight remote procedure call (RPC)
|
|
240
|
+
* protocol. Used for cross-realm communication via postMessage in iframe-
|
|
241
|
+
* embedded surfaces (MCP Apps, sf-embedding, and any future surface that
|
|
242
|
+
* speaks the same wire format).
|
|
243
|
+
*
|
|
244
|
+
* Protocol extension: this module relaxes JSON-RPC 2.0's "no other
|
|
245
|
+
* members" rule for one optional `_meta` field on every envelope. The
|
|
246
|
+
* underscore signals "protocol-meta, not method semantics." `_meta`
|
|
247
|
+
* carries fields applying to every method uniformly (currently `traceId`);
|
|
248
|
+
* method-specific data lives in `params` / `result` / `error`.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* // Creating a request
|
|
252
|
+
* const request: JsonRpcRequest = {
|
|
253
|
+
* jsonrpc: "2.0",
|
|
254
|
+
* id: 1,
|
|
255
|
+
* method: "ui/message",
|
|
256
|
+
* params: { role: "user", content: { type: "text", text: "Hello" } }
|
|
257
|
+
* };
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* // Validating a response
|
|
261
|
+
* window.addEventListener("message", (event) => {
|
|
262
|
+
* if (isJsonRpcResponse(event.data)) {
|
|
263
|
+
* if (isJsonRpcErrorResponse(event.data)) {
|
|
264
|
+
* console.error("Error:", event.data.error.message);
|
|
265
|
+
* } else {
|
|
266
|
+
* console.log("Result:", event.data.result);
|
|
267
|
+
* }
|
|
268
|
+
* }
|
|
269
|
+
* });
|
|
270
|
+
*/
|
|
271
|
+
/**
|
|
272
|
+
* Protocol-meta envelope. Future minors may add fields additively; old peers
|
|
273
|
+
* ignore unknown fields per the standard JSON-RPC forward-compat behavior.
|
|
274
|
+
*/
|
|
275
|
+
interface JsonRpcMeta {
|
|
276
|
+
/** Per-request trace identifier for cross-realm log correlation. */
|
|
277
|
+
traceId?: string;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* JSON-RPC 2.0 base message with the required version field and the
|
|
281
|
+
* optional `_meta` extension.
|
|
282
|
+
*/
|
|
283
|
+
interface JsonRpcBase {
|
|
284
|
+
jsonrpc: "2.0";
|
|
285
|
+
_meta?: JsonRpcMeta;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* JSON-RPC 2.0 Request — has both `id` and `method`.
|
|
289
|
+
*/
|
|
290
|
+
interface JsonRpcRequest<TParams = unknown> extends JsonRpcBase {
|
|
291
|
+
id: number;
|
|
292
|
+
method: string;
|
|
293
|
+
params?: TParams;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* JSON-RPC 2.0 Notification — has `method` but NO `id`. Fire-and-forget.
|
|
297
|
+
*/
|
|
298
|
+
interface JsonRpcNotification<TParams = unknown> extends JsonRpcBase {
|
|
299
|
+
method: string;
|
|
300
|
+
params?: TParams;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* JSON-RPC 2.0 Success Response — has `id` and `result`.
|
|
304
|
+
*/
|
|
305
|
+
interface JsonRpcSuccessResponse<TResult = unknown> extends JsonRpcBase {
|
|
306
|
+
id: number;
|
|
307
|
+
result: TResult;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* JSON-RPC 2.0 Error payload (carried under `error` on an error response).
|
|
311
|
+
*/
|
|
312
|
+
interface JsonRpcError {
|
|
313
|
+
code: number;
|
|
314
|
+
message?: string;
|
|
315
|
+
data?: unknown;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* JSON-RPC 2.0 Error Response — has `id` and `error`.
|
|
319
|
+
*/
|
|
320
|
+
interface JsonRpcErrorResponse extends JsonRpcBase {
|
|
321
|
+
id: number;
|
|
322
|
+
error: JsonRpcError;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Either flavor of response.
|
|
326
|
+
*/
|
|
327
|
+
type JsonRpcResponse<TResult = unknown> = JsonRpcSuccessResponse<TResult> | JsonRpcErrorResponse;
|
|
328
|
+
/**
|
|
329
|
+
* Any JSON-RPC frame the dispatcher might receive.
|
|
330
|
+
*/
|
|
331
|
+
type JsonRpcFrame = JsonRpcRequest | JsonRpcNotification | JsonRpcResponse;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
335
|
+
* All rights reserved.
|
|
336
|
+
* For full license text, see the LICENSE.txt file
|
|
337
|
+
*/
|
|
338
|
+
/**
|
|
339
|
+
* Abstract transport for a JSON-RPC 2.0 client.
|
|
340
|
+
*
|
|
341
|
+
* A `Transport` is a bidirectional, structured-message pipe. The
|
|
342
|
+
* `JsonRpcClient` uses it to send JSON-RPC messages (`post`) and subscribe
|
|
343
|
+
* to inbound ones (`onMessage`). The transport itself is agnostic to the
|
|
344
|
+
* JSON-RPC framing — it simply moves `unknown` payloads between two
|
|
345
|
+
* endpoints.
|
|
346
|
+
*
|
|
347
|
+
* Concrete transports plug into the same shape:
|
|
348
|
+
* - `WindowPostMessageTransport` (window.parent.postMessage; used by
|
|
349
|
+
* MCP Apps)
|
|
350
|
+
* - `MessageChannelTransport` (a transferred `MessagePort`; used by
|
|
351
|
+
* sf-embedding and any future surface that bootstraps with a
|
|
352
|
+
* dedicated channel)
|
|
353
|
+
*/
|
|
354
|
+
interface Transport {
|
|
355
|
+
/**
|
|
356
|
+
* Deliver a single structured message to the peer. Implementations MUST
|
|
357
|
+
* NOT throw on transient conditions (closed port, missing parent
|
|
358
|
+
* window, etc.) — drop the message silently instead, matching the
|
|
359
|
+
* prior `window.parent?.postMessage` behaviour.
|
|
360
|
+
*/
|
|
361
|
+
post(message: unknown): void;
|
|
362
|
+
/**
|
|
363
|
+
* Subscribe to inbound structured messages from the peer. The callback
|
|
364
|
+
* receives the already-unwrapped message payload (never a
|
|
365
|
+
* `MessageEvent`).
|
|
366
|
+
*
|
|
367
|
+
* @returns an unsubscribe function that removes this listener.
|
|
368
|
+
*/
|
|
369
|
+
onMessage(callback: (message: unknown) => void): () => void;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Base class for JSON-RPC 2.0 clients.
|
|
374
|
+
*
|
|
375
|
+
* This class provides core JSON-RPC client functionality for any cross-realm
|
|
376
|
+
* surface that speaks JSON-RPC 2.0 (MCP Apps, sf-embedding, future
|
|
377
|
+
* surfaces). It handles request/response correlation, message validation,
|
|
378
|
+
* and notification dispatch.
|
|
379
|
+
*
|
|
380
|
+
* The transport layer is pluggable via the `Transport` interface and is
|
|
381
|
+
* REQUIRED at construction. There is no default transport — wildcard-targeted
|
|
382
|
+
* `window.postMessage` is structurally unsafe, so callers must construct a
|
|
383
|
+
* transport with an explicit origin (`WindowPostMessageTransport`) or a
|
|
384
|
+
* port-bound transport (`MessageChannelTransport`).
|
|
385
|
+
*
|
|
386
|
+
* Subclasses should extend this class and use the protected `request()`
|
|
387
|
+
* method to send JSON-RPC requests to the peer.
|
|
388
|
+
*
|
|
389
|
+
* @example
|
|
390
|
+
* export class MCPAppsViewSDK extends JsonRpcClient implements ViewSDK {
|
|
391
|
+
* async displayAlert(options: AlertOptions): Promise<void> {
|
|
392
|
+
* await this.request("ui/message", {
|
|
393
|
+
* role: "user",
|
|
394
|
+
* content: { type: "text", text: options.message }
|
|
395
|
+
* });
|
|
396
|
+
* }
|
|
397
|
+
* }
|
|
398
|
+
*
|
|
399
|
+
* @example
|
|
400
|
+
* // Injecting a transport (window.parent.postMessage to a known origin).
|
|
401
|
+
* class MyClient extends JsonRpcClient {
|
|
402
|
+
* constructor(targetOrigin: string) {
|
|
403
|
+
* super(new WindowPostMessageTransport(targetOrigin));
|
|
404
|
+
* }
|
|
405
|
+
* }
|
|
406
|
+
*/
|
|
407
|
+
declare class JsonRpcClient {
|
|
408
|
+
private nextRequestId;
|
|
409
|
+
private pending;
|
|
410
|
+
private notificationHandlers;
|
|
411
|
+
private readonly transport;
|
|
412
|
+
/**
|
|
413
|
+
* Construct a JSON-RPC client bound to the given transport.
|
|
414
|
+
*
|
|
415
|
+
* @param transport - the transport to use.
|
|
416
|
+
*/
|
|
417
|
+
constructor(transport: Transport);
|
|
418
|
+
/**
|
|
419
|
+
* Register a handler for a specific JSON-RPC notification method.
|
|
420
|
+
*
|
|
421
|
+
* Subclasses can register handlers to process specific notification
|
|
422
|
+
* types. When a notification with the registered method is received,
|
|
423
|
+
* the handler will be invoked with the notification params.
|
|
424
|
+
*
|
|
425
|
+
* @param method - The notification method to handle (e.g.
|
|
426
|
+
* "ui/notifications/host-context-changed")
|
|
427
|
+
* @param handler - Callback function to process the notification params
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* this.registerNotificationHandler("ui/notifications/host-context-changed", (params) => {
|
|
431
|
+
* this.handleHostContextChanged(params);
|
|
432
|
+
* });
|
|
433
|
+
*/
|
|
434
|
+
protected registerNotificationHandler(method: string, handler: (params: unknown, meta?: JsonRpcMeta) => void): void;
|
|
435
|
+
/**
|
|
436
|
+
* Handle inbound JSON-RPC messages from the transport.
|
|
437
|
+
*
|
|
438
|
+
* Processes both responses (for requests) and notifications.
|
|
439
|
+
* Non-JSON-RPC payloads are silently ignored so that a shared transport
|
|
440
|
+
* can be used for multiple protocols without cross-talk.
|
|
441
|
+
*/
|
|
442
|
+
private onMessage;
|
|
443
|
+
/**
|
|
444
|
+
* Send a JSON-RPC request to the peer.
|
|
445
|
+
*
|
|
446
|
+
* @param method - The JSON-RPC method name
|
|
447
|
+
* @param params - The method parameters
|
|
448
|
+
* @returns Promise that resolves with the result or rejects with error
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* const result = await this.request("ui/message", {
|
|
452
|
+
* role: "user",
|
|
453
|
+
* content: { type: "text", text: "Hello" }
|
|
454
|
+
* });
|
|
455
|
+
*/
|
|
456
|
+
protected request<TParams = unknown, TResult = unknown>(method: string, params: TParams): Promise<TResult>;
|
|
457
|
+
/**
|
|
458
|
+
* Send a JSON-RPC notification to the peer.
|
|
459
|
+
*
|
|
460
|
+
* Notifications are one-way messages that do not expect a response.
|
|
461
|
+
* Use notifications for:
|
|
462
|
+
* - Informing the host of state changes
|
|
463
|
+
* - Fire-and-forget operations
|
|
464
|
+
* - Events that don't require confirmation
|
|
465
|
+
*
|
|
466
|
+
* Use request() instead when you need:
|
|
467
|
+
* - A response from the host
|
|
468
|
+
* - Confirmation of success/failure
|
|
469
|
+
* - Return values from the operation
|
|
470
|
+
*
|
|
471
|
+
* @param method - The JSON-RPC method name
|
|
472
|
+
* @param params - Optional method parameters
|
|
473
|
+
*
|
|
474
|
+
* @example
|
|
475
|
+
* this.sendNotification("ui/notifications/size-changed", {
|
|
476
|
+
* width: 800,
|
|
477
|
+
* height: 600
|
|
478
|
+
* });
|
|
479
|
+
*/
|
|
480
|
+
protected sendNotification<TParams = unknown>(method: string, params?: TParams): void;
|
|
481
|
+
/**
|
|
482
|
+
* Outbound `_meta` hook. Override to attach protocol-meta (e.g. a
|
|
483
|
+
* per-message `traceId`) to every outgoing request and notification.
|
|
484
|
+
*
|
|
485
|
+
* Default returns `undefined` so the envelope ships without `_meta`,
|
|
486
|
+
* matching JSON-RPC 2.0 baseline behavior.
|
|
487
|
+
*/
|
|
488
|
+
protected getOutboundMeta(_method: string): JsonRpcMeta | undefined;
|
|
489
|
+
/**
|
|
490
|
+
* Inbound `_meta` hook. Invoked once per validated inbound frame
|
|
491
|
+
* (response or notification) before the value is dispatched to the
|
|
492
|
+
* pending-request resolver or notification handlers.
|
|
493
|
+
*
|
|
494
|
+
* Default is a no-op. Override to feed log correlation, tracing, etc.
|
|
495
|
+
*/
|
|
496
|
+
protected onInboundMeta(_frame: JsonRpcFrame, _meta: JsonRpcMeta | undefined): void;
|
|
497
|
+
private applyOutboundMeta;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/** Structure of the `data` field on a JSON-RPC error payload. */
|
|
501
|
+
interface JsonRpcErrorData {
|
|
502
|
+
retryable?: boolean;
|
|
503
|
+
details?: Record<string, unknown>;
|
|
504
|
+
}
|
|
505
|
+
/** Shape of a JSON-RPC error payload (the value under `error` on an error response). */
|
|
506
|
+
interface JsonRpcErrorPayload {
|
|
507
|
+
code: number;
|
|
508
|
+
message?: string;
|
|
509
|
+
data?: JsonRpcErrorData;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* EmbeddingResizer - Handles dynamic iframe/container resizing
|
|
514
|
+
* Uses ResizeObserver to monitor element size changes and notify the host
|
|
515
|
+
*/
|
|
516
|
+
interface ResizeCallback {
|
|
517
|
+
(height: number): void;
|
|
518
|
+
}
|
|
519
|
+
interface EmbeddingResizerOptions {
|
|
520
|
+
/**
|
|
521
|
+
* The element to observe for size changes
|
|
522
|
+
* Defaults to document.body
|
|
523
|
+
*/
|
|
524
|
+
targetElement?: Element;
|
|
525
|
+
/**
|
|
526
|
+
* Callback function invoked when resize is detected
|
|
527
|
+
*/
|
|
528
|
+
onResize: ResizeCallback;
|
|
529
|
+
/**
|
|
530
|
+
* Callback function invoked when the resizer is ready
|
|
531
|
+
*/
|
|
532
|
+
onReady?: () => void;
|
|
533
|
+
/**
|
|
534
|
+
* Whether to wait for DOMContentLoaded before starting observation
|
|
535
|
+
* Defaults to true
|
|
536
|
+
*/
|
|
537
|
+
waitForDOMReady?: boolean;
|
|
538
|
+
}
|
|
539
|
+
declare class EmbeddingResizer {
|
|
540
|
+
#private;
|
|
541
|
+
constructor(options: EmbeddingResizerOptions);
|
|
542
|
+
/**
|
|
543
|
+
* Start observing the target element for size changes
|
|
544
|
+
*/
|
|
545
|
+
start(): void;
|
|
546
|
+
/**
|
|
547
|
+
* Stop observing and clean up resources
|
|
548
|
+
*/
|
|
549
|
+
stop(): void;
|
|
550
|
+
/**
|
|
551
|
+
* Get the current observed height
|
|
552
|
+
*/
|
|
553
|
+
getLastHeight(): number;
|
|
554
|
+
/**
|
|
555
|
+
* Check if currently observing
|
|
556
|
+
*/
|
|
557
|
+
isObserving(): boolean;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* JSON-RPC plumbing shared by both peers of the sf-embedding protocol.
|
|
562
|
+
*
|
|
563
|
+
* Two layers live here:
|
|
564
|
+
*
|
|
565
|
+
* - `BridgeClient` — the OUTBOUND half plus inbound responses/notifications.
|
|
566
|
+
* Extends the library `JsonRpcClient`, so it already correlates outbound
|
|
567
|
+
* `send()` requests with their inbound responses, dispatches inbound
|
|
568
|
+
* notifications to `onNotification` handlers, and stamps every outbound
|
|
569
|
+
* frame with a `_meta.traceId`. It owns the single `Transport`.
|
|
570
|
+
*
|
|
571
|
+
* - `JsonRpcRouter` — the INBOUND-REQUEST half. It HOLDS a `BridgeClient`
|
|
572
|
+
* and adds the one thing the client deliberately lacks: routing inbound
|
|
573
|
+
* JSON-RPC *requests* to registered handlers and replying success/error
|
|
574
|
+
* on the same transport (echoing `_meta` for tracing). Notifications,
|
|
575
|
+
* responses, and outbound traffic are delegated straight to the client —
|
|
576
|
+
* no duplicate handler tables.
|
|
577
|
+
*
|
|
578
|
+
* Request vs response/notification dispatch does not collide on the shared
|
|
579
|
+
* transport: `JsonRpcClient` ignores frames carrying both an `id` and a
|
|
580
|
+
* `method` (requests), so the router is free to claim them.
|
|
581
|
+
*
|
|
582
|
+
* Each peer subclasses `JsonRpcRouter` (see `HostBridge` /
|
|
583
|
+
* `EmbeddingBridge`): the subclass registers its inbound handlers in the
|
|
584
|
+
* constructor and exposes named methods for its outbound requests.
|
|
585
|
+
*/
|
|
586
|
+
|
|
587
|
+
/** Function signature for an inbound-request handler. */
|
|
588
|
+
type RequestHandler<TParams = unknown, TResult = unknown> = (params: TParams, meta?: JsonRpcMeta) => TResult | Promise<TResult>;
|
|
589
|
+
/** Function signature for an inbound-notification handler. */
|
|
590
|
+
type NotificationHandler<TParams = unknown> = (params: TParams, meta?: JsonRpcMeta) => void;
|
|
591
|
+
/** Disposer returned by `onRequest`. */
|
|
592
|
+
type Unregister = () => void;
|
|
593
|
+
/**
|
|
594
|
+
* Outbound + response/notification half of a JSON-RPC peer, bound to one
|
|
595
|
+
* transport. Promotes the library client's `protected` send/notify/register
|
|
596
|
+
* methods to a `public` surface the router (and its subclasses) can call, and
|
|
597
|
+
* exposes `post`/`subscribe` so the router can reply to and listen for inbound
|
|
598
|
+
* requests over the same transport.
|
|
599
|
+
*
|
|
600
|
+
* Stamps `_meta.traceId` on every outbound frame; both peers want tracing.
|
|
601
|
+
*/
|
|
602
|
+
declare class BridgeClient extends JsonRpcClient {
|
|
603
|
+
private readonly sharedTransport;
|
|
604
|
+
constructor(transport: Transport);
|
|
605
|
+
/** Send a request and await its correlated response. */
|
|
606
|
+
send<TParams = unknown, TResult = unknown>(method: string, params: TParams): Promise<TResult>;
|
|
607
|
+
/** Send a fire-and-forget notification. */
|
|
608
|
+
notify<TParams = unknown>(method: string, params?: TParams): void;
|
|
609
|
+
/** Register an inbound-notification handler. */
|
|
610
|
+
onNotification<TParams = unknown>(method: string, handler: NotificationHandler<TParams>): void;
|
|
611
|
+
/** @internal — used by JsonRpcRouter to reply to inbound requests. */
|
|
612
|
+
post(frame: unknown): void;
|
|
613
|
+
/** @internal — used by JsonRpcRouter to claim inbound requests. */
|
|
614
|
+
subscribe(callback: (data: unknown) => void): Unregister;
|
|
615
|
+
/** Tear down the underlying transport if it is disposable (e.g. MessageChannelTransport closes its port). */
|
|
616
|
+
dispose(): void;
|
|
617
|
+
/** Mints `_meta.traceId` for every outbound request and notification. */
|
|
618
|
+
protected getOutboundMeta(_method: string): JsonRpcMeta;
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Inbound-request router. Holds a `BridgeClient` for everything else
|
|
622
|
+
* (outbound requests/notifications, inbound responses, inbound notifications)
|
|
623
|
+
* and adds inbound-request routing + replies on the shared transport.
|
|
624
|
+
*
|
|
625
|
+
* Subclass it per peer: register handlers in the constructor, add named
|
|
626
|
+
* outbound methods that call `send`/`notify`.
|
|
627
|
+
*/
|
|
628
|
+
declare class JsonRpcRouter {
|
|
629
|
+
protected readonly client: BridgeClient;
|
|
630
|
+
private readonly requestHandlers;
|
|
631
|
+
private readonly log;
|
|
632
|
+
private unsubscribe;
|
|
633
|
+
constructor(client: BridgeClient, log?: (...args: unknown[]) => void);
|
|
634
|
+
/** Register a handler for an inbound request method. Returns a disposer; re-registering overwrites. */
|
|
635
|
+
onRequest<TParams = unknown, TResult = unknown>(method: string, handler: RequestHandler<TParams, TResult>): Unregister;
|
|
636
|
+
/** Register an inbound-notification handler (delegates to the client). */
|
|
637
|
+
onNotification<TParams = unknown>(method: string, handler: NotificationHandler<TParams>): void;
|
|
638
|
+
/** Send an outbound request and await its response (delegates to the client). */
|
|
639
|
+
send<TParams = unknown, TResult = unknown>(method: string, params: TParams): Promise<TResult>;
|
|
640
|
+
/** Send an outbound notification (delegates to the client). */
|
|
641
|
+
notify<TParams = unknown>(method: string, params?: TParams): void;
|
|
642
|
+
/**
|
|
643
|
+
* Tear down: drop the inbound-request subscription, clear handlers, and
|
|
644
|
+
* dispose the client's transport (closes the port). Idempotent.
|
|
645
|
+
*/
|
|
646
|
+
dispose(): void;
|
|
647
|
+
/** Route one inbound frame. Only requests are handled here; the rest is the client's. */
|
|
648
|
+
private handle;
|
|
649
|
+
private handleRequest;
|
|
650
|
+
private respondSuccess;
|
|
651
|
+
private respondError;
|
|
652
|
+
private postSafely;
|
|
653
|
+
}
|
|
654
|
+
|
|
34
655
|
type HostInitializedPayload = Record<string, unknown>;
|
|
35
656
|
interface SessionHandle {
|
|
36
|
-
|
|
657
|
+
bridge: EmbeddingBridge;
|
|
37
658
|
hostMetaData: HostMetaData;
|
|
38
659
|
hostInitialized: HostInitializedPayload;
|
|
39
660
|
}
|
|
@@ -43,18 +664,50 @@ declare class SessionFailureError extends Error {
|
|
|
43
664
|
constructor(reason: SessionFailureReason, cause?: unknown);
|
|
44
665
|
}
|
|
45
666
|
interface BootstrapSessionOptions {
|
|
46
|
-
/**
|
|
47
|
-
* Cancellation signal. The browser MessagePort API has no port-close event,
|
|
48
|
-
* so the consumer owns the deadline (e.g. AbortSignal.timeout(30_000)).
|
|
49
|
-
* Honored only on the first call; subsequent calls return the cached promise.
|
|
50
|
-
*/
|
|
667
|
+
/** Cancellation signal. Consumer owns the deadline (e.g. AbortSignal.timeout(30_000)). */
|
|
51
668
|
signal?: AbortSignal;
|
|
52
669
|
}
|
|
53
670
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
671
|
+
* Embedding-side peer. One object that routes inbound requests (via
|
|
672
|
+
* `JsonRpcRouter`), handles inbound notifications, and exposes named methods
|
|
673
|
+
* for the embedding's outbound traffic. Register inbound handlers in the
|
|
674
|
+
* constructor; add outbound methods as the protocol grows.
|
|
57
675
|
*/
|
|
676
|
+
declare class EmbeddingBridge extends JsonRpcRouter {
|
|
677
|
+
private readonly hostInitialized;
|
|
678
|
+
private resizer;
|
|
679
|
+
constructor(transport: Transport);
|
|
680
|
+
/** Await the host's `host-initialized` notification. */
|
|
681
|
+
waitForHostInitialized(): Promise<HostInitializedPayload>;
|
|
682
|
+
/** Announce that the embedding has initialized. */
|
|
683
|
+
sendInitializedNotification(): void;
|
|
684
|
+
/** Subscribe to host UI-state. Returns the initial snapshot + active subscription id. */
|
|
685
|
+
sendUiStateSubscribe(): Promise<UiStateSubscribeResult>;
|
|
686
|
+
/** Tear down an active UI-state subscription. */
|
|
687
|
+
sendUiStateUnsubscribe(subscriptionId: string): Promise<void>;
|
|
688
|
+
/** Register a handler for `ui/notifications/ui-state-changed`. */
|
|
689
|
+
onUiStateChanged(handler: (params: UiStateChangedParams, meta?: JsonRpcMeta) => void): void;
|
|
690
|
+
/** Fire-and-forget dispatch of a custom event (bidirectional `ui/events/dispatch`).
|
|
691
|
+
* `options` controls DOM-event flags on the receiving side; defaults bubble + composed = true. */
|
|
692
|
+
sendEventDispatch(eventType: string, detail: unknown, options?: {
|
|
693
|
+
bubbles?: boolean;
|
|
694
|
+
composed?: boolean;
|
|
695
|
+
cancelable?: boolean;
|
|
696
|
+
}): void;
|
|
697
|
+
/** Subscribe to host-driven events. One subscription per session — local fan-out by eventType is the SDK's job. */
|
|
698
|
+
sendEventSubscribe(): Promise<EventsSubscribeResult>;
|
|
699
|
+
/** Tear down a host-event subscription. */
|
|
700
|
+
sendEventUnsubscribe(subscriptionId: string): Promise<void>;
|
|
701
|
+
/** Register a handler for inbound `ui/events/dispatch` (host → embedding). */
|
|
702
|
+
onEventDispatch(handler: (params: EventsDispatchParams, meta?: JsonRpcMeta) => void): void;
|
|
703
|
+
/** Fire-and-forget resize hint (`ui/notifications/resize`). */
|
|
704
|
+
sendResize(dimensions: ResizeParams): void;
|
|
705
|
+
/** Attach an auto-emit resizer; stopped on dispose. Replaces any prior resizer. */
|
|
706
|
+
attachResizer(resizer: EmbeddingResizer): void;
|
|
707
|
+
dispose(): void;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/** Single-attempt per iframe; recovery from failure requires a host-driven remount. */
|
|
58
711
|
declare function bootstrapSession(options?: BootstrapSessionOptions): Promise<SessionHandle>;
|
|
59
712
|
|
|
60
713
|
/** Combined error vocabulary: standard + transport-level + sf-embedding-specific. */
|
|
@@ -93,5 +746,5 @@ declare function makeJsonRpcError(code: number, options?: {
|
|
|
93
746
|
*/
|
|
94
747
|
declare function readHostMetaData(search: string): HostMetaData | null;
|
|
95
748
|
|
|
96
|
-
export { BootstrapFailureError, ErrorCode, SessionFailureError, bootstrapSession, isBootstrapEnvelope, makeJsonRpcError, readHostMetaData, validateBootstrapEnvelope };
|
|
97
|
-
export type { BootstrapEnvelopeValidationFailure, BootstrapEnvelopeValidationInput, BootstrapEnvelopeValidationResult, BootstrapFailureReason, BootstrapSessionOptions, ErrorCodeValue, HostInitializedPayload, SessionFailureReason, SessionHandle };
|
|
749
|
+
export { BOOTSTRAP_ENVELOPE_TYPE, BootstrapFailureError, BridgeClient, EMBEDDING_INITIALIZED_METHOD, EVENTS_DISPATCH_METHOD, EVENTS_SUBSCRIBE_METHOD, EVENTS_UNSUBSCRIBE_METHOD, EmbeddingBridge, ErrorCode, HEARTBEAT_TYPE, HOST_INITIALIZED_METHOD, HOST_META_DATA_PARAM, HostLwcEvent, JsonRpcHandlerError, JsonRpcRouter, NON_RETRYABLE_CODES, PROTOCOL_NAME, RESIZE_METHOD, SHUTDOWN_TYPE, SessionFailureError, SfEmbeddingErrorCode, UI_STATE_CHANGED_METHOD, UI_STATE_SUBSCRIBE_METHOD, UI_STATE_UNSUBSCRIBE_METHOD, bootstrapSession, isBootstrapEnvelope, makeJsonRpcError, readHostMetaData, validateBootstrapEnvelope };
|
|
750
|
+
export type { BootstrapEnvelope, BootstrapEnvelopeValidationFailure, BootstrapEnvelopeValidationInput, BootstrapEnvelopeValidationResult, BootstrapFailureReason, BootstrapSessionOptions, EmbeddingInitializedParams, ErrorCodeValue, EventsDispatchParams, EventsSubscribeParams, EventsSubscribeResult, EventsUnsubscribeParams, HeartbeatEnvelope, HostErrorEventDetail, HostInitializedParams, HostInitializedPayload, HostLwcEventName, HostMetaData, HostReadyEventDetail, HostStyles, NotificationHandler, PeerInfo, RequestHandler, ResizeParams, SessionFailureReason, SessionHandle, SfEmbeddingErrorCodeValue, ShutdownEnvelope, UiState, UiStateChangedParams, UiStateSubscribeParams, UiStateSubscribeResult, UiStateUnsubscribeParams, Unregister };
|