rimless 0.1.5 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2019 Aurélien Franky
3
+ Copyright (c) 2020 Aurélien Franky
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -5,19 +5,26 @@
5
5
  [license-url]: https://github.com/au-re/rimless/LICENSE
6
6
 
7
7
  <p align="center">
8
- <img src="https://raw.githubusercontent.com/au-re/rimless/master/assets/rimless.png"/>
8
+ <img src="https://raw.githubusercontent.com/au-re/rimless/master/assets/icon.png"/>
9
9
  </p>
10
10
 
11
11
  # rimless
12
12
 
13
13
  [![npm][npm-image]][npm-url]
14
14
  [![Commitizen friendly][commitizen-image]][commitizen-url]
15
+ ![npm bundle size](https://img.shields.io/bundlephobia/minzip/rimless)
15
16
 
16
17
  > Rimless makes event based communication easy with a promise-based API wrapping [postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage). Works with both **iframes** and **webworkers**.
17
18
 
18
19
  You can use `rimless` to call remote procedures, exchange data or expose local functions with **iframes**/**webworkers**.
19
20
 
20
- You can see it in action here https://au-re.github.io/rimless.
21
+ You can see it in action in the code sandbox below:
22
+
23
+ <a href="https://codesandbox.io/p/sandbox/3qrqfl">
24
+
25
+ ![CodeSandbox](https://img.shields.io/badge/Codesandbox-040404?style=for-the-badge&logo=codesandbox&logoColor=DBDBDB)
26
+
27
+ </a>
21
28
 
22
29
  ## Installation
23
30
 
@@ -38,39 +45,42 @@ or from a CDN
38
45
  **in the host website**
39
46
 
40
47
  ```js
41
- import { host } from "rimless";
48
+ import { host } from "rimless";
42
49
 
43
50
  const connection = await host.connect(iframe, {
44
- myVariable: 12,
45
- myFunction: (value) => `hello ${value}`,
51
+ someHostVariable: 12,
52
+ someHostFunction: (value) => `hello ${value}`,
46
53
  });
47
54
 
48
55
  // access variables on the iframe
49
- console.log(connection.remote.myIframeVariable); // 42
56
+ console.log(connection.remote.someGuestVariable); // 42
50
57
 
51
58
  // call remote procedures on the iframe
52
- const result = await connection.remote.myIframeFunction("here");
53
- console.log(result); // hello here
59
+ const result = await connection.remote.someGuestFunction("here");
60
+
61
+ console.log(result); // hello here
54
62
 
55
63
  // close the connection
56
64
  connection.close();
57
65
  ```
66
+
58
67
  **in the iframe**
59
68
 
60
69
  ```js
61
- import { guest } from "rimless";
70
+ import { guest } from "rimless";
62
71
 
63
72
  const connection = await guest.connect({
64
- myIframeVariable: 42,
65
- myIframeFunction: (value) => `hello ${value}`,
73
+ someGuestVariable: 42,
74
+ someGuestFunction: (value) => `hello ${value}`,
66
75
  });
67
76
 
68
77
  // access variables on the host
69
- console.log(connection.remote.myVariable); // 12
78
+ console.log(connection.remote.someHostVariable); // 12
70
79
 
71
80
  // call remote procedures on host
72
- const res = await connection.remote.myFunction("there");
73
- console.log(res); // hello there
81
+ const res = await connection.remote.someHostFunction("there");
82
+
83
+ console.log(res); // hello there
74
84
 
75
85
  // close the connection
76
86
  connection.close();
@@ -83,7 +93,7 @@ connection.close();
83
93
  This is how you can **connect your website** to an iframe or webworker:
84
94
 
85
95
  ```js
86
- import { host } from "rimless";
96
+ import { host } from "rimless";
87
97
 
88
98
  const iframe = document.getElementById("myIframe");
89
99
  const worker = new Worker("myWorker");
@@ -100,7 +110,7 @@ You also need to **connect your iframe/webworker** to the host website.
100
110
  Usage from an iframe:
101
111
 
102
112
  ```js
103
- import { guest } from "rimless";
113
+ import { guest } from "rimless";
104
114
 
105
115
  // connect to the parent website
106
116
  guest.connect();
@@ -122,7 +132,7 @@ guest.connect();
122
132
  To do anything meaningful with this connection you need to provide a schema that defines **the API** of the host/iframe/webworker. Any serializeable values as well as functions are ok to use. In the example below the host website provides a function that will update its background color when invoked.
123
133
 
124
134
  ```js
125
- import { host } from "rimless";
135
+ import { host } from "rimless";
126
136
 
127
137
  const api = {
128
138
  setColor: (color) => {
@@ -142,7 +152,7 @@ The api schema must be passed on connection, the same applies to the `iframe/web
142
152
  With the host API exposed we can now invoke the remote procedure from the iframe.
143
153
 
144
154
  ```js
145
- import { guest } from "rimless";
155
+ import { guest } from "rimless";
146
156
 
147
157
  // connect returns a promise that resolves in a connection object
148
158
  // `connection.remote` contains the api you can invoke
@@ -156,12 +166,13 @@ guest.connect().then((connection) => {
156
166
  Closing a connection will remove all event listeners that were registered.
157
167
 
158
168
  ```js
159
- import { guest } from "rimless";
169
+ import { guest } from "rimless";
160
170
 
161
171
  guest.connect().then((connection) => {
162
172
  connection.close();
163
173
  });
164
174
  ```
175
+
165
176
  ---
166
177
 
167
178
  ## How it Works
@@ -200,7 +211,7 @@ This library is inspired by [Postmate](https://www.npmjs.com/package/postmate) a
200
211
 
201
212
  ## API
202
213
 
203
- Rimless exports two objects: `host` and `guest`.
214
+ Rimless exports two objects: `host` and `guest`.
204
215
 
205
216
  > ### `host.connect`
206
217
 
@@ -208,16 +219,15 @@ Connect your website to a "guest" (iframe/webworker).
208
219
 
209
220
  ```js
210
221
  host.connect(iframe, {
211
- log: (value) => console.log(value)
222
+ log: (value) => console.log(value),
212
223
  });
213
224
  ```
214
225
 
215
- | Name | Type | Description | Required |
216
- | --- | --- | --- | --- |
217
- | `guest` | `HTMLIFrameElement` or `Worker` | Target of the connection | required |
218
- | `schema` | `object` | schema of the api you want to expose | - |
219
- | `options` | `object` | - | - |
220
-
226
+ | Name | Type | Description | Required |
227
+ | --------- | ------------------------------- | ------------------------------------ | -------- |
228
+ | `guest` | `HTMLIFrameElement` or `Worker` | Target of the connection | required |
229
+ | `schema` | `object` | schema of the api you want to expose | - |
230
+ | `options` | `object` | - | - |
221
231
 
222
232
  > ### `guest.connect`
223
233
 
@@ -225,28 +235,17 @@ Connect a "guest" to your website. The guest connection automatically happens ba
225
235
 
226
236
  ```js
227
237
  guest.connect({
228
- log: (value) => console.log(value)
238
+ log: (value) => console.log(value),
229
239
  });
230
240
  ```
231
241
 
232
- | Name | Type | Description | Default |
233
- | --- | --- | --- | --- |
234
- | `schema` | `object` | schema of the api you want to expose | - |
235
- | `options` | `object` | - | - |
242
+ | Name | Type | Description | Default |
243
+ | --------- | -------- | ------------------------------------ | ------- |
244
+ | `schema` | `object` | schema of the api you want to expose | - |
245
+ | `options` | `object` | - | - |
236
246
 
237
247
  ---
238
248
 
239
- ## Contributing
240
-
241
- We use the [airbnb style guide](https://github.com/airbnb/javascript) when writing javascript, with
242
- some minor modifications. Make sure eslint is installed and running before making changes, as it
243
- will ensure your coding style matches that of the project.
244
-
245
- We use [commitizen](https://github.com/commitizen/cz-cli) and
246
- [angular's conventional changelog](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits)
247
- to enforce a consistent commit format. When writing commits, make sure you run `npm run commit`
248
- instead of `git commit`.
249
-
250
249
  ## License
251
250
 
252
251
  [MIT](license-url)
@@ -0,0 +1,159 @@
1
+ import _ from "lodash.get";
2
+ import H from "lodash.set";
3
+ import { nanoid as A } from "nanoid";
4
+ function M() {
5
+ return typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope;
6
+ }
7
+ function L(e) {
8
+ const o = [];
9
+ return function c(n, r = "") {
10
+ Object.keys(n).forEach((t) => {
11
+ const s = r ? `${r}.${t}` : t;
12
+ n[t] === Object(n[t]) && c(n[t], s), typeof n[t] == "function" && o.push(s);
13
+ });
14
+ }(e), o;
15
+ }
16
+ const T = /^(https?:|file:)?\/\/([^/:]+)?(:(\d+))?/, D = { "http:": "80", "https:": "443" };
17
+ function C(e) {
18
+ const { location: o } = document, c = T.exec(e || "");
19
+ let n, r, t;
20
+ if (c ? [, n = o.protocol, r, , t] = c : (n = o.protocol, r = o.hostname, t = o.port), n === "file:")
21
+ return "null";
22
+ const s = t && t !== D[n] ? `:${t}` : "";
23
+ return `${n}//${r}${s}`;
24
+ }
25
+ var a = /* @__PURE__ */ ((e) => (e.MESSAGE = "message", e))(a || {}), S = /* @__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))(S || {});
26
+ function P(e = {}, o = [], c, n) {
27
+ const r = [];
28
+ return o.forEach((t) => {
29
+ async function s(i) {
30
+ const { action: l, callID: E, connectionID: f, callName: u, args: p = [] } = i.data;
31
+ if (l !== S.RPC_REQUEST || !E || !u || u !== t || f !== c) return;
32
+ const d = {
33
+ action: S.RPC_RESOLVE,
34
+ callID: E,
35
+ callName: u,
36
+ connectionID: f,
37
+ error: null,
38
+ result: null
39
+ };
40
+ try {
41
+ const R = await _(e, t)(...p);
42
+ d.result = JSON.parse(JSON.stringify(R));
43
+ } catch (R) {
44
+ d.error = JSON.parse(JSON.stringify(R, Object.getOwnPropertyNames(R)));
45
+ }
46
+ n ? n.postMessage(d) : M() ? self.postMessage(d) : i.source.postMessage(d, i.origin);
47
+ }
48
+ n ? n.addEventListener(a.MESSAGE, s) : self.addEventListener(a.MESSAGE, s), r.push(() => self.removeEventListener(a.MESSAGE, s));
49
+ }), () => r.forEach((t) => t());
50
+ }
51
+ function y(e, o, c, n = [], r) {
52
+ return (...t) => new Promise((s, i) => {
53
+ const l = A();
54
+ function E(u) {
55
+ const { callID: p, connectionID: d, callName: R, result: N, error: I, action: g } = u.data;
56
+ if (!(!p || !R) && R === e && d === o) {
57
+ if (g === S.RPC_RESOLVE) return s(N);
58
+ if (g === S.RPC_REJECT) return i(I);
59
+ }
60
+ }
61
+ const f = {
62
+ action: S.RPC_REQUEST,
63
+ args: JSON.parse(JSON.stringify(t)),
64
+ callID: l,
65
+ callName: e,
66
+ connectionID: o
67
+ };
68
+ r ? r.addEventListener(a.MESSAGE, E) : self.addEventListener(a.MESSAGE, E), n.push(() => self.removeEventListener(a.MESSAGE, E)), r ? r.postMessage(f) : M() ? self.postMessage(f) : (c.source || c.target).postMessage(f, c.origin);
69
+ });
70
+ }
71
+ function O(e = {}, o = [], c, n, r) {
72
+ const t = { ...e }, s = [];
73
+ return o.forEach((i) => {
74
+ const l = y(i, c, n, s, r);
75
+ H(t, i, l);
76
+ }), {
77
+ remote: t,
78
+ unregisterRemote: () => s.forEach((i) => i())
79
+ };
80
+ }
81
+ const G = 10, J = 3e3;
82
+ let m = null, h = !1;
83
+ function w(e = {}) {
84
+ return new Promise((o, c) => {
85
+ const n = L(e);
86
+ function r(s) {
87
+ if (s.data.action !== S.HANDSHAKE_REPLY) return;
88
+ const i = P(e, n, s.data.connectionID), { remote: l, unregisterRemote: E } = O(
89
+ s.data.schema,
90
+ s.data.methods,
91
+ s.data.connectionID,
92
+ s
93
+ ), f = () => {
94
+ self.removeEventListener(a.MESSAGE, r), E(), i();
95
+ };
96
+ return h = !0, o({ remote: l, close: f });
97
+ }
98
+ self.addEventListener(a.MESSAGE, r);
99
+ const t = {
100
+ action: S.HANDSHAKE_REQUEST,
101
+ methods: n,
102
+ schema: JSON.parse(JSON.stringify(e))
103
+ };
104
+ m = setInterval(() => {
105
+ if (h) return clearInterval(m);
106
+ M() ? self.postMessage(t) : window.parent.postMessage(t, "*");
107
+ }, G), setTimeout(() => {
108
+ h || c("connection timeout");
109
+ }, J);
110
+ });
111
+ }
112
+ const V = {
113
+ connect: w
114
+ };
115
+ function U(e, o) {
116
+ const c = e.getAttribute("src"), n = C(c), r = o.origin === n, t = o.source === e.contentWindow;
117
+ return r && t;
118
+ }
119
+ function Q(e, o = {}) {
120
+ if (!e) throw new Error("a target is required");
121
+ const c = e.onerror !== void 0 && e.onmessage !== void 0, n = c ? e : window;
122
+ return new Promise((r) => {
123
+ const t = A();
124
+ function s(i) {
125
+ if (!c && !U(e, i) || i.data.action !== S.HANDSHAKE_REQUEST) return;
126
+ const l = L(o), E = P(
127
+ o,
128
+ l,
129
+ t,
130
+ c ? e : void 0
131
+ ), { remote: f, unregisterRemote: u } = O(
132
+ i.data.schema,
133
+ i.data.methods,
134
+ t,
135
+ i,
136
+ c ? e : void 0
137
+ ), p = {
138
+ action: S.HANDSHAKE_REPLY,
139
+ connectionID: t,
140
+ methods: l,
141
+ schema: JSON.parse(JSON.stringify(o))
142
+ };
143
+ return c ? e.postMessage(p) : i.source.postMessage(p, i.origin), r({ remote: f, close: () => {
144
+ n.removeEventListener(a.MESSAGE, s), u(), E();
145
+ } });
146
+ }
147
+ n.addEventListener(a.MESSAGE, s);
148
+ });
149
+ }
150
+ const $ = {
151
+ connect: Q
152
+ };
153
+ export {
154
+ S as actions,
155
+ a as events,
156
+ V as guest,
157
+ $ as host
158
+ };
159
+ //# sourceMappingURL=index.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.es.js","sources":["../src/helpers.ts","../src/types.ts","../src/rpc.ts","../src/guest.ts","../src/host.ts"],"sourcesContent":["export const CONNECTION_TIMEOUT = 1000;\n\n/**\n * check if the remote is trusted\n *\n * @param event\n */\nexport function isTrustedRemote(_event: any) {\n // TODO: implement\n return true;\n}\n\n/**\n * check if run in a webworker\n *\n * @param event\n */\nexport function isWorker() {\n return typeof WorkerGlobalScope !== \"undefined\" && self instanceof WorkerGlobalScope;\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 paths: string[] = [];\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 paths.push(propPath);\n }\n });\n })(obj);\n return paths;\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 const { location } = document;\n\n const regexResult = urlRegex.exec(url || \"\");\n let protocol;\n let hostname;\n let port;\n\n if (regexResult) {\n // It's an absolute URL. Use the parsed info.\n // regexResult[1] will be undefined if the URL starts with //\n [, protocol = location.protocol, hostname, , port] = regexResult;\n } else {\n // It's a relative path. Use the current location's info.\n protocol = location.protocol;\n hostname = location.hostname;\n port = location.port;\n }\n\n // If the protocol is file, the origin is \"null\"\n // The origin of a document with file protocol is an opaque origin\n // and its serialization \"null\" [1]\n // [1] https://html.spec.whatwg.org/multipage/origin.html#origin\n if (protocol === \"file:\") {\n return \"null\";\n }\n\n // If the port is the default for the protocol, we don't want to add it to the origin string\n // or it won't match the message's event.origin.\n const portSuffix = port && port !== ports[protocol] ? `:${port}` : \"\";\n return `${protocol}//${hostname}${portSuffix}`;\n}\n","export 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 interface ISchema {\n [prop: string]: any;\n}\n\nexport interface IConnection {\n remote: ISchema;\n close: () => void;\n}\n\nexport interface IConnections {\n [connectionID: string]: ISchema;\n}\n\nexport interface IEvent extends EventListener {\n source?: Window;\n origin?: string;\n data?: IHandshakeRequestPayload | IHandshakeConfirmationPayload | IRPCRequestPayload | IRPCResolvePayload;\n}\n\nexport interface IHandshakeRequestPayload {\n action: actions.HANDSHAKE_REQUEST;\n connectionID?: string;\n methods: any[];\n schema: ISchema;\n}\n\nexport interface IHandshakeConfirmationPayload {\n action: actions.HANDSHAKE_REPLY;\n connectionID: string;\n methods: any[];\n schema: ISchema;\n}\n\nexport interface IRPCRequestPayload {\n action: actions.RPC_REQUEST;\n args: any[];\n callID: string;\n callName: string;\n connectionID?: string;\n}\n\nexport interface IRPCResolvePayload {\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","import get from \"lodash.get\";\nimport set from \"lodash.set\";\nimport { nanoid } from \"nanoid\";\n\nimport { isTrustedRemote, isWorker } from \"./helpers\";\nimport { actions, events, IRPCRequestPayload, IRPCResolvePayload, ISchema } from \"./types\";\n\n/**\n * for each function in the schema\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 array of method ids from the local schema\n * @param _connectionID\n * @return a function to cancel all subscriptions\n */\nexport function registerLocalMethods(\n schema: ISchema = {},\n methods: any[] = [],\n _connectionID: string,\n guest?: Worker\n): any {\n const listeners: any[] = [];\n methods.forEach((methodName) => {\n // handle a remote calling a local method\n async function handleCall(event: any) {\n const { action, callID, connectionID, callName, args = [] } = event.data as IRPCRequestPayload;\n\n if (action !== actions.RPC_REQUEST) return;\n if (!isTrustedRemote(event)) return;\n if (!callID || !callName) return;\n if (callName !== methodName) return;\n if (connectionID !== _connectionID) return;\n\n const payload: IRPCResolvePayload = {\n action: actions.RPC_RESOLVE,\n callID,\n callName,\n connectionID,\n error: null,\n result: null,\n };\n\n // run function and return the results to the remote\n try {\n const result = await get(schema, methodName)(...args);\n payload.result = JSON.parse(JSON.stringify(result));\n } catch (error) {\n payload.error = JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)));\n }\n\n if (guest) guest.postMessage(payload);\n else if (isWorker()) (self as any).postMessage(payload);\n else event.source.postMessage(payload, event.origin);\n }\n\n // subscribe to the call event\n if (guest) guest.addEventListener(events.MESSAGE, handleCall);\n else self.addEventListener(events.MESSAGE, handleCall);\n\n listeners.push(() => self.removeEventListener(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 _callName\n * @param _connectionID\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 _callName: string,\n _connectionID: string,\n event: any,\n listeners: Array<() => void> = [],\n guest?: Worker\n) {\n return (...args: any) => {\n return new Promise((resolve, reject) => {\n const callID = nanoid();\n\n // on RPC response\n function handleResponse(event: any) {\n const { callID, connectionID, callName, result, error, action } = event.data as IRPCResolvePayload;\n\n if (!isTrustedRemote(event)) return;\n if (!callID || !callName) return;\n if (callName !== _callName) return;\n if (connectionID !== _connectionID) 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: JSON.parse(JSON.stringify(args)),\n callID,\n callName: _callName,\n connectionID: _connectionID,\n };\n\n if (guest) guest.addEventListener(events.MESSAGE, handleResponse);\n else self.addEventListener(events.MESSAGE, handleResponse);\n listeners.push(() => self.removeEventListener(events.MESSAGE, handleResponse));\n\n if (guest) guest.postMessage(payload);\n else if (isWorker()) (self as any).postMessage(payload);\n else (event.source || event.target).postMessage(payload, event.origin);\n });\n };\n}\n\n/**\n * create an object based on the remote schema and 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: ISchema = {},\n methods: any[] = [],\n _connectionID: string,\n event: any,\n guest?: Worker\n) {\n const remote = { ...schema };\n const listeners: Array<() => void> = [];\n\n methods.forEach((methodName) => {\n const rpc = createRPC(methodName, _connectionID, event, listeners, guest);\n set(remote, methodName, rpc);\n });\n\n return {\n remote,\n unregisterRemote: () => listeners.forEach((unregister) => unregister()),\n };\n}\n","import { extractMethods, isWorker } from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, events, IConnection, ISchema } from \"./types\";\n\nconst REQUEST_INTERVAL = 10;\nconst TIMEOUT_INTERVAL = 3000;\n\nlet interval: any = null;\nlet connected = false;\n\nfunction connect(schema: ISchema = {}): Promise<IConnection> {\n return new Promise((resolve, reject) => {\n const localMethods = extractMethods(schema);\n\n // on handshake response\n function handleHandshakeResponse(event: any) {\n if (event.data.action !== actions.HANDSHAKE_REPLY) return;\n\n // register local methods\n const unregisterLocal = registerLocalMethods(schema, localMethods, event.data.connectionID);\n\n // register remote methods\n const { remote, unregisterRemote } = registerRemoteMethods(\n event.data.schema,\n event.data.methods,\n event.data.connectionID,\n event\n );\n\n // close the connection and all listeners when called\n const close = () => {\n self.removeEventListener(events.MESSAGE, handleHandshakeResponse);\n unregisterRemote();\n unregisterLocal();\n };\n\n connected = true;\n\n // resolve connection object\n const connection = { remote, close };\n return resolve(connection);\n }\n\n // subscribe to HANDSHAKE REPLY MESSAGES\n self.addEventListener(events.MESSAGE, handleHandshakeResponse);\n\n const payload = {\n action: actions.HANDSHAKE_REQUEST,\n methods: localMethods,\n schema: JSON.parse(JSON.stringify(schema)),\n };\n\n interval = setInterval(() => {\n if (connected) return clearInterval(interval);\n\n // publish the HANDSHAKE REQUEST\n if (isWorker()) (self as any).postMessage(payload);\n else window.parent.postMessage(payload, \"*\");\n }, REQUEST_INTERVAL);\n\n // timeout the connection after a time\n setTimeout(() => {\n if (!connected) reject(\"connection timeout\");\n }, TIMEOUT_INTERVAL);\n });\n}\n\nexport default {\n connect,\n};\n","import { nanoid } from \"nanoid\";\n\nimport { extractMethods, getOriginFromURL } from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, events, IConnections, IConnection, ISchema } from \"./types\";\n\nconst connections: IConnections = {};\n\nfunction isValidTarget(iframe: HTMLIFrameElement, event: any) {\n const childURL = iframe.getAttribute(\"src\");\n const childOrigin = getOriginFromURL(childURL);\n const hasProperOrigin = event.origin === childOrigin;\n const hasProperSource = event.source === iframe.contentWindow;\n\n return hasProperOrigin && hasProperSource;\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 iframe\n * @param schema\n * @returns Promise\n */\nfunction connect(guest: HTMLIFrameElement | Worker, schema: ISchema = {}): Promise<IConnection> {\n if (!guest) throw new Error(\"a target is required\");\n\n const guestIsWorker = (guest as Worker).onerror !== undefined && (guest as Worker).onmessage !== undefined;\n const listeners = guestIsWorker ? guest : window;\n\n return new Promise((resolve) => {\n const connectionID = nanoid();\n\n // on handshake request\n function handleHandshake(event: any) {\n if (!guestIsWorker && !isValidTarget(guest as HTMLIFrameElement, event)) return;\n if (event.data.action !== actions.HANDSHAKE_REQUEST) return;\n\n // register local methods\n const localMethods = extractMethods(schema);\n const unregisterLocal = registerLocalMethods(\n schema,\n localMethods,\n connectionID,\n guestIsWorker ? (guest as Worker) : undefined\n );\n\n // register remote methods\n const { remote, unregisterRemote } = registerRemoteMethods(\n event.data.schema,\n event.data.methods,\n connectionID,\n event,\n guestIsWorker ? (guest as Worker) : undefined\n );\n\n const payload = {\n action: actions.HANDSHAKE_REPLY,\n connectionID,\n methods: localMethods,\n schema: JSON.parse(JSON.stringify(schema)),\n };\n\n // confirm the connection\n if (guestIsWorker) (guest as Worker).postMessage(payload);\n else event.source.postMessage(payload, event.origin);\n\n // close the connection and all listeners when called\n const close = () => {\n listeners.removeEventListener(events.MESSAGE, handleHandshake);\n unregisterRemote();\n unregisterLocal();\n };\n\n // resolve connection object\n const connection: IConnection = { remote, close };\n connections[connectionID] = connection;\n return resolve(connection);\n }\n\n // subscribe to HANDSHAKE MESSAGES\n listeners.addEventListener(events.MESSAGE, handleHandshake);\n });\n}\n\nexport default {\n connect,\n};\n"],"names":["isWorker","extractMethods","obj","paths","parse","path","prop","propPath","urlRegex","ports","getOriginFromURL","url","location","regexResult","protocol","hostname","port","portSuffix","events","actions","registerLocalMethods","schema","methods","_connectionID","guest","listeners","methodName","handleCall","event","action","callID","connectionID","callName","args","payload","result","get","error","unregister","createRPC","_callName","resolve","reject","nanoid","handleResponse","registerRemoteMethods","remote","rpc","set","REQUEST_INTERVAL","TIMEOUT_INTERVAL","interval","connected","connect","localMethods","handleHandshakeResponse","unregisterLocal","unregisterRemote","close","isValidTarget","iframe","childURL","childOrigin","hasProperOrigin","hasProperSource","guestIsWorker","handleHandshake","host"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ (function(a,g){typeof exports=="object"&&typeof module<"u"?g(exports,require("lodash.get"),require("lodash.set"),require("nanoid")):typeof define=="function"&&define.amd?define(["exports","lodash.get","lodash.set","nanoid"],g):(a=typeof globalThis<"u"?globalThis:a||self,g(a.rimless={},a.get,a.set,a.nanoid))})(this,function(a,g,I,L){"use strict";function M(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}function m(e){const o=[];return function i(n,r=""){Object.keys(n).forEach(t=>{const s=r?`${r}.${t}`:t;n[t]===Object(n[t])&&i(n[t],s),typeof n[t]=="function"&&o.push(s)})}(e),o}const y=/^(https?:|file:)?\/\/([^/:]+)?(:(\d+))?/,_={"http:":"80","https:":"443"};function H(e){const{location:o}=document,i=y.exec(e||"");let n,r,t;if(i?[,n=o.protocol,r,,t]=i:(n=o.protocol,r=o.hostname,t=o.port),n==="file:")return"null";const s=t&&t!==_[n]?`:${t}`:"";return`${n}//${r}${s}`}var l=(e=>(e.MESSAGE="message",e))(l||{}),E=(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))(E||{});function P(e={},o=[],i,n){const r=[];return o.forEach(t=>{async function s(c){const{action:f,callID:u,connectionID:d,callName:S,args:p=[]}=c.data;if(f!==E.RPC_REQUEST||!u||!S||S!==t||d!==i)return;const R={action:E.RPC_RESOLVE,callID:u,callName:S,connectionID:d,error:null,result:null};try{const h=await g(e,t)(...p);R.result=JSON.parse(JSON.stringify(h))}catch(h){R.error=JSON.parse(JSON.stringify(h,Object.getOwnPropertyNames(h)))}n?n.postMessage(R):M()?self.postMessage(R):c.source.postMessage(R,c.origin)}n?n.addEventListener(l.MESSAGE,s):self.addEventListener(l.MESSAGE,s),r.push(()=>self.removeEventListener(l.MESSAGE,s))}),()=>r.forEach(t=>t())}function D(e,o,i,n=[],r){return(...t)=>new Promise((s,c)=>{const f=L.nanoid();function u(S){const{callID:p,connectionID:R,callName:h,result:K,error:k,action:T}=S.data;if(!(!p||!h)&&h===e&&R===o){if(T===E.RPC_RESOLVE)return s(K);if(T===E.RPC_REJECT)return c(k)}}const d={action:E.RPC_REQUEST,args:JSON.parse(JSON.stringify(t)),callID:f,callName:e,connectionID:o};r?r.addEventListener(l.MESSAGE,u):self.addEventListener(l.MESSAGE,u),n.push(()=>self.removeEventListener(l.MESSAGE,u)),r?r.postMessage(d):M()?self.postMessage(d):(i.source||i.target).postMessage(d,i.origin)})}function O(e={},o=[],i,n,r){const t={...e},s=[];return o.forEach(c=>{const f=D(c,i,n,s,r);I(t,c,f)}),{remote:t,unregisterRemote:()=>s.forEach(c=>c())}}const C=10,G=3e3;let N=null,A=!1;function J(e={}){return new Promise((o,i)=>{const n=m(e);function r(s){if(s.data.action!==E.HANDSHAKE_REPLY)return;const c=P(e,n,s.data.connectionID),{remote:f,unregisterRemote:u}=O(s.data.schema,s.data.methods,s.data.connectionID,s),d=()=>{self.removeEventListener(l.MESSAGE,r),u(),c()};return A=!0,o({remote:f,close:d})}self.addEventListener(l.MESSAGE,r);const t={action:E.HANDSHAKE_REQUEST,methods:n,schema:JSON.parse(JSON.stringify(e))};N=setInterval(()=>{if(A)return clearInterval(N);M()?self.postMessage(t):window.parent.postMessage(t,"*")},C),setTimeout(()=>{A||i("connection timeout")},G)})}const w={connect:J};function U(e,o){const i=e.getAttribute("src"),n=H(i),r=o.origin===n,t=o.source===e.contentWindow;return r&&t}function v(e,o={}){if(!e)throw new Error("a target is required");const i=e.onerror!==void 0&&e.onmessage!==void 0,n=i?e:window;return new Promise(r=>{const t=L.nanoid();function s(c){if(!i&&!U(e,c)||c.data.action!==E.HANDSHAKE_REQUEST)return;const f=m(o),u=P(o,f,t,i?e:void 0),{remote:d,unregisterRemote:S}=O(c.data.schema,c.data.methods,t,c,i?e:void 0),p={action:E.HANDSHAKE_REPLY,connectionID:t,methods:f,schema:JSON.parse(JSON.stringify(o))};return i?e.postMessage(p):c.source.postMessage(p,c.origin),r({remote:d,close:()=>{n.removeEventListener(l.MESSAGE,s),S(),u()}})}n.addEventListener(l.MESSAGE,s)})}const Q={connect:v};a.actions=E,a.events=l,a.guest=w,a.host=Q,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
2
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/helpers.ts","../src/types.ts","../src/rpc.ts","../src/guest.ts","../src/host.ts"],"sourcesContent":["export const CONNECTION_TIMEOUT = 1000;\n\n/**\n * check if the remote is trusted\n *\n * @param event\n */\nexport function isTrustedRemote(_event: any) {\n // TODO: implement\n return true;\n}\n\n/**\n * check if run in a webworker\n *\n * @param event\n */\nexport function isWorker() {\n return typeof WorkerGlobalScope !== \"undefined\" && self instanceof WorkerGlobalScope;\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 paths: string[] = [];\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 paths.push(propPath);\n }\n });\n })(obj);\n return paths;\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 const { location } = document;\n\n const regexResult = urlRegex.exec(url || \"\");\n let protocol;\n let hostname;\n let port;\n\n if (regexResult) {\n // It's an absolute URL. Use the parsed info.\n // regexResult[1] will be undefined if the URL starts with //\n [, protocol = location.protocol, hostname, , port] = regexResult;\n } else {\n // It's a relative path. Use the current location's info.\n protocol = location.protocol;\n hostname = location.hostname;\n port = location.port;\n }\n\n // If the protocol is file, the origin is \"null\"\n // The origin of a document with file protocol is an opaque origin\n // and its serialization \"null\" [1]\n // [1] https://html.spec.whatwg.org/multipage/origin.html#origin\n if (protocol === \"file:\") {\n return \"null\";\n }\n\n // If the port is the default for the protocol, we don't want to add it to the origin string\n // or it won't match the message's event.origin.\n const portSuffix = port && port !== ports[protocol] ? `:${port}` : \"\";\n return `${protocol}//${hostname}${portSuffix}`;\n}\n","export 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 interface ISchema {\n [prop: string]: any;\n}\n\nexport interface IConnection {\n remote: ISchema;\n close: () => void;\n}\n\nexport interface IConnections {\n [connectionID: string]: ISchema;\n}\n\nexport interface IEvent extends EventListener {\n source?: Window;\n origin?: string;\n data?: IHandshakeRequestPayload | IHandshakeConfirmationPayload | IRPCRequestPayload | IRPCResolvePayload;\n}\n\nexport interface IHandshakeRequestPayload {\n action: actions.HANDSHAKE_REQUEST;\n connectionID?: string;\n methods: any[];\n schema: ISchema;\n}\n\nexport interface IHandshakeConfirmationPayload {\n action: actions.HANDSHAKE_REPLY;\n connectionID: string;\n methods: any[];\n schema: ISchema;\n}\n\nexport interface IRPCRequestPayload {\n action: actions.RPC_REQUEST;\n args: any[];\n callID: string;\n callName: string;\n connectionID?: string;\n}\n\nexport interface IRPCResolvePayload {\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","import get from \"lodash.get\";\nimport set from \"lodash.set\";\nimport { nanoid } from \"nanoid\";\n\nimport { isTrustedRemote, isWorker } from \"./helpers\";\nimport { actions, events, IRPCRequestPayload, IRPCResolvePayload, ISchema } from \"./types\";\n\n/**\n * for each function in the schema\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 array of method ids from the local schema\n * @param _connectionID\n * @return a function to cancel all subscriptions\n */\nexport function registerLocalMethods(\n schema: ISchema = {},\n methods: any[] = [],\n _connectionID: string,\n guest?: Worker\n): any {\n const listeners: any[] = [];\n methods.forEach((methodName) => {\n // handle a remote calling a local method\n async function handleCall(event: any) {\n const { action, callID, connectionID, callName, args = [] } = event.data as IRPCRequestPayload;\n\n if (action !== actions.RPC_REQUEST) return;\n if (!isTrustedRemote(event)) return;\n if (!callID || !callName) return;\n if (callName !== methodName) return;\n if (connectionID !== _connectionID) return;\n\n const payload: IRPCResolvePayload = {\n action: actions.RPC_RESOLVE,\n callID,\n callName,\n connectionID,\n error: null,\n result: null,\n };\n\n // run function and return the results to the remote\n try {\n const result = await get(schema, methodName)(...args);\n payload.result = JSON.parse(JSON.stringify(result));\n } catch (error) {\n payload.error = JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)));\n }\n\n if (guest) guest.postMessage(payload);\n else if (isWorker()) (self as any).postMessage(payload);\n else event.source.postMessage(payload, event.origin);\n }\n\n // subscribe to the call event\n if (guest) guest.addEventListener(events.MESSAGE, handleCall);\n else self.addEventListener(events.MESSAGE, handleCall);\n\n listeners.push(() => self.removeEventListener(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 _callName\n * @param _connectionID\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 _callName: string,\n _connectionID: string,\n event: any,\n listeners: Array<() => void> = [],\n guest?: Worker\n) {\n return (...args: any) => {\n return new Promise((resolve, reject) => {\n const callID = nanoid();\n\n // on RPC response\n function handleResponse(event: any) {\n const { callID, connectionID, callName, result, error, action } = event.data as IRPCResolvePayload;\n\n if (!isTrustedRemote(event)) return;\n if (!callID || !callName) return;\n if (callName !== _callName) return;\n if (connectionID !== _connectionID) 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: JSON.parse(JSON.stringify(args)),\n callID,\n callName: _callName,\n connectionID: _connectionID,\n };\n\n if (guest) guest.addEventListener(events.MESSAGE, handleResponse);\n else self.addEventListener(events.MESSAGE, handleResponse);\n listeners.push(() => self.removeEventListener(events.MESSAGE, handleResponse));\n\n if (guest) guest.postMessage(payload);\n else if (isWorker()) (self as any).postMessage(payload);\n else (event.source || event.target).postMessage(payload, event.origin);\n });\n };\n}\n\n/**\n * create an object based on the remote schema and 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: ISchema = {},\n methods: any[] = [],\n _connectionID: string,\n event: any,\n guest?: Worker\n) {\n const remote = { ...schema };\n const listeners: Array<() => void> = [];\n\n methods.forEach((methodName) => {\n const rpc = createRPC(methodName, _connectionID, event, listeners, guest);\n set(remote, methodName, rpc);\n });\n\n return {\n remote,\n unregisterRemote: () => listeners.forEach((unregister) => unregister()),\n };\n}\n","import { extractMethods, isWorker } from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, events, IConnection, ISchema } from \"./types\";\n\nconst REQUEST_INTERVAL = 10;\nconst TIMEOUT_INTERVAL = 3000;\n\nlet interval: any = null;\nlet connected = false;\n\nfunction connect(schema: ISchema = {}): Promise<IConnection> {\n return new Promise((resolve, reject) => {\n const localMethods = extractMethods(schema);\n\n // on handshake response\n function handleHandshakeResponse(event: any) {\n if (event.data.action !== actions.HANDSHAKE_REPLY) return;\n\n // register local methods\n const unregisterLocal = registerLocalMethods(schema, localMethods, event.data.connectionID);\n\n // register remote methods\n const { remote, unregisterRemote } = registerRemoteMethods(\n event.data.schema,\n event.data.methods,\n event.data.connectionID,\n event\n );\n\n // close the connection and all listeners when called\n const close = () => {\n self.removeEventListener(events.MESSAGE, handleHandshakeResponse);\n unregisterRemote();\n unregisterLocal();\n };\n\n connected = true;\n\n // resolve connection object\n const connection = { remote, close };\n return resolve(connection);\n }\n\n // subscribe to HANDSHAKE REPLY MESSAGES\n self.addEventListener(events.MESSAGE, handleHandshakeResponse);\n\n const payload = {\n action: actions.HANDSHAKE_REQUEST,\n methods: localMethods,\n schema: JSON.parse(JSON.stringify(schema)),\n };\n\n interval = setInterval(() => {\n if (connected) return clearInterval(interval);\n\n // publish the HANDSHAKE REQUEST\n if (isWorker()) (self as any).postMessage(payload);\n else window.parent.postMessage(payload, \"*\");\n }, REQUEST_INTERVAL);\n\n // timeout the connection after a time\n setTimeout(() => {\n if (!connected) reject(\"connection timeout\");\n }, TIMEOUT_INTERVAL);\n });\n}\n\nexport default {\n connect,\n};\n","import { nanoid } from \"nanoid\";\n\nimport { extractMethods, getOriginFromURL } from \"./helpers\";\nimport { registerLocalMethods, registerRemoteMethods } from \"./rpc\";\nimport { actions, events, IConnections, IConnection, ISchema } from \"./types\";\n\nconst connections: IConnections = {};\n\nfunction isValidTarget(iframe: HTMLIFrameElement, event: any) {\n const childURL = iframe.getAttribute(\"src\");\n const childOrigin = getOriginFromURL(childURL);\n const hasProperOrigin = event.origin === childOrigin;\n const hasProperSource = event.source === iframe.contentWindow;\n\n return hasProperOrigin && hasProperSource;\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 iframe\n * @param schema\n * @returns Promise\n */\nfunction connect(guest: HTMLIFrameElement | Worker, schema: ISchema = {}): Promise<IConnection> {\n if (!guest) throw new Error(\"a target is required\");\n\n const guestIsWorker = (guest as Worker).onerror !== undefined && (guest as Worker).onmessage !== undefined;\n const listeners = guestIsWorker ? guest : window;\n\n return new Promise((resolve) => {\n const connectionID = nanoid();\n\n // on handshake request\n function handleHandshake(event: any) {\n if (!guestIsWorker && !isValidTarget(guest as HTMLIFrameElement, event)) return;\n if (event.data.action !== actions.HANDSHAKE_REQUEST) return;\n\n // register local methods\n const localMethods = extractMethods(schema);\n const unregisterLocal = registerLocalMethods(\n schema,\n localMethods,\n connectionID,\n guestIsWorker ? (guest as Worker) : undefined\n );\n\n // register remote methods\n const { remote, unregisterRemote } = registerRemoteMethods(\n event.data.schema,\n event.data.methods,\n connectionID,\n event,\n guestIsWorker ? (guest as Worker) : undefined\n );\n\n const payload = {\n action: actions.HANDSHAKE_REPLY,\n connectionID,\n methods: localMethods,\n schema: JSON.parse(JSON.stringify(schema)),\n };\n\n // confirm the connection\n if (guestIsWorker) (guest as Worker).postMessage(payload);\n else event.source.postMessage(payload, event.origin);\n\n // close the connection and all listeners when called\n const close = () => {\n listeners.removeEventListener(events.MESSAGE, handleHandshake);\n unregisterRemote();\n unregisterLocal();\n };\n\n // resolve connection object\n const connection: IConnection = { remote, close };\n connections[connectionID] = connection;\n return resolve(connection);\n }\n\n // subscribe to HANDSHAKE MESSAGES\n listeners.addEventListener(events.MESSAGE, handleHandshake);\n });\n}\n\nexport default {\n connect,\n};\n"],"names":["isWorker","extractMethods","obj","paths","parse","path","prop","propPath","urlRegex","ports","getOriginFromURL","url","location","regexResult","protocol","hostname","port","portSuffix","events","actions","registerLocalMethods","schema","methods","_connectionID","guest","listeners","methodName","handleCall","event","action","callID","connectionID","callName","args","payload","result","get","error","unregister","createRPC","_callName","resolve","reject","nanoid","handleResponse","registerRemoteMethods","remote","rpc","set","REQUEST_INTERVAL","TIMEOUT_INTERVAL","interval","connected","connect","localMethods","handleHandshakeResponse","unregisterLocal","unregisterRemote","close","isValidTarget","iframe","childURL","childOrigin","hasProperOrigin","hasProperSource","guestIsWorker","handleHandshake","host"],"mappings":"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"}
package/package.json CHANGED
@@ -1,98 +1,66 @@
1
1
  {
2
2
  "name": "rimless",
3
3
  "author": "Aurélien Franky",
4
- "version": "0.1.5",
4
+ "version": "0.2.0",
5
5
  "license": "MIT",
6
6
  "homepage": "https://au-re.github.io/rimless",
7
7
  "description": "event base communication made easy with a promise-based API wrapping `postMessage`",
8
- "main": "lib/index.js",
9
- "types": "lib/index.d.ts",
8
+ "type": "module",
9
+ "main": "dist/index.umd.js",
10
+ "module": "dist/index.es.js",
11
+ "types": "dist/index.d.ts",
10
12
  "files": [
11
- "/lib"
13
+ "dist"
12
14
  ],
13
15
  "scripts": {
14
- "analyze": "mkdir -p dependency-map && source-map-explorer --html lib/index.js > dependency-map/index.html",
15
- "coverage": "npm run test -- --coverage",
16
- "start": "start-storybook -p 6060",
17
- "commit": "git-cz",
18
- "test": "jest --watch",
19
- "clean": "rm -rf node_modules && npm i",
20
- "lint": "tslint -c tslint.json 'src/**/*.ts'",
21
- "prepare": "npm run build",
22
- "integrations": "npx serve -p 8080 tests/integrations/",
23
- "browserify": "browserify ./lib/index.js -s rimless | uglifyjs > ./lib/rimless.min.js",
24
- "min2tests": "browserify ./lib/index.js -s rimless > ./tests/integrations/rimless.min.js",
25
- "build": "tsc --build && npm run browserify && npm run min2tests",
26
- "build:storybook": "build-storybook",
27
- "deploy": "gh-pages -d storybook-static",
28
- "predeploy": "npm run build-storybook",
29
- "storybook": "start-storybook -p 6006",
30
- "build-storybook": "build-storybook"
16
+ "dev": "vite",
17
+ "build": "tsc -b && vite build",
18
+ "lint": "eslint . --ignore-pattern '**/*.min.js'",
19
+ "test": "vitest run",
20
+ "preview": "vite preview",
21
+ "storybook": "storybook dev -p 6006",
22
+ "build-storybook": "storybook build",
23
+ "visualize-bundle": "npx vite-bundle-visualizer"
31
24
  },
32
25
  "repository": {
33
26
  "type": "git",
34
27
  "url": "https://github.com/au-re/rimless.git"
35
28
  },
36
29
  "dependencies": {
37
- "lodash.get": "^4.4.2",
38
- "lodash.set": "^4.3.2",
39
- "short-uuid": "^3.1.1"
30
+ "lodash.get": "^4.0.0",
31
+ "lodash.set": "^4.0.0",
32
+ "nanoid": "^5.0.0"
40
33
  },
41
- "devDependencies": {
42
- "@babel/core": "^7.8.7",
43
- "@storybook/addon-actions": "^5.3.14",
44
- "@storybook/addon-docs": "^5.3.14",
45
- "@storybook/addon-links": "^5.3.14",
46
- "@storybook/addons": "^5.3.14",
47
- "@storybook/react": "^5.3.14",
48
- "@types/jest": "^25.1.4",
49
- "@types/lodash.get": "^4.4.6",
50
- "@types/lodash.isequal": "^4.5.5",
51
- "@types/lodash.set": "^4.3.6",
52
- "@types/storybook-readme": "^5.0.4",
53
- "@typescript-eslint/eslint-plugin": "^2.22.0",
54
- "@typescript-eslint/parser": "^2.22.0",
55
- "awesome-typescript-loader": "^5.2.1",
56
- "babel-loader": "^8.0.6",
57
- "browserify": "^16.5.0",
58
- "commitizen": "^4.0.3",
59
- "cz-emoji": "^1.2.1",
60
- "eslint": "^6.8.0",
61
- "eslint-config-airbnb": "^18.0.1",
62
- "eslint-config-airbnb-typescript": "^7.0.0",
63
- "eslint-config-prettier": "^6.10.0",
64
- "eslint-plugin-import": "^2.20.1",
65
- "eslint-plugin-jsx-a11y": "^6.2.3",
66
- "eslint-plugin-prettier": "^3.1.2",
67
- "eslint-plugin-react": "^7.18.3",
68
- "eslint-plugin-react-hooks": "^1.7.0",
69
- "gh-pages": "^2.2.0",
70
- "jest": "^24.8.0",
71
- "react": "^16.13.0",
72
- "react-dom": "^16.13.0",
73
- "source-map-explorer": "^2.3.1",
74
- "source-map-loader": "^0.2.4",
75
- "styled-components": "^5.0.1",
76
- "ts-jest": "^24.0.2",
77
- "typescript": "^3.8.3"
34
+ "peerDependencies": {
35
+ "lodash.get": "^4.0.0",
36
+ "lodash.set": "^4.0.0",
37
+ "nanoid": "^5.0.0"
78
38
  },
79
- "config": {
80
- "cz-emoji": {},
81
- "commitizen": {
82
- "path": "cz-emoji"
83
- }
39
+ "devDependencies": {
40
+ "@chromatic-com/storybook": "^1.7.0",
41
+ "@eslint/js": "^9.9.0",
42
+ "@storybook/addon-essentials": "^8.2.9",
43
+ "@storybook/addon-interactions": "^8.2.9",
44
+ "@storybook/addon-links": "^8.2.9",
45
+ "@storybook/addon-onboarding": "^8.2.9",
46
+ "@storybook/blocks": "^8.2.9",
47
+ "@storybook/react": "^8.2.9",
48
+ "@storybook/react-vite": "^8.2.9",
49
+ "@storybook/test": "^8.2.9",
50
+ "@types/lodash.get": "^4.4.9",
51
+ "@types/lodash.set": "^4.3.9",
52
+ "@vitejs/plugin-react": "^4.3.1",
53
+ "eslint": "^9.12.0",
54
+ "globals": "^15.11.0",
55
+ "happy-dom": "^15.7.4",
56
+ "storybook": "^8.2.9",
57
+ "typescript": "^5.5.3",
58
+ "typescript-eslint": "^8.8.1",
59
+ "vite": "^5.4.1",
60
+ "vite-plugin-dts": "^4.2.4",
61
+ "vitest": "^2.0.5"
84
62
  },
85
- "jest": {
86
- "preset": "ts-jest",
87
- "testEnvironment": "jsdom",
88
- "collectCoverageFrom": [
89
- "src/**/*.{js,jsx,ts,tsx}",
90
- "!src/**/*.stories.{js,jsx,ts,tsx}",
91
- "!src/**/*.d.ts"
92
- ],
93
- "moduleNameMapper": {
94
- "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/config/jext/fileMock.js",
95
- "\\.(css|sass|scss)$": "<rootDir>/config/jest/cssMock.js"
96
- }
63
+ "volta": {
64
+ "node": "18.19.0"
97
65
  }
98
66
  }
package/lib/guest.d.ts DELETED
@@ -1,6 +0,0 @@
1
- import { IConnection, ISchema } from "./types";
2
- declare function connect(schema?: ISchema, options?: any): Promise<IConnection>;
3
- declare const _default: {
4
- connect: typeof connect;
5
- };
6
- export default _default;