@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/index.d.ts CHANGED
@@ -1,5 +1,199 @@
1
- import { BootstrapEnvelope, HostMetaData } from '@salesforce/sf-embedding-contract';
2
- import { JsonRpcClient, JsonRpcErrorPayload } from '@salesforce/jsonrpc';
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
- client: JsonRpcClient;
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
- * Bootstraps the sf-embedding session. Single-attempt per iframe recovery
55
- * from failure requires a host-driven remount (`port1` is one-shot; a new
56
- * session needs a new `MessageChannel` + `instanceId`).
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 };