rimless 0.7.0 → 0.7.1
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/lib/helpers.d.ts +6 -0
- package/lib/rimless.js +190 -169
- package/lib/rimless.js.map +1 -1
- package/lib/rimless.min.js +1 -1
- package/lib/rimless.min.js.map +1 -1
- package/package.json +1 -1
package/lib/helpers.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { Guest, NodeWorker, Target, WorkerLike } from './types';
|
|
2
|
+
type RuntimeEnvironment = "browser" | "worker" | "node" | "bun";
|
|
3
|
+
export declare function getRuntimeEnvironment(): RuntimeEnvironment;
|
|
4
|
+
export declare function isBrowserEnv(): boolean;
|
|
2
5
|
/**
|
|
3
6
|
* check if run in a webworker
|
|
4
7
|
*
|
|
@@ -11,6 +14,8 @@ export declare function isWorker(): boolean;
|
|
|
11
14
|
* @returns boolean
|
|
12
15
|
*/
|
|
13
16
|
export declare function isNodeEnv(): boolean;
|
|
17
|
+
export declare function isBunEnv(): boolean;
|
|
18
|
+
export declare function isServerEnv(): boolean;
|
|
14
19
|
/**
|
|
15
20
|
* check if run in an iframe
|
|
16
21
|
*
|
|
@@ -56,3 +61,4 @@ export declare function removeEventListener(target: Target, event: string, handl
|
|
|
56
61
|
* In Node.js, the event itself contains the data
|
|
57
62
|
*/
|
|
58
63
|
export declare function getEventData(event: any): any;
|
|
64
|
+
export {};
|
package/lib/rimless.js
CHANGED
|
@@ -1,260 +1,281 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
1
|
+
function K() {
|
|
2
|
+
const e = globalThis;
|
|
3
|
+
if (typeof e.window < "u" && typeof e.document < "u")
|
|
4
|
+
return "browser";
|
|
5
|
+
if (typeof e.WorkerGlobalScope < "u" && typeof e.self < "u" && e.self instanceof e.WorkerGlobalScope || typeof e.window > "u" && typeof e.self < "u" && typeof e.importScripts == "function")
|
|
6
|
+
return "worker";
|
|
7
|
+
const t = e.process;
|
|
8
|
+
if (t && typeof t == "object") {
|
|
9
|
+
const n = t.versions ?? {}, s = t.release?.name;
|
|
10
|
+
if (n.bun || s === "bun" || typeof e.Bun < "u")
|
|
11
|
+
return "bun";
|
|
12
|
+
if (n.node && s === "node")
|
|
13
|
+
return "node";
|
|
14
|
+
}
|
|
15
|
+
return typeof e.Bun < "u" ? "bun" : "browser";
|
|
3
16
|
}
|
|
4
|
-
function
|
|
5
|
-
return
|
|
17
|
+
function H() {
|
|
18
|
+
return K();
|
|
6
19
|
}
|
|
7
|
-
function
|
|
20
|
+
function b() {
|
|
21
|
+
return H() === "worker";
|
|
22
|
+
}
|
|
23
|
+
function g() {
|
|
24
|
+
const e = H();
|
|
25
|
+
return e === "node" || e === "bun";
|
|
26
|
+
}
|
|
27
|
+
function U() {
|
|
8
28
|
return window.self !== window.top;
|
|
9
29
|
}
|
|
10
|
-
function
|
|
11
|
-
const
|
|
12
|
-
return function
|
|
13
|
-
Object.keys(
|
|
14
|
-
const c = s ? `${s}.${
|
|
15
|
-
|
|
30
|
+
function O(e) {
|
|
31
|
+
const o = {};
|
|
32
|
+
return function t(n, s = "") {
|
|
33
|
+
Object.keys(n).forEach((r) => {
|
|
34
|
+
const c = s ? `${s}.${r}` : r;
|
|
35
|
+
n[r] === Object(n[r]) && t(n[r], c), typeof n[r] == "function" && (o[c] = n[r], delete n[r]);
|
|
16
36
|
});
|
|
17
|
-
}(
|
|
37
|
+
}(e), o;
|
|
18
38
|
}
|
|
19
|
-
const
|
|
20
|
-
function
|
|
21
|
-
if (!
|
|
22
|
-
const
|
|
23
|
-
if (!
|
|
24
|
-
const [,
|
|
25
|
-
if (
|
|
39
|
+
const Q = /^(https?:|file:)?\/\/([^/:]+)?(:(\d+))?/, Y = { "http:": "80", "https:": "443" };
|
|
40
|
+
function $(e) {
|
|
41
|
+
if (!e) return null;
|
|
42
|
+
const o = Q.exec(e);
|
|
43
|
+
if (!o) return null;
|
|
44
|
+
const [, t = "http:", n, , s] = o;
|
|
45
|
+
if (t === "file:")
|
|
26
46
|
return "file://";
|
|
27
|
-
const
|
|
28
|
-
return `${
|
|
47
|
+
const r = s && s !== Y[t] ? `:${s}` : "";
|
|
48
|
+
return `${t}//${n}${r}`;
|
|
29
49
|
}
|
|
30
|
-
function
|
|
31
|
-
if (!
|
|
32
|
-
const
|
|
33
|
-
let s =
|
|
34
|
-
for (let
|
|
35
|
-
const c =
|
|
36
|
-
|
|
50
|
+
function x(e, o, t) {
|
|
51
|
+
if (!e || typeof e != "object") return e;
|
|
52
|
+
const n = Array.isArray(o) ? o : o.split(".").map((r) => r.match(/^\d+$/) ? Number(r) : r);
|
|
53
|
+
let s = e;
|
|
54
|
+
for (let r = 0; r < n.length; r++) {
|
|
55
|
+
const c = n[r];
|
|
56
|
+
r === n.length - 1 ? s[c] = t : ((!s[c] || typeof s[c] != "object") && (s[c] = typeof n[r + 1] == "number" ? [] : {}), s = s[c]);
|
|
37
57
|
}
|
|
38
|
-
return
|
|
58
|
+
return e;
|
|
39
59
|
}
|
|
40
|
-
function C(
|
|
41
|
-
const
|
|
42
|
-
let
|
|
43
|
-
for (let
|
|
44
|
-
|
|
45
|
-
return
|
|
60
|
+
function C(e = 10) {
|
|
61
|
+
const o = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
62
|
+
let t = "";
|
|
63
|
+
for (let n = 0; n < e; n++)
|
|
64
|
+
t += o.charAt(Math.floor(Math.random() * o.length));
|
|
65
|
+
return t;
|
|
46
66
|
}
|
|
47
|
-
|
|
48
|
-
|
|
67
|
+
const _ = H();
|
|
68
|
+
let D = null;
|
|
69
|
+
if (_ === "node" || _ === "bun")
|
|
49
70
|
try {
|
|
50
|
-
|
|
71
|
+
D = require("worker_threads").parentPort;
|
|
51
72
|
} catch {
|
|
52
73
|
}
|
|
53
|
-
function
|
|
54
|
-
if (
|
|
55
|
-
return
|
|
56
|
-
if (
|
|
74
|
+
function J() {
|
|
75
|
+
if (g())
|
|
76
|
+
return D;
|
|
77
|
+
if (b())
|
|
57
78
|
return self;
|
|
58
|
-
if (
|
|
79
|
+
if (U())
|
|
59
80
|
return window.parent;
|
|
60
81
|
throw new Error("No valid target found for postMessage");
|
|
61
82
|
}
|
|
62
|
-
function
|
|
63
|
-
if (!
|
|
83
|
+
function M(e, o, t, n) {
|
|
84
|
+
if (!e)
|
|
64
85
|
throw new Error("Rimless Error: No target specified for postMessage");
|
|
65
|
-
if (
|
|
66
|
-
|
|
86
|
+
if (g() && e === D) {
|
|
87
|
+
e.postMessage(o, { transfer: n });
|
|
67
88
|
return;
|
|
68
89
|
}
|
|
69
|
-
if (
|
|
70
|
-
|
|
90
|
+
if (b()) {
|
|
91
|
+
e.postMessage(o, { transfer: n });
|
|
71
92
|
return;
|
|
72
93
|
}
|
|
73
|
-
if (
|
|
74
|
-
|
|
94
|
+
if (e.postMessage) {
|
|
95
|
+
e.postMessage(o, { targetOrigin: t || "*", transfer: n });
|
|
75
96
|
return;
|
|
76
97
|
}
|
|
77
98
|
throw new Error("Rimless Error: Invalid target for postMessage");
|
|
78
99
|
}
|
|
79
|
-
function
|
|
80
|
-
return
|
|
100
|
+
function k(e) {
|
|
101
|
+
return D !== null && e === D;
|
|
81
102
|
}
|
|
82
|
-
function
|
|
83
|
-
return
|
|
103
|
+
function V(e) {
|
|
104
|
+
return k(e) || typeof Worker < "u" && e instanceof Worker;
|
|
84
105
|
}
|
|
85
|
-
function L(
|
|
86
|
-
|
|
106
|
+
function L(e, o, t) {
|
|
107
|
+
k(e) ? e.on(o, t) : "addEventListener" in e && e.addEventListener(o, t);
|
|
87
108
|
}
|
|
88
|
-
function N(
|
|
89
|
-
|
|
109
|
+
function N(e, o, t) {
|
|
110
|
+
k(e) ? e.off(o, t) : "removeEventListener" in e && e.removeEventListener(o, t);
|
|
90
111
|
}
|
|
91
|
-
function P(
|
|
92
|
-
return
|
|
112
|
+
function P(e) {
|
|
113
|
+
return e.data || e;
|
|
93
114
|
}
|
|
94
|
-
var h = /* @__PURE__ */ ((
|
|
95
|
-
const
|
|
96
|
-
function
|
|
97
|
-
const
|
|
98
|
-
for (const [c,
|
|
99
|
-
async function
|
|
100
|
-
const
|
|
101
|
-
if (m !==
|
|
115
|
+
var h = /* @__PURE__ */ ((e) => (e.MESSAGE = "message", e))(h || {}), a = /* @__PURE__ */ ((e) => (e.HANDSHAKE_REQUEST = "RIMLESS/HANDSHAKE_REQUEST", e.HANDSHAKE_REPLY = "RIMLESS/HANDSHAKE_REPLY", e.RPC_REQUEST = "RIMLESS/RPC_REQUEST", e.RPC_RESOLVE = "RIMLESS/RPC_RESOLVE", e.RPC_REJECT = "RIMLESS/RPC_REJECT", e))(a || {});
|
|
116
|
+
const y = Symbol();
|
|
117
|
+
function G(e = {}, o, t, n, s) {
|
|
118
|
+
const r = [];
|
|
119
|
+
for (const [c, u] of Object.entries(e)) {
|
|
120
|
+
async function f(i) {
|
|
121
|
+
const l = P(i), { action: m, callID: R, connectionID: E, callName: d, args: p = [] } = l;
|
|
122
|
+
if (m !== a.RPC_REQUEST || !R || !d || d !== c || E !== o) return;
|
|
102
123
|
const S = {
|
|
103
|
-
action:
|
|
124
|
+
action: a.RPC_RESOLVE,
|
|
104
125
|
callID: R,
|
|
105
126
|
callName: d,
|
|
106
|
-
connectionID:
|
|
127
|
+
connectionID: E,
|
|
107
128
|
error: null,
|
|
108
129
|
result: null
|
|
109
130
|
};
|
|
110
|
-
let
|
|
131
|
+
let w;
|
|
111
132
|
try {
|
|
112
|
-
S.result = await
|
|
133
|
+
S.result = await u(...p, s), S.result && S.result[y] && (w = S.result[y] ?? [], delete S.result[y]);
|
|
113
134
|
} catch (I) {
|
|
114
|
-
S.action =
|
|
135
|
+
S.action = a.RPC_REJECT, S.error = JSON.parse(JSON.stringify(I, Object.getOwnPropertyNames(I)));
|
|
115
136
|
}
|
|
116
|
-
|
|
137
|
+
M(n, S, i?.origin, w);
|
|
117
138
|
}
|
|
118
|
-
L(
|
|
139
|
+
L(t, h.MESSAGE, f), r.push(() => N(t, h.MESSAGE, f));
|
|
119
140
|
}
|
|
120
|
-
return () =>
|
|
141
|
+
return () => r.forEach((c) => c());
|
|
121
142
|
}
|
|
122
|
-
function
|
|
123
|
-
return (...c) => new Promise((
|
|
143
|
+
function q(e, o, t, n = [], s, r) {
|
|
144
|
+
return (...c) => new Promise((u, f) => {
|
|
124
145
|
const i = C();
|
|
125
|
-
function E
|
|
126
|
-
const d = P(
|
|
127
|
-
if (!(!p || !
|
|
128
|
-
if (T ===
|
|
129
|
-
if (T ===
|
|
146
|
+
function l(E) {
|
|
147
|
+
const d = P(E), { callID: p, connectionID: S, callName: w, result: I, error: W, action: T } = d;
|
|
148
|
+
if (!(!p || !w) && w === e && p === i && S === o) {
|
|
149
|
+
if (T === a.RPC_RESOLVE) return u(I);
|
|
150
|
+
if (T === a.RPC_REJECT) return f(W);
|
|
130
151
|
}
|
|
131
152
|
}
|
|
132
153
|
const m = {
|
|
133
|
-
action:
|
|
154
|
+
action: a.RPC_REQUEST,
|
|
134
155
|
args: c,
|
|
135
156
|
callID: i,
|
|
136
|
-
callName:
|
|
137
|
-
connectionID:
|
|
157
|
+
callName: e,
|
|
158
|
+
connectionID: o
|
|
138
159
|
}, R = c.reduce(
|
|
139
|
-
(
|
|
160
|
+
(E, d) => d[y]?.length ? E.concat(d[y]) : E,
|
|
140
161
|
// @ts-expect-error: we know this is an array of transferables (if it exists)
|
|
141
|
-
c[
|
|
162
|
+
c[y] ?? []
|
|
142
163
|
);
|
|
143
|
-
L(s, h.MESSAGE,
|
|
164
|
+
L(s, h.MESSAGE, l), n.push(() => N(s, h.MESSAGE, l)), M(r, m, t?.origin, R);
|
|
144
165
|
});
|
|
145
166
|
}
|
|
146
|
-
function v(
|
|
147
|
-
const c = { ...
|
|
148
|
-
for (const
|
|
149
|
-
const i =
|
|
150
|
-
|
|
167
|
+
function v(e = {}, o = [], t, n, s, r) {
|
|
168
|
+
const c = { ...e }, u = [];
|
|
169
|
+
for (const f of o) {
|
|
170
|
+
const i = q(f, t, n, u, s, r);
|
|
171
|
+
x(c, f, i);
|
|
151
172
|
}
|
|
152
173
|
return {
|
|
153
174
|
remote: c,
|
|
154
|
-
unregisterRemote: () =>
|
|
175
|
+
unregisterRemote: () => u.forEach((f) => f())
|
|
155
176
|
};
|
|
156
177
|
}
|
|
157
|
-
const
|
|
158
|
-
const
|
|
159
|
-
return Object.assign(
|
|
178
|
+
const z = (e) => {
|
|
179
|
+
const o = [], n = e((s) => (o.push(s), s));
|
|
180
|
+
return Object.assign(n, { [y]: o });
|
|
160
181
|
};
|
|
161
|
-
function
|
|
162
|
-
return new Promise(async (
|
|
163
|
-
const
|
|
164
|
-
async function c(
|
|
165
|
-
const i = P(
|
|
166
|
-
if (i?.action !==
|
|
167
|
-
const { remote:
|
|
182
|
+
function B(e = {}, o) {
|
|
183
|
+
return new Promise(async (t) => {
|
|
184
|
+
const n = O(e), s = J(), r = self || window;
|
|
185
|
+
async function c(f) {
|
|
186
|
+
const i = P(f);
|
|
187
|
+
if (i?.action !== a.HANDSHAKE_REPLY) return;
|
|
188
|
+
const { remote: l, unregisterRemote: m } = v(
|
|
168
189
|
i.schema,
|
|
169
190
|
i.methodNames,
|
|
170
191
|
i.connectionID,
|
|
171
|
-
|
|
172
|
-
|
|
192
|
+
f,
|
|
193
|
+
r,
|
|
173
194
|
s
|
|
174
|
-
), R =
|
|
175
|
-
await
|
|
176
|
-
const
|
|
177
|
-
action:
|
|
195
|
+
), R = G(n, i.connectionID, r, s, l);
|
|
196
|
+
await o?.onConnectionSetup?.(l);
|
|
197
|
+
const E = {
|
|
198
|
+
action: a.HANDSHAKE_REPLY,
|
|
178
199
|
connectionID: i.connectionID
|
|
179
200
|
};
|
|
180
|
-
|
|
181
|
-
const p = { remote:
|
|
182
|
-
N(
|
|
201
|
+
M(s, E, f?.origin);
|
|
202
|
+
const p = { remote: l, close: () => {
|
|
203
|
+
N(r, h.MESSAGE, c), m(), R();
|
|
183
204
|
}, id: i.connectionID };
|
|
184
|
-
return
|
|
205
|
+
return t(p);
|
|
185
206
|
}
|
|
186
|
-
L(
|
|
187
|
-
const
|
|
188
|
-
action:
|
|
189
|
-
methodNames: Object.keys(
|
|
190
|
-
schema:
|
|
207
|
+
L(r, h.MESSAGE, c);
|
|
208
|
+
const u = {
|
|
209
|
+
action: a.HANDSHAKE_REQUEST,
|
|
210
|
+
methodNames: Object.keys(n),
|
|
211
|
+
schema: e
|
|
191
212
|
};
|
|
192
|
-
|
|
213
|
+
M(s, u);
|
|
193
214
|
});
|
|
194
215
|
}
|
|
195
|
-
const
|
|
196
|
-
connect:
|
|
197
|
-
},
|
|
198
|
-
function
|
|
199
|
-
if (
|
|
216
|
+
const X = {
|
|
217
|
+
connect: B
|
|
218
|
+
}, A = {};
|
|
219
|
+
function F(e, o) {
|
|
220
|
+
if (k(e) || typeof Worker < "u" && e instanceof Worker)
|
|
200
221
|
return !0;
|
|
201
|
-
const
|
|
222
|
+
const t = e;
|
|
202
223
|
try {
|
|
203
|
-
const
|
|
204
|
-
return s ||
|
|
205
|
-
} catch (
|
|
206
|
-
return console.warn("Error checking iframe target:",
|
|
224
|
+
const n = t.src, s = typeof t.srcdoc == "string" && t.srcdoc.length > 0, r = $(n), c = o.origin === r, u = o.source === t.contentWindow;
|
|
225
|
+
return s || n === "about:blank" ? u : c && u || !n;
|
|
226
|
+
} catch (n) {
|
|
227
|
+
return console.warn("Error checking iframe target:", n), !1;
|
|
207
228
|
}
|
|
208
229
|
}
|
|
209
|
-
function
|
|
210
|
-
if (!
|
|
211
|
-
const
|
|
230
|
+
function j(e, o = {}) {
|
|
231
|
+
if (!e) throw new Error("a target is required");
|
|
232
|
+
const t = V(e), n = t || g() ? e : window;
|
|
212
233
|
return new Promise((s) => {
|
|
213
|
-
const
|
|
214
|
-
function c(
|
|
215
|
-
const i =
|
|
216
|
-
if (!
|
|
217
|
-
const
|
|
218
|
-
if (
|
|
219
|
-
const m =
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
234
|
+
const r = C();
|
|
235
|
+
function c(f) {
|
|
236
|
+
const i = t || g() ? e : f.source;
|
|
237
|
+
if (!t && !g() && !F(e, f)) return;
|
|
238
|
+
const l = P(f);
|
|
239
|
+
if (l?.action !== a.HANDSHAKE_REQUEST || A[r]) return;
|
|
240
|
+
const m = O(o), { remote: R, unregisterRemote: E } = v(
|
|
241
|
+
l.schema,
|
|
242
|
+
l.methodNames,
|
|
243
|
+
r,
|
|
244
|
+
f,
|
|
245
|
+
n,
|
|
225
246
|
i
|
|
226
|
-
), d =
|
|
227
|
-
action:
|
|
228
|
-
connectionID:
|
|
229
|
-
schema:
|
|
247
|
+
), d = G(m, r, n, i, R), p = {
|
|
248
|
+
action: a.HANDSHAKE_REPLY,
|
|
249
|
+
connectionID: r,
|
|
250
|
+
schema: o,
|
|
230
251
|
methodNames: Object.keys(m)
|
|
231
252
|
};
|
|
232
|
-
|
|
233
|
-
const
|
|
234
|
-
delete
|
|
235
|
-
}, id:
|
|
236
|
-
|
|
253
|
+
M(i, p, f.origin);
|
|
254
|
+
const w = { remote: R, close: () => {
|
|
255
|
+
delete A[r], N(n, h.MESSAGE, c), N(n, h.MESSAGE, u), E(), d(), t && e.terminate();
|
|
256
|
+
}, id: r };
|
|
257
|
+
A[r] = w;
|
|
237
258
|
}
|
|
238
|
-
L(
|
|
239
|
-
function f
|
|
240
|
-
const i = P(
|
|
241
|
-
if (i?.action ===
|
|
242
|
-
if (!
|
|
259
|
+
L(n, h.MESSAGE, c);
|
|
260
|
+
function u(f) {
|
|
261
|
+
const i = P(f);
|
|
262
|
+
if (i?.action === a.HANDSHAKE_REPLY && r === i.connectionID) {
|
|
263
|
+
if (!A[i.connectionID])
|
|
243
264
|
throw new Error("Rimless Error: No connection found for this connectionID");
|
|
244
|
-
return s(
|
|
265
|
+
return s(A[i.connectionID]);
|
|
245
266
|
}
|
|
246
267
|
}
|
|
247
|
-
L(
|
|
268
|
+
L(n, h.MESSAGE, u);
|
|
248
269
|
});
|
|
249
270
|
}
|
|
250
|
-
const
|
|
251
|
-
connect:
|
|
271
|
+
const Z = {
|
|
272
|
+
connect: j
|
|
252
273
|
};
|
|
253
274
|
export {
|
|
254
|
-
|
|
275
|
+
a as actions,
|
|
255
276
|
h as events,
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
277
|
+
X as guest,
|
|
278
|
+
Z as host,
|
|
279
|
+
z as withTransferable
|
|
259
280
|
};
|
|
260
281
|
//# sourceMappingURL=rimless.js.map
|
package/lib/rimless.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rimless.js","sources":["../src/helpers.ts","../src/types.ts","../src/rpc.ts","../src/guest.ts","../src/host.ts"],"sourcesContent":["import { Guest, NodeWorker, Target, WorkerLike } from \"./types\";\n\n/**\n * check if run in a webworker\n *\n * @returns boolean\n */\nexport function isWorker(): boolean {\n return typeof window === \"undefined\" && typeof self !== \"undefined\";\n}\n\n/**\n * check if run in a Node.js environment\n *\n * @returns boolean\n */\nexport function isNodeEnv(): boolean {\n return typeof process !== \"undefined\" && !!(process as any).versions?.node;\n}\n\n/**\n * check if run in an iframe\n *\n * @returns boolean\n */\nexport function isIframe() {\n return window.self !== window.top;\n}\n\n/**\n * we cannot send functions through postMessage\n * extract the path to all functions in the schema\n *\n * @param obj\n */\nexport function extractMethods(obj: any) {\n const methods: Record<string, (...args: any) => any> = {};\n (function parse(obj: any, path = \"\") {\n Object.keys(obj).forEach((prop) => {\n const propPath = path ? `${path}.${prop}` : prop;\n if (obj[prop] === Object(obj[prop])) {\n parse(obj[prop], propPath);\n }\n if (typeof obj[prop] === \"function\") {\n methods[propPath] = obj[prop];\n delete obj[prop];\n }\n });\n })(obj);\n return methods;\n}\n\nconst urlRegex = /^(https?:|file:)?\\/\\/([^/:]+)?(:(\\d+))?/;\nconst ports: any = { \"http:\": \"80\", \"https:\": \"443\" };\n\n/**\n * convert the url into an origin (remove paths)\n *\n * @param url\n */\nexport function getOriginFromURL(url: string | null) {\n if (!url) return null;\n\n const regexResult = urlRegex.exec(url);\n if (!regexResult) return null;\n\n const [, protocol = \"http:\", hostname, , port] = regexResult;\n\n // If the protocol is file, return file://\n if (protocol === \"file:\") {\n return \"file://\";\n }\n\n // If the port is the default for the protocol, we don't want to add it to the origin string\n const portSuffix = port && port !== ports[protocol] ? `:${port}` : \"\";\n return `${protocol}//${hostname}${portSuffix}`;\n}\n\nexport function get(obj: any, path: string | Array<string | number>, defaultValue?: any): any {\n const keys = Array.isArray(path) ? path : path.split(\".\").filter(Boolean);\n let result = obj;\n\n for (const key of keys) {\n result = result?.[key];\n if (result === undefined) {\n return defaultValue;\n }\n }\n\n return result;\n}\n\nexport function set(obj: any, path: string | (string | number)[], value: any): any {\n if (!obj || typeof obj !== \"object\") return obj;\n\n const pathArray = Array.isArray(path) ? path : path.split(\".\").map((key) => (key.match(/^\\d+$/) ? Number(key) : key));\n\n let current = obj;\n\n for (let i = 0; i < pathArray.length; i++) {\n const key = pathArray[i];\n\n if (i === pathArray.length - 1) {\n current[key] = value;\n } else {\n if (!current[key] || typeof current[key] !== \"object\") {\n current[key] = typeof pathArray[i + 1] === \"number\" ? [] : {};\n }\n current = current[key];\n }\n }\n\n return obj;\n}\n\nexport function generateId(length: number = 10): string {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n let result = \"\";\n for (let i = 0; i < length; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n\nlet parentPort: any = null;\n\nif (isNodeEnv()) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const workerThreads = require(\"worker_threads\");\n parentPort = workerThreads.parentPort;\n } catch (e) {\n // Not in worker thread context\n }\n}\n\n/**\n * Get the appropriate target host for messaging based on the current environment\n * @returns The messaging target for the current environment\n */\nexport function getTargetHost(): any {\n if (isNodeEnv()) {\n return parentPort;\n }\n\n if (isWorker()) {\n return self;\n }\n\n if (isIframe()) {\n return window.parent;\n }\n\n throw new Error(\"No valid target found for postMessage\");\n}\n\n/**\n * Send a message to a target, handling different environments (iframe, web worker, node worker)\n * @param target The target to send the message to\n * @param message The message to send\n * @param origin Optional origin for iframe communication\n * @param transferables Optional transferables for postMessage\n */\nexport function postMessageToTarget(\n target: Target,\n message: any,\n origin?: string,\n transferables?: Transferable[],\n): void {\n if (!target) {\n throw new Error(\"Rimless Error: No target specified for postMessage\");\n }\n\n // Node.js Worker\n if (isNodeEnv() && target === parentPort) {\n target.postMessage(message, { transfer: transferables });\n return;\n }\n\n // Web Worker\n if (isWorker()) {\n target.postMessage(message, { transfer: transferables });\n return;\n }\n\n // iframe or window\n if (target.postMessage) {\n target.postMessage(message, { targetOrigin: origin || \"*\", transfer: transferables });\n return;\n }\n\n throw new Error(\"Rimless Error: Invalid target for postMessage\");\n}\n\nexport function isNodeWorker(guest: Guest | Target): guest is NodeWorker {\n return parentPort !== null && guest === parentPort;\n}\n\nexport function isWorkerLike(guest: Guest): guest is WorkerLike {\n return isNodeWorker(guest) || (typeof Worker !== \"undefined\" && guest instanceof Worker);\n}\n\nexport function addEventListener(target: Target, event: string, handler: EventListenerOrEventListenerObject) {\n if (isNodeWorker(target)) {\n target.on(event, handler);\n } else if (\"addEventListener\" in target) {\n target.addEventListener(event, handler);\n }\n}\n\nexport function removeEventListener(target: Target, event: string, handler: EventListenerOrEventListenerObject) {\n if (isNodeWorker(target)) {\n target.off(event, handler);\n } else if (\"removeEventListener\" in target) {\n target.removeEventListener(event, handler);\n }\n}\n\n/**\n * Normalize message event data across Web and Node.js environments\n * In web, data is in event.data\n * In Node.js, the event itself contains the data\n */\nexport function getEventData(event: any) {\n return event.data || event;\n}\n","export interface NodeWorker {\n on(event: string, handler: any): void;\n off(event: string, handler: any): void;\n postMessage(message: any): void;\n terminate(): void;\n}\n\nexport type WorkerLike = Worker | NodeWorker;\n\nexport enum events {\n MESSAGE = \"message\",\n}\n\nexport enum actions {\n HANDSHAKE_REQUEST = \"RIMLESS/HANDSHAKE_REQUEST\",\n HANDSHAKE_REPLY = \"RIMLESS/HANDSHAKE_REPLY\",\n RPC_REQUEST = \"RIMLESS/RPC_REQUEST\",\n RPC_RESOLVE = \"RIMLESS/RPC_RESOLVE\",\n RPC_REJECT = \"RIMLESS/RPC_REJECT\",\n}\n\nexport type Schema = Record<string, any>;\n\nexport interface Connection {\n id: string;\n remote: Schema;\n close: () => void;\n}\n\nexport type Connections = Record<string, Connection>;\n\nexport interface RimlessEvent extends EventListener {\n source?: Window;\n origin?: string;\n data: HandshakeRequestPayload | HandshakeConfirmationPayload | RPCRequestPayload | RPCResolvePayload;\n}\n\nexport interface HandshakeRequestPayload {\n action: actions.HANDSHAKE_REQUEST;\n connectionID: string;\n methodNames: string[];\n schema: Schema;\n}\n\nexport interface HandshakeConfirmationPayload {\n action: actions.HANDSHAKE_REPLY;\n connectionID: string;\n methodNames: string[];\n schema: Schema;\n}\n\nexport interface RPCRequestPayload {\n action: actions.RPC_REQUEST;\n args: any[];\n callID: string;\n callName: string;\n connectionID: string;\n}\n\nexport interface RPCResolvePayload {\n action: actions.RPC_RESOLVE | actions.RPC_REJECT;\n result?: any | null;\n error?: Error | null;\n callID: string;\n callName: string;\n connectionID: string;\n}\n\nexport interface EventHandlers {\n onConnectionSetup: (remote: Schema) => Promise<void>;\n}\n\nexport type Guest = WorkerLike | HTMLIFrameElement;\nexport type Target = Window | WorkerLike;\nexport type Environment = Window | WorkerLike;\n","import { addEventListener, generateId, getEventData, postMessageToTarget, removeEventListener, set } from \"./helpers\";\nimport {\n actions,\n Environment,\n events,\n RimlessEvent,\n RPCRequestPayload,\n RPCResolvePayload,\n Schema,\n Target,\n} from \"./types\";\n\n/** Private symbol to which we will assign transferable objects */\nconst SYM_TRANSFERABLES = Symbol();\n\n/**\n * for each function in methods\n * 1. subscribe to an event that the remote can call\n * 2. listen for calls from the remote. When called execute the function and emit the results.\n *\n * @param methods an object of method ids : methods from the local schema\n * @param rpcConnectionID\n * @param listenTo Environment to listen for incoming messages\n * @param sendTo Target to send outgoing messages\n * @param remote The remote API object for the current connection\n * @return a function to cancel all subscriptions\n */\nexport function registerLocalMethods(\n methods: Record<string, (...args: any[]) => any> = {},\n rpcConnectionID: string,\n listenTo: Environment,\n sendTo: Target,\n remote: Schema // Add remote parameter\n) {\n const listeners: any[] = [];\n for (const [methodName, method] of Object.entries(methods)) {\n // handle a remote calling a local method\n async function handleCall(event: any) {\n const eventData = getEventData(event);\n const { action, callID, connectionID, callName, args = [] } = eventData as RPCRequestPayload;\n\n if (action !== actions.RPC_REQUEST) return;\n if (!callID || !callName) return;\n if (callName !== methodName) return;\n if (connectionID !== rpcConnectionID) return;\n\n const payload: RPCResolvePayload = {\n action: actions.RPC_RESOLVE,\n callID,\n callName,\n connectionID,\n error: null,\n result: null,\n };\n\n // when a host function returns transferable results to the remote, the\n // transferables are assigned to a special symbol on each function's result\n let transferables: Transferable[] | undefined = undefined;\n\n // run function and return the results to the remote\n try {\n // Pass the remote object as the LAST argument to the local method\n payload.result = await method(...args, remote);\n\n if (payload.result && payload.result[SYM_TRANSFERABLES]) {\n transferables = payload.result[SYM_TRANSFERABLES] ?? [];\n delete payload.result[SYM_TRANSFERABLES];\n }\n } catch (error) {\n payload.action = actions.RPC_REJECT;\n payload.error = JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)));\n }\n\n postMessageToTarget(sendTo, payload, event?.origin, transferables);\n }\n\n // subscribe to the call event\n addEventListener(listenTo, events.MESSAGE, handleCall);\n listeners.push(() => removeEventListener(listenTo, events.MESSAGE, handleCall));\n }\n\n return () => listeners.forEach((unregister) => unregister());\n}\n\n/**\n * Create a function that will make an RPC request to the remote with some arguments.\n * Listen to an event that returns the results from the remote.\n *\n * @param rpcCallName\n * @param rpcConnectionID\n * @param event\n * @param listeners\n * @param guest\n *\n * @returns a promise with the result of the RPC\n */\nexport function createRPC(\n rpcCallName: string,\n rpcConnectionID: string,\n event: RimlessEvent,\n listeners: Array<() => void> = [],\n listenTo: Environment,\n sendTo: Target\n) {\n return (...args: any[]) => {\n return new Promise((resolve, reject) => {\n const requestID = generateId();\n\n // on RPC response\n function handleResponse(event: any) {\n const eventData = getEventData(event);\n const { callID, connectionID, callName, result, error, action } = eventData as RPCResolvePayload;\n\n if (!callID || !callName) return;\n if (callName !== rpcCallName) return;\n if (callID !== requestID) return;\n if (connectionID !== rpcConnectionID) return;\n\n // resolve the response\n if (action === actions.RPC_RESOLVE) return resolve(result);\n if (action === actions.RPC_REJECT) return reject(error);\n }\n\n // send the RPC request with arguments\n const payload = {\n action: actions.RPC_REQUEST,\n args,\n callID: requestID,\n callName: rpcCallName,\n connectionID: rpcConnectionID,\n };\n\n // if the arguments have transferables, post them as well\n const transferables = args.reduce(\n (transferables, arg) =>\n arg[SYM_TRANSFERABLES]?.length ? transferables.concat(arg[SYM_TRANSFERABLES]) : transferables,\n // @ts-expect-error: we know this is an array of transferables (if it exists)\n args[SYM_TRANSFERABLES] ?? []\n );\n\n addEventListener(listenTo, events.MESSAGE, handleResponse);\n listeners.push(() => removeEventListener(listenTo, events.MESSAGE, handleResponse));\n\n postMessageToTarget(sendTo, payload, event?.origin, transferables);\n });\n };\n}\n\n/**\n * create an object based on the remote schema's methods. Functions in that object will\n * emit an event that will trigger the RPC on the remote.\n *\n * @param schema\n * @param methods\n * @param connectionID\n * @param event\n * @param guest\n */\nexport function registerRemoteMethods(\n schema: Schema = {},\n methodNames: Iterable<string> = [],\n connectionID: string,\n event: RimlessEvent,\n listenTo: Environment,\n sendTo: Target\n) {\n const remote = { ...schema };\n const listeners: Array<() => void> = [];\n\n for (const methodName of methodNames) {\n const rpc = createRPC(methodName, connectionID, event, listeners, listenTo, sendTo);\n set(remote, methodName, rpc);\n }\n\n return {\n remote,\n unregisterRemote: () => listeners.forEach((unregister) => unregister()),\n };\n}\n\n/**\n * This function is used by API schema declarations and remote function calls alike to\n * indicate which variables should be declared as transferable over `postMessage` calls.\n *\n * @param cb a function that takes a transfer function as an argument and returns an object\n * (in the loose, `typeof foo === \"object\"` sense)\n * @return result the callback's return value, with an extra array of transferable objects\n * assigned to rimless' private symbol `SYM_TRANSFERABLES`\n *\n * The `transfer(...)` function is called with an object to transfer; if there\n * are many objects to transfer, you may call it multiple times. It will always\n * return the input object. Calling `transfer` only modifies the callback\n * result, not the transferred object itself (or objects themselves).\n *\n * @example\n * host.connect({\n * foo: (...args) => {\n * const foo = new ArrayBuffer(8);\n * return withTransferable((transfer) => transfer(foo));\n * }),\n * });\n *\n * @example\n * host.remote.foo(withTransferable((transfer) => ({\n * stream: transfer(new ReadableStream()),\n * })));\n */\nexport const withTransferable = <Transferable, Result extends object>(\n cb: (transfer: <T extends Transferable>(transferable: T) => T) => Result\n) => {\n const transferables: Transferable[] = [];\n const transfer = <T extends Transferable>(transferable: T) => {\n transferables.push(transferable);\n return transferable;\n };\n\n const result = cb(transfer);\n\n return Object.assign(result, { [SYM_TRANSFERABLES]: transferables });\n};\n","import {\n extractMethods,\n getEventData,\n getTargetHost,\n postMessageToTarget,\n addEventListener,\n removeEventListener,\n} from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, EventHandlers, events, Connection, Schema } from \"./types\";\n\nfunction connect(schema: Schema = {}, eventHandlers?: EventHandlers): Promise<Connection> {\n return new Promise(async (resolve) => {\n const localMethods = extractMethods(schema);\n const sendTo = getTargetHost();\n const listenTo = self || window;\n\n // on handshake response\n async function handleHandshakeResponse(event: any) {\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REPLY) return;\n\n // register remote methods\n const { remote, unregisterRemote } = registerRemoteMethods(\n eventData.schema,\n eventData.methodNames,\n eventData.connectionID,\n event,\n listenTo,\n sendTo,\n );\n\n // register local methods, passing the remote object\n const unregisterLocal = registerLocalMethods(localMethods, eventData.connectionID, listenTo, sendTo, remote);\n\n await eventHandlers?.onConnectionSetup?.(remote);\n\n // send a HANDSHAKE REPLY to the host\n const payload = {\n action: actions.HANDSHAKE_REPLY,\n connectionID: eventData.connectionID,\n };\n\n postMessageToTarget(sendTo, payload, event?.origin);\n\n // close the connection and all listeners when called\n const close = () => {\n removeEventListener(listenTo, events.MESSAGE, handleHandshakeResponse);\n unregisterRemote();\n unregisterLocal();\n };\n\n // resolve connection object\n const connection = { remote, close, id: eventData.connectionID };\n return resolve(connection);\n }\n\n // subscribe to HANDSHAKE RESPONSE MESSAGES\n addEventListener(listenTo, events.MESSAGE, handleHandshakeResponse);\n\n const payload = {\n action: actions.HANDSHAKE_REQUEST,\n methodNames: Object.keys(localMethods),\n schema: schema,\n };\n\n postMessageToTarget(sendTo, payload);\n });\n}\n\nexport default {\n connect,\n};\n","import {\n addEventListener,\n extractMethods,\n generateId,\n getEventData,\n getOriginFromURL,\n isNodeEnv,\n isNodeWorker,\n isWorkerLike,\n postMessageToTarget,\n removeEventListener,\n} from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, events, Guest, Connection, Connections, Schema } from \"./types\";\n\nconst connections: Connections = {};\n\nfunction isValidTarget(guest: Guest, event: any) {\n // If it's a worker, we don't need to validate origin\n if (isNodeWorker(guest) || (typeof Worker !== \"undefined\" && guest instanceof Worker)) {\n return true;\n }\n\n // For iframes, check origin and source\n const iframe = guest as HTMLIFrameElement;\n try {\n const childURL = iframe.src;\n const hasInlineContent = typeof iframe.srcdoc === \"string\" && iframe.srcdoc.length > 0;\n const childOrigin = getOriginFromURL(childURL);\n const hasProperOrigin = event.origin === childOrigin;\n const hasProperSource = event.source === iframe.contentWindow;\n\n // For inline iframes (srcdoc/about:blank) we can only rely on source matching\n if (hasInlineContent || childURL === \"about:blank\") {\n return hasProperSource;\n }\n\n return (hasProperOrigin && hasProperSource) || !childURL;\n } catch (e) {\n console.warn(\"Error checking iframe target:\", e);\n return false;\n }\n}\n\n/**\n * Perform a handshake with the target iframe, when the handshake is confirmed\n * resolve the connection object containing RPCs and properties\n *\n * @param guest\n * @param schema\n * @returns Promise\n */\nfunction connect(guest: Guest, schema: Schema = {}): Promise<Connection> {\n if (!guest) throw new Error(\"a target is required\");\n\n const guestIsWorker = isWorkerLike(guest);\n\n const listenTo = guestIsWorker || isNodeEnv() ? (guest as Worker) : window;\n\n return new Promise((resolve) => {\n const connectionID = generateId();\n\n // on handshake request\n function handleHandshake(event: any) {\n const sendTo = guestIsWorker || isNodeEnv() ? (guest as Worker) : event.source;\n\n if (!guestIsWorker && !isNodeEnv() && !isValidTarget(guest, event)) return;\n\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REQUEST) return;\n if (connections[connectionID]) return;\n\n // Extract local methods first (doesn't need remote yet)\n const localMethods = extractMethods(schema);\n\n // Register remote methods first to get the remote object\n const { remote, unregisterRemote } = registerRemoteMethods(\n eventData.schema,\n eventData.methodNames,\n connectionID,\n event,\n listenTo,\n sendTo,\n );\n\n // Now register local methods, passing the remote object\n const unregisterLocal = registerLocalMethods(localMethods, connectionID, listenTo, sendTo, remote);\n\n // send a HANDSHAKE REPLY to the guest\n const payload = {\n action: actions.HANDSHAKE_REPLY,\n connectionID,\n schema: schema,\n methodNames: Object.keys(localMethods),\n };\n\n postMessageToTarget(sendTo, payload, event.origin);\n\n // close the connection and all listeners when called\n const close = () => {\n delete connections[connectionID];\n removeEventListener(listenTo, events.MESSAGE, handleHandshake);\n removeEventListener(listenTo, events.MESSAGE, handleHandshakeReply);\n unregisterRemote();\n unregisterLocal();\n if (guestIsWorker) {\n (guest as Worker).terminate();\n }\n };\n\n const connection: Connection = { remote, close, id: connectionID };\n connections[connectionID] = connection;\n }\n\n // subscribe to HANDSHAKE MESSAGES\n addEventListener(listenTo, events.MESSAGE, handleHandshake);\n\n // on handshake reply\n function handleHandshakeReply(event: any) {\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REPLY) return;\n if (connectionID !== eventData.connectionID) return;\n\n if (!connections[eventData.connectionID]) {\n throw new Error(\"Rimless Error: No connection found for this connectionID\");\n }\n\n return resolve(connections[eventData.connectionID]);\n }\n\n addEventListener(listenTo, events.MESSAGE, handleHandshakeReply);\n });\n}\n\nexport default {\n connect,\n};\n"],"names":["isWorker","isNodeEnv","isIframe","extractMethods","obj","methods","parse","path","prop","propPath","urlRegex","ports","getOriginFromURL","url","regexResult","protocol","hostname","port","portSuffix","set","value","pathArray","key","current","i","generateId","length","chars","result","parentPort","getTargetHost","postMessageToTarget","target","message","origin","transferables","isNodeWorker","guest","isWorkerLike","addEventListener","event","handler","removeEventListener","getEventData","events","actions","SYM_TRANSFERABLES","registerLocalMethods","rpcConnectionID","listenTo","sendTo","remote","listeners","methodName","method","handleCall","eventData","action","callID","connectionID","callName","args","payload","error","unregister","createRPC","rpcCallName","resolve","reject","requestID","handleResponse","arg","registerRemoteMethods","schema","methodNames","rpc","withTransferable","cb","transferable","connect","eventHandlers","localMethods","handleHandshakeResponse","unregisterRemote","unregisterLocal","connection","connections","isValidTarget","iframe","childURL","hasInlineContent","childOrigin","hasProperOrigin","hasProperSource","guestIsWorker","handleHandshake","handleHandshakeReply","host"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rimless.js","sources":["../src/helpers.ts","../src/types.ts","../src/rpc.ts","../src/guest.ts","../src/host.ts"],"sourcesContent":["import { Guest, NodeWorker, Target, WorkerLike } from \"./types\";\n\ntype RuntimeEnvironment = \"browser\" | \"worker\" | \"node\" | \"bun\";\n\nfunction detectRuntime(): RuntimeEnvironment {\n const globalObject = globalThis as Record<string, any>;\n\n // Prefer explicit browser detection before checking shims\n if (typeof globalObject.window !== \"undefined\" && typeof globalObject.document !== \"undefined\") {\n return \"browser\";\n }\n\n const hasWorkerGlobalScope =\n typeof globalObject.WorkerGlobalScope !== \"undefined\" &&\n typeof globalObject.self !== \"undefined\" &&\n globalObject.self instanceof globalObject.WorkerGlobalScope;\n\n if (\n hasWorkerGlobalScope ||\n (typeof globalObject.window === \"undefined\" &&\n typeof globalObject.self !== \"undefined\" &&\n typeof globalObject.importScripts === \"function\")\n ) {\n return \"worker\";\n }\n\n const processRef = globalObject.process;\n if (processRef && typeof processRef === \"object\") {\n const versions = processRef.versions ?? {};\n const releaseName = processRef.release?.name;\n\n if (versions.bun || releaseName === \"bun\" || typeof globalObject.Bun !== \"undefined\") {\n return \"bun\";\n }\n\n if (versions.node && releaseName === \"node\") {\n return \"node\";\n }\n }\n\n if (typeof globalObject.Bun !== \"undefined\") {\n return \"bun\";\n }\n\n return \"browser\";\n}\n\nexport function getRuntimeEnvironment(): RuntimeEnvironment {\n return detectRuntime();\n}\n\nexport function isBrowserEnv(): boolean {\n return getRuntimeEnvironment() === \"browser\";\n}\n\n/**\n * check if run in a webworker\n *\n * @returns boolean\n */\nexport function isWorker(): boolean {\n return getRuntimeEnvironment() === \"worker\";\n}\n\n/**\n * check if run in a Node.js environment\n *\n * @returns boolean\n */\nexport function isNodeEnv(): boolean {\n return getRuntimeEnvironment() === \"node\";\n}\n\nexport function isBunEnv(): boolean {\n return getRuntimeEnvironment() === \"bun\";\n}\n\nexport function isServerEnv(): boolean {\n const runtime = getRuntimeEnvironment();\n return runtime === \"node\" || runtime === \"bun\";\n}\n\n/**\n * check if run in an iframe\n *\n * @returns boolean\n */\nexport function isIframe() {\n return window.self !== window.top;\n}\n\n/**\n * we cannot send functions through postMessage\n * extract the path to all functions in the schema\n *\n * @param obj\n */\nexport function extractMethods(obj: any) {\n const methods: Record<string, (...args: any) => any> = {};\n (function parse(obj: any, path = \"\") {\n Object.keys(obj).forEach((prop) => {\n const propPath = path ? `${path}.${prop}` : prop;\n if (obj[prop] === Object(obj[prop])) {\n parse(obj[prop], propPath);\n }\n if (typeof obj[prop] === \"function\") {\n methods[propPath] = obj[prop];\n delete obj[prop];\n }\n });\n })(obj);\n return methods;\n}\n\nconst urlRegex = /^(https?:|file:)?\\/\\/([^/:]+)?(:(\\d+))?/;\nconst ports: any = { \"http:\": \"80\", \"https:\": \"443\" };\n\n/**\n * convert the url into an origin (remove paths)\n *\n * @param url\n */\nexport function getOriginFromURL(url: string | null) {\n if (!url) return null;\n\n const regexResult = urlRegex.exec(url);\n if (!regexResult) return null;\n\n const [, protocol = \"http:\", hostname, , port] = regexResult;\n\n // If the protocol is file, return file://\n if (protocol === \"file:\") {\n return \"file://\";\n }\n\n // If the port is the default for the protocol, we don't want to add it to the origin string\n const portSuffix = port && port !== ports[protocol] ? `:${port}` : \"\";\n return `${protocol}//${hostname}${portSuffix}`;\n}\n\nexport function get(obj: any, path: string | Array<string | number>, defaultValue?: any): any {\n const keys = Array.isArray(path) ? path : path.split(\".\").filter(Boolean);\n let result = obj;\n\n for (const key of keys) {\n result = result?.[key];\n if (result === undefined) {\n return defaultValue;\n }\n }\n\n return result;\n}\n\nexport function set(obj: any, path: string | (string | number)[], value: any): any {\n if (!obj || typeof obj !== \"object\") return obj;\n\n const pathArray = Array.isArray(path) ? path : path.split(\".\").map((key) => (key.match(/^\\d+$/) ? Number(key) : key));\n\n let current = obj;\n\n for (let i = 0; i < pathArray.length; i++) {\n const key = pathArray[i];\n\n if (i === pathArray.length - 1) {\n current[key] = value;\n } else {\n if (!current[key] || typeof current[key] !== \"object\") {\n current[key] = typeof pathArray[i + 1] === \"number\" ? [] : {};\n }\n current = current[key];\n }\n }\n\n return obj;\n}\n\nexport function generateId(length: number = 10): string {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n let result = \"\";\n for (let i = 0; i < length; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n\nconst initialRuntime = getRuntimeEnvironment();\nlet parentPort: any = null;\n\nif (initialRuntime === \"node\" || initialRuntime === \"bun\") {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const workerThreads = require(\"worker_threads\");\n parentPort = workerThreads.parentPort;\n } catch (e) {\n // Not in worker thread context\n }\n}\n\n/**\n * Get the appropriate target host for messaging based on the current environment\n * @returns The messaging target for the current environment\n */\nexport function getTargetHost(): any {\n if (isServerEnv()) {\n return parentPort;\n }\n\n if (isWorker()) {\n return self;\n }\n\n if (isIframe()) {\n return window.parent;\n }\n\n throw new Error(\"No valid target found for postMessage\");\n}\n\n/**\n * Send a message to a target, handling different environments (iframe, web worker, node worker)\n * @param target The target to send the message to\n * @param message The message to send\n * @param origin Optional origin for iframe communication\n * @param transferables Optional transferables for postMessage\n */\nexport function postMessageToTarget(\n target: Target,\n message: any,\n origin?: string,\n transferables?: Transferable[],\n): void {\n if (!target) {\n throw new Error(\"Rimless Error: No target specified for postMessage\");\n }\n\n // Node.js Worker\n if (isServerEnv() && target === parentPort) {\n target.postMessage(message, { transfer: transferables });\n return;\n }\n\n // Web Worker\n if (isWorker()) {\n target.postMessage(message, { transfer: transferables });\n return;\n }\n\n // iframe or window\n if (target.postMessage) {\n target.postMessage(message, { targetOrigin: origin || \"*\", transfer: transferables });\n return;\n }\n\n throw new Error(\"Rimless Error: Invalid target for postMessage\");\n}\n\nexport function isNodeWorker(guest: Guest | Target): guest is NodeWorker {\n return parentPort !== null && guest === parentPort;\n}\n\nexport function isWorkerLike(guest: Guest): guest is WorkerLike {\n return isNodeWorker(guest) || (typeof Worker !== \"undefined\" && guest instanceof Worker);\n}\n\nexport function addEventListener(target: Target, event: string, handler: EventListenerOrEventListenerObject) {\n if (isNodeWorker(target)) {\n target.on(event, handler);\n } else if (\"addEventListener\" in target) {\n target.addEventListener(event, handler);\n }\n}\n\nexport function removeEventListener(target: Target, event: string, handler: EventListenerOrEventListenerObject) {\n if (isNodeWorker(target)) {\n target.off(event, handler);\n } else if (\"removeEventListener\" in target) {\n target.removeEventListener(event, handler);\n }\n}\n\n/**\n * Normalize message event data across Web and Node.js environments\n * In web, data is in event.data\n * In Node.js, the event itself contains the data\n */\nexport function getEventData(event: any) {\n return event.data || event;\n}\n","export interface NodeWorker {\n on(event: string, handler: any): void;\n off(event: string, handler: any): void;\n postMessage(message: any): void;\n terminate(): void;\n}\n\nexport type WorkerLike = Worker | NodeWorker;\n\nexport enum events {\n MESSAGE = \"message\",\n}\n\nexport enum actions {\n HANDSHAKE_REQUEST = \"RIMLESS/HANDSHAKE_REQUEST\",\n HANDSHAKE_REPLY = \"RIMLESS/HANDSHAKE_REPLY\",\n RPC_REQUEST = \"RIMLESS/RPC_REQUEST\",\n RPC_RESOLVE = \"RIMLESS/RPC_RESOLVE\",\n RPC_REJECT = \"RIMLESS/RPC_REJECT\",\n}\n\nexport type Schema = Record<string, any>;\n\nexport interface Connection {\n id: string;\n remote: Schema;\n close: () => void;\n}\n\nexport type Connections = Record<string, Connection>;\n\nexport interface RimlessEvent extends EventListener {\n source?: Window;\n origin?: string;\n data: HandshakeRequestPayload | HandshakeConfirmationPayload | RPCRequestPayload | RPCResolvePayload;\n}\n\nexport interface HandshakeRequestPayload {\n action: actions.HANDSHAKE_REQUEST;\n connectionID: string;\n methodNames: string[];\n schema: Schema;\n}\n\nexport interface HandshakeConfirmationPayload {\n action: actions.HANDSHAKE_REPLY;\n connectionID: string;\n methodNames: string[];\n schema: Schema;\n}\n\nexport interface RPCRequestPayload {\n action: actions.RPC_REQUEST;\n args: any[];\n callID: string;\n callName: string;\n connectionID: string;\n}\n\nexport interface RPCResolvePayload {\n action: actions.RPC_RESOLVE | actions.RPC_REJECT;\n result?: any | null;\n error?: Error | null;\n callID: string;\n callName: string;\n connectionID: string;\n}\n\nexport interface EventHandlers {\n onConnectionSetup: (remote: Schema) => Promise<void>;\n}\n\nexport type Guest = WorkerLike | HTMLIFrameElement;\nexport type Target = Window | WorkerLike;\nexport type Environment = Window | WorkerLike;\n","import { addEventListener, generateId, getEventData, postMessageToTarget, removeEventListener, set } from \"./helpers\";\nimport {\n actions,\n Environment,\n events,\n RimlessEvent,\n RPCRequestPayload,\n RPCResolvePayload,\n Schema,\n Target,\n} from \"./types\";\n\n/** Private symbol to which we will assign transferable objects */\nconst SYM_TRANSFERABLES = Symbol();\n\n/**\n * for each function in methods\n * 1. subscribe to an event that the remote can call\n * 2. listen for calls from the remote. When called execute the function and emit the results.\n *\n * @param methods an object of method ids : methods from the local schema\n * @param rpcConnectionID\n * @param listenTo Environment to listen for incoming messages\n * @param sendTo Target to send outgoing messages\n * @param remote The remote API object for the current connection\n * @return a function to cancel all subscriptions\n */\nexport function registerLocalMethods(\n methods: Record<string, (...args: any[]) => any> = {},\n rpcConnectionID: string,\n listenTo: Environment,\n sendTo: Target,\n remote: Schema, // Add remote parameter\n) {\n const listeners: any[] = [];\n for (const [methodName, method] of Object.entries(methods)) {\n // handle a remote calling a local method\n async function handleCall(event: any) {\n const eventData = getEventData(event);\n const { action, callID, connectionID, callName, args = [] } = eventData as RPCRequestPayload;\n\n if (action !== actions.RPC_REQUEST) return;\n if (!callID || !callName) return;\n if (callName !== methodName) return;\n if (connectionID !== rpcConnectionID) return;\n\n const payload: RPCResolvePayload = {\n action: actions.RPC_RESOLVE,\n callID,\n callName,\n connectionID,\n error: null,\n result: null,\n };\n\n // when a host function returns transferable results to the remote, the\n // transferables are assigned to a special symbol on each function's result\n let transferables: Transferable[] | undefined = undefined;\n\n // run function and return the results to the remote\n try {\n // Pass the remote object as the LAST argument to the local method\n payload.result = await method(...args, remote);\n\n if (payload.result && payload.result[SYM_TRANSFERABLES]) {\n transferables = payload.result[SYM_TRANSFERABLES] ?? [];\n delete payload.result[SYM_TRANSFERABLES];\n }\n } catch (error) {\n payload.action = actions.RPC_REJECT;\n payload.error = JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)));\n }\n\n postMessageToTarget(sendTo, payload, event?.origin, transferables);\n }\n\n // subscribe to the call event\n addEventListener(listenTo, events.MESSAGE, handleCall);\n listeners.push(() => removeEventListener(listenTo, events.MESSAGE, handleCall));\n }\n\n return () => listeners.forEach((unregister) => unregister());\n}\n\n/**\n * Create a function that will make an RPC request to the remote with some arguments.\n * Listen to an event that returns the results from the remote.\n *\n * @param rpcCallName\n * @param rpcConnectionID\n * @param event\n * @param listeners\n * @param guest\n *\n * @returns a promise with the result of the RPC\n */\nexport function createRPC(\n rpcCallName: string,\n rpcConnectionID: string,\n event: RimlessEvent,\n listeners: Array<() => void> = [],\n listenTo: Environment,\n sendTo: Target,\n) {\n return (...args: any[]) => {\n return new Promise((resolve, reject) => {\n const requestID = generateId();\n\n // on RPC response\n function handleResponse(event: any) {\n const eventData = getEventData(event);\n const { callID, connectionID, callName, result, error, action } = eventData as RPCResolvePayload;\n\n if (!callID || !callName) return;\n if (callName !== rpcCallName) return;\n if (callID !== requestID) return;\n if (connectionID !== rpcConnectionID) return;\n\n // resolve the response\n if (action === actions.RPC_RESOLVE) return resolve(result);\n if (action === actions.RPC_REJECT) return reject(error);\n }\n\n // send the RPC request with arguments\n const payload = {\n action: actions.RPC_REQUEST,\n args,\n callID: requestID,\n callName: rpcCallName,\n connectionID: rpcConnectionID,\n };\n\n // if the arguments have transferables, post them as well\n const transferables = args.reduce(\n (transferables, arg) =>\n arg[SYM_TRANSFERABLES]?.length ? transferables.concat(arg[SYM_TRANSFERABLES]) : transferables,\n // @ts-expect-error: we know this is an array of transferables (if it exists)\n args[SYM_TRANSFERABLES] ?? [],\n );\n\n addEventListener(listenTo, events.MESSAGE, handleResponse);\n listeners.push(() => removeEventListener(listenTo, events.MESSAGE, handleResponse));\n\n postMessageToTarget(sendTo, payload, event?.origin, transferables);\n });\n };\n}\n\n/**\n * create an object based on the remote schema's methods. Functions in that object will\n * emit an event that will trigger the RPC on the remote.\n *\n * @param schema\n * @param methods\n * @param connectionID\n * @param event\n * @param guest\n */\nexport function registerRemoteMethods(\n schema: Schema = {},\n methodNames: Iterable<string> = [],\n connectionID: string,\n event: RimlessEvent,\n listenTo: Environment,\n sendTo: Target,\n) {\n const remote = { ...schema };\n const listeners: Array<() => void> = [];\n\n for (const methodName of methodNames) {\n const rpc = createRPC(methodName, connectionID, event, listeners, listenTo, sendTo);\n set(remote, methodName, rpc);\n }\n\n return {\n remote,\n unregisterRemote: () => listeners.forEach((unregister) => unregister()),\n };\n}\n\n/**\n * This function is used by API schema declarations and remote function calls alike to\n * indicate which variables should be declared as transferable over `postMessage` calls.\n *\n * @param cb a function that takes a transfer function as an argument and returns an object\n * (in the loose, `typeof foo === \"object\"` sense)\n * @return result the callback's return value, with an extra array of transferable objects\n * assigned to rimless' private symbol `SYM_TRANSFERABLES`\n *\n * The `transfer(...)` function is called with an object to transfer; if there\n * are many objects to transfer, you may call it multiple times. It will always\n * return the input object. Calling `transfer` only modifies the callback\n * result, not the transferred object itself (or objects themselves).\n *\n * @example\n * host.connect({\n * foo: (...args) => {\n * const foo = new ArrayBuffer(8);\n * return withTransferable((transfer) => transfer(foo));\n * }),\n * });\n *\n * @example\n * host.remote.foo(withTransferable((transfer) => ({\n * stream: transfer(new ReadableStream()),\n * })));\n */\nexport const withTransferable = <Transferable, Result extends object>(\n cb: (transfer: <T extends Transferable>(transferable: T) => T) => Result,\n) => {\n const transferables: Transferable[] = [];\n const transfer = <T extends Transferable>(transferable: T) => {\n transferables.push(transferable);\n return transferable;\n };\n\n const result = cb(transfer);\n\n return Object.assign(result, { [SYM_TRANSFERABLES]: transferables });\n};\n","import {\n extractMethods,\n getEventData,\n getTargetHost,\n postMessageToTarget,\n addEventListener,\n removeEventListener,\n} from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, EventHandlers, events, Connection, Schema } from \"./types\";\n\nfunction connect(schema: Schema = {}, eventHandlers?: EventHandlers): Promise<Connection> {\n return new Promise(async (resolve) => {\n const localMethods = extractMethods(schema);\n const sendTo = getTargetHost();\n const listenTo = self || window;\n\n // on handshake response\n async function handleHandshakeResponse(event: any) {\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REPLY) return;\n\n // register remote methods\n const { remote, unregisterRemote } = registerRemoteMethods(\n eventData.schema,\n eventData.methodNames,\n eventData.connectionID,\n event,\n listenTo,\n sendTo,\n );\n\n // register local methods, passing the remote object\n const unregisterLocal = registerLocalMethods(localMethods, eventData.connectionID, listenTo, sendTo, remote);\n\n await eventHandlers?.onConnectionSetup?.(remote);\n\n // send a HANDSHAKE REPLY to the host\n const payload = {\n action: actions.HANDSHAKE_REPLY,\n connectionID: eventData.connectionID,\n };\n\n postMessageToTarget(sendTo, payload, event?.origin);\n\n // close the connection and all listeners when called\n const close = () => {\n removeEventListener(listenTo, events.MESSAGE, handleHandshakeResponse);\n unregisterRemote();\n unregisterLocal();\n };\n\n // resolve connection object\n const connection = { remote, close, id: eventData.connectionID };\n return resolve(connection);\n }\n\n // subscribe to HANDSHAKE RESPONSE MESSAGES\n addEventListener(listenTo, events.MESSAGE, handleHandshakeResponse);\n\n const payload = {\n action: actions.HANDSHAKE_REQUEST,\n methodNames: Object.keys(localMethods),\n schema: schema,\n };\n\n postMessageToTarget(sendTo, payload);\n });\n}\n\nexport default {\n connect,\n};\n","import {\n addEventListener,\n extractMethods,\n generateId,\n getEventData,\n getOriginFromURL,\n isServerEnv,\n isNodeWorker,\n isWorkerLike,\n postMessageToTarget,\n removeEventListener,\n} from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, events, Guest, Connection, Connections, Schema } from \"./types\";\n\nconst connections: Connections = {};\n\nfunction isValidTarget(guest: Guest, event: any) {\n // If it's a worker, we don't need to validate origin\n if (isNodeWorker(guest) || (typeof Worker !== \"undefined\" && guest instanceof Worker)) {\n return true;\n }\n\n // For iframes, check origin and source\n const iframe = guest as HTMLIFrameElement;\n try {\n const childURL = iframe.src;\n const hasInlineContent = typeof iframe.srcdoc === \"string\" && iframe.srcdoc.length > 0;\n const childOrigin = getOriginFromURL(childURL);\n const hasProperOrigin = event.origin === childOrigin;\n const hasProperSource = event.source === iframe.contentWindow;\n\n // For inline iframes (srcdoc/about:blank) we can only rely on source matching\n if (hasInlineContent || childURL === \"about:blank\") {\n return hasProperSource;\n }\n\n return (hasProperOrigin && hasProperSource) || !childURL;\n } catch (e) {\n console.warn(\"Error checking iframe target:\", e);\n return false;\n }\n}\n\n/**\n * Perform a handshake with the target iframe, when the handshake is confirmed\n * resolve the connection object containing RPCs and properties\n *\n * @param guest\n * @param schema\n * @returns Promise\n */\nfunction connect(guest: Guest, schema: Schema = {}): Promise<Connection> {\n if (!guest) throw new Error(\"a target is required\");\n\n const guestIsWorker = isWorkerLike(guest);\n\n const listenTo = guestIsWorker || isServerEnv() ? (guest as Worker) : window;\n\n return new Promise((resolve) => {\n const connectionID = generateId();\n\n // on handshake request\n function handleHandshake(event: any) {\n const sendTo = guestIsWorker || isServerEnv() ? (guest as Worker) : event.source;\n\n if (!guestIsWorker && !isServerEnv() && !isValidTarget(guest, event)) return;\n\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REQUEST) return;\n if (connections[connectionID]) return;\n\n // Extract local methods first (doesn't need remote yet)\n const localMethods = extractMethods(schema);\n\n // Register remote methods first to get the remote object\n const { remote, unregisterRemote } = registerRemoteMethods(\n eventData.schema,\n eventData.methodNames,\n connectionID,\n event,\n listenTo,\n sendTo,\n );\n\n // Now register local methods, passing the remote object\n const unregisterLocal = registerLocalMethods(localMethods, connectionID, listenTo, sendTo, remote);\n\n // send a HANDSHAKE REPLY to the guest\n const payload = {\n action: actions.HANDSHAKE_REPLY,\n connectionID,\n schema: schema,\n methodNames: Object.keys(localMethods),\n };\n\n postMessageToTarget(sendTo, payload, event.origin);\n\n // close the connection and all listeners when called\n const close = () => {\n delete connections[connectionID];\n removeEventListener(listenTo, events.MESSAGE, handleHandshake);\n removeEventListener(listenTo, events.MESSAGE, handleHandshakeReply);\n unregisterRemote();\n unregisterLocal();\n if (guestIsWorker) {\n (guest as Worker).terminate();\n }\n };\n\n const connection: Connection = { remote, close, id: connectionID };\n connections[connectionID] = connection;\n }\n\n // subscribe to HANDSHAKE MESSAGES\n addEventListener(listenTo, events.MESSAGE, handleHandshake);\n\n // on handshake reply\n function handleHandshakeReply(event: any) {\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REPLY) return;\n if (connectionID !== eventData.connectionID) return;\n\n if (!connections[eventData.connectionID]) {\n throw new Error(\"Rimless Error: No connection found for this connectionID\");\n }\n\n return resolve(connections[eventData.connectionID]);\n }\n\n addEventListener(listenTo, events.MESSAGE, handleHandshakeReply);\n });\n}\n\nexport default {\n connect,\n};\n"],"names":["detectRuntime","globalObject","processRef","versions","releaseName","getRuntimeEnvironment","isWorker","isServerEnv","runtime","isIframe","extractMethods","obj","methods","parse","path","prop","propPath","urlRegex","ports","getOriginFromURL","url","regexResult","protocol","hostname","port","portSuffix","set","value","pathArray","key","current","i","generateId","length","chars","result","initialRuntime","parentPort","getTargetHost","postMessageToTarget","target","message","origin","transferables","isNodeWorker","guest","isWorkerLike","addEventListener","event","handler","removeEventListener","getEventData","events","actions","SYM_TRANSFERABLES","registerLocalMethods","rpcConnectionID","listenTo","sendTo","remote","listeners","methodName","method","handleCall","eventData","action","callID","connectionID","callName","args","payload","error","unregister","createRPC","rpcCallName","resolve","reject","requestID","handleResponse","arg","registerRemoteMethods","schema","methodNames","rpc","withTransferable","cb","transferable","connect","eventHandlers","localMethods","handleHandshakeResponse","unregisterRemote","unregisterLocal","connection","connections","isValidTarget","iframe","childURL","hasInlineContent","childOrigin","hasProperOrigin","hasProperSource","e","guestIsWorker","handleHandshake","handleHandshakeReply","host"],"mappings":"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"}
|
package/lib/rimless.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var rimless=function(w){"use strict";function
|
|
1
|
+
var rimless=function(w){"use strict";function K(){const e=globalThis;if(typeof e.window<"u"&&typeof e.document<"u")return"browser";if(typeof e.WorkerGlobalScope<"u"&&typeof e.self<"u"&&e.self instanceof e.WorkerGlobalScope||typeof e.window>"u"&&typeof e.self<"u"&&typeof e.importScripts=="function")return"worker";const t=e.process;if(t&&typeof t=="object"){const n=t.versions??{},i=t.release?.name;if(n.bun||i==="bun"||typeof e.Bun<"u")return"bun";if(n.node&&i==="node")return"node"}return typeof e.Bun<"u"?"bun":"browser"}function H(){return K()}function b(){return H()==="worker"}function g(){const e=H();return e==="node"||e==="bun"}function U(){return window.self!==window.top}function _(e){const o={};return function t(n,i=""){Object.keys(n).forEach(r=>{const s=i?`${i}.${r}`:r;n[r]===Object(n[r])&&t(n[r],s),typeof n[r]=="function"&&(o[s]=n[r],delete n[r])})}(e),o}const Q=/^(https?:|file:)?\/\/([^/:]+)?(:(\d+))?/,Y={"http:":"80","https:":"443"};function $(e){if(!e)return null;const o=Q.exec(e);if(!o)return null;const[,t="http:",n,,i]=o;if(t==="file:")return"file://";const r=i&&i!==Y[t]?`:${i}`:"";return`${t}//${n}${r}`}function J(e,o,t){if(!e||typeof e!="object")return e;const n=Array.isArray(o)?o:o.split(".").map(r=>r.match(/^\d+$/)?Number(r):r);let i=e;for(let r=0;r<n.length;r++){const s=n[r];r===n.length-1?i[s]=t:((!i[s]||typeof i[s]!="object")&&(i[s]=typeof n[r+1]=="number"?[]:{}),i=i[s])}return e}function O(e=10){const o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";let t="";for(let n=0;n<e;n++)t+=o.charAt(Math.floor(Math.random()*o.length));return t}const C=H();let M=null;if(C==="node"||C==="bun")try{M=require("worker_threads").parentPort}catch{}function V(){if(g())return M;if(b())return self;if(U())return window.parent;throw new Error("No valid target found for postMessage")}function D(e,o,t,n){if(!e)throw new Error("Rimless Error: No target specified for postMessage");if(g()&&e===M){e.postMessage(o,{transfer:n});return}if(b()){e.postMessage(o,{transfer:n});return}if(e.postMessage){e.postMessage(o,{targetOrigin:t||"*",transfer:n});return}throw new Error("Rimless Error: Invalid target for postMessage")}function k(e){return M!==null&&e===M}function q(e){return k(e)||typeof Worker<"u"&&e instanceof Worker}function P(e,o,t){k(e)?e.on(o,t):"addEventListener"in e&&e.addEventListener(o,t)}function L(e,o,t){k(e)?e.off(o,t):"removeEventListener"in e&&e.removeEventListener(o,t)}function N(e){return e.data||e}var l=(e=>(e.MESSAGE="message",e))(l||{}),u=(e=>(e.HANDSHAKE_REQUEST="RIMLESS/HANDSHAKE_REQUEST",e.HANDSHAKE_REPLY="RIMLESS/HANDSHAKE_REPLY",e.RPC_REQUEST="RIMLESS/RPC_REQUEST",e.RPC_RESOLVE="RIMLESS/RPC_RESOLVE",e.RPC_REJECT="RIMLESS/RPC_REJECT",e))(u||{});const y=Symbol();function v(e={},o,t,n,i){const r=[];for(const[s,a]of Object.entries(e)){async function f(c){const E=N(c),{action:m,callID:R,connectionID:d,callName:S,args:p=[]}=E;if(m!==u.RPC_REQUEST||!R||!S||S!==s||d!==o)return;const h={action:u.RPC_RESOLVE,callID:R,callName:S,connectionID:d,error:null,result:null};let A;try{h.result=await a(...p,i),h.result&&h.result[y]&&(A=h.result[y]??[],delete h.result[y])}catch(T){h.action=u.RPC_REJECT,h.error=JSON.parse(JSON.stringify(T,Object.getOwnPropertyNames(T)))}D(n,h,c?.origin,A)}P(t,l.MESSAGE,f),r.push(()=>L(t,l.MESSAGE,f))}return()=>r.forEach(s=>s())}function B(e,o,t,n=[],i,r){return(...s)=>new Promise((a,f)=>{const c=O();function E(d){const S=N(d),{callID:p,connectionID:h,callName:A,result:T,error:ee,action:W}=S;if(!(!p||!A)&&A===e&&p===c&&h===o){if(W===u.RPC_RESOLVE)return a(T);if(W===u.RPC_REJECT)return f(ee)}}const m={action:u.RPC_REQUEST,args:s,callID:c,callName:e,connectionID:o},R=s.reduce((d,S)=>S[y]?.length?d.concat(S[y]):d,s[y]??[]);P(i,l.MESSAGE,E),n.push(()=>L(i,l.MESSAGE,E)),D(r,m,t?.origin,R)})}function G(e={},o=[],t,n,i,r){const s={...e},a=[];for(const f of o){const c=B(f,t,n,a,i,r);J(s,f,c)}return{remote:s,unregisterRemote:()=>a.forEach(f=>f())}}const j=e=>{const o=[],n=e(i=>(o.push(i),i));return Object.assign(n,{[y]:o})};function F(e={},o){return new Promise(async t=>{const n=_(e),i=V(),r=self||window;async function s(f){const c=N(f);if(c?.action!==u.HANDSHAKE_REPLY)return;const{remote:E,unregisterRemote:m}=G(c.schema,c.methodNames,c.connectionID,f,r,i),R=v(n,c.connectionID,r,i,E);await o?.onConnectionSetup?.(E);const d={action:u.HANDSHAKE_REPLY,connectionID:c.connectionID};D(i,d,f?.origin);const p={remote:E,close:()=>{L(r,l.MESSAGE,s),m(),R()},id:c.connectionID};return t(p)}P(r,l.MESSAGE,s);const a={action:u.HANDSHAKE_REQUEST,methodNames:Object.keys(n),schema:e};D(i,a)})}const z={connect:F},I={};function X(e,o){if(k(e)||typeof Worker<"u"&&e instanceof Worker)return!0;const t=e;try{const n=t.src,i=typeof t.srcdoc=="string"&&t.srcdoc.length>0,r=$(n),s=o.origin===r,a=o.source===t.contentWindow;return i||n==="about:blank"?a:s&&a||!n}catch(n){return console.warn("Error checking iframe target:",n),!1}}function Z(e,o={}){if(!e)throw new Error("a target is required");const t=q(e),n=t||g()?e:window;return new Promise(i=>{const r=O();function s(f){const c=t||g()?e:f.source;if(!t&&!g()&&!X(e,f))return;const E=N(f);if(E?.action!==u.HANDSHAKE_REQUEST||I[r])return;const m=_(o),{remote:R,unregisterRemote:d}=G(E.schema,E.methodNames,r,f,n,c),S=v(m,r,n,c,R),p={action:u.HANDSHAKE_REPLY,connectionID:r,schema:o,methodNames:Object.keys(m)};D(c,p,f.origin);const A={remote:R,close:()=>{delete I[r],L(n,l.MESSAGE,s),L(n,l.MESSAGE,a),d(),S(),t&&e.terminate()},id:r};I[r]=A}P(n,l.MESSAGE,s);function a(f){const c=N(f);if(c?.action===u.HANDSHAKE_REPLY&&r===c.connectionID){if(!I[c.connectionID])throw new Error("Rimless Error: No connection found for this connectionID");return i(I[c.connectionID])}}P(n,l.MESSAGE,a)})}const x={connect:Z};return w.actions=u,w.events=l,w.guest=z,w.host=x,w.withTransferable=j,Object.defineProperty(w,Symbol.toStringTag,{value:"Module"}),w}({});
|
|
2
2
|
//# sourceMappingURL=rimless.min.js.map
|
package/lib/rimless.min.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rimless.min.js","sources":["../src/helpers.ts","../src/types.ts","../src/rpc.ts","../src/guest.ts","../src/host.ts"],"sourcesContent":["import { Guest, NodeWorker, Target, WorkerLike } from \"./types\";\n\n/**\n * check if run in a webworker\n *\n * @returns boolean\n */\nexport function isWorker(): boolean {\n return typeof window === \"undefined\" && typeof self !== \"undefined\";\n}\n\n/**\n * check if run in a Node.js environment\n *\n * @returns boolean\n */\nexport function isNodeEnv(): boolean {\n return typeof process !== \"undefined\" && !!(process as any).versions?.node;\n}\n\n/**\n * check if run in an iframe\n *\n * @returns boolean\n */\nexport function isIframe() {\n return window.self !== window.top;\n}\n\n/**\n * we cannot send functions through postMessage\n * extract the path to all functions in the schema\n *\n * @param obj\n */\nexport function extractMethods(obj: any) {\n const methods: Record<string, (...args: any) => any> = {};\n (function parse(obj: any, path = \"\") {\n Object.keys(obj).forEach((prop) => {\n const propPath = path ? `${path}.${prop}` : prop;\n if (obj[prop] === Object(obj[prop])) {\n parse(obj[prop], propPath);\n }\n if (typeof obj[prop] === \"function\") {\n methods[propPath] = obj[prop];\n delete obj[prop];\n }\n });\n })(obj);\n return methods;\n}\n\nconst urlRegex = /^(https?:|file:)?\\/\\/([^/:]+)?(:(\\d+))?/;\nconst ports: any = { \"http:\": \"80\", \"https:\": \"443\" };\n\n/**\n * convert the url into an origin (remove paths)\n *\n * @param url\n */\nexport function getOriginFromURL(url: string | null) {\n if (!url) return null;\n\n const regexResult = urlRegex.exec(url);\n if (!regexResult) return null;\n\n const [, protocol = \"http:\", hostname, , port] = regexResult;\n\n // If the protocol is file, return file://\n if (protocol === \"file:\") {\n return \"file://\";\n }\n\n // If the port is the default for the protocol, we don't want to add it to the origin string\n const portSuffix = port && port !== ports[protocol] ? `:${port}` : \"\";\n return `${protocol}//${hostname}${portSuffix}`;\n}\n\nexport function get(obj: any, path: string | Array<string | number>, defaultValue?: any): any {\n const keys = Array.isArray(path) ? path : path.split(\".\").filter(Boolean);\n let result = obj;\n\n for (const key of keys) {\n result = result?.[key];\n if (result === undefined) {\n return defaultValue;\n }\n }\n\n return result;\n}\n\nexport function set(obj: any, path: string | (string | number)[], value: any): any {\n if (!obj || typeof obj !== \"object\") return obj;\n\n const pathArray = Array.isArray(path) ? path : path.split(\".\").map((key) => (key.match(/^\\d+$/) ? Number(key) : key));\n\n let current = obj;\n\n for (let i = 0; i < pathArray.length; i++) {\n const key = pathArray[i];\n\n if (i === pathArray.length - 1) {\n current[key] = value;\n } else {\n if (!current[key] || typeof current[key] !== \"object\") {\n current[key] = typeof pathArray[i + 1] === \"number\" ? [] : {};\n }\n current = current[key];\n }\n }\n\n return obj;\n}\n\nexport function generateId(length: number = 10): string {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n let result = \"\";\n for (let i = 0; i < length; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n\nlet parentPort: any = null;\n\nif (isNodeEnv()) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const workerThreads = require(\"worker_threads\");\n parentPort = workerThreads.parentPort;\n } catch (e) {\n // Not in worker thread context\n }\n}\n\n/**\n * Get the appropriate target host for messaging based on the current environment\n * @returns The messaging target for the current environment\n */\nexport function getTargetHost(): any {\n if (isNodeEnv()) {\n return parentPort;\n }\n\n if (isWorker()) {\n return self;\n }\n\n if (isIframe()) {\n return window.parent;\n }\n\n throw new Error(\"No valid target found for postMessage\");\n}\n\n/**\n * Send a message to a target, handling different environments (iframe, web worker, node worker)\n * @param target The target to send the message to\n * @param message The message to send\n * @param origin Optional origin for iframe communication\n * @param transferables Optional transferables for postMessage\n */\nexport function postMessageToTarget(\n target: Target,\n message: any,\n origin?: string,\n transferables?: Transferable[],\n): void {\n if (!target) {\n throw new Error(\"Rimless Error: No target specified for postMessage\");\n }\n\n // Node.js Worker\n if (isNodeEnv() && target === parentPort) {\n target.postMessage(message, { transfer: transferables });\n return;\n }\n\n // Web Worker\n if (isWorker()) {\n target.postMessage(message, { transfer: transferables });\n return;\n }\n\n // iframe or window\n if (target.postMessage) {\n target.postMessage(message, { targetOrigin: origin || \"*\", transfer: transferables });\n return;\n }\n\n throw new Error(\"Rimless Error: Invalid target for postMessage\");\n}\n\nexport function isNodeWorker(guest: Guest | Target): guest is NodeWorker {\n return parentPort !== null && guest === parentPort;\n}\n\nexport function isWorkerLike(guest: Guest): guest is WorkerLike {\n return isNodeWorker(guest) || (typeof Worker !== \"undefined\" && guest instanceof Worker);\n}\n\nexport function addEventListener(target: Target, event: string, handler: EventListenerOrEventListenerObject) {\n if (isNodeWorker(target)) {\n target.on(event, handler);\n } else if (\"addEventListener\" in target) {\n target.addEventListener(event, handler);\n }\n}\n\nexport function removeEventListener(target: Target, event: string, handler: EventListenerOrEventListenerObject) {\n if (isNodeWorker(target)) {\n target.off(event, handler);\n } else if (\"removeEventListener\" in target) {\n target.removeEventListener(event, handler);\n }\n}\n\n/**\n * Normalize message event data across Web and Node.js environments\n * In web, data is in event.data\n * In Node.js, the event itself contains the data\n */\nexport function getEventData(event: any) {\n return event.data || event;\n}\n","export interface NodeWorker {\n on(event: string, handler: any): void;\n off(event: string, handler: any): void;\n postMessage(message: any): void;\n terminate(): void;\n}\n\nexport type WorkerLike = Worker | NodeWorker;\n\nexport enum events {\n MESSAGE = \"message\",\n}\n\nexport enum actions {\n HANDSHAKE_REQUEST = \"RIMLESS/HANDSHAKE_REQUEST\",\n HANDSHAKE_REPLY = \"RIMLESS/HANDSHAKE_REPLY\",\n RPC_REQUEST = \"RIMLESS/RPC_REQUEST\",\n RPC_RESOLVE = \"RIMLESS/RPC_RESOLVE\",\n RPC_REJECT = \"RIMLESS/RPC_REJECT\",\n}\n\nexport type Schema = Record<string, any>;\n\nexport interface Connection {\n id: string;\n remote: Schema;\n close: () => void;\n}\n\nexport type Connections = Record<string, Connection>;\n\nexport interface RimlessEvent extends EventListener {\n source?: Window;\n origin?: string;\n data: HandshakeRequestPayload | HandshakeConfirmationPayload | RPCRequestPayload | RPCResolvePayload;\n}\n\nexport interface HandshakeRequestPayload {\n action: actions.HANDSHAKE_REQUEST;\n connectionID: string;\n methodNames: string[];\n schema: Schema;\n}\n\nexport interface HandshakeConfirmationPayload {\n action: actions.HANDSHAKE_REPLY;\n connectionID: string;\n methodNames: string[];\n schema: Schema;\n}\n\nexport interface RPCRequestPayload {\n action: actions.RPC_REQUEST;\n args: any[];\n callID: string;\n callName: string;\n connectionID: string;\n}\n\nexport interface RPCResolvePayload {\n action: actions.RPC_RESOLVE | actions.RPC_REJECT;\n result?: any | null;\n error?: Error | null;\n callID: string;\n callName: string;\n connectionID: string;\n}\n\nexport interface EventHandlers {\n onConnectionSetup: (remote: Schema) => Promise<void>;\n}\n\nexport type Guest = WorkerLike | HTMLIFrameElement;\nexport type Target = Window | WorkerLike;\nexport type Environment = Window | WorkerLike;\n","import { addEventListener, generateId, getEventData, postMessageToTarget, removeEventListener, set } from \"./helpers\";\nimport {\n actions,\n Environment,\n events,\n RimlessEvent,\n RPCRequestPayload,\n RPCResolvePayload,\n Schema,\n Target,\n} from \"./types\";\n\n/** Private symbol to which we will assign transferable objects */\nconst SYM_TRANSFERABLES = Symbol();\n\n/**\n * for each function in methods\n * 1. subscribe to an event that the remote can call\n * 2. listen for calls from the remote. When called execute the function and emit the results.\n *\n * @param methods an object of method ids : methods from the local schema\n * @param rpcConnectionID\n * @param listenTo Environment to listen for incoming messages\n * @param sendTo Target to send outgoing messages\n * @param remote The remote API object for the current connection\n * @return a function to cancel all subscriptions\n */\nexport function registerLocalMethods(\n methods: Record<string, (...args: any[]) => any> = {},\n rpcConnectionID: string,\n listenTo: Environment,\n sendTo: Target,\n remote: Schema // Add remote parameter\n) {\n const listeners: any[] = [];\n for (const [methodName, method] of Object.entries(methods)) {\n // handle a remote calling a local method\n async function handleCall(event: any) {\n const eventData = getEventData(event);\n const { action, callID, connectionID, callName, args = [] } = eventData as RPCRequestPayload;\n\n if (action !== actions.RPC_REQUEST) return;\n if (!callID || !callName) return;\n if (callName !== methodName) return;\n if (connectionID !== rpcConnectionID) return;\n\n const payload: RPCResolvePayload = {\n action: actions.RPC_RESOLVE,\n callID,\n callName,\n connectionID,\n error: null,\n result: null,\n };\n\n // when a host function returns transferable results to the remote, the\n // transferables are assigned to a special symbol on each function's result\n let transferables: Transferable[] | undefined = undefined;\n\n // run function and return the results to the remote\n try {\n // Pass the remote object as the LAST argument to the local method\n payload.result = await method(...args, remote);\n\n if (payload.result && payload.result[SYM_TRANSFERABLES]) {\n transferables = payload.result[SYM_TRANSFERABLES] ?? [];\n delete payload.result[SYM_TRANSFERABLES];\n }\n } catch (error) {\n payload.action = actions.RPC_REJECT;\n payload.error = JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)));\n }\n\n postMessageToTarget(sendTo, payload, event?.origin, transferables);\n }\n\n // subscribe to the call event\n addEventListener(listenTo, events.MESSAGE, handleCall);\n listeners.push(() => removeEventListener(listenTo, events.MESSAGE, handleCall));\n }\n\n return () => listeners.forEach((unregister) => unregister());\n}\n\n/**\n * Create a function that will make an RPC request to the remote with some arguments.\n * Listen to an event that returns the results from the remote.\n *\n * @param rpcCallName\n * @param rpcConnectionID\n * @param event\n * @param listeners\n * @param guest\n *\n * @returns a promise with the result of the RPC\n */\nexport function createRPC(\n rpcCallName: string,\n rpcConnectionID: string,\n event: RimlessEvent,\n listeners: Array<() => void> = [],\n listenTo: Environment,\n sendTo: Target\n) {\n return (...args: any[]) => {\n return new Promise((resolve, reject) => {\n const requestID = generateId();\n\n // on RPC response\n function handleResponse(event: any) {\n const eventData = getEventData(event);\n const { callID, connectionID, callName, result, error, action } = eventData as RPCResolvePayload;\n\n if (!callID || !callName) return;\n if (callName !== rpcCallName) return;\n if (callID !== requestID) return;\n if (connectionID !== rpcConnectionID) return;\n\n // resolve the response\n if (action === actions.RPC_RESOLVE) return resolve(result);\n if (action === actions.RPC_REJECT) return reject(error);\n }\n\n // send the RPC request with arguments\n const payload = {\n action: actions.RPC_REQUEST,\n args,\n callID: requestID,\n callName: rpcCallName,\n connectionID: rpcConnectionID,\n };\n\n // if the arguments have transferables, post them as well\n const transferables = args.reduce(\n (transferables, arg) =>\n arg[SYM_TRANSFERABLES]?.length ? transferables.concat(arg[SYM_TRANSFERABLES]) : transferables,\n // @ts-expect-error: we know this is an array of transferables (if it exists)\n args[SYM_TRANSFERABLES] ?? []\n );\n\n addEventListener(listenTo, events.MESSAGE, handleResponse);\n listeners.push(() => removeEventListener(listenTo, events.MESSAGE, handleResponse));\n\n postMessageToTarget(sendTo, payload, event?.origin, transferables);\n });\n };\n}\n\n/**\n * create an object based on the remote schema's methods. Functions in that object will\n * emit an event that will trigger the RPC on the remote.\n *\n * @param schema\n * @param methods\n * @param connectionID\n * @param event\n * @param guest\n */\nexport function registerRemoteMethods(\n schema: Schema = {},\n methodNames: Iterable<string> = [],\n connectionID: string,\n event: RimlessEvent,\n listenTo: Environment,\n sendTo: Target\n) {\n const remote = { ...schema };\n const listeners: Array<() => void> = [];\n\n for (const methodName of methodNames) {\n const rpc = createRPC(methodName, connectionID, event, listeners, listenTo, sendTo);\n set(remote, methodName, rpc);\n }\n\n return {\n remote,\n unregisterRemote: () => listeners.forEach((unregister) => unregister()),\n };\n}\n\n/**\n * This function is used by API schema declarations and remote function calls alike to\n * indicate which variables should be declared as transferable over `postMessage` calls.\n *\n * @param cb a function that takes a transfer function as an argument and returns an object\n * (in the loose, `typeof foo === \"object\"` sense)\n * @return result the callback's return value, with an extra array of transferable objects\n * assigned to rimless' private symbol `SYM_TRANSFERABLES`\n *\n * The `transfer(...)` function is called with an object to transfer; if there\n * are many objects to transfer, you may call it multiple times. It will always\n * return the input object. Calling `transfer` only modifies the callback\n * result, not the transferred object itself (or objects themselves).\n *\n * @example\n * host.connect({\n * foo: (...args) => {\n * const foo = new ArrayBuffer(8);\n * return withTransferable((transfer) => transfer(foo));\n * }),\n * });\n *\n * @example\n * host.remote.foo(withTransferable((transfer) => ({\n * stream: transfer(new ReadableStream()),\n * })));\n */\nexport const withTransferable = <Transferable, Result extends object>(\n cb: (transfer: <T extends Transferable>(transferable: T) => T) => Result\n) => {\n const transferables: Transferable[] = [];\n const transfer = <T extends Transferable>(transferable: T) => {\n transferables.push(transferable);\n return transferable;\n };\n\n const result = cb(transfer);\n\n return Object.assign(result, { [SYM_TRANSFERABLES]: transferables });\n};\n","import {\n extractMethods,\n getEventData,\n getTargetHost,\n postMessageToTarget,\n addEventListener,\n removeEventListener,\n} from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, EventHandlers, events, Connection, Schema } from \"./types\";\n\nfunction connect(schema: Schema = {}, eventHandlers?: EventHandlers): Promise<Connection> {\n return new Promise(async (resolve) => {\n const localMethods = extractMethods(schema);\n const sendTo = getTargetHost();\n const listenTo = self || window;\n\n // on handshake response\n async function handleHandshakeResponse(event: any) {\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REPLY) return;\n\n // register remote methods\n const { remote, unregisterRemote } = registerRemoteMethods(\n eventData.schema,\n eventData.methodNames,\n eventData.connectionID,\n event,\n listenTo,\n sendTo,\n );\n\n // register local methods, passing the remote object\n const unregisterLocal = registerLocalMethods(localMethods, eventData.connectionID, listenTo, sendTo, remote);\n\n await eventHandlers?.onConnectionSetup?.(remote);\n\n // send a HANDSHAKE REPLY to the host\n const payload = {\n action: actions.HANDSHAKE_REPLY,\n connectionID: eventData.connectionID,\n };\n\n postMessageToTarget(sendTo, payload, event?.origin);\n\n // close the connection and all listeners when called\n const close = () => {\n removeEventListener(listenTo, events.MESSAGE, handleHandshakeResponse);\n unregisterRemote();\n unregisterLocal();\n };\n\n // resolve connection object\n const connection = { remote, close, id: eventData.connectionID };\n return resolve(connection);\n }\n\n // subscribe to HANDSHAKE RESPONSE MESSAGES\n addEventListener(listenTo, events.MESSAGE, handleHandshakeResponse);\n\n const payload = {\n action: actions.HANDSHAKE_REQUEST,\n methodNames: Object.keys(localMethods),\n schema: schema,\n };\n\n postMessageToTarget(sendTo, payload);\n });\n}\n\nexport default {\n connect,\n};\n","import {\n addEventListener,\n extractMethods,\n generateId,\n getEventData,\n getOriginFromURL,\n isNodeEnv,\n isNodeWorker,\n isWorkerLike,\n postMessageToTarget,\n removeEventListener,\n} from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, events, Guest, Connection, Connections, Schema } from \"./types\";\n\nconst connections: Connections = {};\n\nfunction isValidTarget(guest: Guest, event: any) {\n // If it's a worker, we don't need to validate origin\n if (isNodeWorker(guest) || (typeof Worker !== \"undefined\" && guest instanceof Worker)) {\n return true;\n }\n\n // For iframes, check origin and source\n const iframe = guest as HTMLIFrameElement;\n try {\n const childURL = iframe.src;\n const hasInlineContent = typeof iframe.srcdoc === \"string\" && iframe.srcdoc.length > 0;\n const childOrigin = getOriginFromURL(childURL);\n const hasProperOrigin = event.origin === childOrigin;\n const hasProperSource = event.source === iframe.contentWindow;\n\n // For inline iframes (srcdoc/about:blank) we can only rely on source matching\n if (hasInlineContent || childURL === \"about:blank\") {\n return hasProperSource;\n }\n\n return (hasProperOrigin && hasProperSource) || !childURL;\n } catch (e) {\n console.warn(\"Error checking iframe target:\", e);\n return false;\n }\n}\n\n/**\n * Perform a handshake with the target iframe, when the handshake is confirmed\n * resolve the connection object containing RPCs and properties\n *\n * @param guest\n * @param schema\n * @returns Promise\n */\nfunction connect(guest: Guest, schema: Schema = {}): Promise<Connection> {\n if (!guest) throw new Error(\"a target is required\");\n\n const guestIsWorker = isWorkerLike(guest);\n\n const listenTo = guestIsWorker || isNodeEnv() ? (guest as Worker) : window;\n\n return new Promise((resolve) => {\n const connectionID = generateId();\n\n // on handshake request\n function handleHandshake(event: any) {\n const sendTo = guestIsWorker || isNodeEnv() ? (guest as Worker) : event.source;\n\n if (!guestIsWorker && !isNodeEnv() && !isValidTarget(guest, event)) return;\n\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REQUEST) return;\n if (connections[connectionID]) return;\n\n // Extract local methods first (doesn't need remote yet)\n const localMethods = extractMethods(schema);\n\n // Register remote methods first to get the remote object\n const { remote, unregisterRemote } = registerRemoteMethods(\n eventData.schema,\n eventData.methodNames,\n connectionID,\n event,\n listenTo,\n sendTo,\n );\n\n // Now register local methods, passing the remote object\n const unregisterLocal = registerLocalMethods(localMethods, connectionID, listenTo, sendTo, remote);\n\n // send a HANDSHAKE REPLY to the guest\n const payload = {\n action: actions.HANDSHAKE_REPLY,\n connectionID,\n schema: schema,\n methodNames: Object.keys(localMethods),\n };\n\n postMessageToTarget(sendTo, payload, event.origin);\n\n // close the connection and all listeners when called\n const close = () => {\n delete connections[connectionID];\n removeEventListener(listenTo, events.MESSAGE, handleHandshake);\n removeEventListener(listenTo, events.MESSAGE, handleHandshakeReply);\n unregisterRemote();\n unregisterLocal();\n if (guestIsWorker) {\n (guest as Worker).terminate();\n }\n };\n\n const connection: Connection = { remote, close, id: connectionID };\n connections[connectionID] = connection;\n }\n\n // subscribe to HANDSHAKE MESSAGES\n addEventListener(listenTo, events.MESSAGE, handleHandshake);\n\n // on handshake reply\n function handleHandshakeReply(event: any) {\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REPLY) return;\n if (connectionID !== eventData.connectionID) return;\n\n if (!connections[eventData.connectionID]) {\n throw new Error(\"Rimless Error: No connection found for this connectionID\");\n }\n\n return resolve(connections[eventData.connectionID]);\n }\n\n addEventListener(listenTo, events.MESSAGE, handleHandshakeReply);\n });\n}\n\nexport default {\n connect,\n};\n"],"names":["isWorker","isNodeEnv","isIframe","extractMethods","obj","methods","parse","path","prop","propPath","urlRegex","ports","getOriginFromURL","url","regexResult","protocol","hostname","port","portSuffix","set","value","pathArray","key","current","i","generateId","length","chars","result","parentPort","getTargetHost","postMessageToTarget","target","message","origin","transferables","isNodeWorker","guest","isWorkerLike","addEventListener","event","handler","removeEventListener","getEventData","events","actions","SYM_TRANSFERABLES","registerLocalMethods","rpcConnectionID","listenTo","sendTo","remote","listeners","methodName","method","handleCall","eventData","action","callID","connectionID","callName","args","payload","error","unregister","createRPC","rpcCallName","resolve","reject","requestID","handleResponse","arg","registerRemoteMethods","schema","methodNames","rpc","withTransferable","cb","transferable","connect","eventHandlers","localMethods","handleHandshakeResponse","unregisterRemote","unregisterLocal","connection","connections","isValidTarget","iframe","childURL","hasInlineContent","childOrigin","hasProperOrigin","hasProperSource","guestIsWorker","handleHandshake","handleHandshakeReply","host"],"mappings":"qCAOO,SAASA,GAAoB,CAClC,OAAO,OAAO,OAAW,KAAe,OAAO,KAAS,GAC1D,CAOO,SAASC,GAAqB,CACnC,OAAO,OAAO,QAAY,KAAe,CAAC,CAAE,QAAgB,UAAU,IACxE,CAOO,SAASC,GAAW,CACzB,OAAO,OAAO,OAAS,OAAO,GAChC,CAQO,SAASC,EAAeC,EAAU,CACvC,MAAMC,EAAiD,CAAA,EACvD,OAAC,SAASC,EAAMF,EAAUG,EAAO,GAAI,CACnC,OAAO,KAAKH,CAAG,EAAE,QAASI,GAAS,CACjC,MAAMC,EAAWF,EAAO,GAAGA,CAAI,IAAIC,CAAI,GAAKA,EACxCJ,EAAII,CAAI,IAAM,OAAOJ,EAAII,CAAI,CAAC,GAChCF,EAAMF,EAAII,CAAI,EAAGC,CAAQ,EAEvB,OAAOL,EAAII,CAAI,GAAM,aACvBH,EAAQI,CAAQ,EAAIL,EAAII,CAAI,EAC5B,OAAOJ,EAAII,CAAI,EAEnB,CAAC,CACH,EAAGJ,CAAG,EACCC,CACT,CAEA,MAAMK,EAAW,0CACXC,EAAa,CAAE,QAAS,KAAM,SAAU,KAAA,EAOvC,SAASC,EAAiBC,EAAoB,CACnD,GAAI,CAACA,EAAK,OAAO,KAEjB,MAAMC,EAAcJ,EAAS,KAAKG,CAAG,EACrC,GAAI,CAACC,EAAa,OAAO,KAEzB,KAAM,CAAA,CAAGC,EAAW,QAASC,EAAA,CAAYC,CAAI,EAAIH,EAGjD,GAAIC,IAAa,QACf,MAAO,UAIT,MAAMG,EAAaD,GAAQA,IAASN,EAAMI,CAAQ,EAAI,IAAIE,CAAI,GAAK,GACnE,MAAO,GAAGF,CAAQ,KAAKC,CAAQ,GAAGE,CAAU,EAC9C,CAgBO,SAASC,EAAIf,EAAUG,EAAoCa,EAAiB,CACjF,GAAI,CAAChB,GAAO,OAAOA,GAAQ,SAAU,OAAOA,EAE5C,MAAMiB,EAAY,MAAM,QAAQd,CAAI,EAAIA,EAAOA,EAAK,MAAM,GAAG,EAAE,IAAKe,GAASA,EAAI,MAAM,OAAO,EAAI,OAAOA,CAAG,EAAIA,CAAI,EAEpH,IAAIC,EAAUnB,EAEd,QAASoB,EAAI,EAAGA,EAAIH,EAAU,OAAQG,IAAK,CACzC,MAAMF,EAAMD,EAAUG,CAAC,EAEnBA,IAAMH,EAAU,OAAS,EAC3BE,EAAQD,CAAG,EAAIF,IAEX,CAACG,EAAQD,CAAG,GAAK,OAAOC,EAAQD,CAAG,GAAM,YAC3CC,EAAQD,CAAG,EAAI,OAAOD,EAAUG,EAAI,CAAC,GAAM,SAAW,CAAA,EAAK,CAAA,GAE7DD,EAAUA,EAAQD,CAAG,EAEzB,CAEA,OAAOlB,CACT,CAEO,SAASqB,EAAWC,EAAiB,GAAY,CACtD,MAAMC,EAAQ,iEACd,IAAIC,EAAS,GACb,QAASJ,EAAI,EAAGA,EAAIE,EAAQF,IAC1BI,GAAUD,EAAM,OAAO,KAAK,MAAM,KAAK,OAAA,EAAWA,EAAM,MAAM,CAAC,EAEjE,OAAOC,CACT,CAEA,IAAIC,EAAkB,KAEtB,GAAI5B,IACF,GAAI,CAGF4B,EADsB,QAAQ,gBAAgB,EACnB,UAC7B,MAAY,CAEZ,CAOK,SAASC,GAAqB,CACnC,GAAI7B,IACF,OAAO4B,EAGT,GAAI7B,IACF,OAAO,KAGT,GAAIE,IACF,OAAO,OAAO,OAGhB,MAAM,IAAI,MAAM,uCAAuC,CACzD,CASO,SAAS6B,EACdC,EACAC,EACAC,EACAC,EACM,CACN,GAAI,CAACH,EACH,MAAM,IAAI,MAAM,oDAAoD,EAItE,GAAI/B,EAAA,GAAe+B,IAAWH,EAAY,CACxCG,EAAO,YAAYC,EAAS,CAAE,SAAUE,EAAe,EACvD,MACF,CAGA,GAAInC,IAAY,CACdgC,EAAO,YAAYC,EAAS,CAAE,SAAUE,EAAe,EACvD,MACF,CAGA,GAAIH,EAAO,YAAa,CACtBA,EAAO,YAAYC,EAAS,CAAE,aAAcC,GAAU,IAAK,SAAUC,EAAe,EACpF,MACF,CAEA,MAAM,IAAI,MAAM,+CAA+C,CACjE,CAEO,SAASC,EAAaC,EAA4C,CACvE,OAAOR,IAAe,MAAQQ,IAAUR,CAC1C,CAEO,SAASS,EAAaD,EAAmC,CAC9D,OAAOD,EAAaC,CAAK,GAAM,OAAO,OAAW,KAAeA,aAAiB,MACnF,CAEO,SAASE,EAAiBP,EAAgBQ,EAAeC,EAA6C,CACvGL,EAAaJ,CAAM,EACrBA,EAAO,GAAGQ,EAAOC,CAAO,EACf,qBAAsBT,GAC/BA,EAAO,iBAAiBQ,EAAOC,CAAO,CAE1C,CAEO,SAASC,EAAoBV,EAAgBQ,EAAeC,EAA6C,CAC1GL,EAAaJ,CAAM,EACrBA,EAAO,IAAIQ,EAAOC,CAAO,EAChB,wBAAyBT,GAClCA,EAAO,oBAAoBQ,EAAOC,CAAO,CAE7C,CAOO,SAASE,EAAaH,EAAY,CACvC,OAAOA,EAAM,MAAQA,CACvB,CCxNO,IAAKI,GAAAA,IACVA,EAAA,QAAU,UADAA,IAAAA,GAAA,CAAA,CAAA,EAIAC,GAAAA,IACVA,EAAA,kBAAoB,4BACpBA,EAAA,gBAAkB,0BAClBA,EAAA,YAAc,sBACdA,EAAA,YAAc,sBACdA,EAAA,WAAa,qBALHA,IAAAA,GAAA,CAAA,CAAA,ECAZ,MAAMC,EAAoB,OAAA,EAcnB,SAASC,EACd1C,EAAmD,CAAA,EACnD2C,EACAC,EACAC,EACAC,EACA,CACA,MAAMC,EAAmB,CAAA,EACzB,SAAW,CAACC,EAAYC,CAAM,IAAK,OAAO,QAAQjD,CAAO,EAAG,CAE1D,eAAekD,EAAWf,EAAY,CACpC,MAAMgB,EAAYb,EAAaH,CAAK,EAC9B,CAAE,OAAAiB,EAAQ,OAAAC,EAAQ,aAAAC,EAAc,SAAAC,EAAU,KAAAC,EAAO,CAAA,GAAOL,EAK9D,GAHIC,IAAWZ,EAAQ,aACnB,CAACa,GAAU,CAACE,GACZA,IAAaP,GACbM,IAAiBX,EAAiB,OAEtC,MAAMc,EAA6B,CACjC,OAAQjB,EAAQ,YAChB,OAAAa,EACA,SAAAE,EACA,aAAAD,EACA,MAAO,KACP,OAAQ,IAAA,EAKV,IAAIxB,EAGJ,GAAI,CAEF2B,EAAQ,OAAS,MAAMR,EAAO,GAAGO,EAAMV,CAAM,EAEzCW,EAAQ,QAAUA,EAAQ,OAAOhB,CAAiB,IACpDX,EAAgB2B,EAAQ,OAAOhB,CAAiB,GAAK,CAAA,EACrD,OAAOgB,EAAQ,OAAOhB,CAAiB,EAE3C,OAASiB,EAAO,CACdD,EAAQ,OAASjB,EAAQ,WACzBiB,EAAQ,MAAQ,KAAK,MAAM,KAAK,UAAUC,EAAO,OAAO,oBAAoBA,CAAK,CAAC,CAAC,CACrF,CAEAhC,EAAoBmB,EAAQY,EAAStB,GAAO,OAAQL,CAAa,CACnE,CAGAI,EAAiBU,EAAUL,EAAO,QAASW,CAAU,EACrDH,EAAU,KAAK,IAAMV,EAAoBO,EAAUL,EAAO,QAASW,CAAU,CAAC,CAChF,CAEA,MAAO,IAAMH,EAAU,QAASY,GAAeA,GAAY,CAC7D,CAcO,SAASC,EACdC,EACAlB,EACAR,EACAY,EAA+B,CAAA,EAC/BH,EACAC,EACA,CACA,MAAO,IAAIW,IACF,IAAI,QAAQ,CAACM,EAASC,IAAW,CACtC,MAAMC,EAAY5C,EAAA,EAGlB,SAAS6C,EAAe9B,EAAY,CAClC,MAAMgB,EAAYb,EAAaH,CAAK,EAC9B,CAAE,OAAAkB,EAAQ,aAAAC,EAAc,SAAAC,EAAU,OAAAhC,EAAQ,MAAAmC,EAAO,OAAAN,GAAWD,EAElE,GAAI,GAACE,GAAU,CAACE,IACZA,IAAaM,GACbR,IAAWW,GACXV,IAAiBX,EAGrB,IAAIS,IAAWZ,EAAQ,YAAa,OAAOsB,EAAQvC,CAAM,EACzD,GAAI6B,IAAWZ,EAAQ,WAAY,OAAOuB,EAAOL,CAAK,EACxD,CAGA,MAAMD,EAAU,CACd,OAAQjB,EAAQ,YAChB,KAAAgB,EACA,OAAQQ,EACR,SAAUH,EACV,aAAclB,CAAA,EAIVb,EAAgB0B,EAAK,OACzB,CAAC1B,EAAeoC,IACdA,EAAIzB,CAAiB,GAAG,OAASX,EAAc,OAAOoC,EAAIzB,CAAiB,CAAC,EAAIX,EAElF0B,EAAKf,CAAiB,GAAK,CAAA,CAAC,EAG9BP,EAAiBU,EAAUL,EAAO,QAAS0B,CAAc,EACzDlB,EAAU,KAAK,IAAMV,EAAoBO,EAAUL,EAAO,QAAS0B,CAAc,CAAC,EAElFvC,EAAoBmB,EAAQY,EAAStB,GAAO,OAAQL,CAAa,CACnE,CAAC,CAEL,CAYO,SAASqC,EACdC,EAAiB,CAAA,EACjBC,EAAgC,CAAA,EAChCf,EACAnB,EACAS,EACAC,EACA,CACA,MAAMC,EAAS,CAAE,GAAGsB,CAAA,EACdrB,EAA+B,CAAA,EAErC,UAAWC,KAAcqB,EAAa,CACpC,MAAMC,EAAMV,EAAUZ,EAAYM,EAAcnB,EAAOY,EAAWH,EAAUC,CAAM,EAClF/B,EAAIgC,EAAQE,EAAYsB,CAAG,CAC7B,CAEA,MAAO,CACL,OAAAxB,EACA,iBAAkB,IAAMC,EAAU,QAASY,GAAeA,GAAY,CAAA,CAE1E,CA6BO,MAAMY,EACXC,GACG,CACH,MAAM1C,EAAgC,CAAA,EAMhCP,EAASiD,EAL2BC,IACxC3C,EAAc,KAAK2C,CAAY,EACxBA,EAGiB,EAE1B,OAAO,OAAO,OAAOlD,EAAQ,CAAE,CAACkB,CAAiB,EAAGX,EAAe,CACrE,EChNA,SAAS4C,EAAQN,EAAiB,CAAA,EAAIO,EAAoD,CACxF,OAAO,IAAI,QAAQ,MAAOb,GAAY,CACpC,MAAMc,EAAe9E,EAAesE,CAAM,EACpCvB,EAASpB,EAAA,EACTmB,EAAW,MAAQ,OAGzB,eAAeiC,EAAwB1C,EAAY,CACjD,MAAMgB,EAAYb,EAAaH,CAAK,EACpC,GAAIgB,GAAW,SAAWX,EAAQ,gBAAiB,OAGnD,KAAM,CAAE,OAAAM,EAAQ,iBAAAgC,CAAA,EAAqBX,EACnChB,EAAU,OACVA,EAAU,YACVA,EAAU,aACVhB,EACAS,EACAC,CAAA,EAIIkC,EAAkBrC,EAAqBkC,EAAczB,EAAU,aAAcP,EAAUC,EAAQC,CAAM,EAE3G,MAAM6B,GAAe,oBAAoB7B,CAAM,EAG/C,MAAMW,EAAU,CACd,OAAQjB,EAAQ,gBAChB,aAAcW,EAAU,YAAA,EAG1BzB,EAAoBmB,EAAQY,EAAStB,GAAO,MAAM,EAUlD,MAAM6C,EAAa,CAAE,OAAAlC,EAAQ,MAPf,IAAM,CAClBT,EAAoBO,EAAUL,EAAO,QAASsC,CAAuB,EACrEC,EAAA,EACAC,EAAA,CACF,EAGoC,GAAI5B,EAAU,YAAA,EAClD,OAAOW,EAAQkB,CAAU,CAC3B,CAGA9C,EAAiBU,EAAUL,EAAO,QAASsC,CAAuB,EAElE,MAAMpB,EAAU,CACd,OAAQjB,EAAQ,kBAChB,YAAa,OAAO,KAAKoC,CAAY,EACrC,OAAAR,CAAA,EAGF1C,EAAoBmB,EAAQY,CAAO,CACrC,CAAC,CACH,CAEA,MAAAzB,EAAe,CAAA,QACb0C,CACF,ECzDMO,EAA2B,CAAA,EAEjC,SAASC,EAAclD,EAAcG,EAAY,CAE/C,GAAIJ,EAAaC,CAAK,GAAM,OAAO,OAAW,KAAeA,aAAiB,OAC5E,MAAO,GAIT,MAAMmD,EAASnD,EACf,GAAI,CACF,MAAMoD,EAAWD,EAAO,IAClBE,EAAmB,OAAOF,EAAO,QAAW,UAAYA,EAAO,OAAO,OAAS,EAC/EG,EAAc/E,EAAiB6E,CAAQ,EACvCG,EAAkBpD,EAAM,SAAWmD,EACnCE,EAAkBrD,EAAM,SAAWgD,EAAO,cAGhD,OAAIE,GAAoBD,IAAa,cAC5BI,EAGDD,GAAmBC,GAAoB,CAACJ,CAClD,OAAS,EAAG,CACV,eAAQ,KAAK,gCAAiC,CAAC,EACxC,EACT,CACF,CAUA,SAASV,EAAQ1C,EAAcoC,EAAiB,GAAyB,CACvE,GAAI,CAACpC,EAAO,MAAM,IAAI,MAAM,sBAAsB,EAElD,MAAMyD,EAAgBxD,EAAaD,CAAK,EAElCY,EAAW6C,GAAiB7F,EAAA,EAAeoC,EAAmB,OAEpE,OAAO,IAAI,QAAS8B,GAAY,CAC9B,MAAMR,EAAelC,EAAA,EAGrB,SAASsE,EAAgBvD,EAAY,CACnC,MAAMU,EAAS4C,GAAiB7F,EAAA,EAAeoC,EAAmBG,EAAM,OAExE,GAAI,CAACsD,GAAiB,CAAC7F,EAAA,GAAe,CAACsF,EAAclD,EAAOG,CAAK,EAAG,OAEpE,MAAMgB,EAAYb,EAAaH,CAAK,EAEpC,GADIgB,GAAW,SAAWX,EAAQ,mBAC9ByC,EAAY3B,CAAY,EAAG,OAG/B,MAAMsB,EAAe9E,EAAesE,CAAM,EAGpC,CAAE,OAAAtB,EAAQ,iBAAAgC,CAAA,EAAqBX,EACnChB,EAAU,OACVA,EAAU,YACVG,EACAnB,EACAS,EACAC,CAAA,EAIIkC,EAAkBrC,EAAqBkC,EAActB,EAAcV,EAAUC,EAAQC,CAAM,EAG3FW,EAAU,CACd,OAAQjB,EAAQ,gBAChB,aAAAc,EACA,OAAAc,EACA,YAAa,OAAO,KAAKQ,CAAY,CAAA,EAGvClD,EAAoBmB,EAAQY,EAAStB,EAAM,MAAM,EAcjD,MAAM6C,EAAyB,CAAE,OAAAlC,EAAQ,MAX3B,IAAM,CAClB,OAAOmC,EAAY3B,CAAY,EAC/BjB,EAAoBO,EAAUL,EAAO,QAASmD,CAAe,EAC7DrD,EAAoBO,EAAUL,EAAO,QAASoD,CAAoB,EAClEb,EAAA,EACAC,EAAA,EACIU,GACDzD,EAAiB,UAAA,CAEtB,EAEgD,GAAIsB,CAAA,EACpD2B,EAAY3B,CAAY,EAAI0B,CAC9B,CAGA9C,EAAiBU,EAAUL,EAAO,QAASmD,CAAe,EAG1D,SAASC,EAAqBxD,EAAY,CACxC,MAAMgB,EAAYb,EAAaH,CAAK,EACpC,GAAIgB,GAAW,SAAWX,EAAQ,iBAC9Bc,IAAiBH,EAAU,aAE/B,IAAI,CAAC8B,EAAY9B,EAAU,YAAY,EACrC,MAAM,IAAI,MAAM,0DAA0D,EAG5E,OAAOW,EAAQmB,EAAY9B,EAAU,YAAY,CAAC,EACpD,CAEAjB,EAAiBU,EAAUL,EAAO,QAASoD,CAAoB,CACjE,CAAC,CACH,CAEA,MAAAC,EAAe,CACb,QAAAlB,CACF"}
|
|
1
|
+
{"version":3,"file":"rimless.min.js","sources":["../src/helpers.ts","../src/types.ts","../src/rpc.ts","../src/guest.ts","../src/host.ts"],"sourcesContent":["import { Guest, NodeWorker, Target, WorkerLike } from \"./types\";\n\ntype RuntimeEnvironment = \"browser\" | \"worker\" | \"node\" | \"bun\";\n\nfunction detectRuntime(): RuntimeEnvironment {\n const globalObject = globalThis as Record<string, any>;\n\n // Prefer explicit browser detection before checking shims\n if (typeof globalObject.window !== \"undefined\" && typeof globalObject.document !== \"undefined\") {\n return \"browser\";\n }\n\n const hasWorkerGlobalScope =\n typeof globalObject.WorkerGlobalScope !== \"undefined\" &&\n typeof globalObject.self !== \"undefined\" &&\n globalObject.self instanceof globalObject.WorkerGlobalScope;\n\n if (\n hasWorkerGlobalScope ||\n (typeof globalObject.window === \"undefined\" &&\n typeof globalObject.self !== \"undefined\" &&\n typeof globalObject.importScripts === \"function\")\n ) {\n return \"worker\";\n }\n\n const processRef = globalObject.process;\n if (processRef && typeof processRef === \"object\") {\n const versions = processRef.versions ?? {};\n const releaseName = processRef.release?.name;\n\n if (versions.bun || releaseName === \"bun\" || typeof globalObject.Bun !== \"undefined\") {\n return \"bun\";\n }\n\n if (versions.node && releaseName === \"node\") {\n return \"node\";\n }\n }\n\n if (typeof globalObject.Bun !== \"undefined\") {\n return \"bun\";\n }\n\n return \"browser\";\n}\n\nexport function getRuntimeEnvironment(): RuntimeEnvironment {\n return detectRuntime();\n}\n\nexport function isBrowserEnv(): boolean {\n return getRuntimeEnvironment() === \"browser\";\n}\n\n/**\n * check if run in a webworker\n *\n * @returns boolean\n */\nexport function isWorker(): boolean {\n return getRuntimeEnvironment() === \"worker\";\n}\n\n/**\n * check if run in a Node.js environment\n *\n * @returns boolean\n */\nexport function isNodeEnv(): boolean {\n return getRuntimeEnvironment() === \"node\";\n}\n\nexport function isBunEnv(): boolean {\n return getRuntimeEnvironment() === \"bun\";\n}\n\nexport function isServerEnv(): boolean {\n const runtime = getRuntimeEnvironment();\n return runtime === \"node\" || runtime === \"bun\";\n}\n\n/**\n * check if run in an iframe\n *\n * @returns boolean\n */\nexport function isIframe() {\n return window.self !== window.top;\n}\n\n/**\n * we cannot send functions through postMessage\n * extract the path to all functions in the schema\n *\n * @param obj\n */\nexport function extractMethods(obj: any) {\n const methods: Record<string, (...args: any) => any> = {};\n (function parse(obj: any, path = \"\") {\n Object.keys(obj).forEach((prop) => {\n const propPath = path ? `${path}.${prop}` : prop;\n if (obj[prop] === Object(obj[prop])) {\n parse(obj[prop], propPath);\n }\n if (typeof obj[prop] === \"function\") {\n methods[propPath] = obj[prop];\n delete obj[prop];\n }\n });\n })(obj);\n return methods;\n}\n\nconst urlRegex = /^(https?:|file:)?\\/\\/([^/:]+)?(:(\\d+))?/;\nconst ports: any = { \"http:\": \"80\", \"https:\": \"443\" };\n\n/**\n * convert the url into an origin (remove paths)\n *\n * @param url\n */\nexport function getOriginFromURL(url: string | null) {\n if (!url) return null;\n\n const regexResult = urlRegex.exec(url);\n if (!regexResult) return null;\n\n const [, protocol = \"http:\", hostname, , port] = regexResult;\n\n // If the protocol is file, return file://\n if (protocol === \"file:\") {\n return \"file://\";\n }\n\n // If the port is the default for the protocol, we don't want to add it to the origin string\n const portSuffix = port && port !== ports[protocol] ? `:${port}` : \"\";\n return `${protocol}//${hostname}${portSuffix}`;\n}\n\nexport function get(obj: any, path: string | Array<string | number>, defaultValue?: any): any {\n const keys = Array.isArray(path) ? path : path.split(\".\").filter(Boolean);\n let result = obj;\n\n for (const key of keys) {\n result = result?.[key];\n if (result === undefined) {\n return defaultValue;\n }\n }\n\n return result;\n}\n\nexport function set(obj: any, path: string | (string | number)[], value: any): any {\n if (!obj || typeof obj !== \"object\") return obj;\n\n const pathArray = Array.isArray(path) ? path : path.split(\".\").map((key) => (key.match(/^\\d+$/) ? Number(key) : key));\n\n let current = obj;\n\n for (let i = 0; i < pathArray.length; i++) {\n const key = pathArray[i];\n\n if (i === pathArray.length - 1) {\n current[key] = value;\n } else {\n if (!current[key] || typeof current[key] !== \"object\") {\n current[key] = typeof pathArray[i + 1] === \"number\" ? [] : {};\n }\n current = current[key];\n }\n }\n\n return obj;\n}\n\nexport function generateId(length: number = 10): string {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n let result = \"\";\n for (let i = 0; i < length; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n\nconst initialRuntime = getRuntimeEnvironment();\nlet parentPort: any = null;\n\nif (initialRuntime === \"node\" || initialRuntime === \"bun\") {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const workerThreads = require(\"worker_threads\");\n parentPort = workerThreads.parentPort;\n } catch (e) {\n // Not in worker thread context\n }\n}\n\n/**\n * Get the appropriate target host for messaging based on the current environment\n * @returns The messaging target for the current environment\n */\nexport function getTargetHost(): any {\n if (isServerEnv()) {\n return parentPort;\n }\n\n if (isWorker()) {\n return self;\n }\n\n if (isIframe()) {\n return window.parent;\n }\n\n throw new Error(\"No valid target found for postMessage\");\n}\n\n/**\n * Send a message to a target, handling different environments (iframe, web worker, node worker)\n * @param target The target to send the message to\n * @param message The message to send\n * @param origin Optional origin for iframe communication\n * @param transferables Optional transferables for postMessage\n */\nexport function postMessageToTarget(\n target: Target,\n message: any,\n origin?: string,\n transferables?: Transferable[],\n): void {\n if (!target) {\n throw new Error(\"Rimless Error: No target specified for postMessage\");\n }\n\n // Node.js Worker\n if (isServerEnv() && target === parentPort) {\n target.postMessage(message, { transfer: transferables });\n return;\n }\n\n // Web Worker\n if (isWorker()) {\n target.postMessage(message, { transfer: transferables });\n return;\n }\n\n // iframe or window\n if (target.postMessage) {\n target.postMessage(message, { targetOrigin: origin || \"*\", transfer: transferables });\n return;\n }\n\n throw new Error(\"Rimless Error: Invalid target for postMessage\");\n}\n\nexport function isNodeWorker(guest: Guest | Target): guest is NodeWorker {\n return parentPort !== null && guest === parentPort;\n}\n\nexport function isWorkerLike(guest: Guest): guest is WorkerLike {\n return isNodeWorker(guest) || (typeof Worker !== \"undefined\" && guest instanceof Worker);\n}\n\nexport function addEventListener(target: Target, event: string, handler: EventListenerOrEventListenerObject) {\n if (isNodeWorker(target)) {\n target.on(event, handler);\n } else if (\"addEventListener\" in target) {\n target.addEventListener(event, handler);\n }\n}\n\nexport function removeEventListener(target: Target, event: string, handler: EventListenerOrEventListenerObject) {\n if (isNodeWorker(target)) {\n target.off(event, handler);\n } else if (\"removeEventListener\" in target) {\n target.removeEventListener(event, handler);\n }\n}\n\n/**\n * Normalize message event data across Web and Node.js environments\n * In web, data is in event.data\n * In Node.js, the event itself contains the data\n */\nexport function getEventData(event: any) {\n return event.data || event;\n}\n","export interface NodeWorker {\n on(event: string, handler: any): void;\n off(event: string, handler: any): void;\n postMessage(message: any): void;\n terminate(): void;\n}\n\nexport type WorkerLike = Worker | NodeWorker;\n\nexport enum events {\n MESSAGE = \"message\",\n}\n\nexport enum actions {\n HANDSHAKE_REQUEST = \"RIMLESS/HANDSHAKE_REQUEST\",\n HANDSHAKE_REPLY = \"RIMLESS/HANDSHAKE_REPLY\",\n RPC_REQUEST = \"RIMLESS/RPC_REQUEST\",\n RPC_RESOLVE = \"RIMLESS/RPC_RESOLVE\",\n RPC_REJECT = \"RIMLESS/RPC_REJECT\",\n}\n\nexport type Schema = Record<string, any>;\n\nexport interface Connection {\n id: string;\n remote: Schema;\n close: () => void;\n}\n\nexport type Connections = Record<string, Connection>;\n\nexport interface RimlessEvent extends EventListener {\n source?: Window;\n origin?: string;\n data: HandshakeRequestPayload | HandshakeConfirmationPayload | RPCRequestPayload | RPCResolvePayload;\n}\n\nexport interface HandshakeRequestPayload {\n action: actions.HANDSHAKE_REQUEST;\n connectionID: string;\n methodNames: string[];\n schema: Schema;\n}\n\nexport interface HandshakeConfirmationPayload {\n action: actions.HANDSHAKE_REPLY;\n connectionID: string;\n methodNames: string[];\n schema: Schema;\n}\n\nexport interface RPCRequestPayload {\n action: actions.RPC_REQUEST;\n args: any[];\n callID: string;\n callName: string;\n connectionID: string;\n}\n\nexport interface RPCResolvePayload {\n action: actions.RPC_RESOLVE | actions.RPC_REJECT;\n result?: any | null;\n error?: Error | null;\n callID: string;\n callName: string;\n connectionID: string;\n}\n\nexport interface EventHandlers {\n onConnectionSetup: (remote: Schema) => Promise<void>;\n}\n\nexport type Guest = WorkerLike | HTMLIFrameElement;\nexport type Target = Window | WorkerLike;\nexport type Environment = Window | WorkerLike;\n","import { addEventListener, generateId, getEventData, postMessageToTarget, removeEventListener, set } from \"./helpers\";\nimport {\n actions,\n Environment,\n events,\n RimlessEvent,\n RPCRequestPayload,\n RPCResolvePayload,\n Schema,\n Target,\n} from \"./types\";\n\n/** Private symbol to which we will assign transferable objects */\nconst SYM_TRANSFERABLES = Symbol();\n\n/**\n * for each function in methods\n * 1. subscribe to an event that the remote can call\n * 2. listen for calls from the remote. When called execute the function and emit the results.\n *\n * @param methods an object of method ids : methods from the local schema\n * @param rpcConnectionID\n * @param listenTo Environment to listen for incoming messages\n * @param sendTo Target to send outgoing messages\n * @param remote The remote API object for the current connection\n * @return a function to cancel all subscriptions\n */\nexport function registerLocalMethods(\n methods: Record<string, (...args: any[]) => any> = {},\n rpcConnectionID: string,\n listenTo: Environment,\n sendTo: Target,\n remote: Schema, // Add remote parameter\n) {\n const listeners: any[] = [];\n for (const [methodName, method] of Object.entries(methods)) {\n // handle a remote calling a local method\n async function handleCall(event: any) {\n const eventData = getEventData(event);\n const { action, callID, connectionID, callName, args = [] } = eventData as RPCRequestPayload;\n\n if (action !== actions.RPC_REQUEST) return;\n if (!callID || !callName) return;\n if (callName !== methodName) return;\n if (connectionID !== rpcConnectionID) return;\n\n const payload: RPCResolvePayload = {\n action: actions.RPC_RESOLVE,\n callID,\n callName,\n connectionID,\n error: null,\n result: null,\n };\n\n // when a host function returns transferable results to the remote, the\n // transferables are assigned to a special symbol on each function's result\n let transferables: Transferable[] | undefined = undefined;\n\n // run function and return the results to the remote\n try {\n // Pass the remote object as the LAST argument to the local method\n payload.result = await method(...args, remote);\n\n if (payload.result && payload.result[SYM_TRANSFERABLES]) {\n transferables = payload.result[SYM_TRANSFERABLES] ?? [];\n delete payload.result[SYM_TRANSFERABLES];\n }\n } catch (error) {\n payload.action = actions.RPC_REJECT;\n payload.error = JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)));\n }\n\n postMessageToTarget(sendTo, payload, event?.origin, transferables);\n }\n\n // subscribe to the call event\n addEventListener(listenTo, events.MESSAGE, handleCall);\n listeners.push(() => removeEventListener(listenTo, events.MESSAGE, handleCall));\n }\n\n return () => listeners.forEach((unregister) => unregister());\n}\n\n/**\n * Create a function that will make an RPC request to the remote with some arguments.\n * Listen to an event that returns the results from the remote.\n *\n * @param rpcCallName\n * @param rpcConnectionID\n * @param event\n * @param listeners\n * @param guest\n *\n * @returns a promise with the result of the RPC\n */\nexport function createRPC(\n rpcCallName: string,\n rpcConnectionID: string,\n event: RimlessEvent,\n listeners: Array<() => void> = [],\n listenTo: Environment,\n sendTo: Target,\n) {\n return (...args: any[]) => {\n return new Promise((resolve, reject) => {\n const requestID = generateId();\n\n // on RPC response\n function handleResponse(event: any) {\n const eventData = getEventData(event);\n const { callID, connectionID, callName, result, error, action } = eventData as RPCResolvePayload;\n\n if (!callID || !callName) return;\n if (callName !== rpcCallName) return;\n if (callID !== requestID) return;\n if (connectionID !== rpcConnectionID) return;\n\n // resolve the response\n if (action === actions.RPC_RESOLVE) return resolve(result);\n if (action === actions.RPC_REJECT) return reject(error);\n }\n\n // send the RPC request with arguments\n const payload = {\n action: actions.RPC_REQUEST,\n args,\n callID: requestID,\n callName: rpcCallName,\n connectionID: rpcConnectionID,\n };\n\n // if the arguments have transferables, post them as well\n const transferables = args.reduce(\n (transferables, arg) =>\n arg[SYM_TRANSFERABLES]?.length ? transferables.concat(arg[SYM_TRANSFERABLES]) : transferables,\n // @ts-expect-error: we know this is an array of transferables (if it exists)\n args[SYM_TRANSFERABLES] ?? [],\n );\n\n addEventListener(listenTo, events.MESSAGE, handleResponse);\n listeners.push(() => removeEventListener(listenTo, events.MESSAGE, handleResponse));\n\n postMessageToTarget(sendTo, payload, event?.origin, transferables);\n });\n };\n}\n\n/**\n * create an object based on the remote schema's methods. Functions in that object will\n * emit an event that will trigger the RPC on the remote.\n *\n * @param schema\n * @param methods\n * @param connectionID\n * @param event\n * @param guest\n */\nexport function registerRemoteMethods(\n schema: Schema = {},\n methodNames: Iterable<string> = [],\n connectionID: string,\n event: RimlessEvent,\n listenTo: Environment,\n sendTo: Target,\n) {\n const remote = { ...schema };\n const listeners: Array<() => void> = [];\n\n for (const methodName of methodNames) {\n const rpc = createRPC(methodName, connectionID, event, listeners, listenTo, sendTo);\n set(remote, methodName, rpc);\n }\n\n return {\n remote,\n unregisterRemote: () => listeners.forEach((unregister) => unregister()),\n };\n}\n\n/**\n * This function is used by API schema declarations and remote function calls alike to\n * indicate which variables should be declared as transferable over `postMessage` calls.\n *\n * @param cb a function that takes a transfer function as an argument and returns an object\n * (in the loose, `typeof foo === \"object\"` sense)\n * @return result the callback's return value, with an extra array of transferable objects\n * assigned to rimless' private symbol `SYM_TRANSFERABLES`\n *\n * The `transfer(...)` function is called with an object to transfer; if there\n * are many objects to transfer, you may call it multiple times. It will always\n * return the input object. Calling `transfer` only modifies the callback\n * result, not the transferred object itself (or objects themselves).\n *\n * @example\n * host.connect({\n * foo: (...args) => {\n * const foo = new ArrayBuffer(8);\n * return withTransferable((transfer) => transfer(foo));\n * }),\n * });\n *\n * @example\n * host.remote.foo(withTransferable((transfer) => ({\n * stream: transfer(new ReadableStream()),\n * })));\n */\nexport const withTransferable = <Transferable, Result extends object>(\n cb: (transfer: <T extends Transferable>(transferable: T) => T) => Result,\n) => {\n const transferables: Transferable[] = [];\n const transfer = <T extends Transferable>(transferable: T) => {\n transferables.push(transferable);\n return transferable;\n };\n\n const result = cb(transfer);\n\n return Object.assign(result, { [SYM_TRANSFERABLES]: transferables });\n};\n","import {\n extractMethods,\n getEventData,\n getTargetHost,\n postMessageToTarget,\n addEventListener,\n removeEventListener,\n} from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, EventHandlers, events, Connection, Schema } from \"./types\";\n\nfunction connect(schema: Schema = {}, eventHandlers?: EventHandlers): Promise<Connection> {\n return new Promise(async (resolve) => {\n const localMethods = extractMethods(schema);\n const sendTo = getTargetHost();\n const listenTo = self || window;\n\n // on handshake response\n async function handleHandshakeResponse(event: any) {\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REPLY) return;\n\n // register remote methods\n const { remote, unregisterRemote } = registerRemoteMethods(\n eventData.schema,\n eventData.methodNames,\n eventData.connectionID,\n event,\n listenTo,\n sendTo,\n );\n\n // register local methods, passing the remote object\n const unregisterLocal = registerLocalMethods(localMethods, eventData.connectionID, listenTo, sendTo, remote);\n\n await eventHandlers?.onConnectionSetup?.(remote);\n\n // send a HANDSHAKE REPLY to the host\n const payload = {\n action: actions.HANDSHAKE_REPLY,\n connectionID: eventData.connectionID,\n };\n\n postMessageToTarget(sendTo, payload, event?.origin);\n\n // close the connection and all listeners when called\n const close = () => {\n removeEventListener(listenTo, events.MESSAGE, handleHandshakeResponse);\n unregisterRemote();\n unregisterLocal();\n };\n\n // resolve connection object\n const connection = { remote, close, id: eventData.connectionID };\n return resolve(connection);\n }\n\n // subscribe to HANDSHAKE RESPONSE MESSAGES\n addEventListener(listenTo, events.MESSAGE, handleHandshakeResponse);\n\n const payload = {\n action: actions.HANDSHAKE_REQUEST,\n methodNames: Object.keys(localMethods),\n schema: schema,\n };\n\n postMessageToTarget(sendTo, payload);\n });\n}\n\nexport default {\n connect,\n};\n","import {\n addEventListener,\n extractMethods,\n generateId,\n getEventData,\n getOriginFromURL,\n isServerEnv,\n isNodeWorker,\n isWorkerLike,\n postMessageToTarget,\n removeEventListener,\n} from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, events, Guest, Connection, Connections, Schema } from \"./types\";\n\nconst connections: Connections = {};\n\nfunction isValidTarget(guest: Guest, event: any) {\n // If it's a worker, we don't need to validate origin\n if (isNodeWorker(guest) || (typeof Worker !== \"undefined\" && guest instanceof Worker)) {\n return true;\n }\n\n // For iframes, check origin and source\n const iframe = guest as HTMLIFrameElement;\n try {\n const childURL = iframe.src;\n const hasInlineContent = typeof iframe.srcdoc === \"string\" && iframe.srcdoc.length > 0;\n const childOrigin = getOriginFromURL(childURL);\n const hasProperOrigin = event.origin === childOrigin;\n const hasProperSource = event.source === iframe.contentWindow;\n\n // For inline iframes (srcdoc/about:blank) we can only rely on source matching\n if (hasInlineContent || childURL === \"about:blank\") {\n return hasProperSource;\n }\n\n return (hasProperOrigin && hasProperSource) || !childURL;\n } catch (e) {\n console.warn(\"Error checking iframe target:\", e);\n return false;\n }\n}\n\n/**\n * Perform a handshake with the target iframe, when the handshake is confirmed\n * resolve the connection object containing RPCs and properties\n *\n * @param guest\n * @param schema\n * @returns Promise\n */\nfunction connect(guest: Guest, schema: Schema = {}): Promise<Connection> {\n if (!guest) throw new Error(\"a target is required\");\n\n const guestIsWorker = isWorkerLike(guest);\n\n const listenTo = guestIsWorker || isServerEnv() ? (guest as Worker) : window;\n\n return new Promise((resolve) => {\n const connectionID = generateId();\n\n // on handshake request\n function handleHandshake(event: any) {\n const sendTo = guestIsWorker || isServerEnv() ? (guest as Worker) : event.source;\n\n if (!guestIsWorker && !isServerEnv() && !isValidTarget(guest, event)) return;\n\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REQUEST) return;\n if (connections[connectionID]) return;\n\n // Extract local methods first (doesn't need remote yet)\n const localMethods = extractMethods(schema);\n\n // Register remote methods first to get the remote object\n const { remote, unregisterRemote } = registerRemoteMethods(\n eventData.schema,\n eventData.methodNames,\n connectionID,\n event,\n listenTo,\n sendTo,\n );\n\n // Now register local methods, passing the remote object\n const unregisterLocal = registerLocalMethods(localMethods, connectionID, listenTo, sendTo, remote);\n\n // send a HANDSHAKE REPLY to the guest\n const payload = {\n action: actions.HANDSHAKE_REPLY,\n connectionID,\n schema: schema,\n methodNames: Object.keys(localMethods),\n };\n\n postMessageToTarget(sendTo, payload, event.origin);\n\n // close the connection and all listeners when called\n const close = () => {\n delete connections[connectionID];\n removeEventListener(listenTo, events.MESSAGE, handleHandshake);\n removeEventListener(listenTo, events.MESSAGE, handleHandshakeReply);\n unregisterRemote();\n unregisterLocal();\n if (guestIsWorker) {\n (guest as Worker).terminate();\n }\n };\n\n const connection: Connection = { remote, close, id: connectionID };\n connections[connectionID] = connection;\n }\n\n // subscribe to HANDSHAKE MESSAGES\n addEventListener(listenTo, events.MESSAGE, handleHandshake);\n\n // on handshake reply\n function handleHandshakeReply(event: any) {\n const eventData = getEventData(event);\n if (eventData?.action !== actions.HANDSHAKE_REPLY) return;\n if (connectionID !== eventData.connectionID) return;\n\n if (!connections[eventData.connectionID]) {\n throw new Error(\"Rimless Error: No connection found for this connectionID\");\n }\n\n return resolve(connections[eventData.connectionID]);\n }\n\n addEventListener(listenTo, events.MESSAGE, handleHandshakeReply);\n });\n}\n\nexport default {\n connect,\n};\n"],"names":["detectRuntime","globalObject","processRef","versions","releaseName","getRuntimeEnvironment","isWorker","isServerEnv","runtime","isIframe","extractMethods","obj","methods","parse","path","prop","propPath","urlRegex","ports","getOriginFromURL","url","regexResult","protocol","hostname","port","portSuffix","set","value","pathArray","key","current","i","generateId","length","chars","result","initialRuntime","parentPort","getTargetHost","postMessageToTarget","target","message","origin","transferables","isNodeWorker","guest","isWorkerLike","addEventListener","event","handler","removeEventListener","getEventData","events","actions","SYM_TRANSFERABLES","registerLocalMethods","rpcConnectionID","listenTo","sendTo","remote","listeners","methodName","method","handleCall","eventData","action","callID","connectionID","callName","args","payload","error","unregister","createRPC","rpcCallName","resolve","reject","requestID","handleResponse","arg","registerRemoteMethods","schema","methodNames","rpc","withTransferable","cb","transferable","connect","eventHandlers","localMethods","handleHandshakeResponse","unregisterRemote","unregisterLocal","connection","connections","isValidTarget","iframe","childURL","hasInlineContent","childOrigin","hasProperOrigin","hasProperSource","e","guestIsWorker","handleHandshake","handleHandshakeReply","host"],"mappings":"qCAIA,SAASA,GAAoC,CAC3C,MAAMC,EAAe,WAGrB,GAAI,OAAOA,EAAa,OAAW,KAAe,OAAOA,EAAa,SAAa,IACjF,MAAO,UAQT,GAJE,OAAOA,EAAa,kBAAsB,KAC1C,OAAOA,EAAa,KAAS,KAC7BA,EAAa,gBAAgBA,EAAa,mBAIzC,OAAOA,EAAa,OAAW,KAC9B,OAAOA,EAAa,KAAS,KAC7B,OAAOA,EAAa,eAAkB,WAExC,MAAO,SAGT,MAAMC,EAAaD,EAAa,QAChC,GAAIC,GAAc,OAAOA,GAAe,SAAU,CAChD,MAAMC,EAAWD,EAAW,UAAY,CAAA,EAClCE,EAAcF,EAAW,SAAS,KAExC,GAAIC,EAAS,KAAOC,IAAgB,OAAS,OAAOH,EAAa,IAAQ,IACvE,MAAO,MAGT,GAAIE,EAAS,MAAQC,IAAgB,OACnC,MAAO,MAEX,CAEA,OAAI,OAAOH,EAAa,IAAQ,IACvB,MAGF,SACT,CAEO,SAASI,GAA4C,CAC1D,OAAOL,EAAA,CACT,CAWO,SAASM,GAAoB,CAClC,OAAOD,MAA4B,QACrC,CAeO,SAASE,GAAuB,CACrC,MAAMC,EAAUH,EAAA,EAChB,OAAOG,IAAY,QAAUA,IAAY,KAC3C,CAOO,SAASC,GAAW,CACzB,OAAO,OAAO,OAAS,OAAO,GAChC,CAQO,SAASC,EAAeC,EAAU,CACvC,MAAMC,EAAiD,CAAA,EACvD,OAAC,SAASC,EAAMF,EAAUG,EAAO,GAAI,CACnC,OAAO,KAAKH,CAAG,EAAE,QAASI,GAAS,CACjC,MAAMC,EAAWF,EAAO,GAAGA,CAAI,IAAIC,CAAI,GAAKA,EACxCJ,EAAII,CAAI,IAAM,OAAOJ,EAAII,CAAI,CAAC,GAChCF,EAAMF,EAAII,CAAI,EAAGC,CAAQ,EAEvB,OAAOL,EAAII,CAAI,GAAM,aACvBH,EAAQI,CAAQ,EAAIL,EAAII,CAAI,EAC5B,OAAOJ,EAAII,CAAI,EAEnB,CAAC,CACH,EAAGJ,CAAG,EACCC,CACT,CAEA,MAAMK,EAAW,0CACXC,EAAa,CAAE,QAAS,KAAM,SAAU,KAAA,EAOvC,SAASC,EAAiBC,EAAoB,CACnD,GAAI,CAACA,EAAK,OAAO,KAEjB,MAAMC,EAAcJ,EAAS,KAAKG,CAAG,EACrC,GAAI,CAACC,EAAa,OAAO,KAEzB,KAAM,CAAA,CAAGC,EAAW,QAASC,EAAA,CAAYC,CAAI,EAAIH,EAGjD,GAAIC,IAAa,QACf,MAAO,UAIT,MAAMG,EAAaD,GAAQA,IAASN,EAAMI,CAAQ,EAAI,IAAIE,CAAI,GAAK,GACnE,MAAO,GAAGF,CAAQ,KAAKC,CAAQ,GAAGE,CAAU,EAC9C,CAgBO,SAASC,EAAIf,EAAUG,EAAoCa,EAAiB,CACjF,GAAI,CAAChB,GAAO,OAAOA,GAAQ,SAAU,OAAOA,EAE5C,MAAMiB,EAAY,MAAM,QAAQd,CAAI,EAAIA,EAAOA,EAAK,MAAM,GAAG,EAAE,IAAKe,GAASA,EAAI,MAAM,OAAO,EAAI,OAAOA,CAAG,EAAIA,CAAI,EAEpH,IAAIC,EAAUnB,EAEd,QAASoB,EAAI,EAAGA,EAAIH,EAAU,OAAQG,IAAK,CACzC,MAAMF,EAAMD,EAAUG,CAAC,EAEnBA,IAAMH,EAAU,OAAS,EAC3BE,EAAQD,CAAG,EAAIF,IAEX,CAACG,EAAQD,CAAG,GAAK,OAAOC,EAAQD,CAAG,GAAM,YAC3CC,EAAQD,CAAG,EAAI,OAAOD,EAAUG,EAAI,CAAC,GAAM,SAAW,CAAA,EAAK,CAAA,GAE7DD,EAAUA,EAAQD,CAAG,EAEzB,CAEA,OAAOlB,CACT,CAEO,SAASqB,EAAWC,EAAiB,GAAY,CACtD,MAAMC,EAAQ,iEACd,IAAIC,EAAS,GACb,QAASJ,EAAI,EAAGA,EAAIE,EAAQF,IAC1BI,GAAUD,EAAM,OAAO,KAAK,MAAM,KAAK,OAAA,EAAWA,EAAM,MAAM,CAAC,EAEjE,OAAOC,CACT,CAEA,MAAMC,EAAiB/B,EAAA,EACvB,IAAIgC,EAAkB,KAEtB,GAAID,IAAmB,QAAUA,IAAmB,MAClD,GAAI,CAGFC,EADsB,QAAQ,gBAAgB,EACnB,UAC7B,MAAY,CAEZ,CAOK,SAASC,GAAqB,CACnC,GAAI/B,IACF,OAAO8B,EAGT,GAAI/B,IACF,OAAO,KAGT,GAAIG,IACF,OAAO,OAAO,OAGhB,MAAM,IAAI,MAAM,uCAAuC,CACzD,CASO,SAAS8B,EACdC,EACAC,EACAC,EACAC,EACM,CACN,GAAI,CAACH,EACH,MAAM,IAAI,MAAM,oDAAoD,EAItE,GAAIjC,EAAA,GAAiBiC,IAAWH,EAAY,CAC1CG,EAAO,YAAYC,EAAS,CAAE,SAAUE,EAAe,EACvD,MACF,CAGA,GAAIrC,IAAY,CACdkC,EAAO,YAAYC,EAAS,CAAE,SAAUE,EAAe,EACvD,MACF,CAGA,GAAIH,EAAO,YAAa,CACtBA,EAAO,YAAYC,EAAS,CAAE,aAAcC,GAAU,IAAK,SAAUC,EAAe,EACpF,MACF,CAEA,MAAM,IAAI,MAAM,+CAA+C,CACjE,CAEO,SAASC,EAAaC,EAA4C,CACvE,OAAOR,IAAe,MAAQQ,IAAUR,CAC1C,CAEO,SAASS,EAAaD,EAAmC,CAC9D,OAAOD,EAAaC,CAAK,GAAM,OAAO,OAAW,KAAeA,aAAiB,MACnF,CAEO,SAASE,EAAiBP,EAAgBQ,EAAeC,EAA6C,CACvGL,EAAaJ,CAAM,EACrBA,EAAO,GAAGQ,EAAOC,CAAO,EACf,qBAAsBT,GAC/BA,EAAO,iBAAiBQ,EAAOC,CAAO,CAE1C,CAEO,SAASC,EAAoBV,EAAgBQ,EAAeC,EAA6C,CAC1GL,EAAaJ,CAAM,EACrBA,EAAO,IAAIQ,EAAOC,CAAO,EAChB,wBAAyBT,GAClCA,EAAO,oBAAoBQ,EAAOC,CAAO,CAE7C,CAOO,SAASE,EAAaH,EAAY,CACvC,OAAOA,EAAM,MAAQA,CACvB,CCvRO,IAAKI,GAAAA,IACVA,EAAA,QAAU,UADAA,IAAAA,GAAA,CAAA,CAAA,EAIAC,GAAAA,IACVA,EAAA,kBAAoB,4BACpBA,EAAA,gBAAkB,0BAClBA,EAAA,YAAc,sBACdA,EAAA,YAAc,sBACdA,EAAA,WAAa,qBALHA,IAAAA,GAAA,CAAA,CAAA,ECAZ,MAAMC,EAAoB,OAAA,EAcnB,SAASC,EACd3C,EAAmD,CAAA,EACnD4C,EACAC,EACAC,EACAC,EACA,CACA,MAAMC,EAAmB,CAAA,EACzB,SAAW,CAACC,EAAYC,CAAM,IAAK,OAAO,QAAQlD,CAAO,EAAG,CAE1D,eAAemD,EAAWf,EAAY,CACpC,MAAMgB,EAAYb,EAAaH,CAAK,EAC9B,CAAE,OAAAiB,EAAQ,OAAAC,EAAQ,aAAAC,EAAc,SAAAC,EAAU,KAAAC,EAAO,CAAA,GAAOL,EAK9D,GAHIC,IAAWZ,EAAQ,aACnB,CAACa,GAAU,CAACE,GACZA,IAAaP,GACbM,IAAiBX,EAAiB,OAEtC,MAAMc,EAA6B,CACjC,OAAQjB,EAAQ,YAChB,OAAAa,EACA,SAAAE,EACA,aAAAD,EACA,MAAO,KACP,OAAQ,IAAA,EAKV,IAAIxB,EAGJ,GAAI,CAEF2B,EAAQ,OAAS,MAAMR,EAAO,GAAGO,EAAMV,CAAM,EAEzCW,EAAQ,QAAUA,EAAQ,OAAOhB,CAAiB,IACpDX,EAAgB2B,EAAQ,OAAOhB,CAAiB,GAAK,CAAA,EACrD,OAAOgB,EAAQ,OAAOhB,CAAiB,EAE3C,OAASiB,EAAO,CACdD,EAAQ,OAASjB,EAAQ,WACzBiB,EAAQ,MAAQ,KAAK,MAAM,KAAK,UAAUC,EAAO,OAAO,oBAAoBA,CAAK,CAAC,CAAC,CACrF,CAEAhC,EAAoBmB,EAAQY,EAAStB,GAAO,OAAQL,CAAa,CACnE,CAGAI,EAAiBU,EAAUL,EAAO,QAASW,CAAU,EACrDH,EAAU,KAAK,IAAMV,EAAoBO,EAAUL,EAAO,QAASW,CAAU,CAAC,CAChF,CAEA,MAAO,IAAMH,EAAU,QAASY,GAAeA,GAAY,CAC7D,CAcO,SAASC,EACdC,EACAlB,EACAR,EACAY,EAA+B,CAAA,EAC/BH,EACAC,EACA,CACA,MAAO,IAAIW,IACF,IAAI,QAAQ,CAACM,EAASC,IAAW,CACtC,MAAMC,EAAY7C,EAAA,EAGlB,SAAS8C,EAAe9B,EAAY,CAClC,MAAMgB,EAAYb,EAAaH,CAAK,EAC9B,CAAE,OAAAkB,EAAQ,aAAAC,EAAc,SAAAC,EAAU,OAAAjC,EAAQ,MAAAoC,GAAO,OAAAN,GAAWD,EAElE,GAAI,GAACE,GAAU,CAACE,IACZA,IAAaM,GACbR,IAAWW,GACXV,IAAiBX,EAGrB,IAAIS,IAAWZ,EAAQ,YAAa,OAAOsB,EAAQxC,CAAM,EACzD,GAAI8B,IAAWZ,EAAQ,WAAY,OAAOuB,EAAOL,EAAK,EACxD,CAGA,MAAMD,EAAU,CACd,OAAQjB,EAAQ,YAChB,KAAAgB,EACA,OAAQQ,EACR,SAAUH,EACV,aAAclB,CAAA,EAIVb,EAAgB0B,EAAK,OACzB,CAAC1B,EAAeoC,IACdA,EAAIzB,CAAiB,GAAG,OAASX,EAAc,OAAOoC,EAAIzB,CAAiB,CAAC,EAAIX,EAElF0B,EAAKf,CAAiB,GAAK,CAAA,CAAC,EAG9BP,EAAiBU,EAAUL,EAAO,QAAS0B,CAAc,EACzDlB,EAAU,KAAK,IAAMV,EAAoBO,EAAUL,EAAO,QAAS0B,CAAc,CAAC,EAElFvC,EAAoBmB,EAAQY,EAAStB,GAAO,OAAQL,CAAa,CACnE,CAAC,CAEL,CAYO,SAASqC,EACdC,EAAiB,CAAA,EACjBC,EAAgC,CAAA,EAChCf,EACAnB,EACAS,EACAC,EACA,CACA,MAAMC,EAAS,CAAE,GAAGsB,CAAA,EACdrB,EAA+B,CAAA,EAErC,UAAWC,KAAcqB,EAAa,CACpC,MAAMC,EAAMV,EAAUZ,EAAYM,EAAcnB,EAAOY,EAAWH,EAAUC,CAAM,EAClFhC,EAAIiC,EAAQE,EAAYsB,CAAG,CAC7B,CAEA,MAAO,CACL,OAAAxB,EACA,iBAAkB,IAAMC,EAAU,QAASY,GAAeA,GAAY,CAAA,CAE1E,CA6BO,MAAMY,EACXC,GACG,CACH,MAAM1C,EAAgC,CAAA,EAMhCR,EAASkD,EAL2BC,IACxC3C,EAAc,KAAK2C,CAAY,EACxBA,EAGiB,EAE1B,OAAO,OAAO,OAAOnD,EAAQ,CAAE,CAACmB,CAAiB,EAAGX,EAAe,CACrE,EChNA,SAAS4C,EAAQN,EAAiB,CAAA,EAAIO,EAAoD,CACxF,OAAO,IAAI,QAAQ,MAAOb,GAAY,CACpC,MAAMc,EAAe/E,EAAeuE,CAAM,EACpCvB,EAASpB,EAAA,EACTmB,EAAW,MAAQ,OAGzB,eAAeiC,EAAwB1C,EAAY,CACjD,MAAMgB,EAAYb,EAAaH,CAAK,EACpC,GAAIgB,GAAW,SAAWX,EAAQ,gBAAiB,OAGnD,KAAM,CAAE,OAAAM,EAAQ,iBAAAgC,CAAA,EAAqBX,EACnChB,EAAU,OACVA,EAAU,YACVA,EAAU,aACVhB,EACAS,EACAC,CAAA,EAIIkC,EAAkBrC,EAAqBkC,EAAczB,EAAU,aAAcP,EAAUC,EAAQC,CAAM,EAE3G,MAAM6B,GAAe,oBAAoB7B,CAAM,EAG/C,MAAMW,EAAU,CACd,OAAQjB,EAAQ,gBAChB,aAAcW,EAAU,YAAA,EAG1BzB,EAAoBmB,EAAQY,EAAStB,GAAO,MAAM,EAUlD,MAAM6C,EAAa,CAAE,OAAAlC,EAAQ,MAPf,IAAM,CAClBT,EAAoBO,EAAUL,EAAO,QAASsC,CAAuB,EACrEC,EAAA,EACAC,EAAA,CACF,EAGoC,GAAI5B,EAAU,YAAA,EAClD,OAAOW,EAAQkB,CAAU,CAC3B,CAGA9C,EAAiBU,EAAUL,EAAO,QAASsC,CAAuB,EAElE,MAAMpB,EAAU,CACd,OAAQjB,EAAQ,kBAChB,YAAa,OAAO,KAAKoC,CAAY,EACrC,OAAAR,CAAA,EAGF1C,EAAoBmB,EAAQY,CAAO,CACrC,CAAC,CACH,CAEA,MAAAzB,EAAe,CAAA,QACb0C,CACF,ECzDMO,EAA2B,CAAA,EAEjC,SAASC,EAAclD,EAAcG,EAAY,CAE/C,GAAIJ,EAAaC,CAAK,GAAM,OAAO,OAAW,KAAeA,aAAiB,OAC5E,MAAO,GAIT,MAAMmD,EAASnD,EACf,GAAI,CACF,MAAMoD,EAAWD,EAAO,IAClBE,EAAmB,OAAOF,EAAO,QAAW,UAAYA,EAAO,OAAO,OAAS,EAC/EG,EAAchF,EAAiB8E,CAAQ,EACvCG,EAAkBpD,EAAM,SAAWmD,EACnCE,EAAkBrD,EAAM,SAAWgD,EAAO,cAGhD,OAAIE,GAAoBD,IAAa,cAC5BI,EAGDD,GAAmBC,GAAoB,CAACJ,CAClD,OAASK,EAAG,CACV,eAAQ,KAAK,gCAAiCA,CAAC,EACxC,EACT,CACF,CAUA,SAASf,EAAQ1C,EAAcoC,EAAiB,GAAyB,CACvE,GAAI,CAACpC,EAAO,MAAM,IAAI,MAAM,sBAAsB,EAElD,MAAM0D,EAAgBzD,EAAaD,CAAK,EAElCY,EAAW8C,GAAiBhG,EAAA,EAAiBsC,EAAmB,OAEtE,OAAO,IAAI,QAAS8B,GAAY,CAC9B,MAAMR,EAAenC,EAAA,EAGrB,SAASwE,EAAgBxD,EAAY,CACnC,MAAMU,EAAS6C,GAAiBhG,EAAA,EAAiBsC,EAAmBG,EAAM,OAE1E,GAAI,CAACuD,GAAiB,CAAChG,EAAA,GAAiB,CAACwF,EAAclD,EAAOG,CAAK,EAAG,OAEtE,MAAMgB,EAAYb,EAAaH,CAAK,EAEpC,GADIgB,GAAW,SAAWX,EAAQ,mBAC9ByC,EAAY3B,CAAY,EAAG,OAG/B,MAAMsB,EAAe/E,EAAeuE,CAAM,EAGpC,CAAE,OAAAtB,EAAQ,iBAAAgC,CAAA,EAAqBX,EACnChB,EAAU,OACVA,EAAU,YACVG,EACAnB,EACAS,EACAC,CAAA,EAIIkC,EAAkBrC,EAAqBkC,EAActB,EAAcV,EAAUC,EAAQC,CAAM,EAG3FW,EAAU,CACd,OAAQjB,EAAQ,gBAChB,aAAAc,EACA,OAAAc,EACA,YAAa,OAAO,KAAKQ,CAAY,CAAA,EAGvClD,EAAoBmB,EAAQY,EAAStB,EAAM,MAAM,EAcjD,MAAM6C,EAAyB,CAAE,OAAAlC,EAAQ,MAX3B,IAAM,CAClB,OAAOmC,EAAY3B,CAAY,EAC/BjB,EAAoBO,EAAUL,EAAO,QAASoD,CAAe,EAC7DtD,EAAoBO,EAAUL,EAAO,QAASqD,CAAoB,EAClEd,EAAA,EACAC,EAAA,EACIW,GACD1D,EAAiB,UAAA,CAEtB,EAEgD,GAAIsB,CAAA,EACpD2B,EAAY3B,CAAY,EAAI0B,CAC9B,CAGA9C,EAAiBU,EAAUL,EAAO,QAASoD,CAAe,EAG1D,SAASC,EAAqBzD,EAAY,CACxC,MAAMgB,EAAYb,EAAaH,CAAK,EACpC,GAAIgB,GAAW,SAAWX,EAAQ,iBAC9Bc,IAAiBH,EAAU,aAE/B,IAAI,CAAC8B,EAAY9B,EAAU,YAAY,EACrC,MAAM,IAAI,MAAM,0DAA0D,EAG5E,OAAOW,EAAQmB,EAAY9B,EAAU,YAAY,CAAC,EACpD,CAEAjB,EAAiBU,EAAUL,EAAO,QAASqD,CAAoB,CACjE,CAAC,CACH,CAEA,MAAAC,EAAe,CACb,QAAAnB,CACF"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rimless",
|
|
3
3
|
"author": "Aurélien Franky",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/au-re/rimless",
|
|
7
7
|
"description": "event base communication made easy with a promise-based API wrapping `postMessage`",
|