@salesforce/platform-sdk 9.12.1 → 9.13.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/platform-sdk",
3
- "version": "9.12.1",
3
+ "version": "9.13.0",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -35,7 +35,8 @@
35
35
  "@conduit-client/service-fetch-network": "3.19.6",
36
36
  "@conduit-client/service-pubsub": "3.19.6",
37
37
  "@conduit-client/service-retry": "3.19.6",
38
- "@conduit-client/utils": "3.19.6"
38
+ "@conduit-client/utils": "3.19.6",
39
+ "@salesforce/jsonrpc": "^9.13.0"
39
40
  },
40
41
  "peerDependencies": {
41
42
  "o11y": ">=260.0.0",
@@ -1,167 +0,0 @@
1
- /**
2
- * Abstract transport for a JSON-RPC 2.0 client.
3
- *
4
- * A `Transport` is a bidirectional, structured-message pipe. The `JsonRpcClient`
5
- * uses it to send JSON-RPC messages (`post`) and subscribe to inbound ones
6
- * (`onMessage`). The transport itself is agnostic to the JSON-RPC framing —
7
- * it simply moves `unknown` payloads between two endpoints.
8
- *
9
- * This abstraction exists so `JsonRpcClient` can be driven by either the
10
- * `window.parent.postMessage` channel (default, preserved for existing MCP
11
- * Apps iframes) or a `MessagePort`-backed transport (used by newer
12
- * microfrontend containers that receive a dedicated channel during
13
- * bootstrap).
14
- */
15
- export interface Transport {
16
- /**
17
- * Deliver a single structured message to the peer. Implementations MUST NOT
18
- * throw on transient conditions (a closed port, a missing parent window,
19
- * etc.) — drop the message silently instead, matching the prior
20
- * `window.parent?.postMessage` behaviour.
21
- */
22
- post(message: unknown): void;
23
- /**
24
- * Subscribe to inbound structured messages from the peer. The callback
25
- * receives the already-unwrapped message payload (never a `MessageEvent`).
26
- *
27
- * @returns an unsubscribe function that removes this listener.
28
- */
29
- onMessage(callback: (message: unknown) => void): () => void;
30
- }
31
- /**
32
- * Default `Transport` backing the JSON-RPC client in an iframe context.
33
- *
34
- * Outbound messages go to `window.parent` via `postMessage(msg, targetOrigin)`,
35
- * and inbound messages come from `window.addEventListener("message", ...)`
36
- * with only the `event.data` payload forwarded to subscribers.
37
- *
38
- * The `targetOrigin` passed to `postMessage` is configurable and defaults to
39
- * `"*"` to preserve the pre-refactor wire behaviour. Callers embedding the
40
- * iframe should pin this to the expected parent origin when it is known, so
41
- * that messages cannot leak to a parent that has been navigated to a
42
- * different origin since the iframe loaded.
43
- *
44
- * Missing `window.parent` (e.g. top-level document) is tolerated: `post` is a
45
- * no-op, matching the prior optional-chaining behaviour.
46
- */
47
- export declare class WindowPostMessageTransport implements Transport {
48
- private readonly targetOrigin;
49
- /**
50
- * @param targetOrigin - origin passed as the second argument to
51
- * `window.parent.postMessage`. Defaults to `"*"` for backwards
52
- * compatibility. Pin to the known parent origin when possible to
53
- * prevent leaking messages to a cross-origin navigated parent.
54
- */
55
- constructor(targetOrigin?: string);
56
- post(message: unknown): void;
57
- onMessage(callback: (message: unknown) => void): () => void;
58
- }
59
- /**
60
- * Base class for JSON-RPC 2.0 clients.
61
- *
62
- * This class provides core JSON-RPC client functionality for MCP Apps and
63
- * sf-mfe implementations. It handles request/response correlation, message
64
- * validation, and error handling.
65
- *
66
- * The transport layer is pluggable via the `Transport` interface. By default
67
- * the client uses `WindowPostMessageTransport`, which preserves the original
68
- * `window.parent.postMessage` wire behaviour. Callers can inject a different
69
- * transport (e.g. a `MessageChannelTransport`) without changing any of the
70
- * request/response semantics below.
71
- *
72
- * Subclasses should extend this class and use the protected `request()` method
73
- * to send JSON-RPC requests to the peer.
74
- *
75
- * @example
76
- * export class MCPAppsViewSDK extends JsonRpcClient implements ViewSDK {
77
- * async displayAlert(options: AlertOptions): Promise<void> {
78
- * await this.request("ui/message", {
79
- * role: "user",
80
- * content: { type: "text", text: options.message }
81
- * });
82
- * }
83
- * }
84
- *
85
- * @example
86
- * // Injecting a custom transport (e.g. for a MessageChannel-based flow).
87
- * class MyClient extends JsonRpcClient {
88
- * constructor(transport: Transport) { super(transport); }
89
- * }
90
- */
91
- export declare class JsonRpcClient {
92
- private nextRequestId;
93
- private pending;
94
- private notificationHandlers;
95
- private readonly transport;
96
- /**
97
- * Construct a JSON-RPC client bound to the given transport.
98
- *
99
- * @param transport - the transport to use; defaults to a
100
- * `WindowPostMessageTransport`, which preserves the original
101
- * `window.parent.postMessage` behaviour.
102
- */
103
- constructor(transport?: Transport);
104
- /**
105
- * Register a handler for a specific JSON-RPC notification method
106
- *
107
- * Subclasses can register handlers to process specific notification types.
108
- * When a notification with the registered method is received, the handler
109
- * will be invoked with the notification params.
110
- *
111
- * @param method - The notification method to handle (e.g. "ui/notifications/host-context-changed")
112
- * @param handler - Callback function to process the notification params
113
- *
114
- * @example
115
- * this.registerNotificationHandler("ui/notifications/host-context-changed", (params) => {
116
- * this.handleHostContextChanged(params);
117
- * });
118
- */
119
- protected registerNotificationHandler(method: string, handler: (params: unknown) => void): void;
120
- /**
121
- * Handle inbound JSON-RPC messages from the transport.
122
- *
123
- * Processes both responses (for requests) and notifications. Non-JSON-RPC
124
- * payloads are silently ignored so that a shared transport can be used for
125
- * multiple protocols without cross-talk.
126
- */
127
- private onMessage;
128
- /**
129
- * Send a JSON-RPC request to the peer.
130
- *
131
- * @param method - The JSON-RPC method name
132
- * @param params - The method parameters
133
- * @returns Promise that resolves with the result or rejects with error
134
- *
135
- * @example
136
- * const result = await this.request("ui/message", {
137
- * role: "user",
138
- * content: { type: "text", text: "Hello" }
139
- * });
140
- */
141
- protected request<TParams = unknown, TResult = unknown>(method: string, params: TParams): Promise<TResult>;
142
- /**
143
- * Send a JSON-RPC notification to the peer.
144
- *
145
- * Notifications are one-way messages that do not expect a response.
146
- * Use notifications for:
147
- * - Informing the host of state changes
148
- * - Fire-and-forget operations
149
- * - Events that don't require confirmation
150
- *
151
- * Use request() instead when you need:
152
- * - A response from the host
153
- * - Confirmation of success/failure
154
- * - Return values from the operation
155
- *
156
- * @param method - The JSON-RPC method name
157
- * @param params - Optional method parameters
158
- *
159
- * @example
160
- * this.sendNotification("ui/notifications/size-changed", {
161
- * width: 800,
162
- * height: 600
163
- * });
164
- */
165
- protected sendNotification<TParams = unknown>(method: string, params?: TParams): void;
166
- }
167
- //# sourceMappingURL=jsonrpc-client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jsonrpc-client.d.ts","sourceRoot":"","sources":["../../src/core/jsonrpc-client.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,SAAS;IACzB;;;;;OAKG;IAEH,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAE7B;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC5D;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,0BAA2B,YAAW,SAAS;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC;;;;;OAKG;gBACS,YAAY,SAAM;IAI9B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI5B,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;CAO3D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,aAAa;IACzB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,oBAAoB,CAAqD;IACjF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IAEtC;;;;;;OAMG;gBACS,SAAS,GAAE,SAA4C;IAMnE;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAO/F;;;;;;OAMG;IACH,OAAO,CAAC,SAAS,CA0Bf;IAEF;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,OAAO,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EACrD,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,GACb,OAAO,CAAC,OAAO,CAAC;IAkBnB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,SAAS,CAAC,gBAAgB,CAAC,OAAO,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;CAQrF"}
@@ -1,123 +0,0 @@
1
- /**
2
- * Copyright (c) 2026, Salesforce, Inc.,
3
- * All rights reserved.
4
- * For full license text, see the LICENSE.txt file
5
- */
6
- /**
7
- * JSON-RPC 2.0 Protocol Types
8
- *
9
- * This module provides TypeScript types and utilities for implementing
10
- * JSON-RPC 2.0 protocol as specified in https://www.jsonrpc.org/specification
11
- *
12
- * JSON-RPC 2.0 is a stateless, light-weight remote procedure call (RPC) protocol.
13
- * Used for iframe communication via postMessage in MCP Apps surface.
14
- *
15
- * @example
16
- * // Creating a request
17
- * const request: JsonRpcRequest = {
18
- * jsonrpc: "2.0",
19
- * id: 1,
20
- * method: "ui/message",
21
- * params: { role: "user", content: { type: "text", text: "Hello" } }
22
- * };
23
- * window.parent.postMessage(request, "*");
24
- *
25
- * @example
26
- * // Validating a response
27
- * window.addEventListener("message", (event) => {
28
- * if (isJsonRpcResponse(event.data)) {
29
- * if (isJsonRpcErrorResponse(event.data)) {
30
- * console.error("Error:", event.data.error.message);
31
- * } else {
32
- * console.log("Result:", event.data.result);
33
- * }
34
- * }
35
- * });
36
- */
37
- /**
38
- * JSON-RPC 2.0 base message with required version field
39
- */
40
- export interface JsonRpcBase {
41
- jsonrpc: "2.0";
42
- }
43
- /**
44
- * JSON-RPC 2.0 Request with numeric ID (per spec)
45
- */
46
- export interface JsonRpcRequest<TParams = unknown> extends JsonRpcBase {
47
- id: number;
48
- method: string;
49
- params?: TParams;
50
- }
51
- /**
52
- * JSON-RPC 2.0 Error object structure
53
- */
54
- export interface JsonRpcError {
55
- code: number;
56
- message?: string;
57
- data?: unknown;
58
- }
59
- /**
60
- * JSON-RPC 2.0 Success Response
61
- */
62
- export interface JsonRpcSuccessResponse<TResult = unknown> extends JsonRpcBase {
63
- id: number;
64
- result: TResult;
65
- }
66
- /**
67
- * JSON-RPC 2.0 Error Response
68
- */
69
- export interface JsonRpcErrorResponse extends JsonRpcBase {
70
- id: number;
71
- error: JsonRpcError;
72
- }
73
- /**
74
- * JSON-RPC 2.0 Notification (no id, no response expected)
75
- */
76
- export interface JsonRpcNotification<TParams = unknown> extends JsonRpcBase {
77
- method: string;
78
- params?: TParams;
79
- }
80
- /**
81
- * Union of all JSON-RPC response types
82
- */
83
- export type JsonRpcResponse<TResult = unknown> = JsonRpcSuccessResponse<TResult> | JsonRpcErrorResponse;
84
- /**
85
- * Union of all JSON-RPC message types
86
- */
87
- export type JsonRpcMessage<TRequest = unknown, TResponse = unknown> = JsonRpcRequest<TRequest> | JsonRpcResponse<TResponse> | JsonRpcNotification;
88
- /**
89
- * Pending request resolver functions
90
- */
91
- export interface JsonRpcPendingRequest {
92
- resolve: (value: unknown) => void;
93
- reject: (error: unknown) => void;
94
- }
95
- /**
96
- * Map of pending JSON-RPC requests by numeric ID
97
- */
98
- export type JsonRpcPendingRequestMap = Map<number, JsonRpcPendingRequest>;
99
- /**
100
- * Type guard to check if message is valid JSON-RPC 2.0 base
101
- */
102
- export declare function isJsonRpcBase(data: unknown): data is JsonRpcBase;
103
- /**
104
- * Type guard for JSON-RPC success response
105
- */
106
- export declare function isJsonRpcSuccessResponse(data: unknown): data is JsonRpcSuccessResponse;
107
- /**
108
- * Type guard for JSON-RPC error response
109
- */
110
- export declare function isJsonRpcErrorResponse(data: unknown): data is JsonRpcErrorResponse;
111
- /**
112
- * Type guard for any JSON-RPC response (success or error)
113
- */
114
- export declare function isJsonRpcResponse(data: unknown): data is JsonRpcResponse;
115
- /**
116
- * Type guard for JSON-RPC notification
117
- */
118
- export declare function isJsonRpcNotification(data: unknown): data is JsonRpcNotification;
119
- /**
120
- * Type guard for JSON-RPC request
121
- */
122
- export declare function isJsonRpcRequest(data: unknown): data is JsonRpcRequest;
123
- //# sourceMappingURL=jsonrpc.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jsonrpc.d.ts","sourceRoot":"","sources":["../../src/core/jsonrpc.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,KAAK,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,OAAO,GAAG,OAAO,CAAE,SAAQ,WAAW;IACrE,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB,CAAC,OAAO,GAAG,OAAO,CAAE,SAAQ,WAAW;IAC7E,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,YAAY,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB,CAAC,OAAO,GAAG,OAAO,CAAE,SAAQ,WAAW;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,OAAO,GAAG,OAAO,IAC1C,sBAAsB,CAAC,OAAO,CAAC,GAC/B,oBAAoB,CAAC;AAExB;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,QAAQ,GAAG,OAAO,EAAE,SAAS,GAAG,OAAO,IAC/D,cAAc,CAAC,QAAQ,CAAC,GACxB,eAAe,CAAC,SAAS,CAAC,GAC1B,mBAAmB,CAAC;AAEvB;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAE1E;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,WAAW,CAOhE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,sBAAsB,CAOtF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,oBAAoB,CAOlF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,eAAe,CAExE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,mBAAmB,CAOhF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,cAAc,CAQtE"}
@@ -1,79 +0,0 @@
1
- import { Transport } from '../jsonrpc-client';
2
- /**
3
- * Subscriber callback invoked for each unwrapped payload delivered on the
4
- * port. Receivers get the `MessageEvent.data` directly — they do not need
5
- * to reach into a `MessageEvent` wrapper.
6
- */
7
- export type MessageChannelTransportListener = (msg: unknown) => void;
8
- /**
9
- * MFE-side `Transport` backed by a `MessagePort`.
10
- *
11
- * During the MFE handshake, the iframe receives a transferred `MessagePort`
12
- * (`event.ports[0]`) in the single bootstrap envelope posted by the host.
13
- * That port is the `port1` half of the host's `MessageChannel`. Wrapping it
14
- * in this class produces the same `Transport` shape that `JsonRpcClient`
15
- * already consumes, so callers can swap in MessagePort-backed traffic
16
- * without changing any of the JSON-RPC request/response/notification
17
- * semantics.
18
- *
19
- * The implementation mirrors the host-side `MessageChannelTransport` that
20
- * ships from `packages/core/src/MessageChannelTransport.ts` in the
21
- * `ui-embedding` repo. Both sides MUST honour the same contract so one
22
- * `JsonRpcClient` can drive either end.
23
- *
24
- * Contract (symmetric with the host-side transport, and with the
25
- * `Transport` interface defined next to `WindowPostMessageTransport`):
26
- *
27
- * - `post(msg)` never throws on transient failure. A closed / neutered /
28
- * disposed port silently drops the message. This matches the
29
- * optional-chaining behaviour of `WindowPostMessageTransport.post`.
30
- * - `onMessage(cb)` delivers the **unwrapped** payload (`MessageEvent.data`),
31
- * not the raw `MessageEvent`. Returns an unsubscribe function.
32
- * - The port is started (`port.start()`) lazily on the first `onMessage`
33
- * subscription. Messages queued via `post` before that first subscribe
34
- * are buffered in-process and flushed FIFO when the port starts.
35
- * - `dispose()` removes listeners, closes the port, clears the outbound
36
- * buffer, and puts the transport into a terminal state where further
37
- * `post` calls silently no-op and further `onMessage` calls return a
38
- * no-op unsubscribe.
39
- *
40
- * Usage from the container bootstrap:
41
- * ```ts
42
- * const transport = new MessageChannelTransport(event.ports[0]);
43
- * // Hand the transport to the session layer; subscription drives start().
44
- * ```
45
- */
46
- export declare class MessageChannelTransport implements Transport {
47
- #private;
48
- constructor(port: MessagePort);
49
- /**
50
- * Post a message to the peer.
51
- *
52
- * Never throws on transient failure — a closed / neutered / disposed
53
- * port silently drops the message. If the transport has not yet
54
- * started (no `onMessage` subscriber), the message is buffered and
55
- * flushed on first subscription.
56
- */
57
- post(message: unknown): void;
58
- /**
59
- * Subscribe to inbound messages from the peer. The callback receives
60
- * the **unwrapped** payload (`MessageEvent.data`) — callers never see
61
- * the `MessageEvent` wrapper.
62
- *
63
- * Starts the underlying port on first subscription and flushes any
64
- * messages queued via `post` before the port was started.
65
- *
66
- * Returns an unsubscribe function. Calling it is idempotent.
67
- */
68
- onMessage(callback: MessageChannelTransportListener): () => void;
69
- /**
70
- * Tear down the transport:
71
- * - remove the internal `message` listener
72
- * - call `port.close()`
73
- * - clear subscriber set and outbound buffer
74
- * - subsequent `post` calls silently no-op
75
- * - subsequent `onMessage` calls return a no-op unsubscribe
76
- */
77
- dispose(): void;
78
- }
79
- //# sourceMappingURL=message-channel-transport.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"message-channel-transport.d.ts","sourceRoot":"","sources":["../../../src/core/mfe-protocol/message-channel-transport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;;GAIG;AACH,MAAM,MAAM,+BAA+B,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;AAUrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,qBAAa,uBAAwB,YAAW,SAAS;;gBAQ5C,IAAI,EAAE,WAAW;IAI7B;;;;;;;OAOG;IACH,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAqB5B;;;;;;;;;OASG;IACH,SAAS,CAAC,QAAQ,EAAE,+BAA+B,GAAG,MAAM,IAAI;IAoBhE;;;;;;;OAOG;IACH,OAAO,IAAI,IAAI;CAyDf"}