swarpc 0.12.0 → 0.14.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/README.md +7 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +20 -9
- package/dist/log.d.ts +5 -0
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +25 -17
- package/dist/nodes.d.ts +3 -0
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +7 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +5 -3
- package/dist/types.d.ts +29 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -0
- package/package.json +4 -2
- package/src/client.ts +22 -9
- package/src/log.ts +41 -22
- package/src/nodes.ts +12 -0
- package/src/server.ts +5 -3
- package/src/types.ts +10 -1
package/README.md
CHANGED
|
@@ -24,7 +24,11 @@ RPC for Service Workers -- move that heavy computation off of your UI thread!
|
|
|
24
24
|
npm add swarpc arktype
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
<details>
|
|
28
|
+
<summary>
|
|
29
|
+
Bleeding edge
|
|
30
|
+
|
|
31
|
+
</summary>
|
|
28
32
|
|
|
29
33
|
If you want to use the latest commit instead of a published version, you can, either by using the Git URL:
|
|
30
34
|
|
|
@@ -42,6 +46,8 @@ npm add file:vendored/swarpc
|
|
|
42
46
|
|
|
43
47
|
This works thanks to the fact that `dist/` is published on the repository (and kept up to date with a CI workflow).
|
|
44
48
|
|
|
49
|
+
</details>
|
|
50
|
+
|
|
45
51
|
## Usage
|
|
46
52
|
|
|
47
53
|
### 1. Declare your procedures in a shared file
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEL,kBAAkB,EAClB,KAAK,MAAM,EACX,KAAK,QAAQ,EACd,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,YAAY,EACZ,KAAK,EACL,OAAO,EAEP,iBAAiB,EACjB,WAAW,EACX,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAGpB;;;;GAIG;AACH,MAAM,MAAM,YAAY,CAAC,UAAU,SAAS,aAAa,IAAI;IAC3D,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;CAC3B,GAAG;KACD,CAAC,IAAI,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;CACrD,CAAC;AAEF;;GAEG;AACH,KAAK,OAAO,CAAC,UAAU,SAAS,aAAa,IAAI;IAC/C,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IACxC,gCAAgC;IAChC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,kCAAkC;IAClC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACzB,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC,CAAC;AAQF,MAAM,MAAM,cAAc,GAAG;IAC3B,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAC7B,UAAU,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IACpC,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAChC,CAAC;AAKF,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,MAAM,CAAC,UAAU,SAAS,aAAa,EACrD,UAAU,EAAE,UAAU,EACtB,EACE,MAAM,EACN,KAAK,EAAE,SAAS,EAChB,QAAkB,EAClB,eAAuB,EACvB,KAAU,EACV,YAAiB,GAClB,GAAE;IACD,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC1B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B,GACL,YAAY,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEL,kBAAkB,EAClB,KAAK,MAAM,EACX,KAAK,QAAQ,EACd,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,YAAY,EACZ,KAAK,EACL,OAAO,EAEP,iBAAiB,EACjB,WAAW,EACX,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAGpB;;;;GAIG;AACH,MAAM,MAAM,YAAY,CAAC,UAAU,SAAS,aAAa,IAAI;IAC3D,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;CAC3B,GAAG;KACD,CAAC,IAAI,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;CACrD,CAAC;AAEF;;GAEG;AACH,KAAK,OAAO,CAAC,UAAU,SAAS,aAAa,IAAI;IAC/C,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IACxC,gCAAgC;IAChC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,kCAAkC;IAClC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACzB,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC,CAAC;AAQF,MAAM,MAAM,cAAc,GAAG;IAC3B,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAC7B,UAAU,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IACpC,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAChC,CAAC;AAKF,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,MAAM,CAAC,UAAU,SAAS,aAAa,EACrD,UAAU,EAAE,UAAU,EACtB,EACE,MAAM,EACN,KAAK,EAAE,SAAS,EAChB,QAAkB,EAClB,eAAuB,EACvB,KAAU,EACV,YAAiB,GAClB,GAAE;IACD,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC1B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B,GACL,YAAY,CAAC,UAAU,CAAC,CA2K1B;AAiCD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,UAAU,SAAS,aAAa,EAC9D,CAAC,EAAE,kBAAkB,EACrB,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,EACzC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,EAC5B,OAAO,CAAC,EAAE,0BAA0B,GACnC,IAAI,CAiBN;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,UAAU,SAAS,aAAa,EACxE,GAAG,EAAE,OAAO,CAAC,UAAU,CAAC,iBAsFzB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
|
package/dist/client.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @mergeModuleWith <project>
|
|
4
4
|
*/
|
|
5
5
|
import { createLogger, } from "./log.js";
|
|
6
|
-
import { makeNodeId, whoToSendTo } from "./nodes.js";
|
|
6
|
+
import { makeNodeId, nodeIdOrSW, whoToSendTo } from "./nodes.js";
|
|
7
7
|
import { zProcedures, } from "./types.js";
|
|
8
8
|
import { findTransferables } from "./utils.js";
|
|
9
9
|
/**
|
|
@@ -80,7 +80,7 @@ export function Client(procedures, { worker, nodes: nodeCount, loglevel = "debug
|
|
|
80
80
|
// Choose which node to use
|
|
81
81
|
nodeId ??= whoToSendTo(nodes, pendingRequests);
|
|
82
82
|
const node = nodes && nodeId ? nodes[nodeId] : undefined;
|
|
83
|
-
const l = createLogger("client", loglevel, nodeId
|
|
83
|
+
const l = createLogger("client", loglevel, nodeIdOrSW(nodeId), requestId);
|
|
84
84
|
return new Promise((resolve, reject) => {
|
|
85
85
|
// Store promise handlers (as well as progress updates handler)
|
|
86
86
|
// so the client listener can resolve/reject the promise (and react to progress updates)
|
|
@@ -104,19 +104,28 @@ export function Client(procedures, { worker, nodes: nodeCount, loglevel = "debug
|
|
|
104
104
|
};
|
|
105
105
|
// @ts-expect-error
|
|
106
106
|
instance[functionName] = _runProcedure;
|
|
107
|
-
instance[functionName].broadcast = async (input,
|
|
107
|
+
instance[functionName].broadcast = async (input, onProgresses, nodesCount) => {
|
|
108
108
|
let nodesToUse = [undefined];
|
|
109
109
|
if (nodes)
|
|
110
110
|
nodesToUse = Object.keys(nodes);
|
|
111
111
|
if (nodesCount)
|
|
112
112
|
nodesToUse = nodesToUse.slice(0, nodesCount);
|
|
113
|
-
const
|
|
114
|
-
|
|
113
|
+
const progresses = new Map();
|
|
114
|
+
function onProgress(nodeId) {
|
|
115
|
+
if (!onProgresses)
|
|
116
|
+
return (_) => { };
|
|
117
|
+
return (progress) => {
|
|
118
|
+
progresses.set(nodeIdOrSW(nodeId), progress);
|
|
119
|
+
onProgresses(progresses);
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
const results = await Promise.allSettled(nodesToUse.map(async (id) => _runProcedure(input, onProgress(id), undefined, id)));
|
|
123
|
+
return results.map((r, i) => ({ ...r, node: nodeIdOrSW(nodesToUse[i]) }));
|
|
115
124
|
};
|
|
116
125
|
instance[functionName].cancelable = (input, onProgress) => {
|
|
117
126
|
const requestId = makeRequestId();
|
|
118
127
|
const nodeId = whoToSendTo(nodes, pendingRequests);
|
|
119
|
-
const l = createLogger("client", loglevel, nodeId
|
|
128
|
+
const l = createLogger("client", loglevel, nodeIdOrSW(nodeId), requestId);
|
|
120
129
|
return {
|
|
121
130
|
request: _runProcedure(input, onProgress, requestId, nodeId),
|
|
122
131
|
cancel(reason) {
|
|
@@ -186,7 +195,7 @@ export function postMessageSync(l, worker, message, options) {
|
|
|
186
195
|
* @returns
|
|
187
196
|
*/
|
|
188
197
|
export async function startClientListener(ctx) {
|
|
189
|
-
if (_clientListenerStarted.has(ctx.nodeId
|
|
198
|
+
if (_clientListenerStarted.has(nodeIdOrSW(ctx.nodeId)))
|
|
190
199
|
return;
|
|
191
200
|
const { logger: l, node: worker } = ctx;
|
|
192
201
|
// Get service worker registration if no worker is provided
|
|
@@ -211,7 +220,7 @@ export async function startClientListener(ctx) {
|
|
|
211
220
|
// We don't use a arktype schema here, we trust the server to send valid data
|
|
212
221
|
const payload = eventData;
|
|
213
222
|
// Ignore #initialize request, it's client->server only
|
|
214
|
-
if ("
|
|
223
|
+
if ("isInitializeRequest" in payload) {
|
|
215
224
|
l.warn(null, "Ignoring unexpected #initialize from server", payload);
|
|
216
225
|
return;
|
|
217
226
|
}
|
|
@@ -249,12 +258,14 @@ export async function startClientListener(ctx) {
|
|
|
249
258
|
else {
|
|
250
259
|
w.addEventListener("message", listener);
|
|
251
260
|
}
|
|
252
|
-
_clientListenerStarted.add(ctx.nodeId
|
|
261
|
+
_clientListenerStarted.add(nodeIdOrSW(ctx.nodeId));
|
|
253
262
|
// Recursive terminal case is ensured by calling this *after* _clientListenerStarted is set to true: startClientListener() will therefore not be called in postMessage() again.
|
|
254
263
|
await postMessage(ctx, {
|
|
255
264
|
by: "sw&rpc",
|
|
256
265
|
functionName: "#initialize",
|
|
266
|
+
isInitializeRequest: true,
|
|
257
267
|
localStorageData: ctx.localStorage,
|
|
268
|
+
nodeId: nodeIdOrSW(ctx.nodeId),
|
|
258
269
|
});
|
|
259
270
|
}
|
|
260
271
|
/**
|
package/dist/log.d.ts
CHANGED
|
@@ -25,5 +25,10 @@ export type RequestBoundLogger = {
|
|
|
25
25
|
/** @source */
|
|
26
26
|
declare const LOG_LEVELS: readonly ["debug", "info", "warn", "error"];
|
|
27
27
|
export type LogLevel = (typeof LOG_LEVELS)[number];
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @param scope
|
|
31
|
+
*/
|
|
32
|
+
export declare function injectIntoConsoleGlobal(scope: WorkerGlobalScope | SharedWorkerGlobalScope, nodeId: string): void;
|
|
28
33
|
export {};
|
|
29
34
|
//# sourceMappingURL=log.d.ts.map
|
package/dist/log.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,GAAG,QAAQ,EACzB,KAAK,EAAE,QAAQ,EACf,GAAG,CAAC,EAAE,MAAM,GACX,MAAM,CAAC;AACV,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,GAAG,QAAQ,EACzB,KAAK,EAAE,QAAQ,EACf,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,kBAAkB,CAAC;AA2BtB;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACtE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACrE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACrE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;CACvE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACjD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAChD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAChD,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;CAClD,CAAC;AAEF,cAAc;AACd,QAAA,MAAM,UAAU,6CAA8C,CAAC;AAE/D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,GAAG,QAAQ,EACzB,KAAK,EAAE,QAAQ,EACf,GAAG,CAAC,EAAE,MAAM,GACX,MAAM,CAAC;AACV,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,GAAG,QAAQ,EACzB,KAAK,EAAE,QAAQ,EACf,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,kBAAkB,CAAC;AA2BtB;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACtE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACrE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACrE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;CACvE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACjD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAChD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAChD,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;CAClD,CAAC;AAEF,cAAc;AACd,QAAA,MAAM,UAAU,6CAA8C,CAAC;AAE/D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AA8EnD;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,iBAAiB,GAAG,uBAAuB,EAClD,MAAM,EAAE,MAAM,QAKf"}
|
package/dist/log.js
CHANGED
|
@@ -22,22 +22,32 @@ export function createLogger(side, level = "debug", nid, rqid) {
|
|
|
22
22
|
}
|
|
23
23
|
/** @source */
|
|
24
24
|
const LOG_LEVELS = ["debug", "info", "warn", "error"];
|
|
25
|
-
|
|
25
|
+
const PATCHABLE_LOG_METHODS = [
|
|
26
|
+
"debug",
|
|
27
|
+
"info",
|
|
28
|
+
"warn",
|
|
29
|
+
"error",
|
|
30
|
+
"log",
|
|
31
|
+
];
|
|
32
|
+
function logger(method, side, ids) {
|
|
26
33
|
if (ids === undefined || typeof ids === "string") {
|
|
27
34
|
const nid = ids ?? null;
|
|
28
|
-
return (rqid,
|
|
35
|
+
return (rqid, ...args) => log(method, side, { nid, rqid }, ...args);
|
|
29
36
|
}
|
|
30
|
-
return (
|
|
37
|
+
return (...args) => log(method, side, ids, ...args);
|
|
31
38
|
}
|
|
39
|
+
const originalConsole = PATCHABLE_LOG_METHODS.reduce((result, method) => {
|
|
40
|
+
result[method] = console[method];
|
|
41
|
+
return result;
|
|
42
|
+
}, {});
|
|
32
43
|
/**
|
|
33
44
|
* Send log messages to the console, with a helpful prefix.
|
|
34
|
-
* @param
|
|
45
|
+
* @param method
|
|
35
46
|
* @param side
|
|
36
47
|
* @param ids request ID and node ID
|
|
37
|
-
* @param message
|
|
38
48
|
* @param args passed to console methods directly
|
|
39
49
|
*/
|
|
40
|
-
function log(
|
|
50
|
+
function log(method, side, { rqid, nid }, ...args) {
|
|
41
51
|
const prefix = [
|
|
42
52
|
`[SWARPC ${side}]`,
|
|
43
53
|
rqid ? `%c${rqid}%c` : "",
|
|
@@ -50,16 +60,14 @@ function log(severity, side, { rqid, nid }, message, ...args) {
|
|
|
50
60
|
prefixStyles.push("color: cyan", "color: inherit");
|
|
51
61
|
if (nid)
|
|
52
62
|
prefixStyles.push("color: hotpink", "color: inherit");
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
else if (severity === "error") {
|
|
63
|
-
console.error(prefix, ...prefixStyles, message, ...args);
|
|
63
|
+
return originalConsole[method](prefix, ...prefixStyles, ...args);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @param scope
|
|
68
|
+
*/
|
|
69
|
+
export function injectIntoConsoleGlobal(scope, nodeId) {
|
|
70
|
+
for (const method of PATCHABLE_LOG_METHODS) {
|
|
71
|
+
scope.self.console[method] = logger(method, "server", nodeId);
|
|
64
72
|
}
|
|
65
73
|
}
|
package/dist/nodes.d.ts
CHANGED
|
@@ -9,4 +9,7 @@ export declare function nodeIdFromScope(scope: WorkerGlobalScope, _scopeType?: "
|
|
|
9
9
|
* @source
|
|
10
10
|
*/
|
|
11
11
|
export declare function makeNodeId(): string;
|
|
12
|
+
export declare const serviceWorkerNodeId: "(SW)";
|
|
13
|
+
export declare function isServiceWorkerNodeId(id: string): id is "(SW)";
|
|
14
|
+
export declare function nodeIdOrSW(id: string | undefined): string | typeof serviceWorkerNodeId;
|
|
12
15
|
//# sourceMappingURL=nodes.d.ts.map
|
package/dist/nodes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C;;GAEG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACpC,SAAS,GAAG,MAAM,CA0BpB;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,iBAAiB,EACxB,UAAU,CAAC,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,GAC9C,MAAM,CAMR;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
|
|
1
|
+
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C;;GAEG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACpC,SAAS,GAAG,MAAM,CA0BpB;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,iBAAiB,EACxB,UAAU,CAAC,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,GAC9C,MAAM,CAMR;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,eAAO,MAAM,mBAAmB,EAAG,MAAe,CAAC;AAEnD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,gBAE/C;AAED,wBAAgB,UAAU,CACxB,EAAE,EAAE,MAAM,GAAG,SAAS,GACrB,MAAM,GAAG,OAAO,mBAAmB,CAErC"}
|
package/dist/nodes.js
CHANGED
|
@@ -34,3 +34,10 @@ export function nodeIdFromScope(scope, _scopeType) {
|
|
|
34
34
|
export function makeNodeId() {
|
|
35
35
|
return "N" + Math.random().toString(16).substring(2, 5).toUpperCase();
|
|
36
36
|
}
|
|
37
|
+
export const serviceWorkerNodeId = "(SW)"; // Fixed ID for the service worker, as there's only one
|
|
38
|
+
export function isServiceWorkerNodeId(id) {
|
|
39
|
+
return id === serviceWorkerNodeId;
|
|
40
|
+
}
|
|
41
|
+
export function nodeIdOrSW(id) {
|
|
42
|
+
return id ?? serviceWorkerNodeId;
|
|
43
|
+
}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAyC,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAChF,OAAO,EACL,kBAAkB,EAMlB,uBAAuB,EACvB,gBAAgB,EAChB,WAAW,EACX,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAMpB;;;GAGG;AACH,MAAM,MAAM,YAAY,CAAC,UAAU,SAAS,aAAa,IAAI;IAC3D,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;IAC1B,CAAC,gBAAgB,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,GAAG;KACD,CAAC,IAAI,MAAM,UAAU,GAAG,CACvB,IAAI,EAAE,uBAAuB,CAC3B,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EACtB,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EACzB,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CACzB,KACE,IAAI;CACV,CAAC;AAKF;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,UAAU,SAAS,aAAa,EACrD,UAAU,EAAE,UAAU,EACtB,EACE,QAAkB,EAClB,KAAK,EACL,UAAU,GACX,GAAE;IACD,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;CAC5C,GACL,YAAY,CAAC,UAAU,CAAC,CA6M1B"}
|
package/dist/server.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/// <reference lib="webworker" />
|
|
6
6
|
import { type } from "arktype";
|
|
7
|
-
import { createLogger } from "./log.js";
|
|
7
|
+
import { createLogger, injectIntoConsoleGlobal } from "./log.js";
|
|
8
8
|
import { PayloadHeaderSchema, PayloadInitializeSchema, PayloadSchema, zImplementations, zProcedures, } from "./types.js";
|
|
9
9
|
import { findTransferables } from "./utils.js";
|
|
10
10
|
import { FauxLocalStorage } from "./localstorage.js";
|
|
@@ -85,9 +85,10 @@ export function Server(procedures, { loglevel = "debug", scope, _scopeType, } =
|
|
|
85
85
|
};
|
|
86
86
|
const listener = async (event) => {
|
|
87
87
|
if (PayloadInitializeSchema.allows(event.data)) {
|
|
88
|
-
const { localStorageData } = event.data;
|
|
88
|
+
const { localStorageData, nodeId } = event.data;
|
|
89
89
|
l.debug(null, "Setting up faux localStorage", localStorageData);
|
|
90
90
|
new FauxLocalStorage(localStorageData).register(scope);
|
|
91
|
+
injectIntoConsoleGlobal(scope, nodeId);
|
|
91
92
|
return;
|
|
92
93
|
}
|
|
93
94
|
// Decode the payload
|
|
@@ -120,7 +121,7 @@ export function Server(procedures, { loglevel = "debug", scope, _scopeType, } =
|
|
|
120
121
|
}
|
|
121
122
|
// Define payload schema for incoming messages
|
|
122
123
|
const payload = PayloadSchema(type(`"${functionName}"`), schemas.input, schemas.progress, schemas.success).assert(event.data);
|
|
123
|
-
if ("
|
|
124
|
+
if ("isInitializeRequest" in payload)
|
|
124
125
|
throw "Unreachable: #initialize request payload should've been handled already";
|
|
125
126
|
// Handle abortion requests (pro-choice ftw!!)
|
|
126
127
|
if (payload.abort) {
|
|
@@ -142,6 +143,7 @@ export function Server(procedures, { loglevel = "debug", scope, _scopeType, } =
|
|
|
142
143
|
// l.debug(requestId, `Progress for ${functionName}`, progress);
|
|
143
144
|
await postMsg({ progress });
|
|
144
145
|
}, {
|
|
146
|
+
nodeId,
|
|
145
147
|
abortSignal: abortControllers.get(requestId)?.signal,
|
|
146
148
|
logger: createLogger("server", loglevel, nodeId, requestId),
|
|
147
149
|
});
|
package/dist/types.d.ts
CHANGED
|
@@ -74,6 +74,10 @@ tools: {
|
|
|
74
74
|
* Logger instance to use for logging messages related to this procedure call, using the same format as SWARPC's built-in logging.
|
|
75
75
|
*/
|
|
76
76
|
logger: RequestBoundLogger;
|
|
77
|
+
/**
|
|
78
|
+
* ID of the Node the request is being processed on.
|
|
79
|
+
*/
|
|
80
|
+
nodeId: string;
|
|
77
81
|
}) => Promise<S["inferIn"]>;
|
|
78
82
|
/**
|
|
79
83
|
* Declarations of procedures by name.
|
|
@@ -108,7 +112,9 @@ export type Hooks<Procedures extends ProceduresMap> = {
|
|
|
108
112
|
export declare const PayloadInitializeSchema: import("arktype/internal/methods/object.ts").ObjectType<{
|
|
109
113
|
by: "sw&rpc";
|
|
110
114
|
functionName: "#initialize";
|
|
115
|
+
isInitializeRequest: true;
|
|
111
116
|
localStorageData: Record<string, unknown>;
|
|
117
|
+
nodeId: string;
|
|
112
118
|
}, {}>;
|
|
113
119
|
export type PayloadInitialize = typeof PayloadInitializeSchema.infer;
|
|
114
120
|
/**
|
|
@@ -187,12 +193,16 @@ export declare const PayloadSchema: import("arktype").Generic<[["Name", string],
|
|
|
187
193
|
PayloadInitializeSchema: import("arktype/internal/methods/object.ts").ObjectType<{
|
|
188
194
|
by: "sw&rpc";
|
|
189
195
|
functionName: "#initialize";
|
|
196
|
+
isInitializeRequest: true;
|
|
190
197
|
localStorageData: Record<string, unknown>;
|
|
198
|
+
nodeId: string;
|
|
191
199
|
}, {}> & {
|
|
192
200
|
readonly " brand": [import("arktype/internal/methods/object.ts").ObjectType<{
|
|
193
201
|
by: "sw&rpc";
|
|
194
202
|
functionName: "#initialize";
|
|
203
|
+
isInitializeRequest: true;
|
|
195
204
|
localStorageData: Record<string, unknown>;
|
|
205
|
+
nodeId: string;
|
|
196
206
|
}, {}>, "unparsed"];
|
|
197
207
|
};
|
|
198
208
|
} & {}>;
|
|
@@ -220,19 +230,25 @@ export declare const PayloadSchema: import("arktype").Generic<[["Name", string],
|
|
|
220
230
|
PayloadInitializeSchema: import("arktype/internal/methods/object.ts").ObjectType<{
|
|
221
231
|
by: "sw&rpc";
|
|
222
232
|
functionName: "#initialize";
|
|
233
|
+
isInitializeRequest: true;
|
|
223
234
|
localStorageData: Record<string, unknown>;
|
|
235
|
+
nodeId: string;
|
|
224
236
|
}, {}> & {
|
|
225
237
|
readonly " brand": [import("arktype/internal/methods/object.ts").ObjectType<{
|
|
226
238
|
by: "sw&rpc";
|
|
227
239
|
functionName: "#initialize";
|
|
240
|
+
isInitializeRequest: true;
|
|
228
241
|
localStorageData: Record<string, unknown>;
|
|
242
|
+
nodeId: string;
|
|
229
243
|
}, {}>, "unparsed"];
|
|
230
244
|
};
|
|
231
245
|
} & {}>;
|
|
232
246
|
PayloadInitializeSchema: {
|
|
233
247
|
by: "sw&rpc";
|
|
234
248
|
functionName: "#initialize";
|
|
249
|
+
isInitializeRequest: true;
|
|
235
250
|
localStorageData: Record<string, unknown>;
|
|
251
|
+
nodeId: string;
|
|
236
252
|
};
|
|
237
253
|
}, {
|
|
238
254
|
PayloadCoreSchema: import("arktype/internal/scope.ts").bindGenericToScope<import("@ark/schema").GenericAst<[["I", unknown], ["P", unknown], ["S", unknown]], {
|
|
@@ -265,12 +281,16 @@ export declare const PayloadSchema: import("arktype").Generic<[["Name", string],
|
|
|
265
281
|
PayloadInitializeSchema: import("arktype/internal/methods/object.ts").ObjectType<{
|
|
266
282
|
by: "sw&rpc";
|
|
267
283
|
functionName: "#initialize";
|
|
284
|
+
isInitializeRequest: true;
|
|
268
285
|
localStorageData: Record<string, unknown>;
|
|
286
|
+
nodeId: string;
|
|
269
287
|
}, {}> & {
|
|
270
288
|
readonly " brand": [import("arktype/internal/methods/object.ts").ObjectType<{
|
|
271
289
|
by: "sw&rpc";
|
|
272
290
|
functionName: "#initialize";
|
|
291
|
+
isInitializeRequest: true;
|
|
273
292
|
localStorageData: Record<string, unknown>;
|
|
293
|
+
nodeId: string;
|
|
274
294
|
}, {}>, "unparsed"];
|
|
275
295
|
};
|
|
276
296
|
} & {}>;
|
|
@@ -298,19 +318,25 @@ export declare const PayloadSchema: import("arktype").Generic<[["Name", string],
|
|
|
298
318
|
PayloadInitializeSchema: import("arktype/internal/methods/object.ts").ObjectType<{
|
|
299
319
|
by: "sw&rpc";
|
|
300
320
|
functionName: "#initialize";
|
|
321
|
+
isInitializeRequest: true;
|
|
301
322
|
localStorageData: Record<string, unknown>;
|
|
323
|
+
nodeId: string;
|
|
302
324
|
}, {}> & {
|
|
303
325
|
readonly " brand": [import("arktype/internal/methods/object.ts").ObjectType<{
|
|
304
326
|
by: "sw&rpc";
|
|
305
327
|
functionName: "#initialize";
|
|
328
|
+
isInitializeRequest: true;
|
|
306
329
|
localStorageData: Record<string, unknown>;
|
|
330
|
+
nodeId: string;
|
|
307
331
|
}, {}>, "unparsed"];
|
|
308
332
|
};
|
|
309
333
|
} & {}>;
|
|
310
334
|
PayloadInitializeSchema: {
|
|
311
335
|
by: "sw&rpc";
|
|
312
336
|
functionName: "#initialize";
|
|
337
|
+
isInitializeRequest: true;
|
|
313
338
|
localStorageData: Record<string, unknown>;
|
|
339
|
+
nodeId: string;
|
|
314
340
|
};
|
|
315
341
|
}>;
|
|
316
342
|
/**
|
|
@@ -330,7 +356,9 @@ export type ClientMethod<P extends Procedure<Type, Type, Type>> = ((input: P["in
|
|
|
330
356
|
* Returns an array of results, one for each node the request was sent to.
|
|
331
357
|
* Each result is a {@link PromiseSettledResult}, with also an additional property, the node ID of the request
|
|
332
358
|
*/
|
|
333
|
-
broadcast: (input: P["input"]["inferIn"], onProgress?: (
|
|
359
|
+
broadcast: (input: P["input"]["inferIn"], onProgress?: (
|
|
360
|
+
/** Map of node IDs to their progress updates */
|
|
361
|
+
progresses: Map<string, P["progress"]["inferOut"]>) => void,
|
|
334
362
|
/** Number of nodes to send the request to. Leave undefined to send to all nodes */
|
|
335
363
|
nodes?: number) => Promise<Array<PromiseSettledResult<P["success"]["inferOut"]> & {
|
|
336
364
|
node: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C;;GAEG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC,SAAS,IAAI,IAAI;IACtE;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC;IACT;;;OAGG;IACH,QAAQ,EAAE,CAAC,CAAC;IACZ;;OAEG;IACH,OAAO,EAAE,CAAC,CAAC;IACX;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,aAAa,CAAC;CACnD,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,GAAG,OAAO,IAAI;IAC3C,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpB;;;OAGG;IACH,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,CACjC,CAAC,SAAS,IAAI,EACd,CAAC,SAAS,IAAI,EACd,CAAC,SAAS,IAAI,IACZ;AACF;;GAEG;AACH,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC;AACpB;;GAEG;AACH,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI;AAC5C;;GAEG;AACH,KAAK,EAAE;IACL;;OAEG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;OAEG;IACH,MAAM,EAAE,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swarpc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Full type-safe RPC library for service worker -- move things off of the UI thread with ease!",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"service-workers",
|
|
@@ -40,12 +40,14 @@
|
|
|
40
40
|
"typedoc:withplugins": "npm run typedoc:plugins && npm run typedoc",
|
|
41
41
|
"prepare": "husky"
|
|
42
42
|
},
|
|
43
|
-
"
|
|
43
|
+
"peerDependencies": {
|
|
44
44
|
"arktype": "^2.1.22"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@8hobbies/typedoc-plugin-plausible": "^2.2.0",
|
|
48
|
+
"@playwright/test": "^1.55.0",
|
|
48
49
|
"@vitest/web-worker": "^3.2.4",
|
|
50
|
+
"date-fns": "^4.1.0",
|
|
49
51
|
"husky": "^9.1.7",
|
|
50
52
|
"kacl": "^1.1.1",
|
|
51
53
|
"knip": "^5.63.1",
|
package/src/client.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
type Logger,
|
|
10
10
|
type LogLevel,
|
|
11
11
|
} from "./log.js";
|
|
12
|
-
import { makeNodeId, whoToSendTo } from "./nodes.js";
|
|
12
|
+
import { makeNodeId, nodeIdOrSW, whoToSendTo } from "./nodes.js";
|
|
13
13
|
import {
|
|
14
14
|
ClientMethod,
|
|
15
15
|
Hooks,
|
|
@@ -186,7 +186,7 @@ export function Client<Procedures extends ProceduresMap>(
|
|
|
186
186
|
nodeId ??= whoToSendTo(nodes, pendingRequests);
|
|
187
187
|
const node = nodes && nodeId ? nodes[nodeId] : undefined;
|
|
188
188
|
|
|
189
|
-
const l = createLogger("client", loglevel, nodeId
|
|
189
|
+
const l = createLogger("client", loglevel, nodeIdOrSW(nodeId), requestId);
|
|
190
190
|
|
|
191
191
|
return new Promise((resolve, reject) => {
|
|
192
192
|
// Store promise handlers (as well as progress updates handler)
|
|
@@ -217,26 +217,37 @@ export function Client<Procedures extends ProceduresMap>(
|
|
|
217
217
|
instance[functionName] = _runProcedure;
|
|
218
218
|
instance[functionName]!.broadcast = async (
|
|
219
219
|
input,
|
|
220
|
-
|
|
220
|
+
onProgresses,
|
|
221
221
|
nodesCount,
|
|
222
222
|
) => {
|
|
223
223
|
let nodesToUse: Array<string | undefined> = [undefined];
|
|
224
224
|
if (nodes) nodesToUse = Object.keys(nodes);
|
|
225
225
|
if (nodesCount) nodesToUse = nodesToUse.slice(0, nodesCount);
|
|
226
226
|
|
|
227
|
+
const progresses = new Map<string, unknown>();
|
|
228
|
+
|
|
229
|
+
function onProgress(nodeId: string | undefined) {
|
|
230
|
+
if (!onProgresses) return (_: unknown) => {};
|
|
231
|
+
|
|
232
|
+
return (progress: unknown) => {
|
|
233
|
+
progresses.set(nodeIdOrSW(nodeId), progress);
|
|
234
|
+
onProgresses(progresses);
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
227
238
|
const results = await Promise.allSettled(
|
|
228
239
|
nodesToUse.map(async (id) =>
|
|
229
|
-
_runProcedure(input, onProgress, undefined, id),
|
|
240
|
+
_runProcedure(input, onProgress(id), undefined, id),
|
|
230
241
|
),
|
|
231
242
|
);
|
|
232
243
|
|
|
233
|
-
return results.map((r, i) => ({ ...r, node: nodesToUse[i]
|
|
244
|
+
return results.map((r, i) => ({ ...r, node: nodeIdOrSW(nodesToUse[i]) }));
|
|
234
245
|
};
|
|
235
246
|
instance[functionName]!.cancelable = (input, onProgress) => {
|
|
236
247
|
const requestId = makeRequestId();
|
|
237
248
|
const nodeId = whoToSendTo(nodes, pendingRequests);
|
|
238
249
|
|
|
239
|
-
const l = createLogger("client", loglevel, nodeId
|
|
250
|
+
const l = createLogger("client", loglevel, nodeIdOrSW(nodeId), requestId);
|
|
240
251
|
|
|
241
252
|
return {
|
|
242
253
|
request: _runProcedure(input, onProgress, requestId, nodeId),
|
|
@@ -336,7 +347,7 @@ export function postMessageSync<Procedures extends ProceduresMap>(
|
|
|
336
347
|
export async function startClientListener<Procedures extends ProceduresMap>(
|
|
337
348
|
ctx: Context<Procedures>,
|
|
338
349
|
) {
|
|
339
|
-
if (_clientListenerStarted.has(ctx.nodeId
|
|
350
|
+
if (_clientListenerStarted.has(nodeIdOrSW(ctx.nodeId))) return;
|
|
340
351
|
|
|
341
352
|
const { logger: l, node: worker } = ctx;
|
|
342
353
|
|
|
@@ -367,7 +378,7 @@ export async function startClientListener<Procedures extends ProceduresMap>(
|
|
|
367
378
|
const payload = eventData as Payload<Procedures>;
|
|
368
379
|
|
|
369
380
|
// Ignore #initialize request, it's client->server only
|
|
370
|
-
if ("
|
|
381
|
+
if ("isInitializeRequest" in payload) {
|
|
371
382
|
l.warn(null, "Ignoring unexpected #initialize from server", payload);
|
|
372
383
|
return;
|
|
373
384
|
}
|
|
@@ -410,13 +421,15 @@ export async function startClientListener<Procedures extends ProceduresMap>(
|
|
|
410
421
|
w.addEventListener("message", listener);
|
|
411
422
|
}
|
|
412
423
|
|
|
413
|
-
_clientListenerStarted.add(ctx.nodeId
|
|
424
|
+
_clientListenerStarted.add(nodeIdOrSW(ctx.nodeId));
|
|
414
425
|
|
|
415
426
|
// Recursive terminal case is ensured by calling this *after* _clientListenerStarted is set to true: startClientListener() will therefore not be called in postMessage() again.
|
|
416
427
|
await postMessage(ctx, {
|
|
417
428
|
by: "sw&rpc",
|
|
418
429
|
functionName: "#initialize",
|
|
430
|
+
isInitializeRequest: true,
|
|
419
431
|
localStorageData: ctx.localStorage,
|
|
432
|
+
nodeId: nodeIdOrSW(ctx.nodeId),
|
|
420
433
|
});
|
|
421
434
|
}
|
|
422
435
|
|
package/src/log.ts
CHANGED
|
@@ -65,51 +65,65 @@ const LOG_LEVELS = ["debug", "info", "warn", "error"] as const;
|
|
|
65
65
|
|
|
66
66
|
export type LogLevel = (typeof LOG_LEVELS)[number];
|
|
67
67
|
|
|
68
|
+
const PATCHABLE_LOG_METHODS = [
|
|
69
|
+
"debug",
|
|
70
|
+
"info",
|
|
71
|
+
"warn",
|
|
72
|
+
"error",
|
|
73
|
+
"log",
|
|
74
|
+
] as const;
|
|
75
|
+
type LogMethod = (typeof PATCHABLE_LOG_METHODS)[number];
|
|
76
|
+
|
|
68
77
|
/**
|
|
69
78
|
* Creates partially-applied logging functions given the first 2 or 3 args
|
|
70
|
-
* @param
|
|
79
|
+
* @param method
|
|
71
80
|
* @param side
|
|
72
81
|
* @param ids request ID, {reqid, nodeId}, or null to not bind it
|
|
73
82
|
* @returns
|
|
74
83
|
*/
|
|
75
84
|
function logger(
|
|
76
|
-
|
|
85
|
+
method: LogMethod,
|
|
77
86
|
side: "server" | "client",
|
|
78
87
|
ids: { rqid: string; nid: string },
|
|
79
|
-
): (
|
|
88
|
+
): (...args: any[]) => void;
|
|
80
89
|
function logger(
|
|
81
|
-
|
|
90
|
+
method: LogMethod,
|
|
82
91
|
side: "server" | "client",
|
|
83
92
|
nid?: string,
|
|
84
|
-
): (rqid: string | null,
|
|
93
|
+
): (rqid: string | null, ...args: any[]) => void;
|
|
85
94
|
function logger(
|
|
86
|
-
|
|
95
|
+
method: LogMethod,
|
|
87
96
|
side: "server" | "client",
|
|
88
97
|
ids?: string | { rqid: string; nid: string },
|
|
89
98
|
) {
|
|
90
99
|
if (ids === undefined || typeof ids === "string") {
|
|
91
100
|
const nid = ids ?? null;
|
|
92
|
-
return (rqid: string | null,
|
|
93
|
-
log(
|
|
101
|
+
return (rqid: string | null, ...args: any[]) =>
|
|
102
|
+
log(method, side, { nid, rqid }, ...args);
|
|
94
103
|
}
|
|
95
104
|
|
|
96
|
-
return (
|
|
97
|
-
log(severity, side, ids, message, ...args);
|
|
105
|
+
return (...args: any[]) => log(method, side, ids, ...args);
|
|
98
106
|
}
|
|
99
107
|
|
|
108
|
+
const originalConsole = PATCHABLE_LOG_METHODS.reduce(
|
|
109
|
+
(result, method) => {
|
|
110
|
+
result[method] = console[method];
|
|
111
|
+
return result;
|
|
112
|
+
},
|
|
113
|
+
{} as Pick<typeof console, LogMethod>,
|
|
114
|
+
);
|
|
115
|
+
|
|
100
116
|
/**
|
|
101
117
|
* Send log messages to the console, with a helpful prefix.
|
|
102
|
-
* @param
|
|
118
|
+
* @param method
|
|
103
119
|
* @param side
|
|
104
120
|
* @param ids request ID and node ID
|
|
105
|
-
* @param message
|
|
106
121
|
* @param args passed to console methods directly
|
|
107
122
|
*/
|
|
108
123
|
function log(
|
|
109
|
-
|
|
124
|
+
method: LogMethod,
|
|
110
125
|
side: "server" | "client",
|
|
111
126
|
{ rqid, nid }: { rqid: string | null; nid: string | null },
|
|
112
|
-
message: string,
|
|
113
127
|
...args: any[]
|
|
114
128
|
) {
|
|
115
129
|
const prefix = [
|
|
@@ -124,13 +138,18 @@ function log(
|
|
|
124
138
|
if (rqid) prefixStyles.push("color: cyan", "color: inherit");
|
|
125
139
|
if (nid) prefixStyles.push("color: hotpink", "color: inherit");
|
|
126
140
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
141
|
+
return originalConsole[method](prefix, ...prefixStyles, ...args);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
*
|
|
146
|
+
* @param scope
|
|
147
|
+
*/
|
|
148
|
+
export function injectIntoConsoleGlobal(
|
|
149
|
+
scope: WorkerGlobalScope | SharedWorkerGlobalScope,
|
|
150
|
+
nodeId: string,
|
|
151
|
+
) {
|
|
152
|
+
for (const method of PATCHABLE_LOG_METHODS) {
|
|
153
|
+
scope.self.console[method] = logger(method, "server", nodeId);
|
|
135
154
|
}
|
|
136
155
|
}
|
package/src/nodes.ts
CHANGED
|
@@ -53,3 +53,15 @@ export function nodeIdFromScope(
|
|
|
53
53
|
export function makeNodeId(): string {
|
|
54
54
|
return "N" + Math.random().toString(16).substring(2, 5).toUpperCase();
|
|
55
55
|
}
|
|
56
|
+
|
|
57
|
+
export const serviceWorkerNodeId = "(SW)" as const; // Fixed ID for the service worker, as there's only one
|
|
58
|
+
|
|
59
|
+
export function isServiceWorkerNodeId(id: string) {
|
|
60
|
+
return id === serviceWorkerNodeId;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function nodeIdOrSW(
|
|
64
|
+
id: string | undefined,
|
|
65
|
+
): string | typeof serviceWorkerNodeId {
|
|
66
|
+
return id ?? serviceWorkerNodeId;
|
|
67
|
+
}
|
package/src/server.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
/// <reference lib="webworker" />
|
|
7
7
|
import { type } from "arktype";
|
|
8
|
-
import { createLogger, type LogLevel } from "./log.js";
|
|
8
|
+
import { createLogger, injectIntoConsoleGlobal, type LogLevel } from "./log.js";
|
|
9
9
|
import {
|
|
10
10
|
ImplementationsMap,
|
|
11
11
|
Payload,
|
|
@@ -141,9 +141,10 @@ export function Server<Procedures extends ProceduresMap>(
|
|
|
141
141
|
event: MessageEvent<any> | ExtendableMessageEvent,
|
|
142
142
|
): Promise<void> => {
|
|
143
143
|
if (PayloadInitializeSchema.allows(event.data)) {
|
|
144
|
-
const { localStorageData } = event.data;
|
|
144
|
+
const { localStorageData, nodeId } = event.data;
|
|
145
145
|
l.debug(null, "Setting up faux localStorage", localStorageData);
|
|
146
146
|
new FauxLocalStorage(localStorageData).register(scope);
|
|
147
|
+
injectIntoConsoleGlobal(scope, nodeId);
|
|
147
148
|
return;
|
|
148
149
|
}
|
|
149
150
|
|
|
@@ -194,7 +195,7 @@ export function Server<Procedures extends ProceduresMap>(
|
|
|
194
195
|
schemas.success,
|
|
195
196
|
).assert(event.data);
|
|
196
197
|
|
|
197
|
-
if ("
|
|
198
|
+
if ("isInitializeRequest" in payload)
|
|
198
199
|
throw "Unreachable: #initialize request payload should've been handled already";
|
|
199
200
|
|
|
200
201
|
// Handle abortion requests (pro-choice ftw!!)
|
|
@@ -225,6 +226,7 @@ export function Server<Procedures extends ProceduresMap>(
|
|
|
225
226
|
await postMsg({ progress });
|
|
226
227
|
},
|
|
227
228
|
{
|
|
229
|
+
nodeId,
|
|
228
230
|
abortSignal: abortControllers.get(requestId)?.signal,
|
|
229
231
|
logger: createLogger("server", loglevel, nodeId, requestId),
|
|
230
232
|
},
|
package/src/types.ts
CHANGED
|
@@ -82,6 +82,10 @@ export type ProcedureImplementation<
|
|
|
82
82
|
* Logger instance to use for logging messages related to this procedure call, using the same format as SWARPC's built-in logging.
|
|
83
83
|
*/
|
|
84
84
|
logger: RequestBoundLogger;
|
|
85
|
+
/**
|
|
86
|
+
* ID of the Node the request is being processed on.
|
|
87
|
+
*/
|
|
88
|
+
nodeId: string;
|
|
85
89
|
},
|
|
86
90
|
) => Promise<S["inferIn"]>;
|
|
87
91
|
|
|
@@ -134,7 +138,9 @@ export type Hooks<Procedures extends ProceduresMap> = {
|
|
|
134
138
|
export const PayloadInitializeSchema = type({
|
|
135
139
|
by: '"sw&rpc"',
|
|
136
140
|
functionName: '"#initialize"',
|
|
141
|
+
isInitializeRequest: "true",
|
|
137
142
|
localStorageData: "Record<string, unknown>",
|
|
143
|
+
nodeId: "string",
|
|
138
144
|
});
|
|
139
145
|
|
|
140
146
|
export type PayloadInitialize = typeof PayloadInitializeSchema.infer;
|
|
@@ -229,7 +235,10 @@ export type ClientMethod<P extends Procedure<Type, Type, Type>> = ((
|
|
|
229
235
|
*/
|
|
230
236
|
broadcast: (
|
|
231
237
|
input: P["input"]["inferIn"],
|
|
232
|
-
onProgress?: (
|
|
238
|
+
onProgress?: (
|
|
239
|
+
/** Map of node IDs to their progress updates */
|
|
240
|
+
progresses: Map<string, P["progress"]["inferOut"]>,
|
|
241
|
+
) => void,
|
|
233
242
|
/** Number of nodes to send the request to. Leave undefined to send to all nodes */
|
|
234
243
|
nodes?: number,
|
|
235
244
|
) => Promise<
|