@xentobias/worker-rpc 1.0.7 → 1.0.10

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.
@@ -140,8 +140,13 @@ export declare class Endpoint {
140
140
  shutdown(options?: ShutdownOptions): Promise<ShutdownResult>;
141
141
  /**
142
142
  * Release this endpoint and clean up resources
143
+ *
144
+ * @param options - Release options
145
+ * @param options.silent - If true, don't notify the remote endpoint (used when remote already released)
143
146
  */
144
- release(): void;
147
+ release(options?: {
148
+ silent?: boolean;
149
+ }): void;
145
150
  /**
146
151
  * Get the underlying message target
147
152
  */
@@ -159,4 +164,3 @@ export declare function isMessagePort(value: unknown): value is MessagePort;
159
164
  * Create an endpoint for a worker or message port
160
165
  */
161
166
  export declare function createEndpoint(target: MessageTarget, options?: EndpointOptions): Endpoint;
162
- //# sourceMappingURL=endpoint.d.ts.map
package/dist/id.d.ts CHANGED
@@ -6,4 +6,3 @@ export declare function generateCallId(): CallId;
6
6
  /** Unique identifier for callback functions */
7
7
  export type CallbackId = `cb:${string}`;
8
8
  export declare function generateCallbackId(): CallbackId;
9
- //# sourceMappingURL=id.d.ts.map
package/dist/index.d.ts CHANGED
@@ -40,4 +40,3 @@ export declare function expose(api: object, options?: EndpointOptions): Endpoint
40
40
  * ```
41
41
  */
42
42
  export declare function remote<T extends object>(worker: MessageTarget, options?: EndpointOptions): RemoteObject<T>;
43
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,581 +1,2 @@
1
1
  // @bun
2
- // src/types.ts
3
- var MessageType;
4
- ((MessageType2) => {
5
- MessageType2[MessageType2["Call"] = 0] = "Call";
6
- MessageType2[MessageType2["Result"] = 1] = "Result";
7
- MessageType2[MessageType2["Error"] = 2] = "Error";
8
- MessageType2[MessageType2["Callback"] = 3] = "Callback";
9
- MessageType2[MessageType2["CallbackRelease"] = 4] = "CallbackRelease";
10
- MessageType2[MessageType2["EndpointRelease"] = 5] = "EndpointRelease";
11
- })(MessageType ||= {});
12
-
13
- // src/id.ts
14
- var instanceId = Math.random().toString(36).slice(2, 8);
15
- var counter = 0;
16
- function generateId() {
17
- return `${instanceId}:${++counter}`;
18
- }
19
- function generateCallId() {
20
- return `c:${generateId()}`;
21
- }
22
- function generateCallbackId() {
23
- return `cb:${generateId()}`;
24
- }
25
-
26
- // src/endpoint.ts
27
- var DEFAULT_TIMEOUT = 30000;
28
-
29
- class Endpoint {
30
- target;
31
- options;
32
- exposedApi = null;
33
- exposeOptions = {};
34
- pendingCalls = new Map;
35
- callbacks = new Map;
36
- remoteCallbacks = new Map;
37
- boundMessageHandler;
38
- released = false;
39
- constructor(target, options = {}) {
40
- this.target = target;
41
- this.options = {
42
- timeout: options.timeout ?? DEFAULT_TIMEOUT,
43
- onError: options.onError ?? console.error,
44
- debug: options.debug ?? false,
45
- onRelease: options.onRelease ?? (() => {})
46
- };
47
- this.boundMessageHandler = this.handleMessage.bind(this);
48
- this.attachListener();
49
- }
50
- attachListener() {
51
- if (this.target.addEventListener) {
52
- this.target.addEventListener("message", this.boundMessageHandler);
53
- } else if (this.target.onmessage !== undefined) {
54
- this.target.onmessage = this.boundMessageHandler;
55
- }
56
- }
57
- detachListener() {
58
- if (this.target.removeEventListener) {
59
- this.target.removeEventListener("message", this.boundMessageHandler);
60
- } else if (this.target.onmessage !== undefined) {
61
- this.target.onmessage = null;
62
- }
63
- }
64
- debug(...args) {
65
- if (this.options.debug) {
66
- console.log("[worker-rpc]", ...args);
67
- }
68
- }
69
- expose(api, options = {}) {
70
- this.exposedApi = api;
71
- this.exposeOptions = {
72
- maxDepth: options.maxDepth ?? 10
73
- };
74
- }
75
- handleMessage(event) {
76
- const message = event.data;
77
- if (typeof message !== "object" || message === null || !("t" in message)) {
78
- return;
79
- }
80
- this.debug("received", MessageType[message.t], message);
81
- switch (message.t) {
82
- case 0 /* Call */:
83
- this.handleCall(message);
84
- break;
85
- case 1 /* Result */:
86
- this.handleResult(message);
87
- break;
88
- case 2 /* Error */:
89
- this.handleError(message);
90
- break;
91
- case 3 /* Callback */:
92
- this.handleCallback(message);
93
- break;
94
- case 4 /* CallbackRelease */:
95
- this.handleCallbackRelease(message);
96
- break;
97
- case 5 /* EndpointRelease */:
98
- this.handleEndpointRelease();
99
- break;
100
- }
101
- }
102
- async handleCall(message) {
103
- const { id, p: path, a: args, c: callbackMap } = message;
104
- try {
105
- const { method, thisArg } = this.resolveMethod(path);
106
- if (typeof method !== "function") {
107
- throw new Error(`Method not found: ${path.join(".")}`);
108
- }
109
- const resolvedArgs = args.map((arg, index) => {
110
- const callbackId = callbackMap?.[index];
111
- if (callbackId) {
112
- return this.createRemoteCallback(callbackId);
113
- }
114
- return arg;
115
- });
116
- const result = await method.apply(thisArg, resolvedArgs);
117
- if (isFunction(result)) {
118
- const callbackId = this.registerCallback(result);
119
- this.send({
120
- t: 1 /* Result */,
121
- id,
122
- v: null,
123
- c: callbackId
124
- });
125
- } else {
126
- this.send({
127
- t: 1 /* Result */,
128
- id,
129
- v: result
130
- });
131
- }
132
- } catch (error) {
133
- const err = error instanceof Error ? error : new Error(String(error));
134
- this.send({
135
- t: 2 /* Error */,
136
- id,
137
- e: err.message,
138
- n: err.name,
139
- s: err.stack
140
- });
141
- }
142
- }
143
- resolveMethod(path) {
144
- if (!this.exposedApi) {
145
- throw new Error("No API exposed");
146
- }
147
- let current = this.exposedApi;
148
- let parent = null;
149
- for (let i = 0;i < path.length; i++) {
150
- const key = path[i];
151
- if (current === null || current === undefined) {
152
- throw new Error(`Cannot access property '${key}' of ${current}`);
153
- }
154
- if (key === undefined) {
155
- throw new Error(`Invalid path at index ${i}`);
156
- }
157
- parent = current;
158
- current = current[key];
159
- if (i >= (this.exposeOptions.maxDepth ?? 10)) {
160
- throw new Error(`Maximum nesting depth exceeded`);
161
- }
162
- }
163
- return { target: this.exposedApi, method: current, thisArg: parent };
164
- }
165
- handleResult(message) {
166
- const pending = this.pendingCalls.get(message.id);
167
- if (!pending) {
168
- this.debug("Received result for unknown call:", message.id);
169
- return;
170
- }
171
- this.pendingCalls.delete(message.id);
172
- if (pending.timer) {
173
- clearTimeout(pending.timer);
174
- }
175
- if (message.c) {
176
- pending.resolve(this.createRemoteCallback(message.c));
177
- } else {
178
- pending.resolve(message.v);
179
- }
180
- }
181
- handleError(message) {
182
- const pending = this.pendingCalls.get(message.id);
183
- if (!pending) {
184
- this.debug("Received error for unknown call:", message.id);
185
- return;
186
- }
187
- this.pendingCalls.delete(message.id);
188
- if (pending.timer) {
189
- clearTimeout(pending.timer);
190
- }
191
- const error = new Error(message.e);
192
- if (message.n) {
193
- error.name = message.n;
194
- }
195
- if (message.s) {
196
- error.stack = message.s;
197
- }
198
- pending.reject(error);
199
- }
200
- async handleCallback(message) {
201
- const { id, c: callbackId, a: args, cb: callbackMap } = message;
202
- const registration = this.callbacks.get(callbackId);
203
- if (!registration) {
204
- this.send({
205
- t: 2 /* Error */,
206
- id,
207
- e: `Callback not found: ${callbackId}`
208
- });
209
- return;
210
- }
211
- try {
212
- const resolvedArgs = args.map((arg, index) => {
213
- const cbId = callbackMap?.[index];
214
- if (cbId) {
215
- return this.createRemoteCallback(cbId);
216
- }
217
- return arg;
218
- });
219
- const result = await registration.fn(...resolvedArgs);
220
- if (registration.remaining > 0) {
221
- registration.remaining--;
222
- if (registration.remaining === 0) {
223
- this.callbacks.delete(callbackId);
224
- }
225
- }
226
- if (isFunction(result)) {
227
- const cbId = this.registerCallback(result);
228
- this.send({
229
- t: 1 /* Result */,
230
- id,
231
- v: null,
232
- c: cbId
233
- });
234
- } else {
235
- this.send({
236
- t: 1 /* Result */,
237
- id,
238
- v: result
239
- });
240
- }
241
- } catch (error) {
242
- const err = error instanceof Error ? error : new Error(String(error));
243
- this.send({
244
- t: 2 /* Error */,
245
- id,
246
- e: err.message,
247
- n: err.name,
248
- s: err.stack
249
- });
250
- }
251
- }
252
- handleCallbackRelease(message) {
253
- for (const callbackId of message.c) {
254
- this.callbacks.delete(callbackId);
255
- }
256
- }
257
- handleEndpointRelease() {
258
- this.debug("Remote endpoint released");
259
- this.options.onRelease();
260
- this.release();
261
- }
262
- registerCallback(fn, remaining = -1) {
263
- const id = generateCallbackId();
264
- this.callbacks.set(id, { fn, remaining });
265
- return id;
266
- }
267
- createRemoteCallback(callbackId) {
268
- let proxy = this.remoteCallbacks.get(callbackId);
269
- if (proxy) {
270
- return proxy;
271
- }
272
- proxy = async (...args) => {
273
- return this.invokeCallback(callbackId, args);
274
- };
275
- this.remoteCallbacks.set(callbackId, proxy);
276
- return proxy;
277
- }
278
- async invokeCallback(callbackId, args) {
279
- const id = generateCallId();
280
- const rawArgs = [];
281
- const callbackMap = {};
282
- const transferables = [];
283
- for (let i = 0;i < args.length; i++) {
284
- const arg = args[i];
285
- if (isFunction(arg)) {
286
- callbackMap[i] = this.registerCallback(arg);
287
- rawArgs.push(null);
288
- } else if (isMessagePort(arg)) {
289
- transferables.push(arg);
290
- rawArgs.push(arg);
291
- } else {
292
- rawArgs.push(arg);
293
- }
294
- }
295
- return new Promise((resolve, reject) => {
296
- const timer = setTimeout(() => {
297
- this.pendingCalls.delete(id);
298
- reject(new Error(`Callback invocation timed out: ${callbackId}`));
299
- }, this.options.timeout);
300
- this.pendingCalls.set(id, { resolve, reject, timer });
301
- const message = {
302
- t: 3 /* Callback */,
303
- id,
304
- c: callbackId,
305
- a: rawArgs,
306
- ...Object.keys(callbackMap).length > 0 && { cb: callbackMap }
307
- };
308
- this.send(message, transferables);
309
- });
310
- }
311
- async call(path, args) {
312
- if (this.released) {
313
- throw new Error("Endpoint has been released");
314
- }
315
- const rawArgs = [];
316
- const callbackMap = {};
317
- const transferables = [];
318
- for (let i = 0;i < args.length; i++) {
319
- const arg = args[i];
320
- switch (true) {
321
- case isFunction(arg): {
322
- callbackMap[i] = this.registerCallback(arg);
323
- rawArgs.push(null);
324
- break;
325
- }
326
- case isMessagePort(arg): {
327
- transferables.push(arg);
328
- rawArgs.push(arg);
329
- break;
330
- }
331
- default: {
332
- rawArgs.push(arg);
333
- break;
334
- }
335
- }
336
- }
337
- const id = generateCallId();
338
- return new Promise((resolve, reject) => {
339
- const timer = setTimeout(() => {
340
- this.pendingCalls.delete(id);
341
- reject(new Error(`Call timed out: ${path.join(".")}`));
342
- }, this.options.timeout);
343
- this.pendingCalls.set(id, { resolve, reject, timer });
344
- const message = {
345
- t: 0 /* Call */,
346
- id,
347
- p: path,
348
- a: rawArgs,
349
- ...Object.keys(callbackMap).length > 0 && { c: callbackMap }
350
- };
351
- this.send(message, transferables);
352
- });
353
- }
354
- send(message, transferables = []) {
355
- this.debug("sending", MessageType[message.t], message);
356
- this.target.postMessage(message, transferables);
357
- }
358
- getPendingCallCount() {
359
- return this.pendingCalls.size;
360
- }
361
- hasPendingCalls() {
362
- return this.pendingCalls.size > 0;
363
- }
364
- async shutdown(options = {}) {
365
- const { timeout = DEFAULT_TIMEOUT } = options;
366
- if (this.released) {
367
- return {
368
- success: true,
369
- timeout: false
370
- };
371
- }
372
- if (!this.hasPendingCalls()) {
373
- this.release();
374
- return {
375
- success: true,
376
- timeout: false
377
- };
378
- }
379
- return new Promise((resolve) => {
380
- let resolved = false;
381
- const complete = (result) => {
382
- if (resolved)
383
- return;
384
- resolved = true;
385
- clearTimeout(timeoutId);
386
- if (!this.released) {
387
- this.release();
388
- }
389
- resolve(result);
390
- };
391
- const timeoutId = setTimeout(() => {
392
- complete({
393
- success: false,
394
- timeout: true
395
- });
396
- }, timeout);
397
- for (const [, pending] of this.pendingCalls) {
398
- const originalResolve = pending.resolve;
399
- const originalReject = pending.reject;
400
- pending.resolve = (value) => {
401
- originalResolve(value);
402
- if (!this.hasPendingCalls()) {
403
- complete({
404
- success: true,
405
- timeout: false
406
- });
407
- }
408
- };
409
- pending.reject = (error) => {
410
- originalReject(error);
411
- if (!this.hasPendingCalls()) {
412
- complete({
413
- success: true,
414
- timeout: false
415
- });
416
- }
417
- };
418
- }
419
- });
420
- }
421
- release() {
422
- if (this.released) {
423
- return;
424
- }
425
- this.released = true;
426
- for (const [, pending] of this.pendingCalls) {
427
- if (pending.timer) {
428
- clearTimeout(pending.timer);
429
- }
430
- pending.reject(new Error("Endpoint released"));
431
- }
432
- this.pendingCalls.clear();
433
- if (this.remoteCallbacks.size > 0) {
434
- const callbackIds = Array.from(this.remoteCallbacks.keys());
435
- this.send({
436
- t: 4 /* CallbackRelease */,
437
- id: generateCallId(),
438
- c: callbackIds
439
- });
440
- this.remoteCallbacks.clear();
441
- }
442
- this.send({
443
- t: 5 /* EndpointRelease */,
444
- id: generateCallId()
445
- });
446
- this.callbacks.clear();
447
- this.detachListener();
448
- }
449
- getTarget() {
450
- return this.target;
451
- }
452
- }
453
- function isFunction(value) {
454
- return typeof value === "function";
455
- }
456
- function isMessagePort(value) {
457
- return typeof MessagePort !== "undefined" && value instanceof MessagePort;
458
- }
459
- function createEndpoint(target, options) {
460
- return new Endpoint(target, options);
461
- }
462
-
463
- // src/proxy.ts
464
- var PATH = Symbol("rpc:path");
465
- var PROXY_ENDPOINT = Symbol("rpc:proxy-endpoint");
466
- var REMOTE_PROXY = Symbol.for("rpc:remote-proxy");
467
- var ENDPOINT = Symbol.for("rpc:endpoint");
468
- var RELEASE = Symbol.for("rpc:release");
469
- var proxyHandler = {
470
- get(target, prop) {
471
- if (prop === REMOTE_PROXY) {
472
- return true;
473
- }
474
- if (prop === ENDPOINT) {
475
- return target[PROXY_ENDPOINT];
476
- }
477
- if (prop === RELEASE) {
478
- return () => {
479
- const endpoint = target[PROXY_ENDPOINT];
480
- endpoint.release();
481
- };
482
- }
483
- if (prop === "then") {
484
- if (target[PATH].length === 0) {
485
- return;
486
- }
487
- const endpoint = target[PROXY_ENDPOINT];
488
- const path = target[PATH];
489
- const promise = endpoint.call(path, []);
490
- return promise.then.bind(promise);
491
- }
492
- if (prop === "toJSON") {
493
- return;
494
- }
495
- if (prop === Symbol.toStringTag || prop === Symbol.iterator || prop === Symbol.asyncIterator || prop === "constructor" || prop === "prototype") {
496
- return;
497
- }
498
- if (typeof prop === "string") {
499
- const endpoint = target[PROXY_ENDPOINT];
500
- const currentPath = target[PATH];
501
- const newPath = [...currentPath, prop];
502
- return createProxyInternal(endpoint, newPath);
503
- }
504
- },
505
- apply(target, _thisArg, args) {
506
- const endpoint = target[PROXY_ENDPOINT];
507
- const path = target[PATH];
508
- return endpoint.call(path, args);
509
- },
510
- set() {
511
- throw new Error("Cannot set properties on a remote proxy");
512
- },
513
- deleteProperty() {
514
- throw new Error("Cannot delete properties on a remote proxy");
515
- },
516
- getPrototypeOf() {
517
- return Function.prototype;
518
- },
519
- has(_target, prop) {
520
- return prop === REMOTE_PROXY || prop === ENDPOINT || prop === RELEASE;
521
- }
522
- };
523
- function createProxyInternal(endpoint, path) {
524
- const target = function() {};
525
- target[PROXY_ENDPOINT] = endpoint;
526
- target[PATH] = path;
527
- return new Proxy(target, proxyHandler);
528
- }
529
- function wrap(endpoint) {
530
- return createProxyInternal(endpoint, []);
531
- }
532
- function isProxy(value) {
533
- if (value === null || value === undefined) {
534
- return false;
535
- }
536
- try {
537
- return value[REMOTE_PROXY] === true;
538
- } catch {
539
- return false;
540
- }
541
- }
542
- function getEndpoint(proxy) {
543
- if (isProxy(proxy)) {
544
- return proxy[ENDPOINT];
545
- }
546
- }
547
- function releaseProxy(proxy) {
548
- if (isProxy(proxy)) {
549
- proxy[RELEASE]();
550
- }
551
- }
552
-
553
- // src/index.ts
554
- function expose(api, options) {
555
- const self = globalThis;
556
- const endpoint2 = createEndpoint(self, options);
557
- endpoint2.expose(api);
558
- return endpoint2;
559
- }
560
- function remote(worker, options) {
561
- const endpoint2 = createEndpoint(worker, options);
562
- return wrap(endpoint2);
563
- }
564
- export {
565
- wrap,
566
- remote,
567
- releaseProxy,
568
- isProxy,
569
- isMessagePort,
570
- isFunction,
571
- getEndpoint,
572
- expose,
573
- createEndpoint,
574
- REMOTE_PROXY,
575
- RELEASE,
576
- PROXY_ENDPOINT,
577
- PATH,
578
- MessageType,
579
- Endpoint,
580
- ENDPOINT
581
- };
2
+ var F;((J)=>{J[J.Call=0]="Call";J[J.Result=1]="Result";J[J.Error=2]="Error";J[J.Callback=3]="Callback";J[J.CallbackRelease=4]="CallbackRelease";J[J.EndpointRelease=5]="EndpointRelease"})(F||={});var v=Math.random().toString(36).slice(2,8),x=0;function _(){return`${v}:${++x}`}function W(){return`c:${_()}`}function f(){return`cb:${_()}`}var N=30000;class h{target;options;exposedApi=null;exposeOptions={};pendingCalls=new Map;callbacks=new Map;remoteCallbacks=new Map;boundMessageHandler;released=!1;constructor(B,z={}){this.target=B,this.options={timeout:z.timeout??N,onError:z.onError??console.error,debug:z.debug??!1,onRelease:z.onRelease??(()=>{})},this.boundMessageHandler=this.handleMessage.bind(this),this.attachListener()}attachListener(){if(this.target.addEventListener)this.target.addEventListener("message",this.boundMessageHandler);else if(this.target.onmessage!==void 0)this.target.onmessage=this.boundMessageHandler}detachListener(){if(this.target.removeEventListener)this.target.removeEventListener("message",this.boundMessageHandler);else if(this.target.onmessage!==void 0)this.target.onmessage=null}debug(...B){if(this.options.debug)console.log("[worker-rpc]",...B)}expose(B,z={}){this.exposedApi=B,this.exposeOptions={maxDepth:z.maxDepth??10}}handleMessage(B){let z=B.data;if(typeof z!=="object"||z===null||!("t"in z))return;switch(this.debug("received",F[z.t],z),z.t){case 0:this.handleCall(z);break;case 1:this.handleResult(z);break;case 2:this.handleError(z);break;case 3:this.handleCallback(z);break;case 4:this.handleCallbackRelease(z);break;case 5:this.handleEndpointRelease();break}}async handleCall(B){let{id:z,p:G,a:Q,c:V}=B;try{let{method:Z,thisArg:J}=this.resolveMethod(G);if(typeof Z!=="function")throw Error(`Method not found: ${G.join(".")}`);let K=Q.map((q,U)=>{let D=V?.[U];if(D)return this.createRemoteCallback(D);return q}),$=await Z.apply(J,K);if(H($)){let q=this.registerCallback($);this.send({t:1,id:z,v:null,c:q})}else this.send({t:1,id:z,v:$})}catch(Z){let J=Z instanceof Error?Z:Error(String(Z));this.send({t:2,id:z,e:J.message,n:J.name,s:J.stack})}}resolveMethod(B){if(!this.exposedApi)throw Error("No API exposed");let z=this.exposedApi,G=null;for(let Q=0;Q<B.length;Q++){let V=B[Q];if(z===null||z===void 0)throw Error(`Cannot access property '${V}' of ${z}`);if(V===void 0)throw Error(`Invalid path at index ${Q}`);if(G=z,z=z[V],Q>=(this.exposeOptions.maxDepth??10))throw Error("Maximum nesting depth exceeded")}return{target:this.exposedApi,method:z,thisArg:G}}handleResult(B){let z=this.pendingCalls.get(B.id);if(!z){this.debug("Received result for unknown call:",B.id);return}if(this.pendingCalls.delete(B.id),z.timer)clearTimeout(z.timer);if(B.c)z.resolve(this.createRemoteCallback(B.c));else z.resolve(B.v)}handleError(B){let z=this.pendingCalls.get(B.id);if(!z){this.debug("Received error for unknown call:",B.id);return}if(this.pendingCalls.delete(B.id),z.timer)clearTimeout(z.timer);let G=Error(B.e);if(B.n)G.name=B.n;if(B.s)G.stack=B.s;z.reject(G)}async handleCallback(B){let{id:z,c:G,a:Q,cb:V}=B,Z=this.callbacks.get(G);if(!Z){this.send({t:2,id:z,e:`Callback not found: ${G}`});return}try{let J=Q.map(($,q)=>{let U=V?.[q];if(U)return this.createRemoteCallback(U);return $}),K=await Z.fn(...J);if(Z.remaining>0){if(Z.remaining--,Z.remaining===0)this.callbacks.delete(G)}if(H(K)){let $=this.registerCallback(K);this.send({t:1,id:z,v:null,c:$})}else this.send({t:1,id:z,v:K})}catch(J){let K=J instanceof Error?J:Error(String(J));this.send({t:2,id:z,e:K.message,n:K.name,s:K.stack})}}handleCallbackRelease(B){for(let z of B.c)this.callbacks.delete(z)}handleEndpointRelease(){this.debug("Remote endpoint released"),this.options.onRelease(),this.release({silent:!0})}registerCallback(B,z=-1){let G=f();return this.callbacks.set(G,{fn:B,remaining:z}),G}createRemoteCallback(B){let z=this.remoteCallbacks.get(B);if(z)return z;return z=async(...G)=>{return this.invokeCallback(B,G)},this.remoteCallbacks.set(B,z),z}async invokeCallback(B,z){let G=W(),Q=[],V={},Z=[];for(let J=0;J<z.length;J++){let K=z[J];if(H(K))V[J]=this.registerCallback(K),Q.push(null);else if(R(K))Z.push(K),Q.push(K);else Q.push(K)}return new Promise((J,K)=>{let $=setTimeout(()=>{this.pendingCalls.delete(G),K(Error(`Callback invocation timed out: ${B}`))},this.options.timeout);this.pendingCalls.set(G,{resolve:J,reject:K,timer:$});let q={t:3,id:G,c:B,a:Q,...Object.keys(V).length>0&&{cb:V}};this.send(q,Z)})}async call(B,z){if(this.released)throw Error("Endpoint has been released");let G=[],Q={},V=[];for(let J=0;J<z.length;J++){let K=z[J];switch(!0){case H(K):{Q[J]=this.registerCallback(K),G.push(null);break}case R(K):{V.push(K),G.push(K);break}default:{G.push(K);break}}}let Z=W();return new Promise((J,K)=>{let $=setTimeout(()=>{this.pendingCalls.delete(Z),K(Error(`Call timed out: ${B.join(".")}`))},this.options.timeout);this.pendingCalls.set(Z,{resolve:J,reject:K,timer:$});let q={t:0,id:Z,p:B,a:G,...Object.keys(Q).length>0&&{c:Q}};this.send(q,V)})}send(B,z=[]){this.debug("sending",F[B.t],B),this.target.postMessage(B,z)}getPendingCallCount(){return this.pendingCalls.size}hasPendingCalls(){return this.pendingCalls.size>0}async shutdown(B={}){let{timeout:z=N}=B;if(this.released)return{success:!0,timeout:!1};if(!this.hasPendingCalls())return this.release(),{success:!0,timeout:!1};return new Promise((G)=>{let Q=!1,V=(J)=>{if(Q)return;if(Q=!0,clearTimeout(Z),!this.released)this.release();G(J)},Z=setTimeout(()=>{V({success:!1,timeout:!0})},z);for(let[,J]of this.pendingCalls){let{resolve:K,reject:$}=J;J.resolve=(q)=>{if(K(q),!this.hasPendingCalls())V({success:!0,timeout:!1})},J.reject=(q)=>{if($(q),!this.hasPendingCalls())V({success:!0,timeout:!1})}}})}release(B={}){if(this.released)return;this.released=!0;for(let[,G]of this.pendingCalls){if(G.timer)clearTimeout(G.timer);G.reject(Error("Endpoint released"))}this.pendingCalls.clear();let{silent:z=!1}=B;if(!z){if(this.remoteCallbacks.size>0){let G=[...this.remoteCallbacks.keys()];this.send({t:4,id:W(),c:G})}this.send({t:5,id:W()})}this.remoteCallbacks.clear(),this.callbacks.clear(),this.detachListener()}getTarget(){return this.target}}function H(B){return typeof B==="function"}function R(B){return typeof MessagePort<"u"&&B instanceof MessagePort}function C(B,z){return new h(B,z)}var L=Symbol("rpc:path"),S=Symbol("rpc:proxy-endpoint"),j=Symbol.for("rpc:remote-proxy"),X=Symbol.for("rpc:endpoint"),Y=Symbol.for("rpc:release"),P={get(B,z){if(z===j)return!0;if(z===X)return B[S];if(z===Y)return()=>{B[S].release()};if(z==="then"){if(B[L].length===0)return;let G=B[S],Q=B[L],V=G.call(Q,[]);return V.then.bind(V)}if(z==="toJSON")return;if(z===Symbol.toStringTag||z===Symbol.iterator||z===Symbol.asyncIterator||z==="constructor"||z==="prototype")return;if(typeof z==="string"){let G=B[S],V=[...B[L],z];return w(G,V)}},apply(B,z,G){let Q=B[S],V=B[L];return Q.call(V,G)},set(){throw Error("Cannot set properties on a remote proxy")},deleteProperty(){throw Error("Cannot delete properties on a remote proxy")},getPrototypeOf(){return Function.prototype},has(B,z){return z===j||z===X||z===Y}};function w(B,z){let G=function(){};return G[S]=B,G[L]=z,new Proxy(G,P)}function O(B){return w(B,[])}function A(B){if(B===null||B===void 0)return!1;try{return B[j]===!0}catch{return!1}}function M(B){if(A(B))return B[X]}function T(B){if(A(B))B[Y]()}function l(B,z){let Q=C(globalThis,z);return Q.expose(B),Q}function i(B,z){let G=C(B,z);return O(G)}export{O as wrap,i as remote,T as releaseProxy,A as isProxy,R as isMessagePort,H as isFunction,M as getEndpoint,l as expose,C as createEndpoint,j as REMOTE_PROXY,Y as RELEASE,S as PROXY_ENDPOINT,L as PATH,F as MessageType,h as Endpoint,X as ENDPOINT};
package/dist/proxy.d.ts CHANGED
@@ -48,4 +48,3 @@ export declare function getEndpoint(proxy: unknown): Endpoint | undefined;
48
48
  * Release a proxy and its underlying endpoint
49
49
  */
50
50
  export declare function releaseProxy(proxy: unknown): void;
51
- //# sourceMappingURL=proxy.d.ts.map
package/dist/types.d.ts CHANGED
@@ -75,13 +75,11 @@ export interface EndpointReleaseMessage extends BaseMessage {
75
75
  export type RpcMessage = CallMessage | ResultMessage | ErrorMessage | CallbackMessage | CallbackReleaseMessage | EndpointReleaseMessage;
76
76
  /** Unwrap a Promise type */
77
77
  export type Unpromise<T> = T extends Promise<infer U> ? U : T;
78
- /** Make a function async if it isn't already */
79
- export type Promisify<T> = T extends (...args: infer A) => infer R ? (...args: A) => Promise<Unpromise<R>> : never;
80
- /** Convert a function type to its remote callable version */
81
- export type RemoteFunction<T> = T extends (...args: infer A) => infer R ? (...args: A) => Promise<Unpromise<R>> : never;
78
+ /** Helper to convert a single property to its remote version */
79
+ export type RemoteProperty<T> = T extends (...args: infer A) => infer R ? (...args: A) => Promise<Unpromise<R>> : T extends object ? RemoteObject<T> : T;
82
80
  /** Convert an object type to its remote callable version */
83
81
  export type RemoteObject<T> = {
84
- [K in keyof T]: T[K] extends (...args: any[]) => any ? RemoteFunction<T[K]> : T[K] extends object ? RemoteObject<T[K]> : T[K];
82
+ [K in keyof T]: RemoteProperty<T[K]>;
85
83
  };
86
84
  /** Pending call information */
87
85
  export interface PendingCall {
@@ -106,4 +104,3 @@ export interface MessageTarget {
106
104
  start?(): void;
107
105
  close?(): void;
108
106
  }
109
- //# sourceMappingURL=types.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xentobias/worker-rpc",
3
- "version": "1.0.7",
3
+ "version": "1.0.10",
4
4
  "description": "High-performance, type-safe RPC for Workers",
5
5
  "module": "src/index.ts",
6
6
  "main": "dist/index.js",
@@ -16,7 +16,7 @@
16
16
  }
17
17
  },
18
18
  "scripts": {
19
- "build": "bun build ./src/index.ts --outdir ./dist --target bun && tsc --declaration",
19
+ "build": "bun build ./src/index.ts --minify --outdir ./dist --target bun && tsc --declaration",
20
20
  "typecheck": "tsc --noEmit",
21
21
  "test": "bun test",
22
22
  "prepublishOnly": "bun run build",
@@ -1 +0,0 @@
1
- {"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"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"}
package/dist/id.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"AAMA,gCAAgC;AAChC,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAGD,+CAA+C;AAC/C,MAAM,MAAM,MAAM,GAAG,KAAK,MAAM,EAAE,CAAC;AAEnC,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,+CAA+C;AAC/C,MAAM,MAAM,UAAU,GAAG,MAAM,MAAM,EAAE,CAAC;AAExC,wBAAgB,kBAAkB,IAAI,UAAU,CAE/C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAkB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAE5E,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEhE,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AAExB;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CAKvE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,EACrC,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,eAAe,GACxB,YAAY,CAAC,CAAC,CAAC,CAGjB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,SAAS,CAAC;AAEjB,iDAAiD;AACjD,eAAO,MAAM,IAAI,eAAqB,CAAC;AAEvC,8CAA8C;AAC9C,eAAO,MAAM,cAAc,eAA+B,CAAC;AAE3D,mDAAmD;AACnD,eAAO,MAAM,YAAY,eAAiC,CAAC;AAE3D,mDAAmD;AACnD,eAAO,MAAM,QAAQ,eAA6B,CAAC;AAEnD,mCAAmC;AACnC,eAAO,MAAM,OAAO,eAA4B,CAAC;AAsGjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAC5E,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,EACnC,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,YAAY,CAAC,CAAC,CAAC,CAAC;AAKnB;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAU/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAIhE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAIjD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAM/C,8DAA8D;AAC9D,MAAM,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC;AAElC,yCAAyC;AACzC,oBAAY,WAAW;IACrB,iCAAiC;IACjC,IAAI,IAAI;IACR,0BAA0B;IAC1B,MAAM,IAAI;IACV,qBAAqB;IACrB,KAAK,IAAI;IACT,0BAA0B;IAC1B,QAAQ,IAAI;IACZ,kCAAkC;IAClC,eAAe,IAAI;IACnB,iDAAiD;IACjD,eAAe,IAAI;CACpB;AAED,6BAA6B;AAC7B,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,CAAC,EAAE,WAAW,CAAC;IACf,+CAA+C;IAC/C,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wCAAwC;AACxC,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,CAAC,EAAE,WAAW,CAAC,IAAI,CAAC;IACpB,4CAA4C;IAC5C,CAAC,EAAE,UAAU,CAAC;IACd,kDAAkD;IAClD,CAAC,EAAE,OAAO,EAAE,CAAC;IACb,8EAA8E;IAC9E,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CAChC;AAED,0BAA0B;AAC1B,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC;IACtB,qDAAqD;IACrD,CAAC,EAAE,OAAO,CAAC;IACX,gDAAgD;IAChD,CAAC,CAAC,EAAE,UAAU,CAAC;CAChB;AAED,qBAAqB;AACrB,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC;IACrB,oBAAoB;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,mDAAmD;IACnD,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,wBAAwB;IACxB,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,kCAAkC;AAClC,MAAM,WAAW,eAAgB,SAAQ,WAAW;IAClD,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC;IACxB,kBAAkB;IAClB,CAAC,EAAE,UAAU,CAAC;IACd,kDAAkD;IAClD,CAAC,EAAE,OAAO,EAAE,CAAC;IACb,qDAAqD;IACrD,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACjC;AAED,kCAAkC;AAClC,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACzD,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC;IAC/B,8BAA8B;IAC9B,CAAC,EAAE,UAAU,EAAE,CAAC;CACjB;AAED,iDAAiD;AACjD,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACzD,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC;CAChC;AAED,iCAAiC;AACjC,MAAM,MAAM,UAAU,GAClB,WAAW,GACX,aAAa,GACb,YAAY,GACZ,eAAe,GACf,sBAAsB,GACtB,sBAAsB,CAAC;AAM3B,4BAA4B;AAC5B,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAE9D,gDAAgD;AAChD,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,GAC9D,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GACrC,KAAK,CAAC;AAEV,6DAA6D;AAC7D,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,GACnE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GACrC,KAAK,CAAC;AAEV,4DAA4D;AAC5D,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;KAC3B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAChD,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACpB,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GACnB,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAClB,CAAC,CAAC,CAAC,CAAC;CACT,CAAC;AAMF,+BAA+B;AAC/B,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;CACvC;AAED,4BAA4B;AAC5B,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,QAAQ,CAAC;IACb,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,yBAAyB;AACzB,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,WAAW,CAAC;AAE1D,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAClD,gBAAgB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;IACtE,mBAAmB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;IACzE,SAAS,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1C,KAAK,CAAC,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,IAAI,IAAI,CAAC;CAChB"}