swarpc 0.14.0 → 0.15.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 CHANGED
@@ -12,6 +12,7 @@ RPC for Service Workers -- move that heavy computation off of your UI thread!
12
12
  ## Features
13
13
 
14
14
  - Fully typesafe
15
+ - Supports any [Standard Schema](https://standardschema.dev)-compliant validation library (ArkType, Zod, Valibot, etc.)
15
16
  - Cancelable requests
16
17
  - Parallelization with multiple worker instances
17
18
  - Automatic [transfer](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects) of transferable values from- and to- worker code
@@ -21,13 +22,19 @@ RPC for Service Workers -- move that heavy computation off of your UI thread!
21
22
  ## Installation
22
23
 
23
24
  ```bash
24
- npm add swarpc arktype
25
+ npm add swarpc
25
26
  ```
26
27
 
27
- <details>
28
+ Also add a [Standard-Schema-compliant validation library](https://standardschema.dev/#what-schema-libraries-implement-the-spec) of your choosing
29
+
30
+ ```bash
31
+ # For example
32
+ npm add arktype
33
+ ```
34
+
35
+ <details>
28
36
  <summary>
29
37
  Bleeding edge
30
-
31
38
  </summary>
32
39
 
33
40
  If you want to use the latest commit instead of a published version, you can, either by using the Git URL:
@@ -50,6 +57,10 @@ This works thanks to the fact that `dist/` is published on the repository (and k
50
57
 
51
58
  ## Usage
52
59
 
60
+ > [!NOTE]
61
+ > We use [ArkType](https://arktype.io) in the following examples, but, as stated above, any validation library
62
+ > is a-okay (provided that it is [Standard Schema v1](https://standardschema.dev)-compliant)
63
+
53
64
  ### 1. Declare your procedures in a shared file
54
65
 
55
66
  ```typescript
@@ -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,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"}
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,CAgL1B;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
@@ -75,7 +75,11 @@ export function Client(procedures, { worker, nodes: nodeCount, loglevel = "debug
75
75
  // Set the method on the instance
76
76
  const _runProcedure = async (input, onProgress = () => { }, reqid, nodeId) => {
77
77
  // Validate the input against the procedure's input schema
78
- procedures[functionName].input.assert(input);
78
+ const validation = procedures[functionName].input["~standard"].validate(input);
79
+ if (validation instanceof Promise)
80
+ throw new Error("Validations must not be async");
81
+ if (validation.issues)
82
+ throw new Error(`Invalid input: ${validation.issues}`);
79
83
  const requestId = reqid ?? makeRequestId();
80
84
  // Choose which node to use
81
85
  nodeId ??= whoToSendTo(nodes, pendingRequests);
@@ -217,7 +221,7 @@ export async function startClientListener(ctx) {
217
221
  // Ignore other messages that aren't for us
218
222
  if (eventData?.by !== "sw&rpc")
219
223
  return;
220
- // We don't use a arktype schema here, we trust the server to send valid data
224
+ // We don't use a schema here, we trust the server to send valid data
221
225
  const payload = eventData;
222
226
  // Ignore #initialize request, it's client->server only
223
227
  if ("isInitializeRequest" in payload) {
package/dist/nodes.d.ts CHANGED
@@ -9,7 +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)";
12
+ declare const serviceWorkerNodeId: "(SW)";
14
13
  export declare function nodeIdOrSW(id: string | undefined): string | typeof serviceWorkerNodeId;
14
+ export {};
15
15
  //# sourceMappingURL=nodes.d.ts.map
@@ -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;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"}
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,QAAA,MAAM,mBAAmB,EAAG,MAAe,CAAC;AAE5C,wBAAgB,UAAU,CACxB,EAAE,EAAE,MAAM,GAAG,SAAS,GACrB,MAAM,GAAG,OAAO,mBAAmB,CAErC"}
package/dist/nodes.js CHANGED
@@ -34,10 +34,7 @@ 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
- }
37
+ const serviceWorkerNodeId = "(SW)"; // Fixed ID for the service worker, as there's only one
41
38
  export function nodeIdOrSW(id) {
42
39
  return id ?? serviceWorkerNodeId;
43
40
  }
@@ -1 +1 @@
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"}
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,EAKlB,uBAAuB,EAEvB,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,CAwM1B"}
package/dist/server.js CHANGED
@@ -5,7 +5,7 @@
5
5
  /// <reference lib="webworker" />
6
6
  import { type } from "arktype";
7
7
  import { createLogger, injectIntoConsoleGlobal } from "./log.js";
8
- import { PayloadHeaderSchema, PayloadInitializeSchema, PayloadSchema, zImplementations, zProcedures, } from "./types.js";
8
+ import { PayloadHeaderSchema, PayloadInitializeSchema, validatePayloadCore as validatePayloadCore, zImplementations, zProcedures, } from "./types.js";
9
9
  import { findTransferables } from "./utils.js";
10
10
  import { FauxLocalStorage } from "./localstorage.js";
11
11
  import { scopeIsDedicated, scopeIsShared, scopeIsService } from "./scopes.js";
@@ -120,11 +120,11 @@ export function Server(procedures, { loglevel = "debug", scope, _scopeType, } =
120
120
  return;
121
121
  }
122
122
  // Define payload schema for incoming messages
123
- const payload = PayloadSchema(type(`"${functionName}"`), schemas.input, schemas.progress, schemas.success).assert(event.data);
123
+ const payload = validatePayloadCore(schemas, event.data);
124
124
  if ("isInitializeRequest" in payload)
125
125
  throw "Unreachable: #initialize request payload should've been handled already";
126
126
  // Handle abortion requests (pro-choice ftw!!)
127
- if (payload.abort) {
127
+ if ("abort" in payload) {
128
128
  const controller = abortControllers.get(requestId);
129
129
  if (!controller)
130
130
  await postError("No abort controller found for request");
@@ -133,7 +133,7 @@ export function Server(procedures, { loglevel = "debug", scope, _scopeType, } =
133
133
  }
134
134
  // Set up the abort controller for this request
135
135
  abortControllers.set(requestId, new AbortController());
136
- if (!payload.input) {
136
+ if (!("input" in payload)) {
137
137
  await postError("No input provided");
138
138
  return;
139
139
  }
@@ -0,0 +1,56 @@
1
+ /** The Standard Schema interface. */
2
+ export interface StandardSchemaV1<Input = unknown, Output = Input> {
3
+ /** The Standard Schema properties. */
4
+ readonly "~standard": StandardSchemaV1.Props<Input, Output>;
5
+ }
6
+ export declare namespace StandardSchemaV1 {
7
+ /** The Standard Schema properties interface. */
8
+ interface Props<Input = unknown, Output = Input> {
9
+ /** The version number of the standard. */
10
+ readonly version: 1;
11
+ /** The vendor name of the schema library. */
12
+ readonly vendor: string;
13
+ /** Validates unknown input values. */
14
+ readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
15
+ /** Inferred types associated with the schema. */
16
+ readonly types?: Types<Input, Output> | undefined;
17
+ }
18
+ /** The result interface of the validate function. */
19
+ type Result<Output> = SuccessResult<Output> | FailureResult;
20
+ /** The result interface if validation succeeds. */
21
+ interface SuccessResult<Output> {
22
+ /** The typed output value. */
23
+ readonly value: Output;
24
+ /** The non-existent issues. */
25
+ readonly issues?: undefined;
26
+ }
27
+ /** The result interface if validation fails. */
28
+ interface FailureResult {
29
+ /** The issues of failed validation. */
30
+ readonly issues: ReadonlyArray<Issue>;
31
+ }
32
+ /** The issue interface of the failure output. */
33
+ interface Issue {
34
+ /** The error message of the issue. */
35
+ readonly message: string;
36
+ /** The path of the issue, if any. */
37
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
38
+ }
39
+ /** The path segment interface of the issue. */
40
+ interface PathSegment {
41
+ /** The key representing a path segment. */
42
+ readonly key: PropertyKey;
43
+ }
44
+ /** The Standard Schema types interface. */
45
+ interface Types<Input = unknown, Output = Input> {
46
+ /** The input type of the schema. */
47
+ readonly input: Input;
48
+ /** The output type of the schema. */
49
+ readonly output: Output;
50
+ }
51
+ /** Infers the input type of a Standard Schema. */
52
+ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
53
+ /** Infers the output type of a Standard Schema. */
54
+ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
55
+ }
56
+ //# sourceMappingURL=standardschema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standardschema.d.ts","sourceRoot":"","sources":["../src/standardschema.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,MAAM,WAAW,gBAAgB,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;IAC/D,sCAAsC;IACtC,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;CAC7D;AAED,MAAM,CAAC,OAAO,WAAW,gBAAgB,CAAC;IACxC,gDAAgD;IAChD,UAAiB,KAAK,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;QACpD,0CAA0C;QAC1C,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QACpB,6CAA6C;QAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,sCAAsC;QACtC,QAAQ,CAAC,QAAQ,EAAE,CACjB,KAAK,EAAE,OAAO,KACX,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9C,iDAAiD;QACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;KACnD;IAED,qDAAqD;IACrD,KAAY,MAAM,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC;IAEnE,mDAAmD;IACnD,UAAiB,aAAa,CAAC,MAAM;QACnC,8BAA8B;QAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,+BAA+B;QAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;KAC7B;IAED,gDAAgD;IAChD,UAAiB,aAAa;QAC5B,uCAAuC;QACvC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;KACvC;IAED,iDAAiD;IACjD,UAAiB,KAAK;QACpB,sCAAsC;QACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,qCAAqC;QACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,SAAS,CAAC;KACtE;IAED,+CAA+C;IAC/C,UAAiB,WAAW;QAC1B,2CAA2C;QAC3C,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;KAC3B;IAED,2CAA2C;IAC3C,UAAiB,KAAK,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;QACpD,oCAAoC;QACpC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QACtB,qCAAqC;QACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB;IAED,kDAAkD;IAClD,KAAY,UAAU,CAAC,MAAM,SAAS,gBAAgB,IAAI,WAAW,CACnE,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAC7B,CAAC,OAAO,CAAC,CAAC;IAEX,mDAAmD;IACnD,KAAY,WAAW,CAAC,MAAM,SAAS,gBAAgB,IAAI,WAAW,CACpE,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAC7B,CAAC,QAAQ,CAAC,CAAC;CACb"}
@@ -0,0 +1 @@
1
+ export {};
package/dist/types.d.ts CHANGED
@@ -2,12 +2,12 @@
2
2
  * @module
3
3
  * @mergeModuleWith <project>
4
4
  */
5
- import { type Type } from "arktype";
5
+ import type { StandardSchemaV1 as Schema } from "./standardschema.js";
6
6
  import { RequestBoundLogger } from "./log.js";
7
7
  /**
8
8
  * A procedure declaration
9
9
  */
10
- export type Procedure<I extends Type, P extends Type, S extends Type> = {
10
+ export type Procedure<I extends Schema, P extends Schema, S extends Schema> = {
11
11
  /**
12
12
  * ArkType type for the input (first argument) of the procedure, when calling it from the client.
13
13
  */
@@ -53,15 +53,15 @@ export type CancelablePromise<T = unknown> = {
53
53
  /**
54
54
  * An implementation of a procedure
55
55
  */
56
- export type ProcedureImplementation<I extends Type, P extends Type, S extends Type> = (
56
+ export type ProcedureImplementation<I extends Schema, P extends Schema, S extends Schema> = (
57
57
  /**
58
58
  * Input data for the procedure
59
59
  */
60
- input: I["inferOut"],
60
+ input: Schema.InferInput<I>,
61
61
  /**
62
62
  * Callback to call with progress updates.
63
63
  */
64
- onProgress: (progress: P["inferIn"]) => void,
64
+ onProgress: (progress: Schema.InferInput<P>) => void,
65
65
  /**
66
66
  * Additional tools useful when implementing the procedure.
67
67
  */
@@ -78,14 +78,14 @@ tools: {
78
78
  * ID of the Node the request is being processed on.
79
79
  */
80
80
  nodeId: string;
81
- }) => Promise<S["inferIn"]>;
81
+ }) => Promise<Schema.InferInput<S>>;
82
82
  /**
83
83
  * Declarations of procedures by name.
84
84
  *
85
85
  * An example of declaring procedures:
86
86
  * {@includeCode ../example/src/lib/procedures.ts}
87
87
  */
88
- export type ProceduresMap = Record<string, Procedure<Type, Type, Type>>;
88
+ export type ProceduresMap = Record<string, Procedure<Schema, Schema, Schema>>;
89
89
  /**
90
90
  * Implementations of procedures by name
91
91
  */
@@ -99,7 +99,7 @@ export type Hooks<Procedures extends ProceduresMap> = {
99
99
  /**
100
100
  * Called when a procedure call has been successful.
101
101
  */
102
- success?: <Procedure extends keyof ProceduresMap>(procedure: Procedure, data: Procedures[Procedure]["success"]["inferOut"]) => void;
102
+ success?: <Procedure extends keyof ProceduresMap>(procedure: Procedure, data: Schema.InferOutput<Procedures[Procedure]["success"]>) => void;
103
103
  /**
104
104
  * Called when a procedure call has failed.
105
105
  */
@@ -107,9 +107,9 @@ export type Hooks<Procedures extends ProceduresMap> = {
107
107
  /**
108
108
  * Called when a procedure call sends progress updates.
109
109
  */
110
- progress?: <Procedure extends keyof ProceduresMap>(procedure: Procedure, data: Procedures[Procedure]["progress"]["inferOut"]) => void;
110
+ progress?: <Procedure extends keyof ProceduresMap>(procedure: Procedure, data: Schema.InferOutput<Procedures[Procedure]["progress"]>) => void;
111
111
  };
112
- export declare const PayloadInitializeSchema: import("arktype/internal/methods/object.ts").ObjectType<{
112
+ export declare const PayloadInitializeSchema: import("arktype/internal/variants/object.ts").ObjectType<{
113
113
  by: "sw&rpc";
114
114
  functionName: "#initialize";
115
115
  isInitializeRequest: true;
@@ -145,11 +145,11 @@ export declare const PayloadCoreSchema: import("arktype").Generic<[["I", unknown
145
145
  };
146
146
  }, {}, {}>;
147
147
  export type PayloadCore<PM extends ProceduresMap, Name extends keyof PM = keyof PM> = {
148
- input: PM[Name]["input"]["inferOut"];
148
+ input: Schema.InferOutput<PM[Name]["input"]>;
149
149
  } | {
150
- progress: PM[Name]["progress"]["inferOut"];
150
+ progress: Schema.InferOutput<PM[Name]["progress"]>;
151
151
  } | {
152
- result: PM[Name]["success"]["inferOut"];
152
+ result: Schema.InferOutput<PM[Name]["success"]>;
153
153
  } | {
154
154
  abort: {
155
155
  reason: string;
@@ -162,183 +162,7 @@ export type PayloadCore<PM extends ProceduresMap, Name extends keyof PM = keyof
162
162
  /**
163
163
  * @source
164
164
  */
165
- export declare const PayloadSchema: import("arktype").Generic<[["Name", string], ["I", unknown], ["P", unknown], ["S", unknown]], readonly [readonly ["PayloadHeaderSchema<Name>", "&", "PayloadCoreSchema<I, P, S>"], "|", "PayloadInitializeSchema"], {
166
- PayloadCoreSchema: import("arktype/internal/scope.ts").bindGenericToScope<import("@ark/schema").GenericAst<[["I", unknown], ["P", unknown], ["S", unknown]], {
167
- readonly "input?": "I";
168
- readonly "progress?": "P";
169
- readonly "result?": "S";
170
- readonly "abort?": {
171
- readonly reason: "string";
172
- };
173
- readonly "error?": {
174
- readonly message: "string";
175
- };
176
- }, {}, {}>, {
177
- PayloadCoreSchema: import("@ark/schema").GenericAst<[["I", unknown], ["P", unknown], ["S", unknown]], {
178
- readonly "input?": "I";
179
- readonly "progress?": "P";
180
- readonly "result?": "S";
181
- readonly "abort?": {
182
- readonly reason: "string";
183
- };
184
- readonly "error?": {
185
- readonly message: "string";
186
- };
187
- }, {}, {}>;
188
- PayloadHeaderSchema: import("@ark/schema").GenericAst<[["Name", string]], {
189
- readonly by: "\"sw&rpc\"";
190
- readonly functionName: "Name";
191
- readonly requestId: "string >= 1";
192
- }, {}, {}>;
193
- PayloadInitializeSchema: import("arktype/internal/methods/object.ts").ObjectType<{
194
- by: "sw&rpc";
195
- functionName: "#initialize";
196
- isInitializeRequest: true;
197
- localStorageData: Record<string, unknown>;
198
- nodeId: string;
199
- }, {}> & {
200
- readonly " brand": [import("arktype/internal/methods/object.ts").ObjectType<{
201
- by: "sw&rpc";
202
- functionName: "#initialize";
203
- isInitializeRequest: true;
204
- localStorageData: Record<string, unknown>;
205
- nodeId: string;
206
- }, {}>, "unparsed"];
207
- };
208
- } & {}>;
209
- PayloadHeaderSchema: import("arktype/internal/scope.ts").bindGenericToScope<import("@ark/schema").GenericAst<[["Name", string]], {
210
- readonly by: "\"sw&rpc\"";
211
- readonly functionName: "Name";
212
- readonly requestId: "string >= 1";
213
- }, {}, {}>, {
214
- PayloadCoreSchema: import("@ark/schema").GenericAst<[["I", unknown], ["P", unknown], ["S", unknown]], {
215
- readonly "input?": "I";
216
- readonly "progress?": "P";
217
- readonly "result?": "S";
218
- readonly "abort?": {
219
- readonly reason: "string";
220
- };
221
- readonly "error?": {
222
- readonly message: "string";
223
- };
224
- }, {}, {}>;
225
- PayloadHeaderSchema: import("@ark/schema").GenericAst<[["Name", string]], {
226
- readonly by: "\"sw&rpc\"";
227
- readonly functionName: "Name";
228
- readonly requestId: "string >= 1";
229
- }, {}, {}>;
230
- PayloadInitializeSchema: import("arktype/internal/methods/object.ts").ObjectType<{
231
- by: "sw&rpc";
232
- functionName: "#initialize";
233
- isInitializeRequest: true;
234
- localStorageData: Record<string, unknown>;
235
- nodeId: string;
236
- }, {}> & {
237
- readonly " brand": [import("arktype/internal/methods/object.ts").ObjectType<{
238
- by: "sw&rpc";
239
- functionName: "#initialize";
240
- isInitializeRequest: true;
241
- localStorageData: Record<string, unknown>;
242
- nodeId: string;
243
- }, {}>, "unparsed"];
244
- };
245
- } & {}>;
246
- PayloadInitializeSchema: {
247
- by: "sw&rpc";
248
- functionName: "#initialize";
249
- isInitializeRequest: true;
250
- localStorageData: Record<string, unknown>;
251
- nodeId: string;
252
- };
253
- }, {
254
- PayloadCoreSchema: import("arktype/internal/scope.ts").bindGenericToScope<import("@ark/schema").GenericAst<[["I", unknown], ["P", unknown], ["S", unknown]], {
255
- readonly "input?": "I";
256
- readonly "progress?": "P";
257
- readonly "result?": "S";
258
- readonly "abort?": {
259
- readonly reason: "string";
260
- };
261
- readonly "error?": {
262
- readonly message: "string";
263
- };
264
- }, {}, {}>, {
265
- PayloadCoreSchema: import("@ark/schema").GenericAst<[["I", unknown], ["P", unknown], ["S", unknown]], {
266
- readonly "input?": "I";
267
- readonly "progress?": "P";
268
- readonly "result?": "S";
269
- readonly "abort?": {
270
- readonly reason: "string";
271
- };
272
- readonly "error?": {
273
- readonly message: "string";
274
- };
275
- }, {}, {}>;
276
- PayloadHeaderSchema: import("@ark/schema").GenericAst<[["Name", string]], {
277
- readonly by: "\"sw&rpc\"";
278
- readonly functionName: "Name";
279
- readonly requestId: "string >= 1";
280
- }, {}, {}>;
281
- PayloadInitializeSchema: import("arktype/internal/methods/object.ts").ObjectType<{
282
- by: "sw&rpc";
283
- functionName: "#initialize";
284
- isInitializeRequest: true;
285
- localStorageData: Record<string, unknown>;
286
- nodeId: string;
287
- }, {}> & {
288
- readonly " brand": [import("arktype/internal/methods/object.ts").ObjectType<{
289
- by: "sw&rpc";
290
- functionName: "#initialize";
291
- isInitializeRequest: true;
292
- localStorageData: Record<string, unknown>;
293
- nodeId: string;
294
- }, {}>, "unparsed"];
295
- };
296
- } & {}>;
297
- PayloadHeaderSchema: import("arktype/internal/scope.ts").bindGenericToScope<import("@ark/schema").GenericAst<[["Name", string]], {
298
- readonly by: "\"sw&rpc\"";
299
- readonly functionName: "Name";
300
- readonly requestId: "string >= 1";
301
- }, {}, {}>, {
302
- PayloadCoreSchema: import("@ark/schema").GenericAst<[["I", unknown], ["P", unknown], ["S", unknown]], {
303
- readonly "input?": "I";
304
- readonly "progress?": "P";
305
- readonly "result?": "S";
306
- readonly "abort?": {
307
- readonly reason: "string";
308
- };
309
- readonly "error?": {
310
- readonly message: "string";
311
- };
312
- }, {}, {}>;
313
- PayloadHeaderSchema: import("@ark/schema").GenericAst<[["Name", string]], {
314
- readonly by: "\"sw&rpc\"";
315
- readonly functionName: "Name";
316
- readonly requestId: "string >= 1";
317
- }, {}, {}>;
318
- PayloadInitializeSchema: import("arktype/internal/methods/object.ts").ObjectType<{
319
- by: "sw&rpc";
320
- functionName: "#initialize";
321
- isInitializeRequest: true;
322
- localStorageData: Record<string, unknown>;
323
- nodeId: string;
324
- }, {}> & {
325
- readonly " brand": [import("arktype/internal/methods/object.ts").ObjectType<{
326
- by: "sw&rpc";
327
- functionName: "#initialize";
328
- isInitializeRequest: true;
329
- localStorageData: Record<string, unknown>;
330
- nodeId: string;
331
- }, {}>, "unparsed"];
332
- };
333
- } & {}>;
334
- PayloadInitializeSchema: {
335
- by: "sw&rpc";
336
- functionName: "#initialize";
337
- isInitializeRequest: true;
338
- localStorageData: Record<string, unknown>;
339
- nodeId: string;
340
- };
341
- }>;
165
+ export declare function validatePayloadCore<PM extends ProceduresMap, Name extends keyof PM>(procedure: PM[Name], payload: unknown): PayloadCore<PM, keyof PM>;
342
166
  /**
343
167
  * The effective payload as sent by the server to the client
344
168
  */
@@ -346,21 +170,21 @@ export type Payload<PM extends ProceduresMap, Name extends keyof PM = keyof PM>
346
170
  /**
347
171
  * A procedure's corresponding method on the client instance -- used to call the procedure. If you want to be able to cancel the request, you can use the `cancelable` method instead of running the procedure directly.
348
172
  */
349
- export type ClientMethod<P extends Procedure<Type, Type, Type>> = ((input: P["input"]["inferIn"], onProgress?: (progress: P["progress"]["inferOut"]) => void) => Promise<P["success"]["inferOut"]>) & {
173
+ export type ClientMethod<P extends Procedure<Schema, Schema, Schema>> = ((input: Schema.InferInput<P["input"]>, onProgress?: (progress: Schema.InferOutput<P["progress"]>) => void) => Promise<Schema.InferOutput<P["success"]>>) & {
350
174
  /**
351
175
  * A method that returns a `CancelablePromise`. Cancel it by calling `.cancel(reason)` on it, and wait for the request to resolve by awaiting the `request` property on the returned object.
352
176
  */
353
- cancelable: (input: P["input"]["inferIn"], onProgress?: (progress: P["progress"]["inferOut"]) => void, requestId?: string) => CancelablePromise<P["success"]["inferOut"]>;
177
+ cancelable: (input: Schema.InferInput<P["input"]>, onProgress?: (progress: Schema.InferOutput<P["progress"]>) => void, requestId?: string) => CancelablePromise<Schema.InferOutput<P["success"]>>;
354
178
  /**
355
179
  * Send the request to specific nodes, or all nodes.
356
180
  * Returns an array of results, one for each node the request was sent to.
357
181
  * Each result is a {@link PromiseSettledResult}, with also an additional property, the node ID of the request
358
182
  */
359
- broadcast: (input: P["input"]["inferIn"], onProgress?: (
183
+ broadcast: (input: Schema.InferInput<P["input"]>, onProgress?: (
360
184
  /** Map of node IDs to their progress updates */
361
- progresses: Map<string, P["progress"]["inferOut"]>) => void,
185
+ progresses: Map<string, Schema.InferOutput<P["progress"]>>) => void,
362
186
  /** Number of nodes to send the request to. Leave undefined to send to all nodes */
363
- nodes?: number) => Promise<Array<PromiseSettledResult<P["success"]["inferOut"]> & {
187
+ nodes?: number) => Promise<Array<PromiseSettledResult<Schema.InferOutput<P["success"]>> & {
364
188
  node: string;
365
189
  }>>;
366
190
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * @module
3
3
  * @mergeModuleWith <project>
4
4
  */
5
- import { type } from "arktype";
5
+ import { ArkErrors, type } from "arktype";
6
6
  export const PayloadInitializeSchema = type({
7
7
  by: '"sw&rpc"',
8
8
  functionName: '"#initialize"',
@@ -28,16 +28,36 @@ export const PayloadCoreSchema = type("<I, P, S>", {
28
28
  "abort?": { reason: "string" },
29
29
  "error?": { message: "string" },
30
30
  });
31
+ const AbortOrError = type.or({ abort: { reason: "string" } }, { error: { message: "string" } });
31
32
  /**
32
33
  * @source
33
34
  */
34
- export const PayloadSchema = type
35
- .scope({ PayloadCoreSchema, PayloadHeaderSchema, PayloadInitializeSchema })
36
- .type("<Name extends string, I, P, S>", [
37
- ["PayloadHeaderSchema<Name>", "&", "PayloadCoreSchema<I, P, S>"],
38
- "|",
39
- "PayloadInitializeSchema",
40
- ]);
35
+ export function validatePayloadCore(procedure, payload) {
36
+ if (typeof payload !== "object")
37
+ throw new Error("payload is not an object");
38
+ if (payload === null)
39
+ throw new Error("payload is null");
40
+ if ("input" in payload) {
41
+ const input = procedure.input["~standard"].validate(payload.input);
42
+ if ("value" in input)
43
+ return { input: input.value };
44
+ }
45
+ if ("progress" in payload) {
46
+ const progress = procedure.progress["~standard"].validate(payload.progress);
47
+ if ("value" in progress)
48
+ return { progress: progress.value };
49
+ }
50
+ if ("result" in payload) {
51
+ const result = procedure.success["~standard"].validate(payload.result);
52
+ if ("value" in result)
53
+ return { result: result.value };
54
+ }
55
+ const abortOrError = AbortOrError(payload);
56
+ if (!(abortOrError instanceof ArkErrors)) {
57
+ return abortOrError;
58
+ }
59
+ throw new Error("invalid payload");
60
+ }
41
61
  /**
42
62
  * Symbol used as the key for the procedures map on the server instance
43
63
  * @internal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swarpc",
3
- "version": "0.14.0",
3
+ "version": "0.15.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,42 +40,42 @@
40
40
  "typedoc:withplugins": "npm run typedoc:plugins && npm run typedoc",
41
41
  "prepare": "husky"
42
42
  },
43
- "peerDependencies": {
44
- "arktype": "^2.1.22"
45
- },
46
43
  "devDependencies": {
47
44
  "@8hobbies/typedoc-plugin-plausible": "^2.2.0",
48
- "@playwright/test": "^1.55.0",
49
- "@vitest/web-worker": "^3.2.4",
45
+ "@playwright/test": "^1.56.1",
46
+ "@vitest/web-worker": "^4.0.6",
50
47
  "date-fns": "^4.1.0",
51
48
  "husky": "^9.1.7",
52
49
  "kacl": "^1.1.1",
53
- "knip": "^5.63.1",
54
- "lint-staged": "^16.1.6",
50
+ "knip": "^5.67.0",
51
+ "lint-staged": "^16.2.6",
55
52
  "nodemon": "^3.1.10",
56
- "oxlint": "^1.14.0",
57
- "pkg-pr-new": "^0.0.59",
53
+ "oxlint": "^1.25.0",
54
+ "pkg-pr-new": "^0.0.60",
58
55
  "prettier": "^3.6.2",
59
56
  "sirv-cli": "^3.0.1",
60
- "typedoc": "^0.28.12",
61
- "typedoc-material-theme": "^1.4.0",
62
- "typedoc-plugin-dt-links": "^2.0.18",
57
+ "typedoc": "^0.28.14",
58
+ "typedoc-material-theme": "^1.4.1",
59
+ "typedoc-plugin-dt-links": "^2.0.27",
63
60
  "typedoc-plugin-extras": "^4.0.1",
64
61
  "typedoc-plugin-inline-sources": "^1.3.0",
65
- "typedoc-plugin-mdn-links": "^5.0.9",
66
- "typedoc-plugin-redirect": "^1.2.0",
67
- "typescript": "^5.9.2",
68
- "vite": "^7.1.4",
69
- "vitest": "^3.2.4"
62
+ "typedoc-plugin-mdn-links": "^5.0.10",
63
+ "typedoc-plugin-redirect": "^1.2.1",
64
+ "typescript": "^5.9.3",
65
+ "vite": "^7.1.12",
66
+ "vitest": "^4.0.6"
70
67
  },
71
68
  "volta": {
72
- "node": "24.7.0",
73
- "npm": "11.6.0"
69
+ "node": "24.11.0",
70
+ "npm": "11.6.2"
74
71
  },
75
72
  "lint-staged": {
76
73
  "*.{ts,js,md,json,yaml,yml}": [
77
74
  "oxlint --fix",
78
75
  "prettier --write"
79
76
  ]
77
+ },
78
+ "dependencies": {
79
+ "arktype": "^2.1.25"
80
80
  }
81
81
  }
package/src/client.ts CHANGED
@@ -178,7 +178,12 @@ export function Client<Procedures extends ProceduresMap>(
178
178
  nodeId?: string,
179
179
  ) => {
180
180
  // Validate the input against the procedure's input schema
181
- procedures[functionName].input.assert(input);
181
+ const validation =
182
+ procedures[functionName].input["~standard"].validate(input);
183
+ if (validation instanceof Promise)
184
+ throw new Error("Validations must not be async");
185
+ if (validation.issues)
186
+ throw new Error(`Invalid input: ${validation.issues}`);
182
187
 
183
188
  const requestId = reqid ?? makeRequestId();
184
189
 
@@ -374,7 +379,7 @@ export async function startClientListener<Procedures extends ProceduresMap>(
374
379
  // Ignore other messages that aren't for us
375
380
  if (eventData?.by !== "sw&rpc") return;
376
381
 
377
- // We don't use a arktype schema here, we trust the server to send valid data
382
+ // We don't use a schema here, we trust the server to send valid data
378
383
  const payload = eventData as Payload<Procedures>;
379
384
 
380
385
  // Ignore #initialize request, it's client->server only
package/src/nodes.ts CHANGED
@@ -54,11 +54,7 @@ export function makeNodeId(): string {
54
54
  return "N" + Math.random().toString(16).substring(2, 5).toUpperCase();
55
55
  }
56
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
- }
57
+ const serviceWorkerNodeId = "(SW)" as const; // Fixed ID for the service worker, as there's only one
62
58
 
63
59
  export function nodeIdOrSW(
64
60
  id: string | undefined,
package/src/server.ts CHANGED
@@ -12,8 +12,8 @@ import {
12
12
  PayloadCore,
13
13
  PayloadHeaderSchema,
14
14
  PayloadInitializeSchema,
15
- PayloadSchema,
16
15
  ProcedureImplementation,
16
+ validatePayloadCore as validatePayloadCore,
17
17
  zImplementations,
18
18
  zProcedures,
19
19
  type ProceduresMap,
@@ -188,18 +188,13 @@ export function Server<Procedures extends ProceduresMap>(
188
188
  }
189
189
 
190
190
  // Define payload schema for incoming messages
191
- const payload = PayloadSchema(
192
- type(`"${functionName}"`),
193
- schemas.input,
194
- schemas.progress,
195
- schemas.success,
196
- ).assert(event.data);
191
+ const payload = validatePayloadCore(schemas, event.data);
197
192
 
198
193
  if ("isInitializeRequest" in payload)
199
194
  throw "Unreachable: #initialize request payload should've been handled already";
200
195
 
201
196
  // Handle abortion requests (pro-choice ftw!!)
202
- if (payload.abort) {
197
+ if ("abort" in payload) {
203
198
  const controller = abortControllers.get(requestId);
204
199
 
205
200
  if (!controller)
@@ -212,7 +207,7 @@ export function Server<Procedures extends ProceduresMap>(
212
207
  // Set up the abort controller for this request
213
208
  abortControllers.set(requestId, new AbortController());
214
209
 
215
- if (!payload.input) {
210
+ if (!("input" in payload)) {
216
211
  await postError("No input provided");
217
212
  return;
218
213
  }
@@ -0,0 +1,70 @@
1
+ /** The Standard Schema interface. */
2
+ export interface StandardSchemaV1<Input = unknown, Output = Input> {
3
+ /** The Standard Schema properties. */
4
+ readonly "~standard": StandardSchemaV1.Props<Input, Output>;
5
+ }
6
+
7
+ export declare namespace StandardSchemaV1 {
8
+ /** The Standard Schema properties interface. */
9
+ export interface Props<Input = unknown, Output = Input> {
10
+ /** The version number of the standard. */
11
+ readonly version: 1;
12
+ /** The vendor name of the schema library. */
13
+ readonly vendor: string;
14
+ /** Validates unknown input values. */
15
+ readonly validate: (
16
+ value: unknown,
17
+ ) => Result<Output> | Promise<Result<Output>>;
18
+ /** Inferred types associated with the schema. */
19
+ readonly types?: Types<Input, Output> | undefined;
20
+ }
21
+
22
+ /** The result interface of the validate function. */
23
+ export type Result<Output> = SuccessResult<Output> | FailureResult;
24
+
25
+ /** The result interface if validation succeeds. */
26
+ export interface SuccessResult<Output> {
27
+ /** The typed output value. */
28
+ readonly value: Output;
29
+ /** The non-existent issues. */
30
+ readonly issues?: undefined;
31
+ }
32
+
33
+ /** The result interface if validation fails. */
34
+ export interface FailureResult {
35
+ /** The issues of failed validation. */
36
+ readonly issues: ReadonlyArray<Issue>;
37
+ }
38
+
39
+ /** The issue interface of the failure output. */
40
+ export interface Issue {
41
+ /** The error message of the issue. */
42
+ readonly message: string;
43
+ /** The path of the issue, if any. */
44
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
45
+ }
46
+
47
+ /** The path segment interface of the issue. */
48
+ export interface PathSegment {
49
+ /** The key representing a path segment. */
50
+ readonly key: PropertyKey;
51
+ }
52
+
53
+ /** The Standard Schema types interface. */
54
+ export interface Types<Input = unknown, Output = Input> {
55
+ /** The input type of the schema. */
56
+ readonly input: Input;
57
+ /** The output type of the schema. */
58
+ readonly output: Output;
59
+ }
60
+
61
+ /** Infers the input type of a Standard Schema. */
62
+ export type InferInput<Schema extends StandardSchemaV1> = NonNullable<
63
+ Schema["~standard"]["types"]
64
+ >["input"];
65
+
66
+ /** Infers the output type of a Standard Schema. */
67
+ export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<
68
+ Schema["~standard"]["types"]
69
+ >["output"];
70
+ }
package/src/types.ts CHANGED
@@ -3,13 +3,17 @@
3
3
  * @mergeModuleWith <project>
4
4
  */
5
5
 
6
- import { type, type Type } from "arktype";
6
+ import type {
7
+ StandardSchemaV1 as Schema,
8
+ StandardSchemaV1,
9
+ } from "./standardschema.js";
10
+ import { ArkErrors, type } from "arktype";
7
11
  import { RequestBoundLogger } from "./log.js";
8
12
 
9
13
  /**
10
14
  * A procedure declaration
11
15
  */
12
- export type Procedure<I extends Type, P extends Type, S extends Type> = {
16
+ export type Procedure<I extends Schema, P extends Schema, S extends Schema> = {
13
17
  /**
14
18
  * ArkType type for the input (first argument) of the procedure, when calling it from the client.
15
19
  */
@@ -58,18 +62,18 @@ export type CancelablePromise<T = unknown> = {
58
62
  * An implementation of a procedure
59
63
  */
60
64
  export type ProcedureImplementation<
61
- I extends Type,
62
- P extends Type,
63
- S extends Type,
65
+ I extends Schema,
66
+ P extends Schema,
67
+ S extends Schema,
64
68
  > = (
65
69
  /**
66
70
  * Input data for the procedure
67
71
  */
68
- input: I["inferOut"],
72
+ input: Schema.InferInput<I>,
69
73
  /**
70
74
  * Callback to call with progress updates.
71
75
  */
72
- onProgress: (progress: P["inferIn"]) => void,
76
+ onProgress: (progress: Schema.InferInput<P>) => void,
73
77
  /**
74
78
  * Additional tools useful when implementing the procedure.
75
79
  */
@@ -87,7 +91,7 @@ export type ProcedureImplementation<
87
91
  */
88
92
  nodeId: string;
89
93
  },
90
- ) => Promise<S["inferIn"]>;
94
+ ) => Promise<Schema.InferInput<S>>;
91
95
 
92
96
  /**
93
97
  * Declarations of procedures by name.
@@ -95,7 +99,7 @@ export type ProcedureImplementation<
95
99
  * An example of declaring procedures:
96
100
  * {@includeCode ../example/src/lib/procedures.ts}
97
101
  */
98
- export type ProceduresMap = Record<string, Procedure<Type, Type, Type>>;
102
+ export type ProceduresMap = Record<string, Procedure<Schema, Schema, Schema>>;
99
103
 
100
104
  /**
101
105
  * Implementations of procedures by name
@@ -117,7 +121,7 @@ export type Hooks<Procedures extends ProceduresMap> = {
117
121
  */
118
122
  success?: <Procedure extends keyof ProceduresMap>(
119
123
  procedure: Procedure,
120
- data: Procedures[Procedure]["success"]["inferOut"],
124
+ data: Schema.InferOutput<Procedures[Procedure]["success"]>,
121
125
  ) => void;
122
126
  /**
123
127
  * Called when a procedure call has failed.
@@ -131,7 +135,7 @@ export type Hooks<Procedures extends ProceduresMap> = {
131
135
  */
132
136
  progress?: <Procedure extends keyof ProceduresMap>(
133
137
  procedure: Procedure,
134
- data: Procedures[Procedure]["progress"]["inferOut"],
138
+ data: Schema.InferOutput<Procedures[Procedure]["progress"]>,
135
139
  ) => void;
136
140
  };
137
141
 
@@ -179,13 +183,13 @@ export type PayloadCore<
179
183
  Name extends keyof PM = keyof PM,
180
184
  > =
181
185
  | {
182
- input: PM[Name]["input"]["inferOut"];
186
+ input: Schema.InferOutput<PM[Name]["input"]>;
183
187
  }
184
188
  | {
185
- progress: PM[Name]["progress"]["inferOut"];
189
+ progress: Schema.InferOutput<PM[Name]["progress"]>;
186
190
  }
187
191
  | {
188
- result: PM[Name]["success"]["inferOut"];
192
+ result: Schema.InferOutput<PM[Name]["success"]>;
189
193
  }
190
194
  | {
191
195
  abort: { reason: string };
@@ -194,16 +198,43 @@ export type PayloadCore<
194
198
  error: { message: string };
195
199
  };
196
200
 
201
+ const AbortOrError = type.or(
202
+ { abort: { reason: "string" } },
203
+ { error: { message: "string" } },
204
+ );
205
+
197
206
  /**
198
207
  * @source
199
208
  */
200
- export const PayloadSchema = type
201
- .scope({ PayloadCoreSchema, PayloadHeaderSchema, PayloadInitializeSchema })
202
- .type("<Name extends string, I, P, S>", [
203
- ["PayloadHeaderSchema<Name>", "&", "PayloadCoreSchema<I, P, S>"],
204
- "|",
205
- "PayloadInitializeSchema",
206
- ]);
209
+ export function validatePayloadCore<
210
+ PM extends ProceduresMap,
211
+ Name extends keyof PM,
212
+ >(procedure: PM[Name], payload: unknown): PayloadCore<PM, keyof PM> {
213
+ if (typeof payload !== "object") throw new Error("payload is not an object");
214
+ if (payload === null) throw new Error("payload is null");
215
+
216
+ if ("input" in payload) {
217
+ const input = procedure.input["~standard"].validate(payload.input);
218
+ if ("value" in input) return { input: input.value };
219
+ }
220
+
221
+ if ("progress" in payload) {
222
+ const progress = procedure.progress["~standard"].validate(payload.progress);
223
+ if ("value" in progress) return { progress: progress.value };
224
+ }
225
+
226
+ if ("result" in payload) {
227
+ const result = procedure.success["~standard"].validate(payload.result);
228
+ if ("value" in result) return { result: result.value };
229
+ }
230
+
231
+ const abortOrError = AbortOrError(payload);
232
+ if (!(abortOrError instanceof ArkErrors)) {
233
+ return abortOrError;
234
+ }
235
+
236
+ throw new Error("invalid payload");
237
+ }
207
238
 
208
239
  /**
209
240
  * The effective payload as sent by the server to the client
@@ -216,33 +247,35 @@ export type Payload<
216
247
  /**
217
248
  * A procedure's corresponding method on the client instance -- used to call the procedure. If you want to be able to cancel the request, you can use the `cancelable` method instead of running the procedure directly.
218
249
  */
219
- export type ClientMethod<P extends Procedure<Type, Type, Type>> = ((
220
- input: P["input"]["inferIn"],
221
- onProgress?: (progress: P["progress"]["inferOut"]) => void,
222
- ) => Promise<P["success"]["inferOut"]>) & {
250
+ export type ClientMethod<P extends Procedure<Schema, Schema, Schema>> = ((
251
+ input: Schema.InferInput<P["input"]>,
252
+ onProgress?: (progress: Schema.InferOutput<P["progress"]>) => void,
253
+ ) => Promise<Schema.InferOutput<P["success"]>>) & {
223
254
  /**
224
255
  * A method that returns a `CancelablePromise`. Cancel it by calling `.cancel(reason)` on it, and wait for the request to resolve by awaiting the `request` property on the returned object.
225
256
  */
226
257
  cancelable: (
227
- input: P["input"]["inferIn"],
228
- onProgress?: (progress: P["progress"]["inferOut"]) => void,
258
+ input: Schema.InferInput<P["input"]>,
259
+ onProgress?: (progress: Schema.InferOutput<P["progress"]>) => void,
229
260
  requestId?: string,
230
- ) => CancelablePromise<P["success"]["inferOut"]>;
261
+ ) => CancelablePromise<Schema.InferOutput<P["success"]>>;
231
262
  /**
232
263
  * Send the request to specific nodes, or all nodes.
233
264
  * Returns an array of results, one for each node the request was sent to.
234
265
  * Each result is a {@link PromiseSettledResult}, with also an additional property, the node ID of the request
235
266
  */
236
267
  broadcast: (
237
- input: P["input"]["inferIn"],
268
+ input: Schema.InferInput<P["input"]>,
238
269
  onProgress?: (
239
270
  /** Map of node IDs to their progress updates */
240
- progresses: Map<string, P["progress"]["inferOut"]>,
271
+ progresses: Map<string, Schema.InferOutput<P["progress"]>>,
241
272
  ) => void,
242
273
  /** Number of nodes to send the request to. Leave undefined to send to all nodes */
243
274
  nodes?: number,
244
275
  ) => Promise<
245
- Array<PromiseSettledResult<P["success"]["inferOut"]> & { node: string }>
276
+ Array<
277
+ PromiseSettledResult<Schema.InferOutput<P["success"]>> & { node: string }
278
+ >
246
279
  >;
247
280
  };
248
281