@salesforce/jsonrpc 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/LICENSE.txt +82 -0
- package/dist/errors.d.ts +52 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +310 -0
- package/dist/jsonrpc-client.d.ts +112 -0
- package/dist/jsonrpc-client.d.ts.map +1 -0
- package/dist/jsonrpc.d.ts +152 -0
- package/dist/jsonrpc.d.ts.map +1 -0
- package/dist/message-channel-transport.d.ts +74 -0
- package/dist/message-channel-transport.d.ts.map +1 -0
- package/dist/transport.d.ts +39 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/window-postmessage-transport.d.ts +22 -0
- package/dist/window-postmessage-transport.d.ts.map +1 -0
- package/package.json +38 -0
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Terms of Use
|
|
2
|
+
|
|
3
|
+
Copyright 2026 Salesforce, Inc. All rights reserved.
|
|
4
|
+
|
|
5
|
+
These Terms of Use govern the download, installation, and/or use of this
|
|
6
|
+
software provided by Salesforce, Inc. ("Salesforce") (the "Software"), were
|
|
7
|
+
last updated on April 15, 2025, and constitute a legally binding
|
|
8
|
+
agreement between you and Salesforce. If you do not agree to these Terms of
|
|
9
|
+
Use, do not install or use the Software.
|
|
10
|
+
|
|
11
|
+
Salesforce grants you a worldwide, non-exclusive, no-charge, royalty-free
|
|
12
|
+
copyright license to reproduce, prepare derivative works of, publicly
|
|
13
|
+
display, publicly perform, sublicense, and distribute the Software and
|
|
14
|
+
derivative works subject to these Terms. These Terms shall be included in
|
|
15
|
+
all copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
Subject to the limited rights expressly granted hereunder, Salesforce
|
|
18
|
+
reserves all rights, title, and interest in and to all intellectual
|
|
19
|
+
property subsisting in the Software. No rights are granted to you hereunder
|
|
20
|
+
other than as expressly set forth herein. Users residing in countries on
|
|
21
|
+
the United States Office of Foreign Assets Control sanction list, or which
|
|
22
|
+
are otherwise subject to a US export embargo, may not use the Software.
|
|
23
|
+
|
|
24
|
+
Implementation of the Software may require development work, for which you
|
|
25
|
+
are responsible. The Software may contain bugs, errors and
|
|
26
|
+
incompatibilities and is made available on an AS IS basis without support,
|
|
27
|
+
updates, or service level commitments.
|
|
28
|
+
|
|
29
|
+
Salesforce reserves the right at any time to modify, suspend, or
|
|
30
|
+
discontinue, the Software (or any part thereof) with or without notice. You
|
|
31
|
+
agree that Salesforce shall not be liable to you or to any third party for
|
|
32
|
+
any modification, suspension, or discontinuance.
|
|
33
|
+
|
|
34
|
+
You agree to defend Salesforce against any claim, demand, suit or
|
|
35
|
+
proceeding made or brought against Salesforce by a third party arising out
|
|
36
|
+
of or accruing from (a) your use of the Software, and (b) any application
|
|
37
|
+
you develop with the Software that infringes any copyright, trademark,
|
|
38
|
+
trade secret, trade dress, patent, or other intellectual property right of
|
|
39
|
+
any person or defames any person or violates their rights of publicity or
|
|
40
|
+
privacy (each a "Claim Against Salesforce"), and will indemnify Salesforce
|
|
41
|
+
from any damages, attorney fees, and costs finally awarded against
|
|
42
|
+
Salesforce as a result of, or for any amounts paid by Salesforce under a
|
|
43
|
+
settlement approved by you in writing of, a Claim Against Salesforce,
|
|
44
|
+
provided Salesforce (x) promptly gives you written notice of the Claim
|
|
45
|
+
Against Salesforce, (y) gives you sole control of the defense and
|
|
46
|
+
settlement of the Claim Against Salesforce (except that you may not settle
|
|
47
|
+
any Claim Against Salesforce unless it unconditionally releases Salesforce
|
|
48
|
+
of all liability), and (z) gives you all reasonable assistance, at your
|
|
49
|
+
expense.
|
|
50
|
+
|
|
51
|
+
WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE SOFTWARE IS NOT
|
|
52
|
+
SUPPORTED AND IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
53
|
+
IMPLIED. IN NO EVENT SHALL SALESFORCE HAVE ANY LIABILITY FOR ANY DAMAGES,
|
|
54
|
+
INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
|
|
55
|
+
PUNITIVE, OR CONSEQUENTIAL DAMAGES, OR DAMAGES BASED ON LOST PROFITS, DATA,
|
|
56
|
+
OR USE, IN CONNECTION WITH THE SOFTWARE, HOWEVER CAUSED AND WHETHER IN
|
|
57
|
+
CONTRACT, TORT, OR UNDER ANY OTHER THEORY OF LIABILITY, WHETHER OR NOT YOU
|
|
58
|
+
HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
59
|
+
|
|
60
|
+
These Terms of Use shall be governed exclusively by the internal laws of
|
|
61
|
+
the State of California, without regard to its conflicts of laws
|
|
62
|
+
rules. Each party hereby consents to the exclusive jurisdiction of the
|
|
63
|
+
state and federal courts located in San Francisco County, California to
|
|
64
|
+
adjudicate any dispute arising out of or relating to these Terms of Use and
|
|
65
|
+
the download, installation, and/or use of the Software. Except as expressly
|
|
66
|
+
stated herein, these Terms of Use constitute the entire agreement between
|
|
67
|
+
the parties, and supersede all prior and contemporaneous agreements,
|
|
68
|
+
proposals, or representations, written or oral, concerning their subject
|
|
69
|
+
matter. No modification, amendment, or waiver of any provision of these
|
|
70
|
+
Terms of Use shall be effective unless it is by an update to these Terms of
|
|
71
|
+
Use that Salesforce makes available, or is in writing and signed by the
|
|
72
|
+
party against whom the modification, amendment, or waiver is to be
|
|
73
|
+
asserted.
|
|
74
|
+
|
|
75
|
+
Data Privacy: Salesforce may collect, process, and store device,
|
|
76
|
+
system, and other information related to your use of the Software. This
|
|
77
|
+
information includes, but is not limited to, IP address, user metrics, and
|
|
78
|
+
other data ("Usage Data"). Salesforce may use Usage Data for analytics,
|
|
79
|
+
product development, and marketing purposes. You acknowledge that files
|
|
80
|
+
generated in conjunction with the Software may contain sensitive or
|
|
81
|
+
confidential data, and you are solely responsible for anonymizing and
|
|
82
|
+
protecting such data.
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
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 error vocabulary common to every cross-realm protocol that uses
|
|
8
|
+
* this package. Centralizes the standard JSON-RPC 2.0 error codes plus the
|
|
9
|
+
* transport-level codes that any JsonRpcClient over a transport with
|
|
10
|
+
* timeouts and cancellation will emit.
|
|
11
|
+
*
|
|
12
|
+
* Codes used by this package:
|
|
13
|
+
* - JSON-RPC 2.0 standard: -32700, -32600..-32603
|
|
14
|
+
* - Transport-level: a handful within -32010..-32099 (see below)
|
|
15
|
+
*/
|
|
16
|
+
export declare const StandardErrorCode: {
|
|
17
|
+
readonly PARSE_ERROR: -32700;
|
|
18
|
+
readonly INVALID_REQUEST: -32600;
|
|
19
|
+
readonly METHOD_NOT_FOUND: -32601;
|
|
20
|
+
readonly INVALID_PARAMS: -32602;
|
|
21
|
+
readonly INTERNAL_ERROR: -32603;
|
|
22
|
+
/** Transport closed; pending requests rejected locally. */
|
|
23
|
+
readonly PORT_CLOSED: -32016;
|
|
24
|
+
/** Payload could not be structured-cloned across the transport. */
|
|
25
|
+
readonly SERIALIZATION_FAILURE: -32017;
|
|
26
|
+
/** `default` / `long` timeout-class request expired. */
|
|
27
|
+
readonly REQUEST_TIMEOUT: -32018;
|
|
28
|
+
/** In-flight cap reached. */
|
|
29
|
+
readonly BACKPRESSURE: -32019;
|
|
30
|
+
/** Terminal response to a $/cancel-ed request. */
|
|
31
|
+
readonly REQUEST_CANCELLED: -32024;
|
|
32
|
+
};
|
|
33
|
+
/** Numeric type of any value in `StandardErrorCode`. */
|
|
34
|
+
export type StandardErrorCodeValue = (typeof StandardErrorCode)[keyof typeof StandardErrorCode];
|
|
35
|
+
/** Structure of the `data` field on a JSON-RPC error payload. */
|
|
36
|
+
export interface JsonRpcErrorData {
|
|
37
|
+
retryable?: boolean;
|
|
38
|
+
details?: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
/** Shape of a JSON-RPC error payload (the value under `error` on an error response). */
|
|
41
|
+
export interface JsonRpcErrorPayload {
|
|
42
|
+
code: number;
|
|
43
|
+
message?: string;
|
|
44
|
+
data?: JsonRpcErrorData;
|
|
45
|
+
}
|
|
46
|
+
/** Builds a JSON-RPC error payload with sensible `retryable` defaults per code. */
|
|
47
|
+
export declare function makeJsonRpcError(code: number, options?: {
|
|
48
|
+
message?: string;
|
|
49
|
+
details?: Record<string, unknown>;
|
|
50
|
+
retryable?: boolean;
|
|
51
|
+
}): JsonRpcErrorPayload;
|
|
52
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB;;;;;;IAS7B,2DAA2D;;IAE3D,mEAAmE;;IAEnE,wDAAwD;;IAExD,6BAA6B;;IAE7B,kDAAkD;;CAEzC,CAAC;AAEX,wDAAwD;AACxD,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAEhG,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,wFAAwF;AACxF,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACxB;AAYD,mFAAmF;AACnF,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IACR,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;CACf,GACJ,mBAAmB,CASrB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @salesforce/jsonrpc
|
|
8
|
+
*
|
|
9
|
+
* JSON-RPC 2.0 primitives for cross-realm communication: envelope types and
|
|
10
|
+
* runtime guards, the request/response engine (JsonRpcClient), and transport
|
|
11
|
+
* adapters (WindowPostMessageTransport, MessageChannelTransport).
|
|
12
|
+
*/
|
|
13
|
+
export type { JsonRpcMeta, JsonRpcBase, JsonRpcRequest, JsonRpcNotification, JsonRpcSuccessResponse, JsonRpcErrorResponse, JsonRpcResponse, JsonRpcError, JsonRpcFrame, JsonRpcPendingRequest, JsonRpcPendingRequestMap, } from './jsonrpc';
|
|
14
|
+
export { isJsonRpcBase, isJsonRpcRequest, isJsonRpcNotification, isJsonRpcSuccessResponse, isJsonRpcErrorResponse, isJsonRpcResponse, isJsonRpcError, } from './jsonrpc';
|
|
15
|
+
export type { Transport } from './transport';
|
|
16
|
+
export { JsonRpcClient } from './jsonrpc-client';
|
|
17
|
+
export { WindowPostMessageTransport } from './window-postmessage-transport';
|
|
18
|
+
export { MessageChannelTransport, type MessageChannelTransportListener, } from './message-channel-transport';
|
|
19
|
+
export { StandardErrorCode, type StandardErrorCodeValue, type JsonRpcErrorData, type JsonRpcErrorPayload, makeJsonRpcError, } from './errors';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;GAMG;AAEH,YAAY,EACX,WAAW,EACX,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,qBAAqB,EACrB,wBAAwB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,GACd,MAAM,WAAW,CAAC;AAEnB,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EACN,uBAAuB,EACvB,KAAK,+BAA+B,GACpC,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACN,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,gBAAgB,GAChB,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
function o(s) {
|
|
2
|
+
return typeof s == "object" && s !== null && !Array.isArray(s);
|
|
3
|
+
}
|
|
4
|
+
function c(s) {
|
|
5
|
+
return typeof s.id == "number" && Number.isInteger(s.id) && s.id >= 0;
|
|
6
|
+
}
|
|
7
|
+
function i(s) {
|
|
8
|
+
return o(s) && s.jsonrpc === "2.0";
|
|
9
|
+
}
|
|
10
|
+
function m(s) {
|
|
11
|
+
if (!i(s)) return !1;
|
|
12
|
+
const t = s;
|
|
13
|
+
return c(t) && typeof t.method == "string";
|
|
14
|
+
}
|
|
15
|
+
function d(s) {
|
|
16
|
+
if (!i(s)) return !1;
|
|
17
|
+
const t = s;
|
|
18
|
+
return !("id" in t) && typeof t.method == "string";
|
|
19
|
+
}
|
|
20
|
+
function p(s) {
|
|
21
|
+
if (!i(s)) return !1;
|
|
22
|
+
const t = s;
|
|
23
|
+
return c(t) && "result" in t && !("error" in t) && !("method" in t);
|
|
24
|
+
}
|
|
25
|
+
function f(s) {
|
|
26
|
+
if (!i(s)) return !1;
|
|
27
|
+
const t = s;
|
|
28
|
+
if (!c(t) || "result" in t || "method" in t) return !1;
|
|
29
|
+
const e = t.error;
|
|
30
|
+
return o(e) && typeof e.code == "number";
|
|
31
|
+
}
|
|
32
|
+
function g(s) {
|
|
33
|
+
return p(s) || f(s);
|
|
34
|
+
}
|
|
35
|
+
function y(s) {
|
|
36
|
+
return o(s) && typeof s.code == "number";
|
|
37
|
+
}
|
|
38
|
+
class M {
|
|
39
|
+
nextRequestId = 1;
|
|
40
|
+
pending = /* @__PURE__ */ new Map();
|
|
41
|
+
notificationHandlers = /* @__PURE__ */ new Map();
|
|
42
|
+
transport;
|
|
43
|
+
/**
|
|
44
|
+
* Construct a JSON-RPC client bound to the given transport.
|
|
45
|
+
*
|
|
46
|
+
* @param transport - the transport to use.
|
|
47
|
+
*/
|
|
48
|
+
constructor(t) {
|
|
49
|
+
this.transport = t, this.transport.onMessage(this.onMessage);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Register a handler for a specific JSON-RPC notification method.
|
|
53
|
+
*
|
|
54
|
+
* Subclasses can register handlers to process specific notification
|
|
55
|
+
* types. When a notification with the registered method is received,
|
|
56
|
+
* the handler will be invoked with the notification params.
|
|
57
|
+
*
|
|
58
|
+
* @param method - The notification method to handle (e.g.
|
|
59
|
+
* "ui/notifications/host-context-changed")
|
|
60
|
+
* @param handler - Callback function to process the notification params
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* this.registerNotificationHandler("ui/notifications/host-context-changed", (params) => {
|
|
64
|
+
* this.handleHostContextChanged(params);
|
|
65
|
+
* });
|
|
66
|
+
*/
|
|
67
|
+
registerNotificationHandler(t, e) {
|
|
68
|
+
this.notificationHandlers.has(t) || this.notificationHandlers.set(t, /* @__PURE__ */ new Set()), this.notificationHandlers.get(t).add(e);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Handle inbound JSON-RPC messages from the transport.
|
|
72
|
+
*
|
|
73
|
+
* Processes both responses (for requests) and notifications.
|
|
74
|
+
* Non-JSON-RPC payloads are silently ignored so that a shared transport
|
|
75
|
+
* can be used for multiple protocols without cross-talk.
|
|
76
|
+
*/
|
|
77
|
+
onMessage = (t) => {
|
|
78
|
+
if (g(t)) {
|
|
79
|
+
const e = this.pending.get(t.id);
|
|
80
|
+
if (!e)
|
|
81
|
+
return;
|
|
82
|
+
this.pending.delete(t.id), f(t) ? e.reject(new Error(t.error.message || "Request failed")) : e.resolve(t.result);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (d(t)) {
|
|
86
|
+
const e = this.notificationHandlers.get(t.method);
|
|
87
|
+
e && e.forEach((r) => r(t.params));
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Send a JSON-RPC request to the peer.
|
|
92
|
+
*
|
|
93
|
+
* @param method - The JSON-RPC method name
|
|
94
|
+
* @param params - The method parameters
|
|
95
|
+
* @returns Promise that resolves with the result or rejects with error
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* const result = await this.request("ui/message", {
|
|
99
|
+
* role: "user",
|
|
100
|
+
* content: { type: "text", text: "Hello" }
|
|
101
|
+
* });
|
|
102
|
+
*/
|
|
103
|
+
request(t, e) {
|
|
104
|
+
const r = this.nextRequestId++, n = {
|
|
105
|
+
jsonrpc: "2.0",
|
|
106
|
+
id: r,
|
|
107
|
+
method: t,
|
|
108
|
+
params: e
|
|
109
|
+
};
|
|
110
|
+
return new Promise((h, u) => {
|
|
111
|
+
this.pending.set(r, {
|
|
112
|
+
resolve: h,
|
|
113
|
+
reject: u
|
|
114
|
+
}), this.transport.post(n);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Send a JSON-RPC notification to the peer.
|
|
119
|
+
*
|
|
120
|
+
* Notifications are one-way messages that do not expect a response.
|
|
121
|
+
* Use notifications for:
|
|
122
|
+
* - Informing the host of state changes
|
|
123
|
+
* - Fire-and-forget operations
|
|
124
|
+
* - Events that don't require confirmation
|
|
125
|
+
*
|
|
126
|
+
* Use request() instead when you need:
|
|
127
|
+
* - A response from the host
|
|
128
|
+
* - Confirmation of success/failure
|
|
129
|
+
* - Return values from the operation
|
|
130
|
+
*
|
|
131
|
+
* @param method - The JSON-RPC method name
|
|
132
|
+
* @param params - Optional method parameters
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* this.sendNotification("ui/notifications/size-changed", {
|
|
136
|
+
* width: 800,
|
|
137
|
+
* height: 600
|
|
138
|
+
* });
|
|
139
|
+
*/
|
|
140
|
+
sendNotification(t, e) {
|
|
141
|
+
const r = {
|
|
142
|
+
jsonrpc: "2.0",
|
|
143
|
+
method: t,
|
|
144
|
+
params: e
|
|
145
|
+
};
|
|
146
|
+
this.transport.post(r);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
class S {
|
|
150
|
+
targetOrigin;
|
|
151
|
+
/**
|
|
152
|
+
* @param targetOrigin - origin passed as the second argument to
|
|
153
|
+
* `window.parent.postMessage`.
|
|
154
|
+
*/
|
|
155
|
+
constructor(t) {
|
|
156
|
+
this.targetOrigin = t;
|
|
157
|
+
}
|
|
158
|
+
post(t) {
|
|
159
|
+
window.parent?.postMessage(t, this.targetOrigin);
|
|
160
|
+
}
|
|
161
|
+
onMessage(t) {
|
|
162
|
+
const e = (r) => {
|
|
163
|
+
t(r.data);
|
|
164
|
+
};
|
|
165
|
+
return window.addEventListener("message", e), () => window.removeEventListener("message", e);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function R() {
|
|
169
|
+
}
|
|
170
|
+
class T {
|
|
171
|
+
#t;
|
|
172
|
+
#e = /* @__PURE__ */ new Set();
|
|
173
|
+
#n = !1;
|
|
174
|
+
#r = !1;
|
|
175
|
+
/** Messages queued before `port.start()` has been called. Flushed on first subscribe. */
|
|
176
|
+
#s = [];
|
|
177
|
+
constructor(t) {
|
|
178
|
+
this.#t = t;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Post a message to the peer.
|
|
182
|
+
*
|
|
183
|
+
* Never throws on transient failure — a closed / neutered / disposed
|
|
184
|
+
* port silently drops the message. If the transport has not yet
|
|
185
|
+
* started (no `onMessage` subscriber), the message is buffered and
|
|
186
|
+
* flushed on first subscription.
|
|
187
|
+
*/
|
|
188
|
+
post(t) {
|
|
189
|
+
if (!this.#r) {
|
|
190
|
+
if (!this.#n) {
|
|
191
|
+
this.#s.push(t);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
this.#t.postMessage(t);
|
|
196
|
+
} catch {
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Subscribe to inbound messages from the peer. The callback receives
|
|
202
|
+
* the **unwrapped** payload (`MessageEvent.data`) — callers never see
|
|
203
|
+
* the `MessageEvent` wrapper.
|
|
204
|
+
*
|
|
205
|
+
* Starts the underlying port on first subscription and flushes any
|
|
206
|
+
* messages queued via `post` before the port was started.
|
|
207
|
+
*
|
|
208
|
+
* Returns an unsubscribe function. Calling it is idempotent.
|
|
209
|
+
*/
|
|
210
|
+
onMessage(t) {
|
|
211
|
+
if (this.#r)
|
|
212
|
+
return R;
|
|
213
|
+
this.#e.add(t), this.#n || this.#o();
|
|
214
|
+
let e = !1;
|
|
215
|
+
return () => {
|
|
216
|
+
e || (e = !0, this.#e.delete(t));
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Tear down the transport:
|
|
221
|
+
* - remove the internal `message` listener
|
|
222
|
+
* - call `port.close()`
|
|
223
|
+
* - clear subscriber set and outbound buffer
|
|
224
|
+
* - subsequent `post` calls silently no-op
|
|
225
|
+
* - subsequent `onMessage` calls return a no-op unsubscribe
|
|
226
|
+
*/
|
|
227
|
+
dispose() {
|
|
228
|
+
if (!this.#r) {
|
|
229
|
+
this.#r = !0;
|
|
230
|
+
try {
|
|
231
|
+
this.#t.removeEventListener("message", this.#i);
|
|
232
|
+
} catch {
|
|
233
|
+
}
|
|
234
|
+
this.#e.clear(), this.#s.length = 0;
|
|
235
|
+
try {
|
|
236
|
+
this.#t.close();
|
|
237
|
+
} catch {
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
#o() {
|
|
242
|
+
this.#n = !0, this.#t.addEventListener("message", this.#i);
|
|
243
|
+
try {
|
|
244
|
+
this.#t.start();
|
|
245
|
+
} catch {
|
|
246
|
+
}
|
|
247
|
+
if (this.#s.length > 0) {
|
|
248
|
+
const t = this.#s;
|
|
249
|
+
this.#s = [];
|
|
250
|
+
for (const e of t)
|
|
251
|
+
try {
|
|
252
|
+
this.#t.postMessage(e);
|
|
253
|
+
} catch {
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
#i = (t) => {
|
|
258
|
+
const e = [...this.#e];
|
|
259
|
+
for (const r of e)
|
|
260
|
+
try {
|
|
261
|
+
r(t.data);
|
|
262
|
+
} catch {
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
const a = {
|
|
267
|
+
// --- Standard JSON-RPC 2.0 ----------------------------------------------
|
|
268
|
+
PARSE_ERROR: -32700,
|
|
269
|
+
INVALID_REQUEST: -32600,
|
|
270
|
+
METHOD_NOT_FOUND: -32601,
|
|
271
|
+
INVALID_PARAMS: -32602,
|
|
272
|
+
INTERNAL_ERROR: -32603,
|
|
273
|
+
// --- Transport-level (any JsonRpcClient over a transport will emit) -----
|
|
274
|
+
/** Transport closed; pending requests rejected locally. */
|
|
275
|
+
PORT_CLOSED: -32016,
|
|
276
|
+
/** Payload could not be structured-cloned across the transport. */
|
|
277
|
+
SERIALIZATION_FAILURE: -32017,
|
|
278
|
+
/** `default` / `long` timeout-class request expired. */
|
|
279
|
+
REQUEST_TIMEOUT: -32018,
|
|
280
|
+
/** In-flight cap reached. */
|
|
281
|
+
BACKPRESSURE: -32019,
|
|
282
|
+
/** Terminal response to a $/cancel-ed request. */
|
|
283
|
+
REQUEST_CANCELLED: -32024
|
|
284
|
+
}, E = /* @__PURE__ */ new Set([
|
|
285
|
+
a.REQUEST_TIMEOUT,
|
|
286
|
+
a.BACKPRESSURE
|
|
287
|
+
]);
|
|
288
|
+
function l(s) {
|
|
289
|
+
return !!E.has(s);
|
|
290
|
+
}
|
|
291
|
+
function b(s, t = {}) {
|
|
292
|
+
const r = { retryable: t.retryable ?? l(s) };
|
|
293
|
+
t.details !== void 0 && (r.details = t.details);
|
|
294
|
+
const n = { code: s };
|
|
295
|
+
return t.message !== void 0 && (n.message = t.message), n.data = r, n;
|
|
296
|
+
}
|
|
297
|
+
export {
|
|
298
|
+
M as JsonRpcClient,
|
|
299
|
+
T as MessageChannelTransport,
|
|
300
|
+
a as StandardErrorCode,
|
|
301
|
+
S as WindowPostMessageTransport,
|
|
302
|
+
i as isJsonRpcBase,
|
|
303
|
+
y as isJsonRpcError,
|
|
304
|
+
f as isJsonRpcErrorResponse,
|
|
305
|
+
d as isJsonRpcNotification,
|
|
306
|
+
m as isJsonRpcRequest,
|
|
307
|
+
g as isJsonRpcResponse,
|
|
308
|
+
p as isJsonRpcSuccessResponse,
|
|
309
|
+
b as makeJsonRpcError
|
|
310
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Transport } from './transport';
|
|
2
|
+
/**
|
|
3
|
+
* Base class for JSON-RPC 2.0 clients.
|
|
4
|
+
*
|
|
5
|
+
* This class provides core JSON-RPC client functionality for any cross-realm
|
|
6
|
+
* surface that speaks JSON-RPC 2.0 (MCP Apps, sf-embedding, future
|
|
7
|
+
* surfaces). It handles request/response correlation, message validation,
|
|
8
|
+
* and notification dispatch.
|
|
9
|
+
*
|
|
10
|
+
* The transport layer is pluggable via the `Transport` interface and is
|
|
11
|
+
* REQUIRED at construction. There is no default transport — wildcard-targeted
|
|
12
|
+
* `window.postMessage` is structurally unsafe, so callers must construct a
|
|
13
|
+
* transport with an explicit origin (`WindowPostMessageTransport`) or a
|
|
14
|
+
* port-bound transport (`MessageChannelTransport`).
|
|
15
|
+
*
|
|
16
|
+
* Subclasses should extend this class and use the protected `request()`
|
|
17
|
+
* method to send JSON-RPC requests to the peer.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* export class MCPAppsViewSDK extends JsonRpcClient implements ViewSDK {
|
|
21
|
+
* async displayAlert(options: AlertOptions): Promise<void> {
|
|
22
|
+
* await this.request("ui/message", {
|
|
23
|
+
* role: "user",
|
|
24
|
+
* content: { type: "text", text: options.message }
|
|
25
|
+
* });
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // Injecting a transport (window.parent.postMessage to a known origin).
|
|
31
|
+
* class MyClient extends JsonRpcClient {
|
|
32
|
+
* constructor(targetOrigin: string) {
|
|
33
|
+
* super(new WindowPostMessageTransport(targetOrigin));
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
*/
|
|
37
|
+
export declare class JsonRpcClient {
|
|
38
|
+
private nextRequestId;
|
|
39
|
+
private pending;
|
|
40
|
+
private notificationHandlers;
|
|
41
|
+
private readonly transport;
|
|
42
|
+
/**
|
|
43
|
+
* Construct a JSON-RPC client bound to the given transport.
|
|
44
|
+
*
|
|
45
|
+
* @param transport - the transport to use.
|
|
46
|
+
*/
|
|
47
|
+
constructor(transport: Transport);
|
|
48
|
+
/**
|
|
49
|
+
* Register a handler for a specific JSON-RPC notification method.
|
|
50
|
+
*
|
|
51
|
+
* Subclasses can register handlers to process specific notification
|
|
52
|
+
* types. When a notification with the registered method is received,
|
|
53
|
+
* the handler will be invoked with the notification params.
|
|
54
|
+
*
|
|
55
|
+
* @param method - The notification method to handle (e.g.
|
|
56
|
+
* "ui/notifications/host-context-changed")
|
|
57
|
+
* @param handler - Callback function to process the notification params
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* this.registerNotificationHandler("ui/notifications/host-context-changed", (params) => {
|
|
61
|
+
* this.handleHostContextChanged(params);
|
|
62
|
+
* });
|
|
63
|
+
*/
|
|
64
|
+
protected registerNotificationHandler(method: string, handler: (params: unknown) => void): void;
|
|
65
|
+
/**
|
|
66
|
+
* Handle inbound JSON-RPC messages from the transport.
|
|
67
|
+
*
|
|
68
|
+
* Processes both responses (for requests) and notifications.
|
|
69
|
+
* Non-JSON-RPC payloads are silently ignored so that a shared transport
|
|
70
|
+
* can be used for multiple protocols without cross-talk.
|
|
71
|
+
*/
|
|
72
|
+
private onMessage;
|
|
73
|
+
/**
|
|
74
|
+
* Send a JSON-RPC request to the peer.
|
|
75
|
+
*
|
|
76
|
+
* @param method - The JSON-RPC method name
|
|
77
|
+
* @param params - The method parameters
|
|
78
|
+
* @returns Promise that resolves with the result or rejects with error
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* const result = await this.request("ui/message", {
|
|
82
|
+
* role: "user",
|
|
83
|
+
* content: { type: "text", text: "Hello" }
|
|
84
|
+
* });
|
|
85
|
+
*/
|
|
86
|
+
protected request<TParams = unknown, TResult = unknown>(method: string, params: TParams): Promise<TResult>;
|
|
87
|
+
/**
|
|
88
|
+
* Send a JSON-RPC notification to the peer.
|
|
89
|
+
*
|
|
90
|
+
* Notifications are one-way messages that do not expect a response.
|
|
91
|
+
* Use notifications for:
|
|
92
|
+
* - Informing the host of state changes
|
|
93
|
+
* - Fire-and-forget operations
|
|
94
|
+
* - Events that don't require confirmation
|
|
95
|
+
*
|
|
96
|
+
* Use request() instead when you need:
|
|
97
|
+
* - A response from the host
|
|
98
|
+
* - Confirmation of success/failure
|
|
99
|
+
* - Return values from the operation
|
|
100
|
+
*
|
|
101
|
+
* @param method - The JSON-RPC method name
|
|
102
|
+
* @param params - Optional method parameters
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* this.sendNotification("ui/notifications/size-changed", {
|
|
106
|
+
* width: 800,
|
|
107
|
+
* height: 600
|
|
108
|
+
* });
|
|
109
|
+
*/
|
|
110
|
+
protected sendNotification<TParams = unknown>(method: string, params?: TParams): void;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=jsonrpc-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc-client.d.ts","sourceRoot":"","sources":["../src/jsonrpc-client.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;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;;;;OAIG;gBACS,SAAS,EAAE,SAAS;IAMhC;;;;;;;;;;;;;;;OAeG;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"}
|
|
@@ -0,0 +1,152 @@
|
|
|
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 runtime guards for implementing
|
|
10
|
+
* JSON-RPC 2.0 as specified in https://www.jsonrpc.org/specification.
|
|
11
|
+
*
|
|
12
|
+
* JSON-RPC 2.0 is a stateless, light-weight remote procedure call (RPC)
|
|
13
|
+
* protocol. Used for cross-realm communication via postMessage in iframe-
|
|
14
|
+
* embedded surfaces (MCP Apps, sf-embedding, and any future surface that
|
|
15
|
+
* speaks the same wire format).
|
|
16
|
+
*
|
|
17
|
+
* Protocol extension: this module relaxes JSON-RPC 2.0's "no other
|
|
18
|
+
* members" rule for one optional `_meta` field on every envelope. The
|
|
19
|
+
* underscore signals "protocol-meta, not method semantics." `_meta`
|
|
20
|
+
* carries fields applying to every method uniformly (currently `traceId`);
|
|
21
|
+
* method-specific data lives in `params` / `result` / `error`.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Creating a request
|
|
25
|
+
* const request: JsonRpcRequest = {
|
|
26
|
+
* jsonrpc: "2.0",
|
|
27
|
+
* id: 1,
|
|
28
|
+
* method: "ui/message",
|
|
29
|
+
* params: { role: "user", content: { type: "text", text: "Hello" } }
|
|
30
|
+
* };
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Validating a response
|
|
34
|
+
* window.addEventListener("message", (event) => {
|
|
35
|
+
* if (isJsonRpcResponse(event.data)) {
|
|
36
|
+
* if (isJsonRpcErrorResponse(event.data)) {
|
|
37
|
+
* console.error("Error:", event.data.error.message);
|
|
38
|
+
* } else {
|
|
39
|
+
* console.log("Result:", event.data.result);
|
|
40
|
+
* }
|
|
41
|
+
* }
|
|
42
|
+
* });
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* Protocol-meta envelope. Future minors may add fields additively; old peers
|
|
46
|
+
* ignore unknown fields per the standard JSON-RPC forward-compat behavior.
|
|
47
|
+
*/
|
|
48
|
+
export interface JsonRpcMeta {
|
|
49
|
+
/** Per-request trace identifier for cross-realm log correlation. */
|
|
50
|
+
traceId?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* JSON-RPC 2.0 base message with the required version field and the
|
|
54
|
+
* optional `_meta` extension.
|
|
55
|
+
*/
|
|
56
|
+
export interface JsonRpcBase {
|
|
57
|
+
jsonrpc: "2.0";
|
|
58
|
+
_meta?: JsonRpcMeta;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* JSON-RPC 2.0 Request — has both `id` and `method`.
|
|
62
|
+
*/
|
|
63
|
+
export interface JsonRpcRequest<TParams = unknown> extends JsonRpcBase {
|
|
64
|
+
id: number;
|
|
65
|
+
method: string;
|
|
66
|
+
params?: TParams;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* JSON-RPC 2.0 Notification — has `method` but NO `id`. Fire-and-forget.
|
|
70
|
+
*/
|
|
71
|
+
export interface JsonRpcNotification<TParams = unknown> extends JsonRpcBase {
|
|
72
|
+
method: string;
|
|
73
|
+
params?: TParams;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* JSON-RPC 2.0 Success Response — has `id` and `result`.
|
|
77
|
+
*/
|
|
78
|
+
export interface JsonRpcSuccessResponse<TResult = unknown> extends JsonRpcBase {
|
|
79
|
+
id: number;
|
|
80
|
+
result: TResult;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* JSON-RPC 2.0 Error payload (carried under `error` on an error response).
|
|
84
|
+
*/
|
|
85
|
+
export interface JsonRpcError {
|
|
86
|
+
code: number;
|
|
87
|
+
message?: string;
|
|
88
|
+
data?: unknown;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* JSON-RPC 2.0 Error Response — has `id` and `error`.
|
|
92
|
+
*/
|
|
93
|
+
export interface JsonRpcErrorResponse extends JsonRpcBase {
|
|
94
|
+
id: number;
|
|
95
|
+
error: JsonRpcError;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Either flavor of response.
|
|
99
|
+
*/
|
|
100
|
+
export type JsonRpcResponse<TResult = unknown> = JsonRpcSuccessResponse<TResult> | JsonRpcErrorResponse;
|
|
101
|
+
/**
|
|
102
|
+
* Any JSON-RPC frame the dispatcher might receive.
|
|
103
|
+
*/
|
|
104
|
+
export type JsonRpcFrame = JsonRpcRequest | JsonRpcNotification | JsonRpcResponse;
|
|
105
|
+
/**
|
|
106
|
+
* Pending-request resolver pair, used by the JsonRpcClient to track
|
|
107
|
+
* in-flight requests waiting for their terminal response.
|
|
108
|
+
*/
|
|
109
|
+
export interface JsonRpcPendingRequest {
|
|
110
|
+
resolve: (value: unknown) => void;
|
|
111
|
+
reject: (error: unknown) => void;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Map of pending JSON-RPC requests by numeric ID.
|
|
115
|
+
*/
|
|
116
|
+
export type JsonRpcPendingRequestMap = Map<number, JsonRpcPendingRequest>;
|
|
117
|
+
/**
|
|
118
|
+
* Type guard: returns true if the value carries the JSON-RPC 2.0 envelope
|
|
119
|
+
* marker. Building block for the more specific guards below.
|
|
120
|
+
*/
|
|
121
|
+
export declare function isJsonRpcBase(value: unknown): value is JsonRpcBase;
|
|
122
|
+
/**
|
|
123
|
+
* Type guard: a well-formed request — has `jsonrpc: "2.0"`, a non-negative
|
|
124
|
+
* integer `id`, and a string `method`.
|
|
125
|
+
*/
|
|
126
|
+
export declare function isJsonRpcRequest(value: unknown): value is JsonRpcRequest;
|
|
127
|
+
/**
|
|
128
|
+
* Type guard: a well-formed notification — has `method` AND no `id` property.
|
|
129
|
+
*/
|
|
130
|
+
export declare function isJsonRpcNotification(value: unknown): value is JsonRpcNotification;
|
|
131
|
+
/**
|
|
132
|
+
* Type guard: a well-formed success response — has `id` + `result`,
|
|
133
|
+
* and does NOT carry `error` or `method` (which would make it ambiguous
|
|
134
|
+
* with error responses or requests/notifications).
|
|
135
|
+
*/
|
|
136
|
+
export declare function isJsonRpcSuccessResponse(value: unknown): value is JsonRpcSuccessResponse;
|
|
137
|
+
/**
|
|
138
|
+
* Type guard: a well-formed error response — has `id`, an `error` whose
|
|
139
|
+
* `code` is numeric, and does NOT carry `result` or `method`.
|
|
140
|
+
*/
|
|
141
|
+
export declare function isJsonRpcErrorResponse(value: unknown): value is JsonRpcErrorResponse;
|
|
142
|
+
/**
|
|
143
|
+
* Type guard: any well-formed response (success or error).
|
|
144
|
+
*/
|
|
145
|
+
export declare function isJsonRpcResponse(value: unknown): value is JsonRpcResponse;
|
|
146
|
+
/**
|
|
147
|
+
* Type guard: a JSON-RPC error payload (the value carried under `error`
|
|
148
|
+
* on an error response). Useful for callers handling rejected promises
|
|
149
|
+
* from the JsonRpcClient.
|
|
150
|
+
*/
|
|
151
|
+
export declare function isJsonRpcError(value: unknown): value is JsonRpcError;
|
|
152
|
+
//# sourceMappingURL=jsonrpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc.d.ts","sourceRoot":"","sources":["../src/jsonrpc.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC3B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,CAAC,EAAE,WAAW,CAAC;CACpB;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,mBAAmB,CAAC,OAAO,GAAG,OAAO,CAAE,SAAQ,WAAW;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;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,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,YAAY,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,OAAO,GAAG,OAAO,IAC1C,sBAAsB,CAAC,OAAO,CAAC,GAC/B,oBAAoB,CAAC;AAExB;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,mBAAmB,GAAG,eAAe,CAAC;AAElF;;;GAGG;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;AAmB1E;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAIxE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAIlF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAIxF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAOpF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAEpE"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Transport } from './transport';
|
|
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
|
+
* `Transport` backed by a `MessagePort`.
|
|
10
|
+
*
|
|
11
|
+
* During an 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
|
+
* Contract (symmetric with the `Transport` interface defined alongside
|
|
20
|
+
* `WindowPostMessageTransport`):
|
|
21
|
+
*
|
|
22
|
+
* - `post(msg)` never throws on transient failure. A closed / neutered /
|
|
23
|
+
* disposed port silently drops the message. This matches the
|
|
24
|
+
* optional-chaining behaviour of `WindowPostMessageTransport.post`.
|
|
25
|
+
* - `onMessage(cb)` delivers the **unwrapped** payload (`MessageEvent.data`),
|
|
26
|
+
* not the raw `MessageEvent`. Returns an unsubscribe function.
|
|
27
|
+
* - The port is started (`port.start()`) lazily on the first `onMessage`
|
|
28
|
+
* subscription. Messages queued via `post` before that first subscribe
|
|
29
|
+
* are buffered in-process and flushed FIFO when the port starts.
|
|
30
|
+
* - `dispose()` removes listeners, closes the port, clears the outbound
|
|
31
|
+
* buffer, and puts the transport into a terminal state where further
|
|
32
|
+
* `post` calls silently no-op and further `onMessage` calls return a
|
|
33
|
+
* no-op unsubscribe.
|
|
34
|
+
*
|
|
35
|
+
* Usage from the container bootstrap:
|
|
36
|
+
* ```ts
|
|
37
|
+
* const transport = new MessageChannelTransport(event.ports[0]);
|
|
38
|
+
* // Hand the transport to the session layer; subscription drives start().
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare class MessageChannelTransport implements Transport {
|
|
42
|
+
#private;
|
|
43
|
+
constructor(port: MessagePort);
|
|
44
|
+
/**
|
|
45
|
+
* Post a message to the peer.
|
|
46
|
+
*
|
|
47
|
+
* Never throws on transient failure — a closed / neutered / disposed
|
|
48
|
+
* port silently drops the message. If the transport has not yet
|
|
49
|
+
* started (no `onMessage` subscriber), the message is buffered and
|
|
50
|
+
* flushed on first subscription.
|
|
51
|
+
*/
|
|
52
|
+
post(message: unknown): void;
|
|
53
|
+
/**
|
|
54
|
+
* Subscribe to inbound messages from the peer. The callback receives
|
|
55
|
+
* the **unwrapped** payload (`MessageEvent.data`) — callers never see
|
|
56
|
+
* the `MessageEvent` wrapper.
|
|
57
|
+
*
|
|
58
|
+
* Starts the underlying port on first subscription and flushes any
|
|
59
|
+
* messages queued via `post` before the port was started.
|
|
60
|
+
*
|
|
61
|
+
* Returns an unsubscribe function. Calling it is idempotent.
|
|
62
|
+
*/
|
|
63
|
+
onMessage(callback: MessageChannelTransportListener): () => void;
|
|
64
|
+
/**
|
|
65
|
+
* Tear down the transport:
|
|
66
|
+
* - remove the internal `message` listener
|
|
67
|
+
* - call `port.close()`
|
|
68
|
+
* - clear subscriber set and outbound buffer
|
|
69
|
+
* - subsequent `post` calls silently no-op
|
|
70
|
+
* - subsequent `onMessage` calls return a no-op unsubscribe
|
|
71
|
+
*/
|
|
72
|
+
dispose(): void;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=message-channel-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-channel-transport.d.ts","sourceRoot":"","sources":["../src/message-channel-transport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;GAIG;AACH,MAAM,MAAM,+BAA+B,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;AAUrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Abstract transport for a JSON-RPC 2.0 client.
|
|
8
|
+
*
|
|
9
|
+
* A `Transport` is a bidirectional, structured-message pipe. The
|
|
10
|
+
* `JsonRpcClient` uses it to send JSON-RPC messages (`post`) and subscribe
|
|
11
|
+
* to inbound ones (`onMessage`). The transport itself is agnostic to the
|
|
12
|
+
* JSON-RPC framing — it simply moves `unknown` payloads between two
|
|
13
|
+
* endpoints.
|
|
14
|
+
*
|
|
15
|
+
* Concrete transports plug into the same shape:
|
|
16
|
+
* - `WindowPostMessageTransport` (window.parent.postMessage; used by
|
|
17
|
+
* MCP Apps)
|
|
18
|
+
* - `MessageChannelTransport` (a transferred `MessagePort`; used by
|
|
19
|
+
* sf-embedding and any future surface that bootstraps with a
|
|
20
|
+
* dedicated channel)
|
|
21
|
+
*/
|
|
22
|
+
export interface Transport {
|
|
23
|
+
/**
|
|
24
|
+
* Deliver a single structured message to the peer. Implementations MUST
|
|
25
|
+
* NOT throw on transient conditions (closed port, missing parent
|
|
26
|
+
* window, etc.) — drop the message silently instead, matching the
|
|
27
|
+
* prior `window.parent?.postMessage` behaviour.
|
|
28
|
+
*/
|
|
29
|
+
post(message: unknown): void;
|
|
30
|
+
/**
|
|
31
|
+
* Subscribe to inbound structured messages from the peer. The callback
|
|
32
|
+
* receives the already-unwrapped message payload (never a
|
|
33
|
+
* `MessageEvent`).
|
|
34
|
+
*
|
|
35
|
+
* @returns an unsubscribe function that removes this listener.
|
|
36
|
+
*/
|
|
37
|
+
onMessage(callback: (message: unknown) => void): () => void;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,SAAS;IACzB;;;;;OAKG;IACH,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAE7B;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC5D"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Transport } from './transport';
|
|
2
|
+
/**
|
|
3
|
+
* Default `Transport` backing the JSON-RPC client in an iframe context.
|
|
4
|
+
*
|
|
5
|
+
* Outbound messages go to `window.parent` via `postMessage(msg, targetOrigin)`,
|
|
6
|
+
* and inbound messages come from `window.addEventListener("message", ...)`
|
|
7
|
+
* with only the `event.data` payload forwarded to subscribers.
|
|
8
|
+
*
|
|
9
|
+
* Missing `window.parent` (e.g. top-level document) is tolerated: `post` is a
|
|
10
|
+
* no-op, matching the prior optional-chaining behaviour.
|
|
11
|
+
*/
|
|
12
|
+
export declare class WindowPostMessageTransport implements Transport {
|
|
13
|
+
private readonly targetOrigin;
|
|
14
|
+
/**
|
|
15
|
+
* @param targetOrigin - origin passed as the second argument to
|
|
16
|
+
* `window.parent.postMessage`.
|
|
17
|
+
*/
|
|
18
|
+
constructor(targetOrigin: string);
|
|
19
|
+
post(message: unknown): void;
|
|
20
|
+
onMessage(callback: (message: unknown) => void): () => void;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=window-postmessage-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"window-postmessage-transport.d.ts","sourceRoot":"","sources":["../src/window-postmessage-transport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;;;;;;GASG;AACH,qBAAa,0BAA2B,YAAW,SAAS;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC;;;OAGG;gBACS,YAAY,EAAE,MAAM;IAIhC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI5B,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;CAO3D"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@salesforce/jsonrpc",
|
|
3
|
+
"version": "9.13.0",
|
|
4
|
+
"description": "Shareable JSON-RPC 2.0 primitives for cross-realm communication: envelope types and runtime guards, the request/response engine (JsonRpcClient), and transport adapters.",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"sideEffects": false,
|
|
11
|
+
"exports": {
|
|
12
|
+
"./package.json": "./package.json",
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "vite build",
|
|
24
|
+
"clean": "rm -rf dist",
|
|
25
|
+
"dev": "vite build --watch",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"test:watch": "vitest",
|
|
28
|
+
"test:coverage": "vitest run --coverage"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"vite": "^7.3.1",
|
|
32
|
+
"vite-plugin-dts": "^4.5.4",
|
|
33
|
+
"vitest": "^4.0.6"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
}
|
|
38
|
+
}
|