swarpc 0.2.4 → 0.4.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/dist/swarpc.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ProceduresMap, SwarpcClient, SwarpcServer } from "./types.js";
1
+ import { type ProceduresMap, type SwarpcClient, type SwarpcServer } from "./types.js";
2
2
  export type { ProceduresMap, SwarpcClient, SwarpcServer } from "./types.js";
3
3
  export declare function Server<Procedures extends ProceduresMap>(procedures: Procedures, { worker }?: {
4
4
  worker?: Worker;
@@ -1 +1 @@
1
- {"version":3,"file":"swarpc.d.ts","sourceRoot":"","sources":["../src/swarpc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE3E,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE3E,wBAAgB,MAAM,CAAC,UAAU,SAAS,aAAa,EACrD,UAAU,EAAE,UAAU,EACtB,EAAE,MAAM,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,YAAY,CAAC,UAAU,CAAC,CAyE1B;AA2DD,wBAAgB,MAAM,CAAC,UAAU,SAAS,aAAa,EACrD,UAAU,EAAE,UAAU,EACtB,EAAE,MAAM,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,YAAY,CAAC,UAAU,CAAC,CAiC1B"}
1
+ {"version":3,"file":"swarpc.d.ts","sourceRoot":"","sources":["../src/swarpc.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,YAAY,CAAA;AAEnB,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE3E,wBAAgB,MAAM,CAAC,UAAU,SAAS,aAAa,EACrD,UAAU,EAAE,UAAU,EACtB,EAAE,MAAM,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,YAAY,CAAC,UAAU,CAAC,CA+E1B;AA4DD,wBAAgB,MAAM,CAAC,UAAU,SAAS,aAAa,EACrD,UAAU,EAAE,UAAU,EACtB,EAAE,MAAM,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,YAAY,CAAC,UAAU,CAAC,CAyC1B"}
package/dist/swarpc.js CHANGED
@@ -1,16 +1,17 @@
1
1
  import { type } from "arktype";
2
+ import { zImplementations, zProcedures, } from "./types.js";
2
3
  export function Server(procedures, { worker } = {}) {
3
4
  const instance = {
4
- procedures,
5
- implementations: {},
6
- start: () => { },
5
+ [zProcedures]: procedures,
6
+ [zImplementations]: {},
7
+ start: (self) => { },
7
8
  };
8
9
  for (const functionName in procedures) {
9
10
  instance[functionName] = ((implementation) => {
10
- if (!instance.procedures[functionName]) {
11
+ if (!instance[zProcedures][functionName]) {
11
12
  throw new Error(`No procedure found for function name: ${functionName}`);
12
13
  }
13
- instance.implementations[functionName] = implementation;
14
+ instance[zImplementations][functionName] = implementation;
14
15
  });
15
16
  }
16
17
  const PayloadSchema = type.or(...Object.entries(procedures).map(([functionName, { input }]) => ({
@@ -31,6 +32,7 @@ export function Server(procedures, { worker } = {}) {
31
32
  };
32
33
  self.addEventListener("message", async (event) => {
33
34
  const { functionName, requestId, input } = PayloadSchema.assert(event.data);
35
+ l.server.debug(requestId, `Received request for ${functionName}`, input);
34
36
  const postError = async (error) => postMessage({
35
37
  functionName,
36
38
  requestId,
@@ -38,18 +40,21 @@ export function Server(procedures, { worker } = {}) {
38
40
  message: "message" in error ? error.message : String(error),
39
41
  },
40
42
  });
41
- const implementation = instance.implementations[functionName];
43
+ const implementation = instance[zImplementations][functionName];
42
44
  if (!implementation) {
43
45
  await postError("No implementation found");
44
46
  return;
45
47
  }
46
48
  await implementation(input, async (progress) => {
49
+ l.server.debug(requestId, `Progress for ${functionName}`, progress);
47
50
  await postMessage({ functionName, requestId, progress });
48
51
  })
49
52
  .catch(async (error) => {
53
+ l.server.error(requestId, `Error in ${functionName}`, error);
50
54
  await postError(error);
51
55
  })
52
56
  .then(async (result) => {
57
+ l.server.debug(requestId, `Result for ${functionName}`, result);
53
58
  await postMessage({ functionName, requestId, result });
54
59
  });
55
60
  });
@@ -57,7 +62,7 @@ export function Server(procedures, { worker } = {}) {
57
62
  return instance;
58
63
  }
59
64
  function generateRequestId() {
60
- return Math.random().toString(36).substring(2, 15);
65
+ return Math.random().toString(16).substring(2, 8).toUpperCase();
61
66
  }
62
67
  const pendingRequests = new Map();
63
68
  let _clientListenerStarted = false;
@@ -70,10 +75,11 @@ async function startClientListener(worker) {
70
75
  throw new Error("[SWARPC Client] Service Worker is not active");
71
76
  }
72
77
  if (!navigator.serviceWorker.controller) {
73
- console.warn("[SWARPC Client] Service Worker is not controlling the page");
78
+ l.client.warn("", "Service Worker is not controlling the page");
74
79
  }
75
80
  }
76
81
  const w = worker ?? navigator.serviceWorker;
82
+ l.client.debug("", "Starting client listener on", w);
77
83
  w.addEventListener("message", (event) => {
78
84
  const { functionName, requestId, ...data } = event.data || {};
79
85
  if (!requestId) {
@@ -98,8 +104,12 @@ async function startClientListener(worker) {
98
104
  _clientListenerStarted = true;
99
105
  }
100
106
  export function Client(procedures, { worker } = {}) {
101
- const instance = { procedures };
107
+ const instance = { [zProcedures]: procedures };
102
108
  for (const functionName of Object.keys(procedures)) {
109
+ if (typeof functionName !== "string") {
110
+ throw new Error(`[SWARPC Client] Invalid function name, don't use symbols`);
111
+ }
112
+ // @ts-expect-error
103
113
  instance[functionName] = (async (input, onProgress = () => { }) => {
104
114
  procedures[functionName].input.assert(input);
105
115
  await startClientListener(worker);
@@ -109,12 +119,45 @@ export function Client(procedures, { worker } = {}) {
109
119
  }
110
120
  return new Promise((resolve, reject) => {
111
121
  if (!worker && !navigator.serviceWorker.controller)
112
- console.warn("[SWARPC Client] Service Worker is not controlling the page");
122
+ l.client.warn("", "Service Worker is not controlling the page");
113
123
  const requestId = generateRequestId();
114
124
  pendingRequests.set(requestId, { resolve, onProgress, reject });
125
+ l.client.debug(requestId, `Requesting ${functionName} with`, input);
115
126
  w.postMessage({ functionName, input, requestId });
116
127
  });
117
128
  });
118
129
  }
119
130
  return instance;
120
131
  }
132
+ const l = {
133
+ server: {
134
+ debug: (rqid, message, ...args) => log("debug", "server", rqid, message, ...args),
135
+ info: (rqid, message, ...args) => log("info", "server", rqid, message, ...args),
136
+ warn: (rqid, message, ...args) => log("warn", "server", rqid, message, ...args),
137
+ error: (rqid, message, ...args) => log("error", "server", rqid, message, ...args),
138
+ },
139
+ client: {
140
+ debug: (rqid, message, ...args) => log("debug", "client", rqid, message, ...args),
141
+ info: (rqid, message, ...args) => log("info", "client", rqid, message, ...args),
142
+ warn: (rqid, message, ...args) => log("warn", "client", rqid, message, ...args),
143
+ error: (rqid, message, ...args) => log("error", "client", rqid, message, ...args),
144
+ },
145
+ };
146
+ function log(severity, side, rqid, message, ...args) {
147
+ const prefix = "[" +
148
+ ["SWARPC", side, rqid ? `%c${rqid}%c` : ""].filter(Boolean).join(" ") +
149
+ "]";
150
+ const prefixStyles = rqid ? ["color: cyan;", "color: inherit;"] : [];
151
+ if (severity === "debug") {
152
+ console.debug(prefix, ...prefixStyles, message, ...args);
153
+ }
154
+ else if (severity === "info") {
155
+ console.info(prefix, ...prefixStyles, message, ...args);
156
+ }
157
+ else if (severity === "warn") {
158
+ console.warn(prefix, ...prefixStyles, message, ...args);
159
+ }
160
+ else if (severity === "error") {
161
+ console.error(prefix, ...prefixStyles, message, ...args);
162
+ }
163
+ }
package/dist/types.d.ts CHANGED
@@ -6,17 +6,20 @@ export type Procedure<I extends Type, P extends Type, S extends Type> = {
6
6
  };
7
7
  export type ProcedureImplementation<I extends Type, P extends Type, S extends Type> = (input: I["inferOut"], onProgress: (progress: P["inferOut"]) => void) => Promise<S["inferOut"]>;
8
8
  export type ProceduresMap = Record<string, Procedure<Type, Type, Type>>;
9
+ export type ImplementationsMap<Procedures extends ProceduresMap> = {
10
+ [F in keyof Procedures]: ProcedureImplementation<Procedures[F]["input"], Procedures[F]["progress"], Procedures[F]["success"]>;
11
+ };
9
12
  export type ClientMethod<P extends Procedure<Type, Type, Type>> = (input: P["input"]["inferIn"], onProgress?: (progress: P["progress"]["inferOut"]) => void) => Promise<P["success"]["inferOut"]>;
13
+ export declare const zImplementations: unique symbol;
14
+ export declare const zProcedures: unique symbol;
10
15
  export type SwarpcClient<Procedures extends ProceduresMap> = {
11
- procedures: Procedures;
16
+ [zProcedures]: Procedures;
12
17
  } & {
13
18
  [F in keyof Procedures]: ClientMethod<Procedures[F]>;
14
19
  };
15
20
  export type SwarpcServer<Procedures extends ProceduresMap> = {
16
- procedures: Procedures;
17
- implementations: {
18
- [F in keyof Procedures]: ProcedureImplementation<Procedures[F]["input"], Procedures[F]["progress"], Procedures[F]["success"]>;
19
- };
21
+ [zProcedures]: Procedures;
22
+ [zImplementations]: ImplementationsMap<Procedures>;
20
23
  start(self: Window): void;
21
24
  } & {
22
25
  [F in keyof Procedures]: (impl: ProcedureImplementation<Procedures[F]["input"], Procedures[F]["progress"], Procedures[F]["success"]>) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC,SAAS,IAAI,IAAI;IACtE,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,EAAE,CAAC,CAAC;IACZ,OAAO,EAAE,CAAC,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,uBAAuB,CACjC,CAAC,SAAS,IAAI,EACd,CAAC,SAAS,IAAI,EACd,CAAC,SAAS,IAAI,IACZ,CACF,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC,EACpB,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,KAC1C,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;AAE5B,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAExE,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAChE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,EAC5B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,KACvD,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;AAEvC,MAAM,MAAM,YAAY,CAAC,UAAU,SAAS,aAAa,IAAI;IAC3D,UAAU,EAAE,UAAU,CAAC;CACxB,GAAG;KACD,CAAC,IAAI,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,UAAU,SAAS,aAAa,IAAI;IAC3D,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE;SACd,CAAC,IAAI,MAAM,UAAU,GAAG,uBAAuB,CAC9C,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EACtB,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EACzB,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CACzB;KACF,CAAC;IACF,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAEnC,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC,SAAS,IAAI,IAAI;IACtE,KAAK,EAAE,CAAC,CAAA;IACR,QAAQ,EAAE,CAAC,CAAA;IACX,OAAO,EAAE,CAAC,CAAA;CACX,CAAA;AAED,MAAM,MAAM,uBAAuB,CACjC,CAAC,SAAS,IAAI,EACd,CAAC,SAAS,IAAI,EACd,CAAC,SAAS,IAAI,IACZ,CACF,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC,EACpB,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,KAC1C,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;AAE3B,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AAEvE,MAAM,MAAM,kBAAkB,CAAC,UAAU,SAAS,aAAa,IAAI;KAChE,CAAC,IAAI,MAAM,UAAU,GAAG,uBAAuB,CAC9C,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EACtB,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EACzB,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CACzB;CACF,CAAA;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAChE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,EAC5B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,KACvD,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;AAEtC,eAAO,MAAM,gBAAgB,eAAmC,CAAA;AAChE,eAAO,MAAM,WAAW,eAA8B,CAAA;AAEtD,MAAM,MAAM,YAAY,CAAC,UAAU,SAAS,aAAa,IAAI;IAC3D,CAAC,WAAW,CAAC,EAAE,UAAU,CAAA;CAC1B,GAAG;KACD,CAAC,IAAI,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;CACrD,CAAA;AAED,MAAM,MAAM,YAAY,CAAC,UAAU,SAAS,aAAa,IAAI;IAC3D,CAAC,WAAW,CAAC,EAAE,UAAU,CAAA;IACzB,CAAC,gBAAgB,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAA;IAClD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,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,CAAA"}
package/dist/types.js CHANGED
@@ -1 +1,2 @@
1
- export {};
1
+ export const zImplementations = Symbol("SWARPC implementations");
2
+ export const zProcedures = Symbol("SWARPC procedures");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swarpc",
3
- "version": "0.2.4",
3
+ "version": "0.4.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",
package/src/swarpc.ts CHANGED
@@ -1,5 +1,12 @@
1
1
  import { type } from "arktype"
2
- import type { ProceduresMap, SwarpcClient, SwarpcServer } from "./types.js"
2
+ import {
3
+ ImplementationsMap,
4
+ zImplementations,
5
+ zProcedures,
6
+ type ProceduresMap,
7
+ type SwarpcClient,
8
+ type SwarpcServer,
9
+ } from "./types.js"
3
10
 
4
11
  export type { ProceduresMap, SwarpcClient, SwarpcServer } from "./types.js"
5
12
 
@@ -8,17 +15,17 @@ export function Server<Procedures extends ProceduresMap>(
8
15
  { worker }: { worker?: Worker } = {}
9
16
  ): SwarpcServer<Procedures> {
10
17
  const instance = {
11
- procedures,
12
- implementations: {} as SwarpcServer<Procedures>["implementations"],
13
- start: () => {},
18
+ [zProcedures]: procedures,
19
+ [zImplementations]: {} as ImplementationsMap<Procedures>,
20
+ start: (self: Window) => {},
14
21
  } as SwarpcServer<Procedures>
15
22
 
16
23
  for (const functionName in procedures) {
17
24
  instance[functionName] = ((implementation) => {
18
- if (!instance.procedures[functionName]) {
25
+ if (!instance[zProcedures][functionName]) {
19
26
  throw new Error(`No procedure found for function name: ${functionName}`)
20
27
  }
21
- instance.implementations[functionName] = implementation as any
28
+ instance[zImplementations][functionName] = implementation as any
22
29
  }) as SwarpcServer<Procedures>[typeof functionName]
23
30
  }
24
31
 
@@ -51,6 +58,9 @@ export function Server<Procedures extends ProceduresMap>(
51
58
  const { functionName, requestId, input } = PayloadSchema.assert(
52
59
  event.data
53
60
  )
61
+
62
+ l.server.debug(requestId, `Received request for ${functionName}`, input)
63
+
54
64
  const postError = async (error: any) =>
55
65
  postMessage({
56
66
  functionName,
@@ -60,19 +70,22 @@ export function Server<Procedures extends ProceduresMap>(
60
70
  },
61
71
  })
62
72
 
63
- const implementation = instance.implementations[functionName]
73
+ const implementation = instance[zImplementations][functionName]
64
74
  if (!implementation) {
65
75
  await postError("No implementation found")
66
76
  return
67
77
  }
68
78
 
69
79
  await implementation(input, async (progress: any) => {
80
+ l.server.debug(requestId, `Progress for ${functionName}`, progress)
70
81
  await postMessage({ functionName, requestId, progress })
71
82
  })
72
83
  .catch(async (error: any) => {
84
+ l.server.error(requestId, `Error in ${functionName}`, error)
73
85
  await postError(error)
74
86
  })
75
87
  .then(async (result: any) => {
88
+ l.server.debug(requestId, `Result for ${functionName}`, result)
76
89
  await postMessage({ functionName, requestId, result })
77
90
  })
78
91
  })
@@ -82,7 +95,7 @@ export function Server<Procedures extends ProceduresMap>(
82
95
  }
83
96
 
84
97
  function generateRequestId(): string {
85
- return Math.random().toString(36).substring(2, 15)
98
+ return Math.random().toString(16).substring(2, 8).toUpperCase()
86
99
  }
87
100
 
88
101
  type PendingRequest = {
@@ -104,11 +117,12 @@ async function startClientListener(worker?: Worker) {
104
117
  }
105
118
 
106
119
  if (!navigator.serviceWorker.controller) {
107
- console.warn("[SWARPC Client] Service Worker is not controlling the page")
120
+ l.client.warn("", "Service Worker is not controlling the page")
108
121
  }
109
122
  }
110
123
 
111
124
  const w = worker ?? navigator.serviceWorker
125
+ l.client.debug("", "Starting client listener on", w)
112
126
  w.addEventListener("message", (event) => {
113
127
  const { functionName, requestId, ...data } =
114
128
  (event as MessageEvent).data || {}
@@ -142,11 +156,20 @@ export function Client<Procedures extends ProceduresMap>(
142
156
  procedures: Procedures,
143
157
  { worker }: { worker?: Worker } = {}
144
158
  ): SwarpcClient<Procedures> {
145
- const instance = { procedures } as Partial<SwarpcClient<Procedures>>
159
+ const instance = { [zProcedures]: procedures } as Partial<
160
+ SwarpcClient<Procedures>
161
+ >
146
162
 
147
163
  for (const functionName of Object.keys(procedures) as Array<
148
164
  keyof Procedures
149
165
  >) {
166
+ if (typeof functionName !== "string") {
167
+ throw new Error(
168
+ `[SWARPC Client] Invalid function name, don't use symbols`
169
+ )
170
+ }
171
+
172
+ // @ts-expect-error
150
173
  instance[functionName] = (async (input: unknown, onProgress = () => {}) => {
151
174
  procedures[functionName].input.assert(input)
152
175
  await startClientListener(worker)
@@ -160,14 +183,13 @@ export function Client<Procedures extends ProceduresMap>(
160
183
 
161
184
  return new Promise((resolve, reject) => {
162
185
  if (!worker && !navigator.serviceWorker.controller)
163
- console.warn(
164
- "[SWARPC Client] Service Worker is not controlling the page"
165
- )
186
+ l.client.warn("", "Service Worker is not controlling the page")
166
187
 
167
188
  const requestId = generateRequestId()
168
189
 
169
190
  pendingRequests.set(requestId, { resolve, onProgress, reject })
170
191
 
192
+ l.client.debug(requestId, `Requesting ${functionName} with`, input)
171
193
  w.postMessage({ functionName, input, requestId })
172
194
  })
173
195
  }) as SwarpcClient<Procedures>[typeof functionName]
@@ -175,3 +197,51 @@ export function Client<Procedures extends ProceduresMap>(
175
197
 
176
198
  return instance as SwarpcClient<Procedures>
177
199
  }
200
+
201
+ const l = {
202
+ server: {
203
+ debug: (rqid: string | null, message: string, ...args: any[]) =>
204
+ log("debug", "server", rqid, message, ...args),
205
+ info: (rqid: string | null, message: string, ...args: any[]) =>
206
+ log("info", "server", rqid, message, ...args),
207
+ warn: (rqid: string | null, message: string, ...args: any[]) =>
208
+ log("warn", "server", rqid, message, ...args),
209
+ error: (rqid: string | null, message: string, ...args: any[]) =>
210
+ log("error", "server", rqid, message, ...args),
211
+ },
212
+ client: {
213
+ debug: (rqid: string | null, message: string, ...args: any[]) =>
214
+ log("debug", "client", rqid, message, ...args),
215
+ info: (rqid: string | null, message: string, ...args: any[]) =>
216
+ log("info", "client", rqid, message, ...args),
217
+ warn: (rqid: string | null, message: string, ...args: any[]) =>
218
+ log("warn", "client", rqid, message, ...args),
219
+ error: (rqid: string | null, message: string, ...args: any[]) =>
220
+ log("error", "client", rqid, message, ...args),
221
+ },
222
+ }
223
+
224
+ function log(
225
+ severity: "debug" | "info" | "warn" | "error",
226
+ side: "server" | "client",
227
+ rqid: string | null,
228
+ message: string,
229
+ ...args: any[]
230
+ ) {
231
+ const prefix =
232
+ "[" +
233
+ ["SWARPC", side, rqid ? `%c${rqid}%c` : ""].filter(Boolean).join(" ") +
234
+ "]"
235
+
236
+ const prefixStyles = rqid ? ["color: cyan;", "color: inherit;"] : []
237
+
238
+ if (severity === "debug") {
239
+ console.debug(prefix, ...prefixStyles, message, ...args)
240
+ } else if (severity === "info") {
241
+ console.info(prefix, ...prefixStyles, message, ...args)
242
+ } else if (severity === "warn") {
243
+ console.warn(prefix, ...prefixStyles, message, ...args)
244
+ } else if (severity === "error") {
245
+ console.error(prefix, ...prefixStyles, message, ...args)
246
+ }
247
+ }
package/src/types.ts CHANGED
@@ -1,10 +1,10 @@
1
- import type { Type } from "arktype";
1
+ import type { Type } from "arktype"
2
2
 
3
3
  export type Procedure<I extends Type, P extends Type, S extends Type> = {
4
- input: I;
5
- progress: P;
6
- success: S;
7
- };
4
+ input: I
5
+ progress: P
6
+ success: S
7
+ }
8
8
 
9
9
  export type ProcedureImplementation<
10
10
  I extends Type,
@@ -13,31 +13,36 @@ export type ProcedureImplementation<
13
13
  > = (
14
14
  input: I["inferOut"],
15
15
  onProgress: (progress: P["inferOut"]) => void
16
- ) => Promise<S["inferOut"]>;
16
+ ) => Promise<S["inferOut"]>
17
17
 
18
- export type ProceduresMap = Record<string, Procedure<Type, Type, Type>>;
18
+ export type ProceduresMap = Record<string, Procedure<Type, Type, Type>>
19
+
20
+ export type ImplementationsMap<Procedures extends ProceduresMap> = {
21
+ [F in keyof Procedures]: ProcedureImplementation<
22
+ Procedures[F]["input"],
23
+ Procedures[F]["progress"],
24
+ Procedures[F]["success"]
25
+ >
26
+ }
19
27
 
20
28
  export type ClientMethod<P extends Procedure<Type, Type, Type>> = (
21
29
  input: P["input"]["inferIn"],
22
30
  onProgress?: (progress: P["progress"]["inferOut"]) => void
23
- ) => Promise<P["success"]["inferOut"]>;
31
+ ) => Promise<P["success"]["inferOut"]>
32
+
33
+ export const zImplementations = Symbol("SWARPC implementations")
34
+ export const zProcedures = Symbol("SWARPC procedures")
24
35
 
25
36
  export type SwarpcClient<Procedures extends ProceduresMap> = {
26
- procedures: Procedures;
37
+ [zProcedures]: Procedures
27
38
  } & {
28
- [F in keyof Procedures]: ClientMethod<Procedures[F]>;
29
- };
39
+ [F in keyof Procedures]: ClientMethod<Procedures[F]>
40
+ }
30
41
 
31
42
  export type SwarpcServer<Procedures extends ProceduresMap> = {
32
- procedures: Procedures;
33
- implementations: {
34
- [F in keyof Procedures]: ProcedureImplementation<
35
- Procedures[F]["input"],
36
- Procedures[F]["progress"],
37
- Procedures[F]["success"]
38
- >;
39
- };
40
- start(self: Window): void;
43
+ [zProcedures]: Procedures
44
+ [zImplementations]: ImplementationsMap<Procedures>
45
+ start(self: Window): void
41
46
  } & {
42
47
  [F in keyof Procedures]: (
43
48
  impl: ProcedureImplementation<
@@ -45,5 +50,5 @@ export type SwarpcServer<Procedures extends ProceduresMap> = {
45
50
  Procedures[F]["progress"],
46
51
  Procedures[F]["success"]
47
52
  >
48
- ) => void;
49
- };
53
+ ) => void
54
+ }