@zudojs/rpc 1.4.3 → 1.5.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.
Files changed (114) hide show
  1. package/README.md +22 -0
  2. package/dist/index.d.ts +1 -2
  3. package/dist/index.js +1 -2
  4. package/dist/rpc/client/index.d.ts +0 -1
  5. package/dist/rpc/client/index.js +0 -1
  6. package/dist/rpc/client/rpcClient.core.d.ts +0 -1
  7. package/dist/rpc/client/rpcClient.core.js +0 -1
  8. package/dist/rpc/client/rpcWireError.helper.d.ts +0 -1
  9. package/dist/rpc/client/rpcWireError.helper.js +0 -1
  10. package/dist/rpc/constants/index.d.ts +1 -2
  11. package/dist/rpc/constants/index.js +1 -2
  12. package/dist/rpc/constants/rpcConstants.core.d.ts +7 -1
  13. package/dist/rpc/constants/rpcConstants.core.js +7 -1
  14. package/dist/rpc/context/index.d.ts +0 -1
  15. package/dist/rpc/context/index.js +0 -1
  16. package/dist/rpc/context/rpcContext.type.d.ts +0 -1
  17. package/dist/rpc/context/rpcContext.type.js +0 -1
  18. package/dist/rpc/dispatcher/index.d.ts +0 -1
  19. package/dist/rpc/dispatcher/index.js +0 -1
  20. package/dist/rpc/dispatcher/rpcDispatcher.core.d.ts +0 -1
  21. package/dist/rpc/dispatcher/rpcDispatcher.core.js +10 -4
  22. package/dist/rpc/dispatcher/rpcDispatcher.downstream.d.ts +26 -0
  23. package/dist/rpc/dispatcher/rpcDispatcher.downstream.js +41 -0
  24. package/dist/rpc/errors/index.d.ts +0 -1
  25. package/dist/rpc/errors/index.js +0 -1
  26. package/dist/rpc/errors/rpc.errors.d.ts +0 -1
  27. package/dist/rpc/errors/rpc.errors.js +0 -1
  28. package/dist/rpc/errors/rpcErrorCause.helper.d.ts +10 -0
  29. package/dist/rpc/errors/rpcErrorCause.helper.js +18 -0
  30. package/dist/rpc/interceptor/index.d.ts +0 -1
  31. package/dist/rpc/interceptor/index.js +0 -1
  32. package/dist/rpc/interceptor/rpcInterceptor.type.d.ts +0 -1
  33. package/dist/rpc/interceptor/rpcInterceptor.type.js +0 -1
  34. package/dist/rpc/middleware/index.d.ts +0 -1
  35. package/dist/rpc/middleware/index.js +0 -1
  36. package/dist/rpc/middleware/rpcMiddleware.core.d.ts +0 -1
  37. package/dist/rpc/middleware/rpcMiddleware.core.js +0 -1
  38. package/dist/rpc/procedure/index.d.ts +0 -1
  39. package/dist/rpc/procedure/index.js +0 -1
  40. package/dist/rpc/procedure/rpcProcedure.type.d.ts +0 -1
  41. package/dist/rpc/procedure/rpcProcedure.type.js +0 -1
  42. package/dist/rpc/procedure/rpcProcedureRegistry.core.d.ts +0 -1
  43. package/dist/rpc/procedure/rpcProcedureRegistry.core.js +0 -1
  44. package/dist/rpc/procedure/rpcProcedureRouter.core.d.ts +0 -1
  45. package/dist/rpc/procedure/rpcProcedureRouter.core.js +0 -1
  46. package/dist/rpc/reliability/cancellation/rpcAbort.helper.d.ts +0 -1
  47. package/dist/rpc/reliability/cancellation/rpcAbort.helper.js +0 -1
  48. package/dist/rpc/reliability/cancellation/rpcCancellation.helper.d.ts +0 -1
  49. package/dist/rpc/reliability/cancellation/rpcCancellation.helper.js +0 -1
  50. package/dist/rpc/reliability/deadline/rpcDeadline.helper.d.ts +0 -1
  51. package/dist/rpc/reliability/deadline/rpcDeadline.helper.js +0 -1
  52. package/dist/rpc/reliability/index.d.ts +0 -1
  53. package/dist/rpc/reliability/index.js +0 -1
  54. package/dist/rpc/reliability/retry/rpcRetry.helper.d.ts +9 -1
  55. package/dist/rpc/reliability/retry/rpcRetry.helper.js +0 -1
  56. package/dist/rpc/reliability/timeout/rpcTimeout.helper.d.ts +0 -1
  57. package/dist/rpc/reliability/timeout/rpcTimeout.helper.js +0 -1
  58. package/dist/rpc/server/index.d.ts +0 -1
  59. package/dist/rpc/server/index.js +0 -1
  60. package/dist/rpc/server/rpcBaseErrorMapping.helper.d.ts +0 -1
  61. package/dist/rpc/server/rpcBaseErrorMapping.helper.js +0 -1
  62. package/dist/rpc/server/rpcDownstreamMapping.helper.d.ts +15 -0
  63. package/dist/rpc/server/rpcDownstreamMapping.helper.js +27 -0
  64. package/dist/rpc/server/rpcErrorMapping.helper.d.ts +2 -4
  65. package/dist/rpc/server/rpcErrorMapping.helper.js +6 -4
  66. package/dist/rpc/server/rpcServer.core.d.ts +0 -1
  67. package/dist/rpc/server/rpcServer.core.js +0 -1
  68. package/dist/rpc/streaming/index.d.ts +0 -1
  69. package/dist/rpc/streaming/index.js +0 -1
  70. package/dist/rpc/streaming/rpcStreaming.type.d.ts +0 -1
  71. package/dist/rpc/streaming/rpcStreaming.type.js +0 -1
  72. package/dist/rpc/transport/codec/index.d.ts +0 -1
  73. package/dist/rpc/transport/codec/index.js +0 -1
  74. package/dist/rpc/transport/codec/rpcBody.helper.d.ts +0 -1
  75. package/dist/rpc/transport/codec/rpcBody.helper.js +0 -1
  76. package/dist/rpc/transport/codec/rpcCodec.helper.d.ts +0 -1
  77. package/dist/rpc/transport/codec/rpcCodec.helper.js +0 -1
  78. package/dist/rpc/transport/http/index.d.ts +0 -1
  79. package/dist/rpc/transport/http/index.js +0 -1
  80. package/dist/rpc/transport/http/rpcFetchHandler.core.d.ts +0 -1
  81. package/dist/rpc/transport/http/rpcFetchHandler.core.js +0 -1
  82. package/dist/rpc/transport/http/rpcHttpExchange.helper.d.ts +0 -1
  83. package/dist/rpc/transport/http/rpcHttpExchange.helper.js +1 -10
  84. package/dist/rpc/transport/http/rpcHttpStatus.helper.d.ts +0 -1
  85. package/dist/rpc/transport/http/rpcHttpStatus.helper.js +0 -1
  86. package/dist/rpc/transport/http/rpcHttpTransport.core.d.ts +0 -1
  87. package/dist/rpc/transport/http/rpcHttpTransport.core.js +0 -1
  88. package/dist/rpc/transport/index.d.ts +0 -1
  89. package/dist/rpc/transport/index.js +0 -1
  90. package/dist/rpc/transport/memory/index.d.ts +0 -1
  91. package/dist/rpc/transport/memory/index.js +0 -1
  92. package/dist/rpc/transport/memory/rpcMemoryTransport.core.d.ts +0 -1
  93. package/dist/rpc/transport/memory/rpcMemoryTransport.core.js +0 -1
  94. package/dist/rpc/transport/rpcTransport.type.d.ts +0 -1
  95. package/dist/rpc/transport/rpcTransport.type.js +0 -1
  96. package/dist/rpc/types/index.d.ts +0 -1
  97. package/dist/rpc/types/index.js +0 -1
  98. package/dist/rpc/types/rpcMetadata.type.d.ts +0 -1
  99. package/dist/rpc/types/rpcMetadata.type.js +0 -1
  100. package/dist/rpc/types/rpcProcedureName.type.d.ts +0 -1
  101. package/dist/rpc/types/rpcProcedureName.type.js +0 -1
  102. package/dist/rpc/types/rpcRequest.type.d.ts +0 -1
  103. package/dist/rpc/types/rpcRequest.type.js +0 -1
  104. package/dist/rpc/types/rpcResponse.type.d.ts +0 -1
  105. package/dist/rpc/types/rpcResponse.type.js +0 -1
  106. package/dist/rpc/validation/index.d.ts +0 -1
  107. package/dist/rpc/validation/index.js +0 -1
  108. package/dist/rpc/validation/rpcValidation.core.d.ts +0 -1
  109. package/dist/rpc/validation/rpcValidation.core.js +0 -1
  110. package/dist/testing/index.d.ts +0 -1
  111. package/dist/testing/index.js +0 -1
  112. package/package.json +7 -7
  113. package/dist/rpc/validation/rpcUnsafeKey.helper.d.ts +0 -18
  114. package/dist/rpc/validation/rpcUnsafeKey.helper.js +0 -60
package/README.md CHANGED
@@ -206,6 +206,14 @@ A pending call's deadline and a `retry()` backoff hold a normal (ref'd)
206
206
  timer, cleared as soon as the call settles, so a plain script awaiting a call
207
207
  stays alive until it resolves or times out.
208
208
 
209
+ `retry(operation, { attempts, delay, backoff, jitter, retryIf, signal })`
210
+ counts **calls**, not retries: `attempts: 3` runs the operation up to three
211
+ times (one call plus two retries) and `attempts: 1` never retries. This is
212
+ the opposite of `@zudojs/lifecycle`, whose `attempts` counts the retries after
213
+ the first call. `delay` is the base backoff in milliseconds (`"fixed"` by
214
+ default; `"linear"` and `"exponential"` scale it per attempt, capped by
215
+ `maxDelay`), and `jitter` defaults to `"full"`.
216
+
209
217
  ### Middleware and trusted identity
210
218
 
211
219
  Everything in a frame, `metadata` included, is written by the caller: any
@@ -274,6 +282,20 @@ generic message. To send a custom code, build the error with `expose: true`. A h
274
282
  `output` schema is treated the same way: it is the server's fault, not the
275
283
  caller's.
276
284
 
285
+ A failure of something the handler *called* is reported as
286
+ `RPC_UNAVAILABLE`, not as an internal error and not as this procedure's own
287
+ timeout: an `RPCTransportError`, or an `RPCTimeoutError` naming another
288
+ procedure, thrown inside a handler or middleware — what an `RPCClient`
289
+ raises when a downstream service cannot be reached or does not answer — is
290
+ wrapped in an `RPCUnavailableError` (the original as `cause`) and answered
291
+ with `{ code: "RPC_UNAVAILABLE", message: UNAVAILABLE_ERROR_MESSAGE }`, so
292
+ the caller can retry while the downstream error's own text stays out of the
293
+ response; the wrapped error is handed to `onInternalError` for logging. A
294
+ timeout about the procedure itself still goes out as `RPC_TIMEOUT`: the
295
+ dispatcher's own (including when a cooperative handler rethrows
296
+ `context.signal.reason`) and one a handler throws under its own procedure
297
+ name.
298
+
277
299
  ```typescript
278
300
  const server = new RPCServer(undefined, undefined, {
279
301
  limits: { maxPayloadBytes: 256 * 1024, maxRequestIdLength: 128 },
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@
27
27
  */
28
28
  export type { RPCProcedureName, RPCMetadata, RPCMetadataOptions, RPCRequest, RPCRequestOptions, RPCErrorPayload, RPCResponse, } from "./rpc/types/index.js";
29
29
  export { createRPCMetadata, createRPCRequest, createRPCResponse, createRPCErrorResponse, } from "./rpc/types/index.js";
30
- export { DEFAULT_RPC_TIMEOUT, MAX_RPC_PAYLOAD_SIZE, MAX_RPC_REQUEST_ID_LENGTH, MAX_PENDING_REQUESTS, MAX_MIDDLEWARE, MAX_PROCEDURES, MAX_PROCEDURE_NAME_LENGTH, MAX_TIMER_DELAY, PROCEDURE_NAME_PATTERN, INTERNAL_ERROR_MESSAGE, DEFAULT_RPC_HTTP_MAX_BODY_BYTES, MAX_RPC_FRAME_DEPTH, } from "./rpc/constants/index.js";
30
+ export { DEFAULT_RPC_TIMEOUT, MAX_RPC_PAYLOAD_SIZE, MAX_RPC_REQUEST_ID_LENGTH, MAX_PENDING_REQUESTS, MAX_MIDDLEWARE, MAX_PROCEDURES, MAX_PROCEDURE_NAME_LENGTH, MAX_TIMER_DELAY, PROCEDURE_NAME_PATTERN, INTERNAL_ERROR_MESSAGE, UNAVAILABLE_ERROR_MESSAGE, DEFAULT_RPC_HTTP_MAX_BODY_BYTES, MAX_RPC_FRAME_DEPTH, } from "./rpc/constants/index.js";
31
31
  export type { RPCRequestLimits, RPCSchema } from "./rpc/validation/index.js";
32
32
  export { assertValidProcedureName, assertValidRequest, measurePayloadBytes, toValidationIssues, parseInput, parseOutput, } from "./rpc/validation/index.js";
33
33
  export type { RPCErrorOptions } from "./rpc/errors/index.js";
@@ -50,4 +50,3 @@ export type { RPCInterceptor } from "./rpc/interceptor/index.js";
50
50
  export { createNoopRPCInterceptor } from "./rpc/interceptor/index.js";
51
51
  export type { RPCStreamingHandler, RPCStreamingProcedure, } from "./rpc/streaming/index.js";
52
52
  export { createRPCStreamingProcedure } from "./rpc/streaming/index.js";
53
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@
27
27
  */
28
28
  export { createRPCMetadata, createRPCRequest, createRPCResponse, createRPCErrorResponse, } from "./rpc/types/index.js";
29
29
  // Constants
30
- export { DEFAULT_RPC_TIMEOUT, MAX_RPC_PAYLOAD_SIZE, MAX_RPC_REQUEST_ID_LENGTH, MAX_PENDING_REQUESTS, MAX_MIDDLEWARE, MAX_PROCEDURES, MAX_PROCEDURE_NAME_LENGTH, MAX_TIMER_DELAY, PROCEDURE_NAME_PATTERN, INTERNAL_ERROR_MESSAGE, DEFAULT_RPC_HTTP_MAX_BODY_BYTES, MAX_RPC_FRAME_DEPTH, } from "./rpc/constants/index.js";
30
+ export { DEFAULT_RPC_TIMEOUT, MAX_RPC_PAYLOAD_SIZE, MAX_RPC_REQUEST_ID_LENGTH, MAX_PENDING_REQUESTS, MAX_MIDDLEWARE, MAX_PROCEDURES, MAX_PROCEDURE_NAME_LENGTH, MAX_TIMER_DELAY, PROCEDURE_NAME_PATTERN, INTERNAL_ERROR_MESSAGE, UNAVAILABLE_ERROR_MESSAGE, DEFAULT_RPC_HTTP_MAX_BODY_BYTES, MAX_RPC_FRAME_DEPTH, } from "./rpc/constants/index.js";
31
31
  export { assertValidProcedureName, assertValidRequest, measurePayloadBytes, toValidationIssues, parseInput, parseOutput, } from "./rpc/validation/index.js";
32
32
  export { RPCError, RPCProcedureNotFoundError, RPCInvalidRequestError, RPCValidationError, RPCAuthenticationError, RPCForbiddenError, RPCTimeoutError, RPCCancelledError, RPCInternalError, RPCTransportError, RPCSerializationError, RPCDeserializationError, RPCUnavailableError, RPCRateLimitedError, RPCDeadlineExceededError, RPCDuplicateProcedureError, createRPCError, isRPCError, } from "./rpc/errors/index.js";
33
33
  export { createRPCProcedure } from "./rpc/procedure/index.js";
@@ -44,4 +44,3 @@ export * from "./rpc/client/index.js";
44
44
  export { createTimeout, withTimeout, runWithTimeout, getRemainingTime, isDeadlineExceeded, throwIfDeadlineExceeded, readDeadline, createCancellableSignal, cancelSignal, throwIfCancelled, combineSignals, DEFAULT_RETRY_OPTIONS, calculateRetryDelay, retry, } from "./rpc/reliability/index.js";
45
45
  export { createNoopRPCInterceptor } from "./rpc/interceptor/index.js";
46
46
  export { createRPCStreamingProcedure } from "./rpc/streaming/index.js";
47
- //# sourceMappingURL=index.js.map
@@ -5,4 +5,3 @@
5
5
  export type { RPCCallOptions, RPCClientOptions } from "./rpcClient.core.js";
6
6
  export { RPCClient } from "./rpcClient.core.js";
7
7
  export { rpcErrorFromWire } from "./rpcWireError.helper.js";
8
- //# sourceMappingURL=index.d.ts.map
@@ -4,4 +4,3 @@
4
4
  */
5
5
  export { RPCClient } from "./rpcClient.core.js";
6
6
  export { rpcErrorFromWire } from "./rpcWireError.helper.js";
7
- //# sourceMappingURL=index.js.map
@@ -76,4 +76,3 @@ export declare class RPCClient {
76
76
  */
77
77
  private toCancellation;
78
78
  }
79
- //# sourceMappingURL=rpcClient.core.d.ts.map
@@ -200,4 +200,3 @@ function withWireCode(error) {
200
200
  }
201
201
  return error;
202
202
  }
203
- //# sourceMappingURL=rpcClient.core.js.map
@@ -10,4 +10,3 @@ import { RPCError } from "../errors/rpc.errors.js";
10
10
  * `"RPC_NOT_FOUND"` …) and its `details`.
11
11
  */
12
12
  export declare function rpcErrorFromWire(payload: RPCErrorPayload | undefined, procedure: string): RPCError;
13
- //# sourceMappingURL=rpcWireError.helper.d.ts.map
@@ -68,4 +68,3 @@ function withWire(error, code, details) {
68
68
  }
69
69
  return error;
70
70
  }
71
- //# sourceMappingURL=rpcWireError.helper.js.map
@@ -3,5 +3,4 @@
3
3
  * and frame sizes, procedure-name rules, and the fixed internal-error
4
4
  * message returned to remote callers.
5
5
  */
6
- export { DEFAULT_RPC_TIMEOUT, MAX_RPC_PAYLOAD_SIZE, MAX_RPC_REQUEST_ID_LENGTH, MAX_PENDING_REQUESTS, MAX_MIDDLEWARE, MAX_PROCEDURES, MAX_PROCEDURE_NAME_LENGTH, MAX_TIMER_DELAY, PROCEDURE_NAME_PATTERN, INTERNAL_ERROR_MESSAGE, DEFAULT_RPC_HTTP_MAX_BODY_BYTES, MAX_RPC_FRAME_DEPTH, } from "./rpcConstants.core.js";
7
- //# sourceMappingURL=index.d.ts.map
6
+ export { DEFAULT_RPC_TIMEOUT, MAX_RPC_PAYLOAD_SIZE, MAX_RPC_REQUEST_ID_LENGTH, MAX_PENDING_REQUESTS, MAX_MIDDLEWARE, MAX_PROCEDURES, MAX_PROCEDURE_NAME_LENGTH, MAX_TIMER_DELAY, PROCEDURE_NAME_PATTERN, INTERNAL_ERROR_MESSAGE, UNAVAILABLE_ERROR_MESSAGE, DEFAULT_RPC_HTTP_MAX_BODY_BYTES, MAX_RPC_FRAME_DEPTH, } from "./rpcConstants.core.js";
@@ -3,5 +3,4 @@
3
3
  * and frame sizes, procedure-name rules, and the fixed internal-error
4
4
  * message returned to remote callers.
5
5
  */
6
- export { DEFAULT_RPC_TIMEOUT, MAX_RPC_PAYLOAD_SIZE, MAX_RPC_REQUEST_ID_LENGTH, MAX_PENDING_REQUESTS, MAX_MIDDLEWARE, MAX_PROCEDURES, MAX_PROCEDURE_NAME_LENGTH, MAX_TIMER_DELAY, PROCEDURE_NAME_PATTERN, INTERNAL_ERROR_MESSAGE, DEFAULT_RPC_HTTP_MAX_BODY_BYTES, MAX_RPC_FRAME_DEPTH, } from "./rpcConstants.core.js";
7
- //# sourceMappingURL=index.js.map
6
+ export { DEFAULT_RPC_TIMEOUT, MAX_RPC_PAYLOAD_SIZE, MAX_RPC_REQUEST_ID_LENGTH, MAX_PENDING_REQUESTS, MAX_MIDDLEWARE, MAX_PROCEDURES, MAX_PROCEDURE_NAME_LENGTH, MAX_TIMER_DELAY, PROCEDURE_NAME_PATTERN, INTERNAL_ERROR_MESSAGE, UNAVAILABLE_ERROR_MESSAGE, DEFAULT_RPC_HTTP_MAX_BODY_BYTES, MAX_RPC_FRAME_DEPTH, } from "./rpcConstants.core.js";
@@ -54,6 +54,13 @@ export declare const MAX_TIMER_DELAY = 2147483647;
54
54
  * request id instead.
55
55
  */
56
56
  export declare const INTERNAL_ERROR_MESSAGE = "The server encountered an internal error while handling this request.";
57
+ /**
58
+ * Message sent with `RPC_UNAVAILABLE` when a handler failed because a
59
+ * service it called — over RPC or otherwise — could not be reached or
60
+ * timed out. The downstream error's own text (hosts, paths, timeouts) is
61
+ * server detail and goes to `onInternalError` instead.
62
+ */
63
+ export declare const UNAVAILABLE_ERROR_MESSAGE = "A service this request depends on is temporarily unavailable.";
57
64
  /**
58
65
  * Default limit, in bytes, on an HTTP request or response body carrying
59
66
  * one RPC frame: the payload limit plus headroom for the frame envelope
@@ -65,4 +72,3 @@ export declare const DEFAULT_RPC_HTTP_MAX_BODY_BYTES: number;
65
72
  * Bounds the work a hostile peer can force with deeply nested JSON.
66
73
  */
67
74
  export declare const MAX_RPC_FRAME_DEPTH = 128;
68
- //# sourceMappingURL=rpcConstants.core.d.ts.map
@@ -54,6 +54,13 @@ export const MAX_TIMER_DELAY = 2_147_483_647;
54
54
  * request id instead.
55
55
  */
56
56
  export const INTERNAL_ERROR_MESSAGE = "The server encountered an internal error while handling this request.";
57
+ /**
58
+ * Message sent with `RPC_UNAVAILABLE` when a handler failed because a
59
+ * service it called — over RPC or otherwise — could not be reached or
60
+ * timed out. The downstream error's own text (hosts, paths, timeouts) is
61
+ * server detail and goes to `onInternalError` instead.
62
+ */
63
+ export const UNAVAILABLE_ERROR_MESSAGE = "A service this request depends on is temporarily unavailable.";
57
64
  /**
58
65
  * Default limit, in bytes, on an HTTP request or response body carrying
59
66
  * one RPC frame: the payload limit plus headroom for the frame envelope
@@ -65,4 +72,3 @@ export const DEFAULT_RPC_HTTP_MAX_BODY_BYTES = MAX_RPC_PAYLOAD_SIZE + 64 * 1024;
65
72
  * Bounds the work a hostile peer can force with deeply nested JSON.
66
73
  */
67
74
  export const MAX_RPC_FRAME_DEPTH = 128;
68
- //# sourceMappingURL=rpcConstants.core.js.map
@@ -4,4 +4,3 @@
4
4
  */
5
5
  export type { RPCAuthContext, RPCContext, RPCContextOptions, } from "./rpcContext.type.js";
6
6
  export { createRPCContext } from "./rpcContext.type.js";
7
- //# sourceMappingURL=index.d.ts.map
@@ -3,4 +3,3 @@
3
3
  * metadata, the transport's trusted `auth`, and the validated `input`.
4
4
  */
5
5
  export { createRPCContext } from "./rpcContext.type.js";
6
- //# sourceMappingURL=index.js.map
@@ -61,4 +61,3 @@ export declare function bindRPCContextInput(context: RPCContext, input: unknown)
61
61
  * Creates a new RPC context.
62
62
  */
63
63
  export declare function createRPCContext(request: RPCRequest, signal: AbortSignal, options?: RPCContextOptions): RPCContext;
64
- //# sourceMappingURL=rpcContext.type.d.ts.map
@@ -32,4 +32,3 @@ export function createRPCContext(request, signal, options = {}) {
32
32
  };
33
33
  return Object.freeze(context);
34
34
  }
35
- //# sourceMappingURL=rpcContext.type.js.map
@@ -1,3 +1,2 @@
1
1
  export type { RPCDispatcherOptions } from "./rpcDispatcher.core.js";
2
2
  export { RPCDispatcher } from "./rpcDispatcher.core.js";
3
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1 @@
1
1
  export { RPCDispatcher } from "./rpcDispatcher.core.js";
2
- //# sourceMappingURL=index.js.map
@@ -68,4 +68,3 @@ export declare class RPCDispatcher {
68
68
  */
69
69
  private resolveTimeout;
70
70
  }
71
- //# sourceMappingURL=rpcDispatcher.core.d.ts.map
@@ -5,6 +5,7 @@ import { DEFAULT_RPC_TIMEOUT } from "../constants/rpcConstants.core.js";
5
5
  import { parseInput, parseOutput } from "../validation/rpcValidation.core.js";
6
6
  import { readDeadline, throwIfDeadlineExceeded, } from "../reliability/deadline/rpcDeadline.helper.js";
7
7
  import { createTimeout } from "../reliability/timeout/rpcTimeout.helper.js";
8
+ import { toUpstreamError } from "./rpcDispatcher.downstream.js";
8
9
  import { abortReasonToRPCError, raceAbort, } from "../reliability/cancellation/rpcAbort.helper.js";
9
10
  /**
10
11
  * Dispatches RPC requests to registered procedures.
@@ -66,9 +67,15 @@ export class RPCDispatcher {
66
67
  ? parseInput(procedure.options.input, request.payload, request.procedure)
67
68
  : request.payload;
68
69
  bindRPCContextInput(context, input);
69
- const result = await this.middleware.execute(context, async () => {
70
- return procedure.handler(input, context);
71
- });
70
+ let result;
71
+ try {
72
+ result = await this.middleware.execute(context, async () => {
73
+ return procedure.handler(input, context);
74
+ });
75
+ }
76
+ catch (error) {
77
+ throw toUpstreamError(error, request.procedure, controller.signal);
78
+ }
72
79
  return procedure.options?.output
73
80
  ? parseOutput(procedure.options.output, result, request.procedure)
74
81
  : result;
@@ -148,4 +155,3 @@ export class RPCDispatcher {
148
155
  return configured;
149
156
  }
150
157
  }
151
- //# sourceMappingURL=rpcDispatcher.core.js.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Translation of downstream failures raised inside a handler.
3
+ *
4
+ * A handler that calls another service over RPC gets that client's errors:
5
+ * an `RPCTransportError` when the peer could not be reached, an
6
+ * `RPCTimeoutError` when it did not answer in time. Rethrown as they are,
7
+ * the transport error went out as `RPC_INTERNAL_ERROR` (its code is not
8
+ * public vocabulary) and the timeout as `RPC_TIMEOUT` — which told the
9
+ * caller *this* procedure had timed out, when it was a dependency that had.
10
+ * Both are one condition from the caller's point of view: the service is
11
+ * unavailable right now, and the call may be retried.
12
+ */
13
+ /**
14
+ * Returns the error a handler's failure should propagate as.
15
+ *
16
+ * A downstream failure becomes an `RPCUnavailableError` with the original
17
+ * as `cause`; the server maps it to `RPC_UNAVAILABLE` and hands the cause
18
+ * to `onInternalError`. Downstream means an `RPCTransportError` (only a
19
+ * transport raises one) or an `RPCTimeoutError` that names a procedure
20
+ * other than this one — an `RPCClient` stamps the procedure it was calling
21
+ * on every timeout it raises. A timeout about this procedure — the
22
+ * dispatcher's own, which a cooperative handler rethrows from
23
+ * `context.signal.reason`, or one a handler throws under its own name —
24
+ * stays `RPC_TIMEOUT`, as does everything else.
25
+ */
26
+ export declare function toUpstreamError(error: unknown, procedureName: string, signal: AbortSignal): unknown;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Translation of downstream failures raised inside a handler.
3
+ *
4
+ * A handler that calls another service over RPC gets that client's errors:
5
+ * an `RPCTransportError` when the peer could not be reached, an
6
+ * `RPCTimeoutError` when it did not answer in time. Rethrown as they are,
7
+ * the transport error went out as `RPC_INTERNAL_ERROR` (its code is not
8
+ * public vocabulary) and the timeout as `RPC_TIMEOUT` — which told the
9
+ * caller *this* procedure had timed out, when it was a dependency that had.
10
+ * Both are one condition from the caller's point of view: the service is
11
+ * unavailable right now, and the call may be retried.
12
+ */
13
+ import { RPCTimeoutError, RPCTransportError, RPCUnavailableError, } from "../errors/rpc.errors.js";
14
+ import { withCause } from "../errors/rpcErrorCause.helper.js";
15
+ import { UNAVAILABLE_ERROR_MESSAGE } from "../constants/rpcConstants.core.js";
16
+ /**
17
+ * Returns the error a handler's failure should propagate as.
18
+ *
19
+ * A downstream failure becomes an `RPCUnavailableError` with the original
20
+ * as `cause`; the server maps it to `RPC_UNAVAILABLE` and hands the cause
21
+ * to `onInternalError`. Downstream means an `RPCTransportError` (only a
22
+ * transport raises one) or an `RPCTimeoutError` that names a procedure
23
+ * other than this one — an `RPCClient` stamps the procedure it was calling
24
+ * on every timeout it raises. A timeout about this procedure — the
25
+ * dispatcher's own, which a cooperative handler rethrows from
26
+ * `context.signal.reason`, or one a handler throws under its own name —
27
+ * stays `RPC_TIMEOUT`, as does everything else.
28
+ */
29
+ export function toUpstreamError(error, procedureName, signal) {
30
+ if (signal.aborted && error === signal.reason) {
31
+ return error;
32
+ }
33
+ const downstream = error instanceof RPCTransportError ||
34
+ (error instanceof RPCTimeoutError &&
35
+ error.procedureName !== undefined &&
36
+ error.procedureName !== procedureName);
37
+ if (downstream) {
38
+ return withCause(new RPCUnavailableError(UNAVAILABLE_ERROR_MESSAGE, procedureName), error);
39
+ }
40
+ return error;
41
+ }
@@ -1,3 +1,2 @@
1
1
  export { RPCError, RPCProcedureNotFoundError, RPCInvalidRequestError, RPCValidationError, RPCAuthenticationError, RPCForbiddenError, RPCTimeoutError, RPCCancelledError, RPCInternalError, RPCTransportError, RPCSerializationError, RPCDeserializationError, RPCUnavailableError, RPCRateLimitedError, RPCDeadlineExceededError, RPCDuplicateProcedureError, createRPCError, isRPCError, } from "./rpc.errors.js";
2
2
  export type { RPCErrorOptions } from "./rpc.errors.js";
3
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1 @@
1
1
  export { RPCError, RPCProcedureNotFoundError, RPCInvalidRequestError, RPCValidationError, RPCAuthenticationError, RPCForbiddenError, RPCTimeoutError, RPCCancelledError, RPCInternalError, RPCTransportError, RPCSerializationError, RPCDeserializationError, RPCUnavailableError, RPCRateLimitedError, RPCDeadlineExceededError, RPCDuplicateProcedureError, createRPCError, isRPCError, } from "./rpc.errors.js";
2
- //# sourceMappingURL=index.js.map
@@ -1,3 +1,2 @@
1
1
  export { RPCError, RPCProcedureNotFoundError, RPCInvalidRequestError, RPCValidationError, RPCAuthenticationError, RPCForbiddenError, RPCTimeoutError, RPCCancelledError, RPCInternalError, RPCTransportError, RPCSerializationError, RPCDeserializationError, RPCUnavailableError, RPCRateLimitedError, RPCDeadlineExceededError, RPCDuplicateProcedureError, createRPCError, isRPCError, } from "@zudojs/errors";
2
2
  export type { RPCErrorOptions } from "@zudojs/errors";
3
- //# sourceMappingURL=rpc.errors.d.ts.map
@@ -1,2 +1 @@
1
1
  export { RPCError, RPCProcedureNotFoundError, RPCInvalidRequestError, RPCValidationError, RPCAuthenticationError, RPCForbiddenError, RPCTimeoutError, RPCCancelledError, RPCInternalError, RPCTransportError, RPCSerializationError, RPCDeserializationError, RPCUnavailableError, RPCRateLimitedError, RPCDeadlineExceededError, RPCDuplicateProcedureError, createRPCError, isRPCError, } from "@zudojs/errors";
2
- //# sourceMappingURL=rpc.errors.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Attaches a cause to an error whose constructor takes none.
3
+ *
4
+ * The `@zudojs/errors` RPC classes fix their options in the constructor, so
5
+ * an error that wraps another (a transport failure wrapping a fetch error,
6
+ * an unavailable error wrapping a downstream timeout) gets its `cause` set
7
+ * afterwards. Non-enumerable, like the platform's own `Error.cause`, so it
8
+ * is not serialized by accident.
9
+ */
10
+ export declare function withCause<T extends Error>(error: T, cause: unknown): T;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Attaches a cause to an error whose constructor takes none.
3
+ *
4
+ * The `@zudojs/errors` RPC classes fix their options in the constructor, so
5
+ * an error that wraps another (a transport failure wrapping a fetch error,
6
+ * an unavailable error wrapping a downstream timeout) gets its `cause` set
7
+ * afterwards. Non-enumerable, like the platform's own `Error.cause`, so it
8
+ * is not serialized by accident.
9
+ */
10
+ export function withCause(error, cause) {
11
+ Object.defineProperty(error, "cause", {
12
+ value: cause,
13
+ enumerable: false,
14
+ configurable: true,
15
+ writable: true,
16
+ });
17
+ return error;
18
+ }
@@ -1,3 +1,2 @@
1
1
  export type { RPCInterceptor } from "./rpcInterceptor.type.js";
2
2
  export { createNoopRPCInterceptor } from "./rpcInterceptor.type.js";
3
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1 @@
1
1
  export { createNoopRPCInterceptor } from "./rpcInterceptor.type.js";
2
- //# sourceMappingURL=index.js.map
@@ -9,4 +9,3 @@ export interface RPCInterceptor {
9
9
  * Creates a no-op interceptor.
10
10
  */
11
11
  export declare function createNoopRPCInterceptor(): RPCInterceptor;
12
- //# sourceMappingURL=rpcInterceptor.type.d.ts.map
@@ -8,4 +8,3 @@ export function createNoopRPCInterceptor() {
8
8
  },
9
9
  };
10
10
  }
11
- //# sourceMappingURL=rpcInterceptor.type.js.map
@@ -1,3 +1,2 @@
1
1
  export type { RPCMiddleware } from "./rpcMiddleware.core.js";
2
2
  export { RPCMiddlewareStack } from "./rpcMiddleware.core.js";
3
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1 @@
1
1
  export { RPCMiddlewareStack } from "./rpcMiddleware.core.js";
2
- //# sourceMappingURL=index.js.map
@@ -26,4 +26,3 @@ export declare class RPCMiddlewareStack {
26
26
  */
27
27
  execute(context: RPCContext, handler: () => Promise<unknown>): Promise<unknown>;
28
28
  }
29
- //# sourceMappingURL=rpcMiddleware.core.d.ts.map
@@ -49,4 +49,3 @@ export class RPCMiddlewareStack {
49
49
  return runAt(0);
50
50
  }
51
51
  }
52
- //# sourceMappingURL=rpcMiddleware.core.js.map
@@ -2,4 +2,3 @@ export type { RPCHandler, RPCProcedure, RPCProcedureOptions, } from "./rpcProced
2
2
  export { createRPCProcedure } from "./rpcProcedure.type.js";
3
3
  export { RPCProcedureRegistry } from "./rpcProcedureRegistry.core.js";
4
4
  export { RPCProcedureRouter } from "./rpcProcedureRouter.core.js";
5
- //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,3 @@
1
1
  export { createRPCProcedure } from "./rpcProcedure.type.js";
2
2
  export { RPCProcedureRegistry } from "./rpcProcedureRegistry.core.js";
3
3
  export { RPCProcedureRouter } from "./rpcProcedureRouter.core.js";
4
- //# sourceMappingURL=index.js.map
@@ -46,4 +46,3 @@ export interface RPCProcedure<TInput = unknown, TOutput = unknown> {
46
46
  * Creates a new RPC procedure.
47
47
  */
48
48
  export declare function createRPCProcedure<TInput = unknown, TOutput = unknown>(name: RPCProcedureName, handler: RPCHandler<TInput, TOutput>, options?: RPCProcedureOptions<TInput, TOutput>): RPCProcedure<TInput, TOutput>;
49
- //# sourceMappingURL=rpcProcedure.type.d.ts.map
@@ -17,4 +17,3 @@ export function createRPCProcedure(name, handler, options = {}) {
17
17
  options: Object.freeze(options),
18
18
  });
19
19
  }
20
- //# sourceMappingURL=rpcProcedure.type.js.map
@@ -51,4 +51,3 @@ export declare class RPCProcedureRegistry {
51
51
  */
52
52
  clear(): void;
53
53
  }
54
- //# sourceMappingURL=rpcProcedureRegistry.core.d.ts.map
@@ -88,4 +88,3 @@ export class RPCProcedureRegistry {
88
88
  this.procedures.clear();
89
89
  }
90
90
  }
91
- //# sourceMappingURL=rpcProcedureRegistry.core.js.map
@@ -34,4 +34,3 @@ export declare class RPCProcedureRouter {
34
34
  */
35
35
  clear(): void;
36
36
  }
37
- //# sourceMappingURL=rpcProcedureRouter.core.d.ts.map
@@ -61,4 +61,3 @@ export class RPCProcedureRouter {
61
61
  this.routes.clear();
62
62
  }
63
63
  }
64
- //# sourceMappingURL=rpcProcedureRouter.core.js.map
@@ -14,4 +14,3 @@ export declare function abortReasonToRPCError(signal: AbortSignal, procedureName
14
14
  * Settles with `promise`, or rejects as soon as `signal` aborts.
15
15
  */
16
16
  export declare function raceAbort<T>(promise: Promise<T>, signal: AbortSignal | undefined, procedureName?: string): Promise<T>;
17
- //# sourceMappingURL=rpcAbort.helper.d.ts.map
@@ -37,4 +37,3 @@ export function raceAbort(promise, signal, procedureName) {
37
37
  });
38
38
  });
39
39
  }
40
- //# sourceMappingURL=rpcAbort.helper.js.map
@@ -38,4 +38,3 @@ export declare function combineSignals(...signals: readonly (AbortSignal | undef
38
38
  readonly signal: AbortSignal;
39
39
  dispose(): void;
40
40
  };
41
- //# sourceMappingURL=rpcCancellation.helper.d.ts.map
@@ -74,4 +74,3 @@ export function combineSignals(...signals) {
74
74
  },
75
75
  };
76
76
  }
77
- //# sourceMappingURL=rpcCancellation.helper.js.map
@@ -28,4 +28,3 @@ export declare function throwIfDeadlineExceeded(deadline: number, procedureName?
28
28
  export declare function readDeadline(metadata: {
29
29
  readonly deadline?: unknown;
30
30
  }): number | undefined;
31
- //# sourceMappingURL=rpcDeadline.helper.d.ts.map
@@ -45,4 +45,3 @@ export function readDeadline(metadata) {
45
45
  }
46
46
  return deadline;
47
47
  }
48
- //# sourceMappingURL=rpcDeadline.helper.js.map
@@ -4,4 +4,3 @@ export type { CancellableSignal } from "./cancellation/rpcCancellation.helper.js
4
4
  export { createCancellableSignal, cancelSignal, throwIfCancelled, combineSignals, } from "./cancellation/rpcCancellation.helper.js";
5
5
  export type { RPCBackoff, RPCJitter, RPCRetryOptions, } from "./retry/rpcRetry.helper.js";
6
6
  export { DEFAULT_RETRY_OPTIONS, calculateRetryDelay, retry, } from "./retry/rpcRetry.helper.js";
7
- //# sourceMappingURL=index.d.ts.map
@@ -2,4 +2,3 @@ export { createTimeout, withTimeout, runWithTimeout, } from "./timeout/rpcTimeou
2
2
  export { getRemainingTime, isDeadlineExceeded, throwIfDeadlineExceeded, readDeadline, } from "./deadline/rpcDeadline.helper.js";
3
3
  export { createCancellableSignal, cancelSignal, throwIfCancelled, combineSignals, } from "./cancellation/rpcCancellation.helper.js";
4
4
  export { DEFAULT_RETRY_OPTIONS, calculateRetryDelay, retry, } from "./retry/rpcRetry.helper.js";
5
- //# sourceMappingURL=index.js.map
@@ -15,7 +15,16 @@ export type RPCJitter = "none" | "full" | "equal";
15
15
  * Retry options.
16
16
  */
17
17
  export interface RPCRetryOptions {
18
+ /**
19
+ * Total number of calls, not the number of retries: `attempts: 3` calls
20
+ * the operation up to three times (one call plus two retries), and
21
+ * `attempts: 1` never retries. Values below 1 are treated as 1.
22
+ *
23
+ * Note that `@zudojs/lifecycle` counts the other way — its `attempts`
24
+ * is the number of retries after the first call.
25
+ */
18
26
  readonly attempts: number;
27
+ /** Base delay before a retry, in milliseconds; see `backoff`. */
19
28
  readonly delay: number;
20
29
  readonly maxDelay?: number;
21
30
  readonly backoff?: RPCBackoff;
@@ -51,4 +60,3 @@ export declare function calculateRetryDelay(attempt: number, options: RPCRetryOp
51
60
  * failing dependency do not synchronise into a retry wave.
52
61
  */
53
62
  export declare function retry<T>(operation: () => Promise<T>, options: RPCRetryOptions): Promise<T>;
54
- //# sourceMappingURL=rpcRetry.helper.d.ts.map
@@ -121,4 +121,3 @@ export async function retry(operation, options) {
121
121
  // error beats inventing a new one if that ever changes.
122
122
  throw lastError ?? new Error("Retry loop exited without running.");
123
123
  }
124
- //# sourceMappingURL=rpcRetry.helper.js.map
@@ -29,4 +29,3 @@ export declare function withTimeout<T>(promise: Promise<T>, duration: number, pr
29
29
  * stop its own work rather than continuing unobserved.
30
30
  */
31
31
  export declare function runWithTimeout<T>(operation: (signal: AbortSignal) => Promise<T>, duration: number, procedureName?: string, parentSignal?: AbortSignal): Promise<T>;
32
- //# sourceMappingURL=rpcTimeout.helper.d.ts.map
@@ -84,4 +84,3 @@ export async function runWithTimeout(operation, duration, procedureName, parentS
84
84
  parentSignal?.removeEventListener("abort", onParentAbort);
85
85
  }
86
86
  }
87
- //# sourceMappingURL=rpcTimeout.helper.js.map
@@ -6,4 +6,3 @@ export type { RPCServerOptions } from "./rpcServer.core.js";
6
6
  export { RPCServer } from "./rpcServer.core.js";
7
7
  export type { RPCMappedError } from "./rpcErrorMapping.helper.js";
8
8
  export { mapRPCError } from "./rpcErrorMapping.helper.js";
9
- //# sourceMappingURL=index.d.ts.map
@@ -4,4 +4,3 @@
4
4
  */
5
5
  export { RPCServer } from "./rpcServer.core.js";
6
6
  export { mapRPCError } from "./rpcErrorMapping.helper.js";
7
- //# sourceMappingURL=index.js.map
@@ -23,4 +23,3 @@ export declare function mapExposedBaseError(error: unknown): RPCErrorPayload | u
23
23
  * `RPC_INTERNAL_ERROR`.
24
24
  */
25
25
  export declare function withheldRPCErrorCode(code: string): string;
26
- //# sourceMappingURL=rpcBaseErrorMapping.helper.d.ts.map
@@ -67,4 +67,3 @@ export function mapExposedBaseError(error) {
67
67
  export function withheldRPCErrorCode(code) {
68
68
  return Object.hasOwn(RPC_HTTP_STATUS, code) ? code : "RPC_INTERNAL_ERROR";
69
69
  }
70
- //# sourceMappingURL=rpcBaseErrorMapping.helper.js.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Wire mapping for failures of something the server itself called.
3
+ *
4
+ * A transport failure inside a handler is a dependency the server could not
5
+ * reach, not a fault of the request: `RPC_UNAVAILABLE`, so the caller may
6
+ * retry, with the transport's own text (hosts, paths) withheld. An
7
+ * `RPCUnavailableError` carrying a `cause` is the dispatcher's wrap of such
8
+ * a failure; its cause is worth logging, so it is reported as internal too.
9
+ */
10
+ import type { RPCMappedError } from "./rpcErrorMapping.helper.js";
11
+ /**
12
+ * Maps a downstream failure onto `RPC_UNAVAILABLE`, marked internal so the
13
+ * original reaches `onInternalError`; `undefined` for anything else.
14
+ */
15
+ export declare function mapDownstreamError(error: Error): RPCMappedError | undefined;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Wire mapping for failures of something the server itself called.
3
+ *
4
+ * A transport failure inside a handler is a dependency the server could not
5
+ * reach, not a fault of the request: `RPC_UNAVAILABLE`, so the caller may
6
+ * retry, with the transport's own text (hosts, paths) withheld. An
7
+ * `RPCUnavailableError` carrying a `cause` is the dispatcher's wrap of such
8
+ * a failure; its cause is worth logging, so it is reported as internal too.
9
+ */
10
+ import { RPCTransportError, RPCUnavailableError, } from "../errors/rpc.errors.js";
11
+ import { UNAVAILABLE_ERROR_MESSAGE } from "../constants/rpcConstants.core.js";
12
+ /**
13
+ * Maps a downstream failure onto `RPC_UNAVAILABLE`, marked internal so the
14
+ * original reaches `onInternalError`; `undefined` for anything else.
15
+ */
16
+ export function mapDownstreamError(error) {
17
+ if (error instanceof RPCTransportError) {
18
+ return unavailable(UNAVAILABLE_ERROR_MESSAGE);
19
+ }
20
+ if (error instanceof RPCUnavailableError && error.cause !== undefined) {
21
+ return unavailable(error.message);
22
+ }
23
+ return undefined;
24
+ }
25
+ function unavailable(message) {
26
+ return { payload: { code: "RPC_UNAVAILABLE", message }, internal: true };
27
+ }