swarpc 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ <div align=center>
2
+ <h1>sw&rpc</h1>
3
+
4
+ RPC for Service Workers -- move that heavy computation off of your UI thread!
5
+
6
+ </div>
7
+
8
+ * * *
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm add swarpc
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ### 1. Declare your procedures in a shared file
19
+
20
+ ```javascript
21
+ import { type } from "arktype"
22
+
23
+ export const procedures = {
24
+ searchIMDb: {
25
+ // Input for the procedure
26
+ input: type({ query: "string", "pageSize?": "number" }),
27
+ // Function to be called whenever you can update progress while the procedure is running -- long computations are a first-class concern here. Examples include using the fetch-progress NPM package.
28
+ progress: type({ transmitted: "number", total: "number" }),
29
+ // Output of a successful procedure call
30
+ success: type({
31
+ id: "string",
32
+ primary_title: "string",
33
+ genres: "string[]",
34
+ }).array(),
35
+ },
36
+ }
37
+ ```
38
+
39
+ ### 2. Register your procedures in the service worker
40
+
41
+ In your service worker file:
42
+
43
+ ```javascript
44
+ import fetchProgress from "fetch-progress"
45
+ import { Server } from "swarpc"
46
+ import { procedures } from "./procedures.js"
47
+
48
+ // 1. Give yourself a server instance
49
+ const swarpc = Server(procedures)
50
+
51
+ // 2. Implement your procedures
52
+ swarpc.searchIMDb(async ({ query, pageSize = 10 }, onProgress) => {
53
+ const queryParams = new URLSearchParams({
54
+ page_size: pageSize.toString(),
55
+ query,
56
+ })
57
+
58
+ return fetch(`https://rest.imdbapi.dev/v2/search/titles?${queryParams}`)
59
+ .then(fetchProgress({ onProgress }))
60
+ .then((response) => response.json())
61
+ })
62
+
63
+ // ...
64
+
65
+ // 3. Start the event listener
66
+ swarpc.start(self)
67
+ ```
68
+
69
+ ### 3. Call your procedures from the client
70
+
71
+ Here's a Svelte example!
72
+
73
+ ```svelte
74
+ <script>
75
+ import { Client } from "swarpc"
76
+ import { procedures } from "./procedures.js"
77
+
78
+ const swarpc = Client(procedures)
79
+
80
+ let query = $state("")
81
+ let results = $state([])
82
+ let progress = $state(0)
83
+ </script>
84
+
85
+ <search>
86
+ <input type="text" bind:value={query} placeholder="Search IMDb" />
87
+ <button on:click={async () => {
88
+ results = await swarpc.searchIMDb({ query }, (p) => {
89
+ progress = p.transmitted / p.total
90
+ })
91
+ }}>
92
+ Search
93
+ </button>
94
+ </search>
95
+
96
+ {#if progress > 0 && progress < 1}
97
+ <progress value={progress} max="1" />
98
+ {/if}
99
+
100
+ <ul>
101
+ {#each results as { id, primary_title, genres } (id)}
102
+ <li>{primary_title} - {genres.join(", ")}</li>
103
+ {/each}
104
+ </ul>
105
+ ```
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @import { Type } from 'arktype';
3
+ */
4
+ /**
5
+ * @template {Type} I
6
+ * @template {Type} P
7
+ * @template {Type} S
8
+ * @typedef {Object} Procedure
9
+ * @property {I} input
10
+ * @property {P} progress
11
+ * @property {S} success
12
+ */
13
+ /**
14
+ * @template {Type} I
15
+ * @template {Type} P
16
+ * @template {Type} S
17
+ * @typedef {(input: I['inferOut'], onProgress: (progress: P['inferOut']) => void) => Promise<NoInfer<S>['inferOut'] | NoInfer<S>['inferOut']>} ProcedureImplementation
18
+ */
19
+ /**
20
+ * @typedef {Record<string, Procedure<Type, Type, Type>>} ProceduresMap
21
+ */
22
+ /**
23
+ * @template {ProceduresMap} Procedures
24
+ * @typedef {{ procedures: Procedures, implementations: {[F in keyof Procedures]: ProcedureImplementation<Procedures[F]['input'], Procedures[F]['progress'], Procedures[F]['success']> }, start: (self: Window) => void } & { [F in keyof Procedures]: (impl: NoInfer<ProcedureImplementation<Procedures[F]['input'], Procedures[F]['progress'], Procedures[F]['success'] >>) => void }} SwarpServer
25
+ */
26
+ /**
27
+ * @template {ProceduresMap} Procedures
28
+ * @param {Procedures} procedures
29
+ * @returns {SwarpServer<Procedures>}
30
+ */
31
+ export function Server<Procedures extends ProceduresMap>(procedures: Procedures): SwarpServer<Procedures>;
32
+ /**
33
+ * @template {Procedure<Type, Type, Type>} P
34
+ * @typedef {(input: P['input']['inferOut'], onProgress?: (progress: P['progress']['inferOut']) => void) => Promise<P['success']['inferOut']>} ClientMethod
35
+ */
36
+ /**
37
+ * @template {ProceduresMap} Procedures
38
+ * @typedef {{ procedures: Procedures } & { [F in keyof Procedures]: ClientMethod<Procedures[F]> }} SwarpClient
39
+ */
40
+ /**
41
+ * @template {ProceduresMap} Procedures
42
+ * @param {Procedures} procedures
43
+ * @returns {SwarpClient<Procedures>}
44
+ */
45
+ export function Client<Procedures extends ProceduresMap>(procedures: Procedures): SwarpClient<Procedures>;
46
+ export type Procedure<I extends Type, P extends Type, S extends Type> = {
47
+ input: I;
48
+ progress: P;
49
+ success: S;
50
+ };
51
+ export type ProcedureImplementation<I extends Type, P extends Type, S extends Type> = (input: I["inferOut"], onProgress: (progress: P["inferOut"]) => void) => Promise<NoInfer<S>["inferOut"] | NoInfer<S>["inferOut"]>;
52
+ export type ProceduresMap = Record<string, Procedure<Type, Type, Type>>;
53
+ export type SwarpServer<Procedures extends ProceduresMap> = {
54
+ procedures: Procedures;
55
+ implementations: { [F in keyof Procedures]: ProcedureImplementation<Procedures[F]["input"], Procedures[F]["progress"], Procedures[F]["success"]>; };
56
+ start: (self: Window) => void;
57
+ } & { [F in keyof Procedures]: (impl: NoInfer<ProcedureImplementation<Procedures[F]["input"], Procedures[F]["progress"], Procedures[F]["success"]>>) => void; };
58
+ export type ClientMethod<P extends Procedure<Type, Type, Type>> = (input: P["input"]["inferOut"], onProgress?: (progress: P["progress"]["inferOut"]) => void) => Promise<P["success"]["inferOut"]>;
59
+ export type SwarpClient<Procedures extends ProceduresMap> = {
60
+ procedures: Procedures;
61
+ } & { [F in keyof Procedures]: ClientMethod<Procedures[F]>; };
62
+ import type { Type } from 'arktype';
63
+ import type { Type as Type_1 } from 'arktype';
64
+ //# sourceMappingURL=swarpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swarpc.d.ts","sourceRoot":"","sources":["../src/swarpc.js"],"names":[],"mappings":"AACA;;GAEG;AAEH;;;;;;;;GAQG;AAEH;;;;;GAKG;AAEH;;GAEG;AAEH;;;GAGG;AAEH;;;;GAIG;AACH,uBAJ6B,UAAU,SAAzB,aAAc,cACjB,UAAU,GACR,WAAW,CAAC,UAAU,CAAC,CAgFnC;AAED;;;GAGG;AAEH;;;GAGG;AAEH;;;;GAIG;AACH,uBAJ6B,UAAU,SAAzB,aAAc,cACjB,UAAU,GACR,WAAW,CAAC,UAAU,CAAC,CA+BnC;sBA1JmB,CAAC,SAAR,IAAM,EACC,CAAC,SAAR,IAAM,EACC,CAAC,SAAR,IAAM;WAEL,CAAC;cACD,CAAC;aACD,CAAC;;oCAIK,CAAC,SAAR,IAAM,EACC,CAAC,SAAR,IAAM,EACC,CAAC,SAAR,IAAM,IACN,CAAC,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;4BAIjI,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;wBAI3B,UAAU,SAAzB,aAAc,IACf;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,eAAe,EAAE,GAAE,CAAC,IAAI,MAAM,UAAU,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAE,CAAC;IAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAG,GAAG,GAAG,CAAC,IAAI,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAE,CAAC,KAAK,IAAI,GAAE;yBAyF7U,CAAC,SAA9B,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAE,IAC7B,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC;wBAIhH,UAAU,SAAzB,aAAc,IACf;IAAE,UAAU,EAAE,UAAU,CAAA;CAAE,GAAG,GAAG,CAAC,IAAI,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAE;0BAzHzE,SAAS;oCAAT,SAAS"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swarpc",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
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",
@@ -20,11 +20,20 @@
20
20
  "license": "MIT",
21
21
  "author": "Gwenn Le Bihan <gwenn.lebihan7@gmail.com>",
22
22
  "type": "module",
23
+ "files": [
24
+ "dist",
25
+ "src"
26
+ ],
23
27
  "main": "src/swarpc.js",
28
+ "types": "dist/swarpc.d.ts",
24
29
  "scripts": {
30
+ "build": "tsc",
25
31
  "test": "echo \"Error: no test specified\" && exit 1"
26
32
  },
27
33
  "dependencies": {
28
34
  "arktype": "^2.1.20"
35
+ },
36
+ "devDependencies": {
37
+ "typescript": "^5.8.3"
29
38
  }
30
39
  }
@@ -21,7 +21,7 @@ import { type } from "arktype"
21
21
  */
22
22
 
23
23
  /**
24
- * @typedef {Record<string, Procedure<any, any, any>>} ProceduresMap
24
+ * @typedef {Record<string, Procedure<Type, Type, Type>>} ProceduresMap
25
25
  */
26
26
 
27
27
  /**