@orpc/client 0.0.0-next.65596ea → 0.0.0-next.65fbdd2
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 +14 -11
- package/dist/adapters/fetch/index.d.mts +25 -12
- package/dist/adapters/fetch/index.d.ts +25 -12
- package/dist/adapters/fetch/index.mjs +25 -8
- package/dist/adapters/message-port/index.d.mts +38 -17
- package/dist/adapters/message-port/index.d.ts +38 -17
- package/dist/adapters/message-port/index.mjs +30 -14
- package/dist/adapters/standard/index.d.mts +6 -5
- package/dist/adapters/standard/index.d.ts +6 -5
- package/dist/adapters/standard/index.mjs +4 -2
- package/dist/adapters/websocket/index.d.mts +14 -14
- package/dist/adapters/websocket/index.d.ts +14 -14
- package/dist/adapters/websocket/index.mjs +27 -11
- package/dist/index.d.mts +88 -27
- package/dist/index.d.ts +88 -27
- package/dist/index.mjs +55 -8
- package/dist/plugins/index.d.mts +65 -10
- package/dist/plugins/index.d.ts +65 -10
- package/dist/plugins/index.mjs +126 -27
- package/dist/shared/{client.C0KbSWlC.d.ts → client.2jUAqzYU.d.ts} +1 -2
- package/dist/shared/{client.7UM0t5o-.d.ts → client.B3pNRBih.d.ts} +3 -3
- package/dist/shared/{client.BdD8cpjs.d.mts → client.BFAVy68H.d.mts} +3 -3
- package/dist/shared/client.BLtwTQUg.mjs +40 -0
- package/dist/shared/{client.DpICn1BD.mjs → client.C88vqCBB.mjs} +63 -20
- package/dist/shared/{client.CRWEpqLB.mjs → client.CAeDqlZP.mjs} +37 -41
- package/dist/shared/{client.BMoG_EdN.d.mts → client.CpCa3si8.d.mts} +1 -2
- package/dist/shared/client.i2uoJbEp.d.mts +83 -0
- package/dist/shared/client.i2uoJbEp.d.ts +83 -0
- package/package.json +7 -7
- package/dist/shared/client.4TS_0JaO.d.mts +0 -29
- package/dist/shared/client.4TS_0JaO.d.ts +0 -29
package/dist/plugins/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Value, Promisable } from '@orpc/shared';
|
|
2
|
-
import { StandardHeaders, StandardRequest } from '@orpc/standard-server';
|
|
3
|
-
import {
|
|
4
|
-
import { a as
|
|
2
|
+
import { StandardHeaders, StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
|
|
3
|
+
import { BatchResponseMode } from '@orpc/standard-server/batch';
|
|
4
|
+
import { S as StandardLinkClientInterceptorOptions, a as StandardLinkPlugin, b as StandardLinkOptions, c as StandardLinkInterceptorOptions } from '../shared/client.2jUAqzYU.js';
|
|
5
|
+
import { b as ClientContext } from '../shared/client.i2uoJbEp.js';
|
|
5
6
|
|
|
6
7
|
interface BatchLinkPluginGroup<T extends ClientContext> {
|
|
7
8
|
condition(options: StandardLinkClientInterceptorOptions<T>): boolean;
|
|
@@ -17,6 +18,12 @@ interface BatchLinkPluginOptions<T extends ClientContext> {
|
|
|
17
18
|
* @default 10
|
|
18
19
|
*/
|
|
19
20
|
maxSize?: Value<Promisable<number>, [readonly [StandardLinkClientInterceptorOptions<T>, ...StandardLinkClientInterceptorOptions<T>[]]]>;
|
|
21
|
+
/**
|
|
22
|
+
* The batch response mode.
|
|
23
|
+
*
|
|
24
|
+
* @default 'streaming'
|
|
25
|
+
*/
|
|
26
|
+
mode?: Value<BatchResponseMode, [readonly [StandardLinkClientInterceptorOptions<T>, ...StandardLinkClientInterceptorOptions<T>[]]]>;
|
|
20
27
|
/**
|
|
21
28
|
* Defines the URL to use for the batch request.
|
|
22
29
|
*
|
|
@@ -52,10 +59,10 @@ interface BatchLinkPluginOptions<T extends ClientContext> {
|
|
|
52
59
|
exclude?: (options: StandardLinkClientInterceptorOptions<T>) => boolean;
|
|
53
60
|
}
|
|
54
61
|
/**
|
|
55
|
-
* The Batch
|
|
62
|
+
* The Batch Requests Plugin allows you to combine multiple requests and responses into a single batch,
|
|
56
63
|
* reducing the overhead of sending each one separately.
|
|
57
64
|
*
|
|
58
|
-
* @see {@link https://orpc.
|
|
65
|
+
* @see {@link https://orpc.dev/docs/plugins/batch-requests Batch Requests Plugin Docs}
|
|
59
66
|
*/
|
|
60
67
|
declare class BatchLinkPlugin<T extends ClientContext> implements StandardLinkPlugin<T> {
|
|
61
68
|
#private;
|
|
@@ -66,6 +73,7 @@ declare class BatchLinkPlugin<T extends ClientContext> implements StandardLinkPl
|
|
|
66
73
|
private readonly batchHeaders;
|
|
67
74
|
private readonly mapRequestItem;
|
|
68
75
|
private readonly exclude;
|
|
76
|
+
private readonly mode;
|
|
69
77
|
private pending;
|
|
70
78
|
order: number;
|
|
71
79
|
constructor(options: NoInfer<BatchLinkPluginOptions<T>>);
|
|
@@ -95,7 +103,7 @@ interface DedupeRequestsPluginOptions<T extends ClientContext> {
|
|
|
95
103
|
/**
|
|
96
104
|
* Prevents duplicate requests by deduplicating similar ones to reduce server load.
|
|
97
105
|
*
|
|
98
|
-
* @see {@link https://orpc.
|
|
106
|
+
* @see {@link https://orpc.dev/docs/plugins/dedupe-requests Dedupe Requests Plugin}
|
|
99
107
|
*/
|
|
100
108
|
declare class DedupeRequestsPlugin<T extends ClientContext> implements StandardLinkPlugin<T> {
|
|
101
109
|
#private;
|
|
@@ -142,17 +150,64 @@ interface ClientRetryPluginOptions {
|
|
|
142
150
|
/**
|
|
143
151
|
* The Client Retry Plugin enables retrying client calls when errors occur.
|
|
144
152
|
*
|
|
145
|
-
* @see {@link https://orpc.
|
|
153
|
+
* @see {@link https://orpc.dev/docs/plugins/client-retry Client Retry Plugin Docs}
|
|
146
154
|
*/
|
|
147
155
|
declare class ClientRetryPlugin<T extends ClientRetryPluginContext> implements StandardLinkPlugin<T> {
|
|
148
156
|
private readonly defaultRetry;
|
|
149
157
|
private readonly defaultRetryDelay;
|
|
150
158
|
private readonly defaultShouldRetry;
|
|
151
159
|
private readonly defaultOnRetry;
|
|
160
|
+
order: number;
|
|
152
161
|
constructor(options?: ClientRetryPluginOptions);
|
|
153
162
|
init(options: StandardLinkOptions<T>): void;
|
|
154
163
|
}
|
|
155
164
|
|
|
165
|
+
interface RetryAfterPluginOptions<T extends ClientContext> {
|
|
166
|
+
/**
|
|
167
|
+
* Override condition to determine whether to retry or not.
|
|
168
|
+
*
|
|
169
|
+
* @default ((response) => response.status === 429 || response.status === 503)
|
|
170
|
+
*/
|
|
171
|
+
condition?: Value<boolean, [
|
|
172
|
+
response: StandardLazyResponse,
|
|
173
|
+
options: StandardLinkClientInterceptorOptions<T>
|
|
174
|
+
]>;
|
|
175
|
+
/**
|
|
176
|
+
* Maximum attempts before giving up retries.
|
|
177
|
+
*
|
|
178
|
+
* @default 3
|
|
179
|
+
*/
|
|
180
|
+
maxAttempts?: Value<number, [
|
|
181
|
+
response: StandardLazyResponse,
|
|
182
|
+
options: StandardLinkClientInterceptorOptions<T>
|
|
183
|
+
]>;
|
|
184
|
+
/**
|
|
185
|
+
* Maximum timeout in milliseconds to wait before giving up retries.
|
|
186
|
+
*
|
|
187
|
+
* @default 5 * 60 * 1000 (5 minutes)
|
|
188
|
+
*/
|
|
189
|
+
timeout?: Value<number, [
|
|
190
|
+
response: StandardLazyResponse,
|
|
191
|
+
options: StandardLinkClientInterceptorOptions<T>
|
|
192
|
+
]>;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The Retry After Plugin automatically retries requests based on server `Retry-After` headers.
|
|
196
|
+
* This is particularly useful for handling rate limiting and temporary server unavailability.
|
|
197
|
+
*
|
|
198
|
+
* @see {@link https://orpc.dev/docs/plugins/retry-after Retry After Plugin Docs}
|
|
199
|
+
*/
|
|
200
|
+
declare class RetryAfterPlugin<T extends ClientContext> implements StandardLinkPlugin<T> {
|
|
201
|
+
private readonly condition;
|
|
202
|
+
private readonly maxAttempts;
|
|
203
|
+
private readonly timeout;
|
|
204
|
+
order: number;
|
|
205
|
+
constructor(options?: RetryAfterPluginOptions<T>);
|
|
206
|
+
init(options: StandardLinkOptions<T>): void;
|
|
207
|
+
private parseRetryAfterHeader;
|
|
208
|
+
private delayExecution;
|
|
209
|
+
}
|
|
210
|
+
|
|
156
211
|
interface SimpleCsrfProtectionLinkPluginOptions<T extends ClientContext> {
|
|
157
212
|
/**
|
|
158
213
|
* The name of the header to check.
|
|
@@ -179,7 +234,7 @@ interface SimpleCsrfProtectionLinkPluginOptions<T extends ClientContext> {
|
|
|
179
234
|
* It helps ensure that requests to your procedures originate from JavaScript code,
|
|
180
235
|
* not from other sources like standard HTML forms or direct browser navigation.
|
|
181
236
|
*
|
|
182
|
-
* @see {@link https://orpc.
|
|
237
|
+
* @see {@link https://orpc.dev/docs/plugins/simple-csrf-protection Simple CSRF Protection Plugin Docs}
|
|
183
238
|
*/
|
|
184
239
|
declare class SimpleCsrfProtectionLinkPlugin<T extends ClientContext> implements StandardLinkPlugin<T> {
|
|
185
240
|
private readonly headerName;
|
|
@@ -190,5 +245,5 @@ declare class SimpleCsrfProtectionLinkPlugin<T extends ClientContext> implements
|
|
|
190
245
|
init(options: StandardLinkOptions<T>): void;
|
|
191
246
|
}
|
|
192
247
|
|
|
193
|
-
export { BatchLinkPlugin, ClientRetryPlugin, ClientRetryPluginInvalidEventIteratorRetryResponse, DedupeRequestsPlugin, SimpleCsrfProtectionLinkPlugin };
|
|
194
|
-
export type { BatchLinkPluginGroup, BatchLinkPluginOptions, ClientRetryPluginAttemptOptions, ClientRetryPluginContext, ClientRetryPluginOptions, DedupeRequestsPluginGroup, DedupeRequestsPluginOptions, SimpleCsrfProtectionLinkPluginOptions };
|
|
248
|
+
export { BatchLinkPlugin, ClientRetryPlugin, ClientRetryPluginInvalidEventIteratorRetryResponse, DedupeRequestsPlugin, RetryAfterPlugin, SimpleCsrfProtectionLinkPlugin };
|
|
249
|
+
export type { BatchLinkPluginGroup, BatchLinkPluginOptions, ClientRetryPluginAttemptOptions, ClientRetryPluginContext, ClientRetryPluginOptions, DedupeRequestsPluginGroup, DedupeRequestsPluginOptions, RetryAfterPluginOptions, SimpleCsrfProtectionLinkPluginOptions };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { isAsyncIteratorObject, value, splitInHalf, toArray, stringifyJSON } from '@orpc/shared';
|
|
1
|
+
import { isAsyncIteratorObject, defer, value, splitInHalf, toArray, stringifyJSON, overlayProxy, AsyncIteratorClass } from '@orpc/shared';
|
|
2
2
|
import { toBatchRequest, parseBatchResponse, toBatchAbortSignal } from '@orpc/standard-server/batch';
|
|
3
|
-
import { replicateStandardLazyResponse, getEventMeta } from '@orpc/standard-server';
|
|
3
|
+
import { replicateStandardLazyResponse, getEventMeta, flattenHeader } from '@orpc/standard-server';
|
|
4
|
+
import { C as COMMON_ORPC_ERROR_DEFS } from '../shared/client.CAeDqlZP.mjs';
|
|
4
5
|
|
|
5
6
|
class BatchLinkPlugin {
|
|
6
7
|
groups;
|
|
@@ -10,6 +11,7 @@ class BatchLinkPlugin {
|
|
|
10
11
|
batchHeaders;
|
|
11
12
|
mapRequestItem;
|
|
12
13
|
exclude;
|
|
14
|
+
mode;
|
|
13
15
|
pending;
|
|
14
16
|
order = 5e6;
|
|
15
17
|
constructor(options) {
|
|
@@ -17,6 +19,7 @@ class BatchLinkPlugin {
|
|
|
17
19
|
this.pending = /* @__PURE__ */ new Map();
|
|
18
20
|
this.maxSize = options.maxSize ?? 10;
|
|
19
21
|
this.maxUrlLength = options.maxUrlLength ?? 2083;
|
|
22
|
+
this.mode = options.mode ?? "streaming";
|
|
20
23
|
this.batchUrl = options.url ?? (([options2]) => `${options2.request.url.origin}${options2.request.url.pathname}/__batch__`);
|
|
21
24
|
this.batchHeaders = options.headers ?? (([options2, ...rest]) => {
|
|
22
25
|
const headers = {};
|
|
@@ -62,7 +65,7 @@ class BatchLinkPlugin {
|
|
|
62
65
|
});
|
|
63
66
|
});
|
|
64
67
|
options.clientInterceptors.push((options2) => {
|
|
65
|
-
if (this.exclude(options2) || options2.request.body instanceof Blob || options2.request.body instanceof FormData || isAsyncIteratorObject(options2.request.body)) {
|
|
68
|
+
if (this.exclude(options2) || options2.request.body instanceof Blob || options2.request.body instanceof FormData || isAsyncIteratorObject(options2.request.body) || options2.request.signal?.aborted) {
|
|
66
69
|
return options2.next();
|
|
67
70
|
}
|
|
68
71
|
const group = this.groups.find((group2) => group2.condition(options2));
|
|
@@ -71,7 +74,7 @@ class BatchLinkPlugin {
|
|
|
71
74
|
}
|
|
72
75
|
return new Promise((resolve, reject) => {
|
|
73
76
|
this.#enqueueRequest(group, options2, resolve, reject);
|
|
74
|
-
|
|
77
|
+
defer(() => this.#processPendingBatches());
|
|
75
78
|
});
|
|
76
79
|
});
|
|
77
80
|
}
|
|
@@ -127,16 +130,28 @@ class BatchLinkPlugin {
|
|
|
127
130
|
this.#executeBatch(method, group, second);
|
|
128
131
|
return;
|
|
129
132
|
}
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
const mode = value(this.mode, options);
|
|
134
|
+
try {
|
|
135
|
+
const lazyResponse = await options[0].next({
|
|
136
|
+
request: { ...batchRequest, headers: { ...batchRequest.headers, "x-orpc-batch": mode } },
|
|
137
|
+
signal: batchRequest.signal,
|
|
138
|
+
context: group.context,
|
|
139
|
+
input: group.input,
|
|
140
|
+
path: toArray(group.path)
|
|
141
|
+
});
|
|
142
|
+
const parsed = parseBatchResponse({ ...lazyResponse, body: await lazyResponse.body() });
|
|
143
|
+
for await (const item of parsed) {
|
|
144
|
+
batchItems[item.index]?.[1]({ ...item, body: () => Promise.resolve(item.body) });
|
|
145
|
+
}
|
|
146
|
+
} catch (err) {
|
|
147
|
+
if (batchRequest.signal?.aborted && batchRequest.signal.reason === err) {
|
|
148
|
+
for (const [{ signal }, , reject] of batchItems) {
|
|
149
|
+
if (signal?.aborted) {
|
|
150
|
+
reject(signal.reason);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
throw err;
|
|
140
155
|
}
|
|
141
156
|
throw new Error("Something went wrong make batch response not contains enough responses. This can be a bug please report it.");
|
|
142
157
|
} catch (error) {
|
|
@@ -169,7 +184,7 @@ class DedupeRequestsPlugin {
|
|
|
169
184
|
}
|
|
170
185
|
return new Promise((resolve, reject) => {
|
|
171
186
|
this.#enqueue(group, options2, resolve, reject);
|
|
172
|
-
|
|
187
|
+
defer(() => this.#dequeue());
|
|
173
188
|
});
|
|
174
189
|
});
|
|
175
190
|
}
|
|
@@ -249,6 +264,7 @@ class ClientRetryPlugin {
|
|
|
249
264
|
defaultRetryDelay;
|
|
250
265
|
defaultShouldRetry;
|
|
251
266
|
defaultOnRetry;
|
|
267
|
+
order = 18e5;
|
|
252
268
|
constructor(options = {}) {
|
|
253
269
|
this.defaultRetry = options.default?.retry ?? 0;
|
|
254
270
|
this.defaultRetryDelay = options.default?.retryDelay ?? ((o) => o.lastEventRetry ?? 2e3);
|
|
@@ -303,7 +319,7 @@ class ClientRetryPlugin {
|
|
|
303
319
|
return await interceptorOptions.next(updatedInterceptorOptions);
|
|
304
320
|
} catch (error) {
|
|
305
321
|
currentError = { error };
|
|
306
|
-
if (updatedInterceptorOptions.signal?.aborted
|
|
322
|
+
if (updatedInterceptorOptions.signal?.aborted) {
|
|
307
323
|
throw error;
|
|
308
324
|
}
|
|
309
325
|
} finally {
|
|
@@ -316,19 +332,17 @@ class ClientRetryPlugin {
|
|
|
316
332
|
if (!isAsyncIteratorObject(output)) {
|
|
317
333
|
return output;
|
|
318
334
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
335
|
+
let current = output;
|
|
336
|
+
let isIteratorAborted = false;
|
|
337
|
+
return overlayProxy(() => current, new AsyncIteratorClass(
|
|
338
|
+
async () => {
|
|
322
339
|
while (true) {
|
|
323
340
|
try {
|
|
324
341
|
const item = await current.next();
|
|
325
342
|
const meta = getEventMeta(item.value);
|
|
326
343
|
lastEventId = meta?.id ?? lastEventId;
|
|
327
344
|
lastEventRetry = meta?.retry ?? lastEventRetry;
|
|
328
|
-
|
|
329
|
-
return item.value;
|
|
330
|
-
}
|
|
331
|
-
yield item.value;
|
|
345
|
+
return item;
|
|
332
346
|
} catch (error) {
|
|
333
347
|
const meta = getEventMeta(error);
|
|
334
348
|
lastEventId = meta?.id ?? lastEventId;
|
|
@@ -340,12 +354,97 @@ class ClientRetryPlugin {
|
|
|
340
354
|
);
|
|
341
355
|
}
|
|
342
356
|
current = maybeEventIterator;
|
|
357
|
+
if (isIteratorAborted) {
|
|
358
|
+
await current.return?.();
|
|
359
|
+
throw error;
|
|
360
|
+
}
|
|
343
361
|
}
|
|
344
362
|
}
|
|
345
|
-
}
|
|
346
|
-
|
|
363
|
+
},
|
|
364
|
+
async (reason) => {
|
|
365
|
+
isIteratorAborted = true;
|
|
366
|
+
if (reason !== "next") {
|
|
367
|
+
await current.return?.();
|
|
368
|
+
}
|
|
347
369
|
}
|
|
348
|
-
|
|
370
|
+
));
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
class RetryAfterPlugin {
|
|
376
|
+
condition;
|
|
377
|
+
maxAttempts;
|
|
378
|
+
timeout;
|
|
379
|
+
order = 19e5;
|
|
380
|
+
constructor(options = {}) {
|
|
381
|
+
this.condition = options.condition ?? ((response) => response.status === COMMON_ORPC_ERROR_DEFS.TOO_MANY_REQUESTS.status || response.status === COMMON_ORPC_ERROR_DEFS.SERVICE_UNAVAILABLE.status);
|
|
382
|
+
this.maxAttempts = options.maxAttempts ?? 3;
|
|
383
|
+
this.timeout = options.timeout ?? 5 * 60 * 1e3;
|
|
384
|
+
}
|
|
385
|
+
init(options) {
|
|
386
|
+
options.clientInterceptors ??= [];
|
|
387
|
+
options.clientInterceptors.push(async (interceptorOptions) => {
|
|
388
|
+
const startTime = Date.now();
|
|
389
|
+
let attemptCount = 0;
|
|
390
|
+
while (true) {
|
|
391
|
+
attemptCount++;
|
|
392
|
+
const response = await interceptorOptions.next();
|
|
393
|
+
if (!value(this.condition, response, interceptorOptions)) {
|
|
394
|
+
return response;
|
|
395
|
+
}
|
|
396
|
+
const retryAfterHeader = flattenHeader(response.headers["retry-after"]);
|
|
397
|
+
const retryAfterMs = this.parseRetryAfterHeader(retryAfterHeader);
|
|
398
|
+
if (retryAfterMs === void 0) {
|
|
399
|
+
return response;
|
|
400
|
+
}
|
|
401
|
+
if (attemptCount >= value(this.maxAttempts, response, interceptorOptions)) {
|
|
402
|
+
return response;
|
|
403
|
+
}
|
|
404
|
+
const timeoutMs = value(this.timeout, response, interceptorOptions);
|
|
405
|
+
const elapsedTime = Date.now() - startTime;
|
|
406
|
+
if (elapsedTime + retryAfterMs > timeoutMs) {
|
|
407
|
+
return response;
|
|
408
|
+
}
|
|
409
|
+
await this.delayExecution(retryAfterMs, interceptorOptions.signal);
|
|
410
|
+
if (interceptorOptions.signal?.aborted) {
|
|
411
|
+
return response;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
parseRetryAfterHeader(value2) {
|
|
417
|
+
value2 = value2?.trim();
|
|
418
|
+
if (!value2) {
|
|
419
|
+
return void 0;
|
|
420
|
+
}
|
|
421
|
+
const seconds = Number(value2);
|
|
422
|
+
if (Number.isFinite(seconds)) {
|
|
423
|
+
return Math.max(0, seconds * 1e3);
|
|
424
|
+
}
|
|
425
|
+
const retryDate = Date.parse(value2);
|
|
426
|
+
if (!Number.isNaN(retryDate)) {
|
|
427
|
+
return Math.max(0, retryDate - Date.now());
|
|
428
|
+
}
|
|
429
|
+
return void 0;
|
|
430
|
+
}
|
|
431
|
+
delayExecution(ms, signal) {
|
|
432
|
+
return new Promise((resolve) => {
|
|
433
|
+
if (signal?.aborted) {
|
|
434
|
+
resolve();
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
let timeout;
|
|
438
|
+
const onAbort = () => {
|
|
439
|
+
clearTimeout(timeout);
|
|
440
|
+
timeout = void 0;
|
|
441
|
+
resolve();
|
|
442
|
+
};
|
|
443
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
444
|
+
timeout = setTimeout(() => {
|
|
445
|
+
signal?.removeEventListener("abort", onAbort);
|
|
446
|
+
resolve();
|
|
447
|
+
}, ms);
|
|
349
448
|
});
|
|
350
449
|
}
|
|
351
450
|
}
|
|
@@ -383,4 +482,4 @@ class SimpleCsrfProtectionLinkPlugin {
|
|
|
383
482
|
}
|
|
384
483
|
}
|
|
385
484
|
|
|
386
|
-
export { BatchLinkPlugin, ClientRetryPlugin, ClientRetryPluginInvalidEventIteratorRetryResponse, DedupeRequestsPlugin, SimpleCsrfProtectionLinkPlugin };
|
|
485
|
+
export { BatchLinkPlugin, ClientRetryPlugin, ClientRetryPluginInvalidEventIteratorRetryResponse, DedupeRequestsPlugin, RetryAfterPlugin, SimpleCsrfProtectionLinkPlugin };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Interceptor } from '@orpc/shared';
|
|
2
2
|
import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
|
|
3
|
-
import {
|
|
3
|
+
import { b as ClientContext, c as ClientOptions, C as ClientLink } from './client.i2uoJbEp.js';
|
|
4
4
|
|
|
5
5
|
interface StandardLinkPlugin<T extends ClientContext> {
|
|
6
6
|
order?: number;
|
|
@@ -33,7 +33,6 @@ interface StandardLinkOptions<T extends ClientContext> {
|
|
|
33
33
|
plugins?: StandardLinkPlugin<T>[];
|
|
34
34
|
}
|
|
35
35
|
declare class StandardLink<T extends ClientContext> implements ClientLink<T> {
|
|
36
|
-
#private;
|
|
37
36
|
readonly codec: StandardLinkCodec<T>;
|
|
38
37
|
readonly sender: StandardLinkClient<T>;
|
|
39
38
|
private readonly interceptors;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.
|
|
1
|
+
import { b as ClientContext, c as ClientOptions, f as HTTPMethod } from './client.i2uoJbEp.js';
|
|
2
|
+
import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.2jUAqzYU.js';
|
|
3
3
|
import { Segment, Value, Promisable } from '@orpc/shared';
|
|
4
4
|
import { StandardHeaders, StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
|
|
5
5
|
|
|
@@ -67,7 +67,7 @@ interface StandardRPCLinkCodecOptions<T extends ClientContext> {
|
|
|
67
67
|
/**
|
|
68
68
|
* Inject headers to the request.
|
|
69
69
|
*/
|
|
70
|
-
headers?: Value<Promisable<StandardHeaders>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
|
|
70
|
+
headers?: Value<Promisable<StandardHeaders | Headers>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
|
|
71
71
|
}
|
|
72
72
|
declare class StandardRPCLinkCodec<T extends ClientContext> implements StandardLinkCodec<T> {
|
|
73
73
|
private readonly serializer;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.
|
|
1
|
+
import { b as ClientContext, c as ClientOptions, f as HTTPMethod } from './client.i2uoJbEp.mjs';
|
|
2
|
+
import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.CpCa3si8.mjs';
|
|
3
3
|
import { Segment, Value, Promisable } from '@orpc/shared';
|
|
4
4
|
import { StandardHeaders, StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
|
|
5
5
|
|
|
@@ -67,7 +67,7 @@ interface StandardRPCLinkCodecOptions<T extends ClientContext> {
|
|
|
67
67
|
/**
|
|
68
68
|
* Inject headers to the request.
|
|
69
69
|
*/
|
|
70
|
-
headers?: Value<Promisable<StandardHeaders>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
|
|
70
|
+
headers?: Value<Promisable<StandardHeaders | Headers>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
|
|
71
71
|
}
|
|
72
72
|
declare class StandardRPCLinkCodec<T extends ClientContext> implements StandardLinkCodec<T> {
|
|
73
73
|
private readonly serializer;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AsyncIteratorClass, isTypescriptObject } from '@orpc/shared';
|
|
2
|
+
import { getEventMeta, withEventMeta } from '@orpc/standard-server';
|
|
3
|
+
|
|
4
|
+
function mapEventIterator(iterator, maps) {
|
|
5
|
+
const mapError = async (error) => {
|
|
6
|
+
let mappedError = await maps.error(error);
|
|
7
|
+
if (mappedError !== error) {
|
|
8
|
+
const meta = getEventMeta(error);
|
|
9
|
+
if (meta && isTypescriptObject(mappedError)) {
|
|
10
|
+
mappedError = withEventMeta(mappedError, meta);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return mappedError;
|
|
14
|
+
};
|
|
15
|
+
return new AsyncIteratorClass(async () => {
|
|
16
|
+
const { done, value } = await (async () => {
|
|
17
|
+
try {
|
|
18
|
+
return await iterator.next();
|
|
19
|
+
} catch (error) {
|
|
20
|
+
throw await mapError(error);
|
|
21
|
+
}
|
|
22
|
+
})();
|
|
23
|
+
let mappedValue = await maps.value(value, done);
|
|
24
|
+
if (mappedValue !== value) {
|
|
25
|
+
const meta = getEventMeta(value);
|
|
26
|
+
if (meta && isTypescriptObject(mappedValue)) {
|
|
27
|
+
mappedValue = withEventMeta(mappedValue, meta);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return { done, value: mappedValue };
|
|
31
|
+
}, async () => {
|
|
32
|
+
try {
|
|
33
|
+
await iterator.return?.();
|
|
34
|
+
} catch (error) {
|
|
35
|
+
throw await mapError(error);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { mapEventIterator as m };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { toArray, intercept, isObject, value,
|
|
1
|
+
import { toArray, runWithSpan, ORPC_NAME, isAsyncIteratorObject, asyncIteratorWithSpan, intercept, getGlobalOtelConfig, isObject, value, stringifyJSON } from '@orpc/shared';
|
|
2
2
|
import { mergeStandardHeaders, ErrorEvent } from '@orpc/standard-server';
|
|
3
|
-
import { C as COMMON_ORPC_ERROR_DEFS,
|
|
3
|
+
import { C as COMMON_ORPC_ERROR_DEFS, d as isORPCErrorStatus, e as isORPCErrorJson, g as createORPCErrorFromJson, c as ORPCError, t as toORPCError } from './client.CAeDqlZP.mjs';
|
|
4
|
+
import { toStandardHeaders as toStandardHeaders$1 } from '@orpc/standard-server-fetch';
|
|
5
|
+
import { m as mapEventIterator } from './client.BLtwTQUg.mjs';
|
|
4
6
|
|
|
5
7
|
class CompositeStandardLinkPlugin {
|
|
6
8
|
plugins;
|
|
@@ -26,20 +28,52 @@ class StandardLink {
|
|
|
26
28
|
interceptors;
|
|
27
29
|
clientInterceptors;
|
|
28
30
|
call(path, input, options) {
|
|
29
|
-
return
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
return runWithSpan(
|
|
32
|
+
{ name: `${ORPC_NAME}.${path.join("/")}`, signal: options.signal },
|
|
33
|
+
(span) => {
|
|
34
|
+
span?.setAttribute("rpc.system", ORPC_NAME);
|
|
35
|
+
span?.setAttribute("rpc.method", path.join("."));
|
|
36
|
+
if (isAsyncIteratorObject(input)) {
|
|
37
|
+
input = asyncIteratorWithSpan(
|
|
38
|
+
{ name: "consume_event_iterator_input", signal: options.signal },
|
|
39
|
+
input
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return intercept(this.interceptors, { ...options, path, input }, async ({ path: path2, input: input2, ...options2 }) => {
|
|
43
|
+
const otelConfig = getGlobalOtelConfig();
|
|
44
|
+
let otelContext;
|
|
45
|
+
const currentSpan = otelConfig?.trace.getActiveSpan() ?? span;
|
|
46
|
+
if (currentSpan && otelConfig) {
|
|
47
|
+
otelContext = otelConfig?.trace.setSpan(otelConfig.context.active(), currentSpan);
|
|
48
|
+
}
|
|
49
|
+
const request = await runWithSpan(
|
|
50
|
+
{ name: "encode_request", context: otelContext },
|
|
51
|
+
() => this.codec.encode(path2, input2, options2)
|
|
52
|
+
);
|
|
53
|
+
const response = await intercept(
|
|
54
|
+
this.clientInterceptors,
|
|
55
|
+
{ ...options2, input: input2, path: path2, request },
|
|
56
|
+
({ input: input3, path: path3, request: request2, ...options3 }) => {
|
|
57
|
+
return runWithSpan(
|
|
58
|
+
{ name: "send_request", signal: options3.signal, context: otelContext },
|
|
59
|
+
() => this.sender.call(request2, options3, path3, input3)
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
const output = await runWithSpan(
|
|
64
|
+
{ name: "decode_response", context: otelContext },
|
|
65
|
+
() => this.codec.decode(response, options2, path2, input2)
|
|
66
|
+
);
|
|
67
|
+
if (isAsyncIteratorObject(output)) {
|
|
68
|
+
return asyncIteratorWithSpan(
|
|
69
|
+
{ name: "consume_event_iterator_output", signal: options2.signal },
|
|
70
|
+
output
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return output;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
40
76
|
);
|
|
41
|
-
const output = await this.codec.decode(response, options, path, input);
|
|
42
|
-
return output;
|
|
43
77
|
}
|
|
44
78
|
}
|
|
45
79
|
|
|
@@ -192,6 +226,12 @@ class StandardRPCJsonSerializer {
|
|
|
192
226
|
function toHttpPath(path) {
|
|
193
227
|
return `/${path.map(encodeURIComponent).join("/")}`;
|
|
194
228
|
}
|
|
229
|
+
function toStandardHeaders(headers) {
|
|
230
|
+
if (typeof headers.forEach === "function") {
|
|
231
|
+
return toStandardHeaders$1(headers);
|
|
232
|
+
}
|
|
233
|
+
return headers;
|
|
234
|
+
}
|
|
195
235
|
function getMalformedResponseErrorCode(status) {
|
|
196
236
|
return Object.entries(COMMON_ORPC_ERROR_DEFS).find(([, def]) => def.status === status)?.[0] ?? "MALFORMED_ORPC_ERROR_RESPONSE";
|
|
197
237
|
}
|
|
@@ -211,14 +251,14 @@ class StandardRPCLinkCodec {
|
|
|
211
251
|
expectedMethod;
|
|
212
252
|
headers;
|
|
213
253
|
async encode(path, input, options) {
|
|
254
|
+
let headers = toStandardHeaders(await value(this.headers, options, path, input));
|
|
255
|
+
if (options.lastEventId !== void 0) {
|
|
256
|
+
headers = mergeStandardHeaders(headers, { "last-event-id": options.lastEventId });
|
|
257
|
+
}
|
|
214
258
|
const expectedMethod = await value(this.expectedMethod, options, path, input);
|
|
215
|
-
let headers = await value(this.headers, options, path, input);
|
|
216
259
|
const baseUrl = await value(this.baseUrl, options, path, input);
|
|
217
260
|
const url = new URL(baseUrl);
|
|
218
261
|
url.pathname = `${url.pathname.replace(/\/$/, "")}${toHttpPath(path)}`;
|
|
219
|
-
if (options.lastEventId !== void 0) {
|
|
220
|
-
headers = mergeStandardHeaders(headers, { "last-event-id": options.lastEventId });
|
|
221
|
-
}
|
|
222
262
|
const serialized = this.serializer.serialize(input);
|
|
223
263
|
if (expectedMethod === "GET" && !(serialized instanceof FormData) && !isAsyncIteratorObject(serialized)) {
|
|
224
264
|
const maxUrlLength = await value(this.maxUrlLength, options, path, input);
|
|
@@ -330,6 +370,9 @@ class StandardRPCSerializer {
|
|
|
330
370
|
return this.#deserialize(data);
|
|
331
371
|
}
|
|
332
372
|
#deserialize(data) {
|
|
373
|
+
if (data === void 0) {
|
|
374
|
+
return void 0;
|
|
375
|
+
}
|
|
333
376
|
if (!(data instanceof FormData)) {
|
|
334
377
|
return this.jsonSerializer.deserialize(data.json, data.meta ?? []);
|
|
335
378
|
}
|
|
@@ -352,4 +395,4 @@ class StandardRPCLink extends StandardLink {
|
|
|
352
395
|
}
|
|
353
396
|
}
|
|
354
397
|
|
|
355
|
-
export { CompositeStandardLinkPlugin as C, StandardLink as S, STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as a, StandardRPCJsonSerializer as b, StandardRPCLink as c, StandardRPCLinkCodec as d, StandardRPCSerializer as e, getMalformedResponseErrorCode as g, toHttpPath as t };
|
|
398
|
+
export { CompositeStandardLinkPlugin as C, StandardLink as S, STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as a, StandardRPCJsonSerializer as b, StandardRPCLink as c, StandardRPCLinkCodec as d, StandardRPCSerializer as e, toStandardHeaders as f, getMalformedResponseErrorCode as g, toHttpPath as t };
|