@orpc/client 2.0.0-beta.44 → 2.0.0-beta.46

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 (29) hide show
  1. package/README.md +100 -62
  2. package/dist/adapters/fetch/index.d.mts +3 -3
  3. package/dist/adapters/fetch/index.d.ts +3 -3
  4. package/dist/adapters/fetch/index.mjs +3 -3
  5. package/dist/adapters/message-port/index.d.mts +2 -2
  6. package/dist/adapters/message-port/index.d.ts +2 -2
  7. package/dist/adapters/message-port/index.mjs +3 -3
  8. package/dist/adapters/standard/index.d.mts +8 -8
  9. package/dist/adapters/standard/index.d.ts +8 -8
  10. package/dist/adapters/standard/index.mjs +3 -3
  11. package/dist/adapters/websocket/index.d.mts +9 -9
  12. package/dist/adapters/websocket/index.d.ts +9 -9
  13. package/dist/adapters/websocket/index.mjs +3 -3
  14. package/dist/index.d.mts +10 -11
  15. package/dist/index.d.ts +10 -11
  16. package/dist/index.mjs +4 -4
  17. package/dist/plugins/index.d.mts +51 -38
  18. package/dist/plugins/index.d.ts +51 -38
  19. package/dist/plugins/index.mjs +17 -10
  20. package/dist/shared/{client.DZHZRyR6.d.mts → client.BoHJeq15.d.mts} +30 -12
  21. package/dist/shared/{client.DZHZRyR6.d.ts → client.BoHJeq15.d.ts} +30 -12
  22. package/dist/shared/{client.B7P_ugvl.mjs → client.CKQeJJ2U.mjs} +9 -4
  23. package/dist/shared/{client.BPa_Mmuh.d.mts → client.DqIWeNhQ.d.mts} +7 -8
  24. package/dist/shared/{client.BPa_Mmuh.d.ts → client.DqIWeNhQ.d.ts} +7 -8
  25. package/dist/shared/{client.CHH2CNMj.d.ts → client.JBJwBhR8.d.ts} +5 -11
  26. package/dist/shared/{client.CrHurHrq.mjs → client.LF04eOvL.mjs} +10 -4
  27. package/dist/shared/{client.BLfXUpyF.mjs → client._wG5INmC.mjs} +16 -17
  28. package/dist/shared/{client.BzAY7ZC2.d.mts → client.euYjjcFz.d.mts} +5 -11
  29. package/package.json +6 -6
@@ -3,7 +3,19 @@ import { StandardUrl, StandardHeaders, StandardRequest, StandardLazyResponse } f
3
3
  import { ClientContext } from '../index.js';
4
4
  import { StandardLinkPlugin, StandardLinkTransportInterceptorOptions, StandardLinkOptions, StandardLinkInterceptorOptions } from '../adapters/standard/index.js';
5
5
 
6
- type BatchLinkPluginMode = 'streaming' | 'buffered';
6
+ /**
7
+ * Header that marks a request as a batch, set by the Batch Link Plugin and detected by the Batch Handler Plugin.
8
+ * Nothing between the client and server, such as a CORS policy or proxy, should block or strip it.
9
+ *
10
+ * @see {@link https://orpc.dev/docs/plugins/batch#setup | Batch Plugin - Setup}
11
+ */
12
+ declare const BATCH_HEADER = "orpc-batch";
13
+ /**
14
+ * Default `maxSize` of both the Batch Link Plugin and the Batch Handler Plugin.
15
+ *
16
+ * @see {@link https://orpc.dev/docs/plugins/batch#max-size | Batch Plugin - Max Size}
17
+ */
18
+ declare const DEFAULT_BATCH_MAX_SIZE = 10;
7
19
  interface BatchLinkPluginGroup<T extends ClientContext> {
8
20
  /**
9
21
  * Determines whether a request should be included in this batch group.
@@ -21,7 +33,7 @@ interface BatchLinkPluginGroup<T extends ClientContext> {
21
33
  *
22
34
  * @default []
23
35
  */
24
- path?: Value<string[], [items: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]>;
36
+ path?: Value<string[], [items: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]> | undefined;
25
37
  }
26
38
  interface BatchLinkPluginOptions<T extends ClientContext> {
27
39
  groups: [BatchLinkPluginGroup<T>, ...BatchLinkPluginGroup<T>[]];
@@ -30,20 +42,22 @@ interface BatchLinkPluginOptions<T extends ClientContext> {
30
42
  *
31
43
  * @default () => true
32
44
  */
33
- filter?: Value<boolean, [options: StandardLinkTransportInterceptorOptions<T>]>;
45
+ filter?: Value<boolean, [options: StandardLinkTransportInterceptorOptions<T>]> | undefined;
34
46
  /**
35
47
  * Only requests with the same scope are batched together.
36
48
  * On the server, return a value unique to the incoming request so different users never share a batch.
37
49
  *
38
50
  * @default () => undefined
39
51
  */
40
- scope?: (options: StandardLinkTransportInterceptorOptions<T>) => unknown;
52
+ scope?: ((options: StandardLinkTransportInterceptorOptions<T>) => unknown) | undefined;
41
53
  /**
42
- * The maximum number of requests in the batch.
54
+ * The maximum number of requests in the batch. Larger batches are split.
55
+ * Keep it at or below the server Batch Handler Plugin's `maxSize`, which rejects larger batches with a `413`.
43
56
  *
44
- * @default 10
57
+ * @default DEFAULT_BATCH_MAX_SIZE (10)
58
+ * @see {@link https://orpc.dev/docs/plugins/batch#max-size | Batch Plugin - Max Size}
45
59
  */
46
- maxSize?: Value<Promisable<number>, [subOptionsList: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]>;
60
+ maxSize?: Value<Promisable<number>, [subOptionsList: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]> | undefined;
47
61
  /**
48
62
  * How long (in ms) to wait for more requests before sending the batch,
49
63
  * counted from the first queued request.
@@ -51,20 +65,13 @@ interface BatchLinkPluginOptions<T extends ClientContext> {
51
65
  *
52
66
  * @default 0
53
67
  */
54
- wait?: number;
55
- /**
56
- * The batch response mode.
57
- * A `buffered` batch still streams once a procedure in it returns a stream.
58
- *
59
- * @default 'streaming'
60
- */
61
- mode?: Value<BatchLinkPluginMode, [subOptionsList: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]>;
68
+ wait?: number | undefined;
62
69
  /**
63
70
  * URL for the batch request.
64
71
  *
65
72
  * @default URL of the first subrequest in the batch + '/__batch__'
66
73
  */
67
- url?: Value<Promisable<StandardUrl>, [subOptionsList: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]>;
74
+ url?: Value<Promisable<StandardUrl>, [subOptionsList: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]> | undefined;
68
75
  /**
69
76
  * The maximum length of the URL that runtime supports,
70
77
  * if exceeded, the batch will be split into smaller batches and sent sequentially.
@@ -73,25 +80,25 @@ interface BatchLinkPluginOptions<T extends ClientContext> {
73
80
  *
74
81
  * @default 2083
75
82
  */
76
- maxUrlLength?: Value<Promisable<number>, [subOptionsList: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]>;
83
+ maxUrlLength?: Value<Promisable<number>, [subOptionsList: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]> | undefined;
77
84
  /**
78
85
  * Headers used for the batch request.
79
86
  *
80
87
  * @default Common headers among all subrequests in the batch.
81
88
  */
82
- headers?: Value<Promisable<StandardHeaders>, [subOptionsList: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]>;
89
+ headers?: Value<Promisable<StandardHeaders>, [subOptionsList: [StandardLinkTransportInterceptorOptions<T>, ...StandardLinkTransportInterceptorOptions<T>[]]]> | undefined;
83
90
  /**
84
91
  * Map each subrequest in the batch before it is sent.
85
92
  *
86
93
  * @default Removes headers that are duplicated with the batch headers
87
94
  */
88
- mapSubrequest?: (subOptions: StandardLinkTransportInterceptorOptions<T>, partialBatchRequest: Pick<StandardRequest, 'url' | 'headers'>) => StandardRequest;
95
+ mapSubrequest?: ((subOptions: StandardLinkTransportInterceptorOptions<T>, partialBatchRequest: Pick<StandardRequest, 'url' | 'headers'>) => StandardRequest) | undefined;
89
96
  /**
90
97
  * Maps each subresponse before returning the final response.
91
98
  *
92
99
  * @default Low-priority merges headers from the batch response into each subresponse.
93
100
  */
94
- mapSubresponse?: (subResponse: StandardLazyResponse, batchResponse: StandardLazyResponse, subOptions: StandardLinkTransportInterceptorOptions<T>) => StandardLazyResponse;
101
+ mapSubresponse?: ((subResponse: StandardLazyResponse, batchResponse: StandardLazyResponse, subOptions: StandardLinkTransportInterceptorOptions<T>) => StandardLazyResponse) | undefined;
95
102
  }
96
103
  /**
97
104
  * Combines multiple client requests into a single batch request
@@ -109,7 +116,6 @@ declare class BatchLinkPlugin<T extends ClientContext> implements StandardLinkPl
109
116
  private readonly scope;
110
117
  private readonly maxSize;
111
118
  private readonly wait;
112
- private readonly mode;
113
119
  private readonly batchUrl;
114
120
  private readonly maxUrlLength;
115
121
  private readonly batchHeaders;
@@ -152,14 +158,14 @@ interface DedupeLinkPluginOptions<T extends ClientContext> {
152
158
  *
153
159
  * @default ({ request }) => request.method === 'GET' || request.method === 'QUERY'
154
160
  */
155
- filter?: Value<boolean, [options: StandardLinkTransportInterceptorOptions<T>]>;
161
+ filter?: Value<boolean, [options: StandardLinkTransportInterceptorOptions<T>]> | undefined;
156
162
  /**
157
163
  * Only requests with the same scope are deduplicated together.
158
164
  * On the server, return a value unique to the incoming request so different users never share a response.
159
165
  *
160
166
  * @default () => undefined
161
167
  */
162
- scope?: (options: StandardLinkTransportInterceptorOptions<T>) => unknown;
168
+ scope?: ((options: StandardLinkTransportInterceptorOptions<T>) => unknown) | undefined;
163
169
  /**
164
170
  * How long (in ms) to wait for more identical requests before sending,
165
171
  * counted from the first queued request.
@@ -167,7 +173,7 @@ interface DedupeLinkPluginOptions<T extends ClientContext> {
167
173
  *
168
174
  * @default 0
169
175
  */
170
- wait?: number;
176
+ wait?: number | undefined;
171
177
  }
172
178
  /**
173
179
  * Prevents redundant requests by deduplicating similar in-flight requests,
@@ -196,7 +202,7 @@ interface RequestCompressionLinkPluginOptions<T extends ClientContext> {
196
202
  *
197
203
  * @default 'gzip'
198
204
  */
199
- encoding?: 'gzip' | 'deflate' | 'deflate-raw';
205
+ encoding?: 'gzip' | 'deflate' | 'deflate-raw' | undefined;
200
206
  /**
201
207
  * The minimum request size in bytes required to trigger compression.
202
208
  * Requests smaller than this threshold will not be compressed to avoid overhead.
@@ -204,7 +210,7 @@ interface RequestCompressionLinkPluginOptions<T extends ClientContext> {
204
210
  *
205
211
  * @default 1024 (1KB)
206
212
  */
207
- threshold?: number;
213
+ threshold?: number | undefined;
208
214
  /**
209
215
  * Determines whether a request with the given Content-Type should be compressed.
210
216
  * Only consulted for binary transfers (streams, files, and file form-data parts).
@@ -212,7 +218,7 @@ interface RequestCompressionLinkPluginOptions<T extends ClientContext> {
212
218
  *
213
219
  * @default isCompressibleContentType (covers common text-based formats)
214
220
  */
215
- isCompressibleContentType?: (contentType: string | null | undefined, options: StandardLinkTransportInterceptorOptions<T>) => boolean;
221
+ isCompressibleContentType?: ((contentType: string | null | undefined, options: StandardLinkTransportInterceptorOptions<T>) => boolean) | undefined;
216
222
  }
217
223
  /**
218
224
  * Compresses request bodies before sending them to the server,
@@ -240,7 +246,7 @@ interface ResponseCompressionLinkPluginOptions<_T extends ClientContext> {
240
246
  *
241
247
  * @default ['gzip', 'deflate']
242
248
  */
243
- encodings?: readonly ('gzip' | 'deflate' | 'deflate-raw')[];
249
+ encodings?: readonly ('gzip' | 'deflate' | 'deflate-raw')[] | undefined;
244
250
  }
245
251
  /**
246
252
  * Advertises Accept-Encoding on requests and decompresses response bodies
@@ -287,7 +293,7 @@ interface RetryLinkPluginContext {
287
293
  *
288
294
  * @default 0
289
295
  */
290
- retry?: Value<Promisable<number>, [Omit<StandardLinkInterceptorOptions<RetryLinkPluginContext>, 'next'>]>;
296
+ retry?: Value<Promisable<number>, [Omit<StandardLinkInterceptorOptions<RetryLinkPluginContext>, 'next'>]> | undefined;
291
297
  /**
292
298
  * Delay (in ms) before retrying.
293
299
  *
@@ -296,17 +302,17 @@ interface RetryLinkPluginContext {
296
302
  *
297
303
  * @default (o) => o.lastEventRetry ?? 2000
298
304
  */
299
- retryDelay?: Value<Promisable<number>, [RetryLinkPluginAttemptOptions<RetryLinkPluginContext>]>;
305
+ retryDelay?: Value<Promisable<number>, [RetryLinkPluginAttemptOptions<RetryLinkPluginContext>]> | undefined;
300
306
  /**
301
307
  * Determine whether to retry.
302
308
  *
303
- * @default true
309
+ * @default (o) => isRetryableError(o.error)
304
310
  */
305
- shouldRetry?: Value<Promisable<boolean>, [RetryLinkPluginAttemptOptions<RetryLinkPluginContext>]>;
311
+ shouldRetry?: Value<Promisable<boolean>, [RetryLinkPluginAttemptOptions<RetryLinkPluginContext>]> | undefined;
306
312
  /**
307
313
  * Hook called before each retry. Can return a cleanup callback.
308
314
  */
309
- onRetry?: (options: RetryLinkPluginAttemptOptions<RetryLinkPluginContext>) => void | ((isSuccess: boolean) => void);
315
+ onRetry?: ((options: RetryLinkPluginAttemptOptions<RetryLinkPluginContext>) => void | ((isSuccess: boolean) => void)) | undefined;
310
316
  }
311
317
  interface RetryLinkPluginOptions<_T extends RetryLinkPluginContext> {
312
318
  /**
@@ -314,6 +320,13 @@ interface RetryLinkPluginOptions<_T extends RetryLinkPluginContext> {
314
320
  */
315
321
  default?: RetryLinkPluginContext | undefined;
316
322
  }
323
+ /**
324
+ * Default `shouldRetry` check of `RetryLinkPlugin`. Returns `false` only for errors
325
+ * from a 4xx response other than `408` and `429`.
326
+ *
327
+ * @see {@link https://orpc.dev/docs/plugins/retry#client-error-responses | Retry Plugin - Client Error Responses}
328
+ */
329
+ declare function isRetryableError(error: unknown): boolean;
317
330
  /**
318
331
  * Automatically retries failed requests based on customizable retry strategies,
319
332
  * improving the resilience of your application.
@@ -342,7 +355,7 @@ interface RetryAfterLinkPluginOptions<T extends ClientContext> {
342
355
  condition?: Value<boolean, [
343
356
  response: StandardLazyResponse,
344
357
  options: StandardLinkTransportInterceptorOptions<T>
345
- ]>;
358
+ ]> | undefined;
346
359
  /**
347
360
  * Maximum attempts before giving up retries.
348
361
  *
@@ -351,7 +364,7 @@ interface RetryAfterLinkPluginOptions<T extends ClientContext> {
351
364
  maxAttempts?: Value<number, [
352
365
  response: StandardLazyResponse,
353
366
  options: StandardLinkTransportInterceptorOptions<T>
354
- ]>;
367
+ ]> | undefined;
355
368
  /**
356
369
  * Maximum timeout in milliseconds to wait before giving up retries.
357
370
  *
@@ -360,7 +373,7 @@ interface RetryAfterLinkPluginOptions<T extends ClientContext> {
360
373
  timeout?: Value<number, [
361
374
  response: StandardLazyResponse,
362
375
  options: StandardLinkTransportInterceptorOptions<T>
363
- ]>;
376
+ ]> | undefined;
364
377
  }
365
378
  /**
366
379
  * The Retry After Link Plugin automatically retries requests based on server `retry-after` header.
@@ -403,5 +416,5 @@ declare class TimeoutLinkPlugin<T extends ClientContext> implements StandardLink
403
416
  init(options: StandardLinkOptions<T>): StandardLinkOptions<T>;
404
417
  }
405
418
 
406
- export { BatchLinkPlugin, RetryLinkPlugin as ClientRetryPlugin, DedupeLinkPlugin, DedupeLinkPlugin as DedupeRequestsPlugin, RequestCompressionLinkPlugin, ResponseCompressionLinkPlugin, RetryAfterLinkPlugin, RetryAfterLinkPlugin as RetryAfterPlugin, RetryLinkPlugin, TimeoutLinkPlugin };
407
- export type { BatchLinkPluginGroup, BatchLinkPluginMode, BatchLinkPluginOptions, RetryLinkPluginContext as ClientRetryPluginContext, DedupeLinkPluginGroup, DedupeLinkPluginOptions, RequestCompressionLinkPluginOptions, ResponseCompressionLinkPluginOptions, RetryAfterLinkPluginOptions, RetryLinkPluginAttemptOptions, RetryLinkPluginContext, RetryLinkPluginOptions, TimeoutLinkPluginOptions };
419
+ export { BATCH_HEADER, BatchLinkPlugin, RetryLinkPlugin as ClientRetryPlugin, DEFAULT_BATCH_MAX_SIZE, DedupeLinkPlugin, DedupeLinkPlugin as DedupeRequestsPlugin, RequestCompressionLinkPlugin, ResponseCompressionLinkPlugin, RetryAfterLinkPlugin, RetryAfterLinkPlugin as RetryAfterPlugin, RetryLinkPlugin, TimeoutLinkPlugin, isRetryableError };
420
+ export type { BatchLinkPluginGroup, BatchLinkPluginOptions, RetryLinkPluginContext as ClientRetryPluginContext, DedupeLinkPluginGroup, DedupeLinkPluginOptions, RequestCompressionLinkPluginOptions, ResponseCompressionLinkPluginOptions, RetryAfterLinkPluginOptions, RetryLinkPluginAttemptOptions, RetryLinkPluginContext, RetryLinkPluginOptions, TimeoutLinkPluginOptions };
@@ -1,9 +1,11 @@
1
1
  import { toArray, value, splitInHalf, promiseWithResolvers, safeEncodeURIComponent, stringifyJSON, once, isAsyncIteratorObject, defer, captureAsyncContext, loadBytes, allAbortSignal, runWithSignal, replicateAsyncIterator, replicateReadableStream, wrapAsyncIterator, throwIfAborted, isCompressibleContentType, override, AsyncIteratorClass, sleep, AbortError, anyAbortSignal } from '@orpc/shared';
2
2
  import { parseStandardUrl, flattenStandardHeader, generateContentDisposition, getEventMeta } from '@standard-server/core';
3
- import { ClientPeer, isServerPeerSendMessage, decodePeerMessage } from '@standard-server/peer';
3
+ import { ClientPeer, isPeerMessage, isServerPeerSendMessage, decodePeerMessage } from '@standard-server/peer';
4
4
  import { toFetchHeaders, toStandardBody } from '@standard-server/fetch';
5
- import { C as COMMON_ERROR_STATUS_MAP } from '../shared/client.CrHurHrq.mjs';
5
+ import { O as ORPCError, R as ResponseError, C as COMMON_ERROR_STATUS_MAP } from '../shared/client.LF04eOvL.mjs';
6
6
 
7
+ const BATCH_HEADER = "orpc-batch";
8
+ const DEFAULT_BATCH_MAX_SIZE = 10;
7
9
  class BatchLinkPlugin {
8
10
  name = "~batch";
9
11
  groups;
@@ -11,7 +13,6 @@ class BatchLinkPlugin {
11
13
  scope;
12
14
  maxSize;
13
15
  wait;
14
- mode;
15
16
  batchUrl;
16
17
  maxUrlLength;
17
18
  batchHeaders;
@@ -22,9 +23,8 @@ class BatchLinkPlugin {
22
23
  this.groups = options.groups;
23
24
  this.filter = options.filter ?? (() => true);
24
25
  this.scope = options.scope ?? (() => void 0);
25
- this.maxSize = options.maxSize ?? 10;
26
+ this.maxSize = options.maxSize ?? DEFAULT_BATCH_MAX_SIZE;
26
27
  this.wait = options.wait ?? 0;
27
- this.mode = options.mode ?? "streaming";
28
28
  this.batchUrl = options.url ?? ((options2) => {
29
29
  const [pathname] = parseStandardUrl(options2[0].request.url);
30
30
  return `${pathname}/__batch__`;
@@ -141,7 +141,6 @@ class BatchLinkPlugin {
141
141
  }
142
142
  const url = await value(this.batchUrl, subOptionsList);
143
143
  const headers = await value(this.batchHeaders, subOptionsList);
144
- const mode = value(this.mode, subOptionsList);
145
144
  let suppressErrorFromCurrentBatch = false;
146
145
  const controller = new AbortController();
147
146
  const pendingMessages = [];
@@ -185,7 +184,7 @@ class BatchLinkPlugin {
185
184
  const request = {
186
185
  url,
187
186
  method,
188
- headers: { ...headers, "orpc-batch": mode },
187
+ headers: { ...headers, [BATCH_HEADER]: "1" },
189
188
  signal: controller.signal
190
189
  };
191
190
  if (method === "GET") {
@@ -225,7 +224,7 @@ class BatchLinkPlugin {
225
224
  return;
226
225
  }
227
226
  const body = await batchResponse.resolveBody();
228
- if (Array.isArray(body) && body.every((v) => isServerPeerSendMessage(v))) {
227
+ if (Array.isArray(body) && body.every((v) => isPeerMessage(v) && isServerPeerSendMessage(v))) {
229
228
  for (const message of body) {
230
229
  await peer.message(message);
231
230
  }
@@ -745,6 +744,14 @@ function parseContentEncodings(header) {
745
744
  return header.split(",").map((part) => part.trim().toLowerCase());
746
745
  }
747
746
 
747
+ function isRetryableError(error) {
748
+ const responseError = error instanceof ORPCError ? error.cause : error;
749
+ if (!(responseError instanceof ResponseError)) {
750
+ return true;
751
+ }
752
+ const { status } = responseError.response;
753
+ return status < 400 || status >= 500 || status === COMMON_ERROR_STATUS_MAP.TIMEOUT || status === COMMON_ERROR_STATUS_MAP.TOO_MANY_REQUESTS;
754
+ }
748
755
  class RetryLinkPlugin {
749
756
  defaultRetry;
750
757
  defaultRetryDelay;
@@ -754,7 +761,7 @@ class RetryLinkPlugin {
754
761
  constructor(options = {}) {
755
762
  this.defaultRetry = options.default?.retry ?? 0;
756
763
  this.defaultRetryDelay = options.default?.retryDelay ?? ((o) => o.lastEventRetry ?? 2e3);
757
- this.defaultShouldRetry = options.default?.shouldRetry ?? true;
764
+ this.defaultShouldRetry = options.default?.shouldRetry ?? ((o) => isRetryableError(o.error));
758
765
  this.defaultOnRetry = options.default?.onRetry;
759
766
  }
760
767
  init(options) {
@@ -961,4 +968,4 @@ class TimeoutLinkPlugin {
961
968
  }
962
969
  }
963
970
 
964
- export { BatchLinkPlugin, RetryLinkPlugin as ClientRetryPlugin, DedupeLinkPlugin, DedupeLinkPlugin as DedupeRequestsPlugin, RequestCompressionLinkPlugin, ResponseCompressionLinkPlugin, RetryAfterLinkPlugin, RetryAfterLinkPlugin as RetryAfterPlugin, RetryLinkPlugin, TimeoutLinkPlugin };
971
+ export { BATCH_HEADER, BatchLinkPlugin, RetryLinkPlugin as ClientRetryPlugin, DEFAULT_BATCH_MAX_SIZE, DedupeLinkPlugin, DedupeLinkPlugin as DedupeRequestsPlugin, RequestCompressionLinkPlugin, ResponseCompressionLinkPlugin, RetryAfterLinkPlugin, RetryAfterLinkPlugin as RetryAfterPlugin, RetryLinkPlugin, TimeoutLinkPlugin, isRetryableError };
@@ -10,7 +10,7 @@ interface ClientOptions<T extends ClientContext> {
10
10
  context: T;
11
11
  }
12
12
  type FriendlyClientOptions<T extends ClientContext> = Omit<ClientOptions<T>, 'context'> & (object extends T ? {
13
- context?: T;
13
+ context?: T | undefined;
14
14
  } : {
15
15
  context: T;
16
16
  });
@@ -134,7 +134,7 @@ type ORPCErrorCode = Registry extends {
134
134
  ORPCErrorCode: infer T extends string;
135
135
  } ? T : (keyof typeof COMMON_ERROR_STATUS_MAP) | (string & {});
136
136
  type ORPCErrorOptions<TData> = ErrorOptions & {
137
- message?: string;
137
+ message?: string | undefined;
138
138
  } & (undefined extends TData ? {
139
139
  data?: TData;
140
140
  } : {
@@ -186,18 +186,37 @@ interface ORPCErrorJSON<TCode extends string, TData> extends Pick<ORPCError<TCod
186
186
  }
187
187
  type AnyORPCError = ORPCError<any, any>;
188
188
  type AnyORPCErrorJSON = ORPCErrorJSON<any, any>;
189
- interface MalformedResponseErrorOptions extends ErrorOptions {
189
+ interface ResponseErrorOptions extends ErrorOptions {
190
190
  /**
191
- * @default inferred from the response body or status
191
+ * @default inferred from the response status
192
192
  */
193
- message?: string;
193
+ message?: string | undefined;
194
194
  response: StandardResponse;
195
195
  }
196
+ /**
197
+ * Error carrying the resolved response a link received. Links set it as the `cause`
198
+ * of an `ORPCError` decoded from an error response, so details that are not part
199
+ * of the error itself, such as its status or headers, stay available.
200
+ *
201
+ * @see {@link https://orpc.dev/docs/rpc/link#error-responses | RPC Link - Error Responses}
202
+ * @see {@link https://orpc.dev/docs/openapi/link#error-responses | OpenAPI Link - Error Responses}
203
+ */
204
+ declare class ResponseError extends Error {
205
+ readonly name: string;
206
+ response: StandardResponse;
207
+ constructor(options: ResponseErrorOptions);
208
+ }
209
+ interface MalformedResponseErrorOptions extends ResponseErrorOptions {
210
+ /**
211
+ * @default inferred from the response body or status
212
+ */
213
+ message?: string | undefined;
214
+ }
196
215
  /**
197
216
  * Error thrown by links when a response does not follow the expected oRPC format,
198
- * for example when a proxy or gateway answers instead of your handler. Carries the
199
- * resolved response. Unless overridden via `options.message`, the message is
200
- * inferred from the response body or status.
217
+ * for example when a proxy or gateway answers instead of your handler. Extends
218
+ * `ResponseError`, so it carries the resolved response. Unless overridden via
219
+ * `options.message`, the message is inferred from the response body or status.
201
220
  *
202
221
  * Unlike `ORPCError`, it reaches a handler's callers as a generic `INTERNAL_SERVER_ERROR`
203
222
  * when thrown from the handler, so an upstream's response is not sent to them.
@@ -205,11 +224,10 @@ interface MalformedResponseErrorOptions extends ErrorOptions {
205
224
  * @see {@link https://orpc.dev/docs/rpc/link#malformed-responses | RPC Link - Malformed Responses}
206
225
  * @see {@link https://orpc.dev/docs/openapi/link#malformed-responses | OpenAPI Link - Malformed Responses}
207
226
  */
208
- declare class MalformedResponseError extends Error {
227
+ declare class MalformedResponseError extends ResponseError {
209
228
  readonly name = "MalformedResponseError";
210
- response: StandardResponse;
211
229
  constructor(options: MalformedResponseErrorOptions);
212
230
  }
213
231
 
214
- export { MalformedResponseError as M, ORPCError as h, COMMON_ERROR_STATUS_MAP as j };
215
- export type { AnyORPCError as A, ClientContext as C, FriendlyClientOptions as F, InferClientContext as I, NestedClient as N, ORPCErrorCode as O, ClientOptions as a, ClientLink as b, AnyNestedClient as c, InferClientError as d, Client as e, ClientRest as f, ORPCErrorJSON as g, AnyORPCErrorJSON as i, InferClientBodyInputs as k, InferClientBodyOutputs as l, InferClientErrors as m, InferClientInputs as n, InferClientOutputs as o, MalformedResponseErrorOptions as p, ORPCErrorOptions as q };
232
+ export { MalformedResponseError as M, ResponseError as R, ORPCError as h, COMMON_ERROR_STATUS_MAP as j };
233
+ export type { AnyORPCError as A, ClientContext as C, FriendlyClientOptions as F, InferClientContext as I, NestedClient as N, ORPCErrorCode as O, ClientOptions as a, ClientLink as b, AnyNestedClient as c, InferClientError as d, Client as e, ClientRest as f, ORPCErrorJSON as g, AnyORPCErrorJSON as i, InferClientBodyInputs as k, InferClientBodyOutputs as l, InferClientErrors as m, InferClientInputs as n, InferClientOutputs as o, MalformedResponseErrorOptions as p, ORPCErrorOptions as q, ResponseErrorOptions as r };
@@ -10,7 +10,7 @@ interface ClientOptions<T extends ClientContext> {
10
10
  context: T;
11
11
  }
12
12
  type FriendlyClientOptions<T extends ClientContext> = Omit<ClientOptions<T>, 'context'> & (object extends T ? {
13
- context?: T;
13
+ context?: T | undefined;
14
14
  } : {
15
15
  context: T;
16
16
  });
@@ -134,7 +134,7 @@ type ORPCErrorCode = Registry extends {
134
134
  ORPCErrorCode: infer T extends string;
135
135
  } ? T : (keyof typeof COMMON_ERROR_STATUS_MAP) | (string & {});
136
136
  type ORPCErrorOptions<TData> = ErrorOptions & {
137
- message?: string;
137
+ message?: string | undefined;
138
138
  } & (undefined extends TData ? {
139
139
  data?: TData;
140
140
  } : {
@@ -186,18 +186,37 @@ interface ORPCErrorJSON<TCode extends string, TData> extends Pick<ORPCError<TCod
186
186
  }
187
187
  type AnyORPCError = ORPCError<any, any>;
188
188
  type AnyORPCErrorJSON = ORPCErrorJSON<any, any>;
189
- interface MalformedResponseErrorOptions extends ErrorOptions {
189
+ interface ResponseErrorOptions extends ErrorOptions {
190
190
  /**
191
- * @default inferred from the response body or status
191
+ * @default inferred from the response status
192
192
  */
193
- message?: string;
193
+ message?: string | undefined;
194
194
  response: StandardResponse;
195
195
  }
196
+ /**
197
+ * Error carrying the resolved response a link received. Links set it as the `cause`
198
+ * of an `ORPCError` decoded from an error response, so details that are not part
199
+ * of the error itself, such as its status or headers, stay available.
200
+ *
201
+ * @see {@link https://orpc.dev/docs/rpc/link#error-responses | RPC Link - Error Responses}
202
+ * @see {@link https://orpc.dev/docs/openapi/link#error-responses | OpenAPI Link - Error Responses}
203
+ */
204
+ declare class ResponseError extends Error {
205
+ readonly name: string;
206
+ response: StandardResponse;
207
+ constructor(options: ResponseErrorOptions);
208
+ }
209
+ interface MalformedResponseErrorOptions extends ResponseErrorOptions {
210
+ /**
211
+ * @default inferred from the response body or status
212
+ */
213
+ message?: string | undefined;
214
+ }
196
215
  /**
197
216
  * Error thrown by links when a response does not follow the expected oRPC format,
198
- * for example when a proxy or gateway answers instead of your handler. Carries the
199
- * resolved response. Unless overridden via `options.message`, the message is
200
- * inferred from the response body or status.
217
+ * for example when a proxy or gateway answers instead of your handler. Extends
218
+ * `ResponseError`, so it carries the resolved response. Unless overridden via
219
+ * `options.message`, the message is inferred from the response body or status.
201
220
  *
202
221
  * Unlike `ORPCError`, it reaches a handler's callers as a generic `INTERNAL_SERVER_ERROR`
203
222
  * when thrown from the handler, so an upstream's response is not sent to them.
@@ -205,11 +224,10 @@ interface MalformedResponseErrorOptions extends ErrorOptions {
205
224
  * @see {@link https://orpc.dev/docs/rpc/link#malformed-responses | RPC Link - Malformed Responses}
206
225
  * @see {@link https://orpc.dev/docs/openapi/link#malformed-responses | OpenAPI Link - Malformed Responses}
207
226
  */
208
- declare class MalformedResponseError extends Error {
227
+ declare class MalformedResponseError extends ResponseError {
209
228
  readonly name = "MalformedResponseError";
210
- response: StandardResponse;
211
229
  constructor(options: MalformedResponseErrorOptions);
212
230
  }
213
231
 
214
- export { MalformedResponseError as M, ORPCError as h, COMMON_ERROR_STATUS_MAP as j };
215
- export type { AnyORPCError as A, ClientContext as C, FriendlyClientOptions as F, InferClientContext as I, NestedClient as N, ORPCErrorCode as O, ClientOptions as a, ClientLink as b, AnyNestedClient as c, InferClientError as d, Client as e, ClientRest as f, ORPCErrorJSON as g, AnyORPCErrorJSON as i, InferClientBodyInputs as k, InferClientBodyOutputs as l, InferClientErrors as m, InferClientInputs as n, InferClientOutputs as o, MalformedResponseErrorOptions as p, ORPCErrorOptions as q };
232
+ export { MalformedResponseError as M, ResponseError as R, ORPCError as h, COMMON_ERROR_STATUS_MAP as j };
233
+ export type { AnyORPCError as A, ClientContext as C, FriendlyClientOptions as F, InferClientContext as I, NestedClient as N, ORPCErrorCode as O, ClientOptions as a, ClientLink as b, AnyNestedClient as c, InferClientError as d, Client as e, ClientRest as f, ORPCErrorJSON as g, AnyORPCErrorJSON as i, InferClientBodyInputs as k, InferClientBodyOutputs as l, InferClientErrors as m, InferClientInputs as n, InferClientOutputs as o, MalformedResponseErrorOptions as p, ORPCErrorOptions as q, ResponseErrorOptions as r };
@@ -1,8 +1,8 @@
1
1
  import { sortPlugins, runWithSpan, ORPC_NAME, getTracer, isAsyncIteratorObject, override, traceAsyncIterator, traceReadableStream, intercept, value, pathToHttpPath, stringifyJSON } from '@orpc/shared';
2
2
  import { mergeStandardHeaders, parseStandardUrl } from '@standard-server/core';
3
3
  import { toStandardHeaders } from '@standard-server/fetch';
4
- import { M as MalformedResponseError } from './client.CrHurHrq.mjs';
5
- import { R as RPCSerializer, i as isORPCErrorJson, c as createORPCErrorFromJson } from './client.BLfXUpyF.mjs';
4
+ import { M as MalformedResponseError, R as ResponseError } from './client.LF04eOvL.mjs';
5
+ import { R as RPCSerializer, i as isORPCErrorJson, c as createORPCErrorFromJson } from './client._wG5INmC.mjs';
6
6
 
7
7
  class CompositeStandardLinkPlugin {
8
8
  name = "~composite";
@@ -150,7 +150,12 @@ class RPCLinkCodec {
150
150
  })();
151
151
  if (!isOk) {
152
152
  if (isORPCErrorJson(deserialized)) {
153
- return { kind: "error", error: createORPCErrorFromJson(deserialized) };
153
+ return {
154
+ kind: "error",
155
+ error: createORPCErrorFromJson(deserialized, {
156
+ cause: new ResponseError({ response: { status: response.status, headers: response.headers, body } })
157
+ })
158
+ };
154
159
  }
155
160
  throw new MalformedResponseError({ response: { headers: response.headers, status: response.status, body } });
156
161
  }
@@ -164,4 +169,4 @@ function toResolvedStandardHeaders(headers) {
164
169
  return headers;
165
170
  }
166
171
 
167
- export { CompositeStandardLinkPlugin as C, RPCLinkCodec as R, StandardLink as S };
172
+ export { RPCLinkCodec as R, StandardLink as S };
@@ -28,7 +28,7 @@ interface RPCJsonSerializerHandler {
28
28
  *
29
29
  * @default false
30
30
  */
31
- isTerminal?: boolean;
31
+ isTerminal?: boolean | undefined;
32
32
  }
33
33
  interface RPCJsonSerializerOptions {
34
34
  /**
@@ -88,13 +88,13 @@ declare class RPCJsonSerializer {
88
88
  private readonly handlerEntries;
89
89
  private readonly omitUndefinedProperties;
90
90
  constructor(options?: RPCJsonSerializerOptions);
91
- serialize(data: unknown): RPCJsonSerialization;
91
+ serializeJson(data: unknown): RPCJsonSerialization;
92
92
  /**
93
93
  * `segments` is a shared mutable stack (push/pop while walking),
94
94
  * so it must be copied before being stored in `meta` or `maps`.
95
95
  */
96
96
  private serializeValue;
97
- deserialize(serialized: RPCJsonSerialization): unknown;
97
+ deserializeJson(serialized: RPCJsonSerialization): unknown;
98
98
  }
99
99
 
100
100
  interface RPCSerializerSerializeOptions {
@@ -104,7 +104,7 @@ interface RPCSerializerSerializeOptions {
104
104
  *
105
105
  * @default true
106
106
  */
107
- useFormDataForBlobFields?: boolean;
107
+ useFormDataForBlobFields?: boolean | undefined;
108
108
  }
109
109
  interface RPCSerializerOptions extends RPCJsonSerializerOptions {
110
110
  /**
@@ -118,14 +118,13 @@ interface RPCSerializerOptions extends RPCJsonSerializerOptions {
118
118
  *
119
119
  * @see {@link https://orpc.dev/docs/rpc/serializer | RPC Serializer}
120
120
  */
121
- declare class RPCSerializer {
122
- private readonly jsonSerializer;
121
+ declare class RPCSerializer extends RPCJsonSerializer {
123
122
  private readonly defaultSerializeOptions;
124
123
  constructor(options?: RPCSerializerOptions);
125
124
  serialize(data: unknown, options?: RPCSerializerSerializeOptions): StandardBody;
126
- private serializeValue;
125
+ private serializePayload;
127
126
  deserialize(data: StandardBody): unknown;
128
- private deserializeValue;
127
+ private deserializePayload;
129
128
  }
130
129
 
131
130
  export { RPCJsonSerializer as b, RPCSerializer as e };
@@ -28,7 +28,7 @@ interface RPCJsonSerializerHandler {
28
28
  *
29
29
  * @default false
30
30
  */
31
- isTerminal?: boolean;
31
+ isTerminal?: boolean | undefined;
32
32
  }
33
33
  interface RPCJsonSerializerOptions {
34
34
  /**
@@ -88,13 +88,13 @@ declare class RPCJsonSerializer {
88
88
  private readonly handlerEntries;
89
89
  private readonly omitUndefinedProperties;
90
90
  constructor(options?: RPCJsonSerializerOptions);
91
- serialize(data: unknown): RPCJsonSerialization;
91
+ serializeJson(data: unknown): RPCJsonSerialization;
92
92
  /**
93
93
  * `segments` is a shared mutable stack (push/pop while walking),
94
94
  * so it must be copied before being stored in `meta` or `maps`.
95
95
  */
96
96
  private serializeValue;
97
- deserialize(serialized: RPCJsonSerialization): unknown;
97
+ deserializeJson(serialized: RPCJsonSerialization): unknown;
98
98
  }
99
99
 
100
100
  interface RPCSerializerSerializeOptions {
@@ -104,7 +104,7 @@ interface RPCSerializerSerializeOptions {
104
104
  *
105
105
  * @default true
106
106
  */
107
- useFormDataForBlobFields?: boolean;
107
+ useFormDataForBlobFields?: boolean | undefined;
108
108
  }
109
109
  interface RPCSerializerOptions extends RPCJsonSerializerOptions {
110
110
  /**
@@ -118,14 +118,13 @@ interface RPCSerializerOptions extends RPCJsonSerializerOptions {
118
118
  *
119
119
  * @see {@link https://orpc.dev/docs/rpc/serializer | RPC Serializer}
120
120
  */
121
- declare class RPCSerializer {
122
- private readonly jsonSerializer;
121
+ declare class RPCSerializer extends RPCJsonSerializer {
123
122
  private readonly defaultSerializeOptions;
124
123
  constructor(options?: RPCSerializerOptions);
125
124
  serialize(data: unknown, options?: RPCSerializerSerializeOptions): StandardBody;
126
- private serializeValue;
125
+ private serializePayload;
127
126
  deserialize(data: StandardBody): unknown;
128
- private deserializeValue;
127
+ private deserializePayload;
129
128
  }
130
129
 
131
130
  export { RPCJsonSerializer as b, RPCSerializer as e };