@procedures/client 0.46.0 → 0.47.2
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/CHANGELOG.md +99 -68
- package/README.md +4 -4
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/http/server/transport.d.ts +5 -0
- package/dist/adapters/http/server/transport.d.ts.map +1 -1
- package/dist/adapters/http/server/transport.js +7 -0
- package/dist/adapters/http/server/transport.js.map +1 -1
- package/dist/adapters/local/client/transport.d.ts.map +1 -1
- package/dist/adapters/local/client/transport.js +12 -1
- package/dist/adapters/local/client/transport.js.map +1 -1
- package/dist/adapters/websocket/client/node.d.ts.map +1 -1
- package/dist/adapters/websocket/client/node.js +9 -2
- package/dist/adapters/websocket/client/node.js.map +1 -1
- package/dist/adapters/websocket/server/transport.d.ts.map +1 -1
- package/dist/adapters/websocket/server/transport.js +14 -5
- package/dist/adapters/websocket/server/transport.js.map +1 -1
- package/dist/browser.d.ts +2 -2
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +7 -3
- package/dist/browser.js.map +1 -1
- package/dist/client/client.d.ts +10 -1
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +46 -5
- package/dist/client/client.js.map +1 -1
- package/dist/client/errors/known-codes.d.ts +16 -0
- package/dist/client/errors/known-codes.d.ts.map +1 -0
- package/dist/client/errors/known-codes.js +20 -0
- package/dist/client/errors/known-codes.js.map +1 -0
- package/dist/client/validation/index.d.ts +1 -1
- package/dist/client/validation/index.js +1 -1
- package/dist/events/publisher.js +1 -1
- package/dist/events/publisher.js.map +1 -1
- package/dist/procedures/caller.d.ts +1 -1
- package/dist/procedures/caller.js +1 -1
- package/dist/procedures/collection/admission.d.ts +1 -1
- package/dist/procedures/collection/admission.js +1 -1
- package/dist/procedures/core/array.js +1 -1
- package/dist/procedures/core/array.js.map +1 -1
- package/dist/procedures/core/comparison.js +1 -1
- package/dist/procedures/core/comparison.js.map +1 -1
- package/dist/procedures/core/index.d.ts.map +1 -1
- package/dist/procedures/core/index.js +4 -2
- package/dist/procedures/core/index.js.map +1 -1
- package/dist/procedures/core/math.js +1 -1
- package/dist/procedures/core/math.js.map +1 -1
- package/dist/procedures/core/meta.js +1 -1
- package/dist/procedures/core/meta.js.map +1 -1
- package/dist/procedures/core/object.js +1 -1
- package/dist/procedures/core/object.js.map +1 -1
- package/dist/procedures/core/operands.d.ts.map +1 -1
- package/dist/procedures/core/operands.js +7 -2
- package/dist/procedures/core/operands.js.map +1 -1
- package/dist/procedures/core/outputs.d.ts +1 -1
- package/dist/procedures/core/outputs.d.ts.map +1 -1
- package/dist/procedures/core/outputs.js +1 -1
- package/dist/procedures/core/outputs.js.map +1 -1
- package/dist/procedures/core/string.js +1 -1
- package/dist/procedures/core/string.js.map +1 -1
- package/dist/procedures/core/type.js +1 -1
- package/dist/procedures/core/type.js.map +1 -1
- package/dist/procedures/define-procedure.d.ts.map +1 -1
- package/dist/procedures/define-procedure.js +28 -12
- package/dist/procedures/define-procedure.js.map +1 -1
- package/dist/procedures/index.d.ts +6 -5
- package/dist/procedures/index.d.ts.map +1 -1
- package/dist/procedures/index.js +6 -4
- package/dist/procedures/index.js.map +1 -1
- package/dist/procedures/invoke.d.ts.map +1 -1
- package/dist/procedures/invoke.js +14 -1
- package/dist/procedures/invoke.js.map +1 -1
- package/dist/procedures/module.d.ts +34 -0
- package/dist/procedures/module.d.ts.map +1 -1
- package/dist/procedures/module.js +90 -0
- package/dist/procedures/module.js.map +1 -1
- package/dist/procedures/ref.d.ts +10 -1
- package/dist/procedures/ref.d.ts.map +1 -1
- package/dist/procedures/ref.js +64 -0
- package/dist/procedures/ref.js.map +1 -1
- package/dist/procedures/registry.d.ts +64 -0
- package/dist/procedures/registry.d.ts.map +1 -1
- package/dist/procedures/registry.js +60 -0
- package/dist/procedures/registry.js.map +1 -1
- package/dist/procedures/segments.d.ts.map +1 -1
- package/dist/procedures/segments.js +13 -3
- package/dist/procedures/segments.js.map +1 -1
- package/dist/procedures/types.d.ts +6 -0
- package/dist/procedures/types.d.ts.map +1 -1
- package/dist/procedures/types.js.map +1 -1
- package/dist/server/error-policy.d.ts.map +1 -1
- package/dist/server/error-policy.js +2 -1
- package/dist/server/error-policy.js.map +1 -1
- package/dist/server/face-rules.d.ts +1 -1
- package/dist/server/face-rules.js +1 -1
- package/dist/server/host-procedures.d.ts.map +1 -1
- package/dist/server/host-procedures.js +12 -8
- package/dist/server/host-procedures.js.map +1 -1
- package/dist/server/procedure-server.d.ts +18 -5
- package/dist/server/procedure-server.d.ts.map +1 -1
- package/dist/server/procedure-server.js +28 -8
- package/dist/server/procedure-server.js.map +1 -1
- package/dist/server/server.d.ts +5 -0
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +9 -1
- package/dist/server/server.js.map +1 -1
- package/dist/testing/transport-contract.d.ts +1 -1
- package/dist/testing/transport-contract.js +2 -2
- package/dist/testing/transport-contract.js.map +1 -1
- package/dist/tracing/traceparent.d.ts +6 -0
- package/dist/tracing/traceparent.d.ts.map +1 -1
- package/dist/tracing/traceparent.js +27 -6
- package/dist/tracing/traceparent.js.map +1 -1
- package/package.json +5 -4
- package/src/adapters/http/server/transport.ts +8 -0
- package/src/adapters/local/client/transport.ts +11 -1
- package/src/adapters/websocket/client/node.ts +11 -2
- package/src/adapters/websocket/server/transport.ts +17 -5
- package/src/browser.ts +11 -0
- package/src/client/client.ts +46 -4
- package/src/client/errors/known-codes.ts +22 -0
- package/src/client/validation/index.ts +1 -1
- package/src/events/publisher.ts +1 -1
- package/src/procedures/caller.ts +1 -1
- package/src/procedures/collection/admission.ts +1 -1
- package/src/procedures/core/array.ts +1 -1
- package/src/procedures/core/comparison.ts +1 -1
- package/src/procedures/core/index.ts +4 -1
- package/src/procedures/core/math.ts +1 -1
- package/src/procedures/core/meta.ts +1 -1
- package/src/procedures/core/object.ts +1 -1
- package/src/procedures/core/operands.ts +8 -1
- package/src/procedures/core/outputs.ts +1 -1
- package/src/procedures/core/string.ts +1 -1
- package/src/procedures/core/type.ts +1 -1
- package/src/procedures/define-procedure.ts +25 -10
- package/src/procedures/index.ts +7 -2
- package/src/procedures/invoke.ts +15 -1
- package/src/procedures/module.ts +113 -2
- package/src/procedures/ref.ts +58 -1
- package/src/procedures/registry.ts +99 -0
- package/src/procedures/segments.ts +12 -3
- package/src/procedures/types.ts +6 -0
- package/src/server/error-policy.ts +2 -1
- package/src/server/face-rules.ts +1 -1
- package/src/server/host-procedures.ts +12 -8
- package/src/server/procedure-server.ts +29 -8
- package/src/server/server.ts +10 -1
- package/src/testing/transport-contract.ts +2 -2
- package/src/tracing/traceparent.ts +28 -5
|
@@ -146,7 +146,8 @@ export interface ProcedureServerOptions extends ServerOptions {
|
|
|
146
146
|
* the server answers `UNAUTHORIZED`. Only a local request (`LOCAL_CREDENTIALS`) skips it. The
|
|
147
147
|
* server refuses a request without credentials (CLI-1). Before, only the Express middleware of
|
|
148
148
|
* the peer examined the token, so a `ProcedureServer` with the HTTP or WebSocket transport of the
|
|
149
|
-
* core and the token of a host policy accepted each request.
|
|
149
|
+
* core and the token of a host policy accepted each request. An empty token means "refuse each
|
|
150
|
+
* network request": no presented token matches it, not even an empty one.
|
|
150
151
|
*/
|
|
151
152
|
token?: string | undefined;
|
|
152
153
|
|
|
@@ -235,16 +236,18 @@ export interface RegisterProcedureOptions {
|
|
|
235
236
|
}
|
|
236
237
|
|
|
237
238
|
/**
|
|
238
|
-
* True when the presented token is the expected one.
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
239
|
+
* True when the presented token is the expected one. An empty expected token matches nothing, not
|
|
240
|
+
* even an empty presented token, so a server with an empty token refuses each network request.
|
|
241
|
+
* The comparison reads each character of the presented token one time, so its time depends only
|
|
242
|
+
* on what the caller sent. The time tells neither the expected token nor its length. The function
|
|
243
|
+
* runs in a browser too, so it uses no `node:crypto`.
|
|
242
244
|
*/
|
|
243
245
|
export function tokenMatches(expected: string, presented: string | undefined): boolean {
|
|
244
246
|
if (presented === undefined) return false;
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
|
|
247
|
+
// An empty expected token and a difference of the lengths make the result false, after the same
|
|
248
|
+
// loop as an equal length. The modulo reuses the expected characters for a longer token.
|
|
249
|
+
let difference = (expected.length === 0 ? 1 : 0) | (expected.length ^ presented.length);
|
|
250
|
+
for (let index = 0; index < presented.length; index++) difference |= presented.charCodeAt(index) ^ expected.charCodeAt(index % expected.length);
|
|
248
251
|
return difference === 0;
|
|
249
252
|
}
|
|
250
253
|
|
|
@@ -835,6 +838,16 @@ export class ProcedureServer extends Server implements RepositoryProvider, StopP
|
|
|
835
838
|
return procedure ? (request) => this.invoke(procedure, request) : null;
|
|
836
839
|
}
|
|
837
840
|
|
|
841
|
+
/**
|
|
842
|
+
* A miss of a lazy registry loads the packages of the path, then the server looks up the
|
|
843
|
+
* handler again (roadmap O93). An eager registry, or a server that does not serve its registry,
|
|
844
|
+
* finds no handler here.
|
|
845
|
+
*/
|
|
846
|
+
protected override findLateHandler(method: Method, request: ServerRequest<unknown>): Promise<ServerHandler | null> | null {
|
|
847
|
+
if (!this.servesRegistry || !this.procedureRegistry.lazy) return null;
|
|
848
|
+
return this.procedureRegistry.resolve(methodToPath(method)).then(() => this.findHandler(method, request));
|
|
849
|
+
}
|
|
850
|
+
|
|
838
851
|
/**
|
|
839
852
|
* Run a procedure for a request. A keyed call to a procedure that is not repeatable runs one
|
|
840
853
|
* time for its key (R1).
|
|
@@ -1207,6 +1220,14 @@ export class ProcedureServer extends Server implements RepositoryProvider, StopP
|
|
|
1207
1220
|
return this.servedKeys().size;
|
|
1208
1221
|
}
|
|
1209
1222
|
|
|
1223
|
+
/**
|
|
1224
|
+
* This method loads each package of a lazy registry that the server serves (roadmap O93). Then
|
|
1225
|
+
* `procedureCount` and the lists count each procedure. For an eager registry it does nothing.
|
|
1226
|
+
*/
|
|
1227
|
+
async loadAll(): Promise<void> {
|
|
1228
|
+
if (this.servesRegistry && this.procedureRegistry.lazy) await this.procedureRegistry.loadAll();
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1210
1231
|
/**
|
|
1211
1232
|
* Check if the server serves a procedure now.
|
|
1212
1233
|
*
|
package/src/server/server.ts
CHANGED
|
@@ -309,7 +309,8 @@ export class Server {
|
|
|
309
309
|
|
|
310
310
|
try {
|
|
311
311
|
// Find handler
|
|
312
|
-
|
|
312
|
+
// A miss can load the procedure first (a lazy registry, roadmap O93). A hit does not wait.
|
|
313
|
+
const handler = this.findHandler(request.method, request) ?? (await this.findLateHandler(request.method, request));
|
|
313
314
|
if (!handler) {
|
|
314
315
|
throw new HandlerNotFoundError(request.method);
|
|
315
316
|
}
|
|
@@ -363,6 +364,14 @@ export class Server {
|
|
|
363
364
|
return null;
|
|
364
365
|
}
|
|
365
366
|
|
|
367
|
+
/**
|
|
368
|
+
* This method finds a handler after `findHandler()` found none. The default finds none at once.
|
|
369
|
+
* `ProcedureServer` loads the procedure of a lazy registry here (roadmap O93).
|
|
370
|
+
*/
|
|
371
|
+
protected findLateHandler(_method: Method, _request: ServerRequest<unknown>): Promise<ServerHandler | null> | null {
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
|
|
366
375
|
/**
|
|
367
376
|
* Check if a method matches a matcher.
|
|
368
377
|
*/
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
* skips the cases of that feature. Each skip thus is data in the test file of the face.
|
|
21
21
|
*
|
|
22
22
|
* The suite is the entry point `@procedures/client/testing`, so a face in another package (and
|
|
23
|
-
* a server of an app
|
|
23
|
+
* a server of an app) runs the same cases with the client that it uses. The
|
|
24
24
|
* suite imports no test runner: the caller gives `describe`, `it`, `afterEach` and `expect`
|
|
25
25
|
* (`ContractRunner`). Those of Vitest fit.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
-
import
|
|
28
|
+
import * as z from "zod";
|
|
29
29
|
import {
|
|
30
30
|
Client,
|
|
31
31
|
VersionConflictError,
|
|
@@ -20,12 +20,35 @@ export interface TraceContext {
|
|
|
20
20
|
readonly sampled: boolean;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* The size of the pool of random bytes. One fill gives 256 trace ids or 512 span ids. Before
|
|
25
|
+
* (roadmap O94), each id called `getRandomValues` for 8 or 16 bytes: in a chain of 200 steps, the
|
|
26
|
+
* random ids took about 10 % of the per-step time of the host.
|
|
27
|
+
*/
|
|
28
|
+
export const RANDOM_POOL_BYTES = 4096;
|
|
29
|
+
|
|
30
|
+
/** The two hex digits of each byte value. */
|
|
31
|
+
const HEX = Array.from({ length: 256 }, (_, value) => value.toString(16).padStart(2, "0"));
|
|
32
|
+
|
|
33
|
+
const pool = new Uint8Array(RANDOM_POOL_BYTES);
|
|
34
|
+
// The pool starts empty: the first id fills it
|
|
35
|
+
let next = RANDOM_POOL_BYTES;
|
|
36
|
+
|
|
37
|
+
/** This function fills the pool with new random bytes. Each byte goes to one id only. */
|
|
38
|
+
function refill(): void {
|
|
25
39
|
const crypto = (globalThis as { crypto?: { getRandomValues?: (array: Uint8Array) => Uint8Array } }).crypto;
|
|
26
|
-
if (crypto?.getRandomValues) crypto.getRandomValues(
|
|
27
|
-
else for (let index = 0; index <
|
|
28
|
-
|
|
40
|
+
if (crypto?.getRandomValues) crypto.getRandomValues(pool);
|
|
41
|
+
else for (let index = 0; index < RANDOM_POOL_BYTES; index++) pool[index] = Math.floor(Math.random() * 256);
|
|
42
|
+
next = 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** This function gives `bytes` random bytes of the pool as hex digits. `bytes` is 16 or less. */
|
|
46
|
+
function randomHex(bytes: number): string {
|
|
47
|
+
if (next + bytes > RANDOM_POOL_BYTES) refill();
|
|
48
|
+
let hex = "";
|
|
49
|
+
for (let index = next; index < next + bytes; index++) hex += HEX[pool[index]!]!;
|
|
50
|
+
next += bytes;
|
|
51
|
+
return hex;
|
|
29
52
|
}
|
|
30
53
|
|
|
31
54
|
/** This function makes a new trace id: 32 random hex digits. */
|