@orpc/client 0.0.0-next.32a6de9 → 0.0.0-next.32e1281

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.
@@ -1,6 +1,6 @@
1
- import { isAsyncIteratorObject, value, splitInHalf, toArray } from '@orpc/shared';
2
- import { toBatchRequest, parseBatchResponse } from '@orpc/standard-server/batch';
3
- import { getEventMeta } from '@orpc/standard-server';
1
+ import { isAsyncIteratorObject, defer, value, splitInHalf, toArray, stringifyJSON } from '@orpc/shared';
2
+ import { toBatchRequest, parseBatchResponse, toBatchAbortSignal } from '@orpc/standard-server/batch';
3
+ import { replicateStandardLazyResponse, getEventMeta } from '@orpc/standard-server';
4
4
 
5
5
  class BatchLinkPlugin {
6
6
  groups;
@@ -10,12 +10,15 @@ class BatchLinkPlugin {
10
10
  batchHeaders;
11
11
  mapRequestItem;
12
12
  exclude;
13
+ mode;
13
14
  pending;
15
+ order = 5e6;
14
16
  constructor(options) {
15
17
  this.groups = options.groups;
16
18
  this.pending = /* @__PURE__ */ new Map();
17
19
  this.maxSize = options.maxSize ?? 10;
18
20
  this.maxUrlLength = options.maxUrlLength ?? 2083;
21
+ this.mode = options.mode ?? "streaming";
19
22
  this.batchUrl = options.url ?? (([options2]) => `${options2.request.url.origin}${options2.request.url.pathname}/__batch__`);
20
23
  this.batchHeaders = options.headers ?? (([options2, ...rest]) => {
21
24
  const headers = {};
@@ -70,7 +73,7 @@ class BatchLinkPlugin {
70
73
  }
71
74
  return new Promise((resolve, reject) => {
72
75
  this.#enqueueRequest(group, options2, resolve, reject);
73
- setTimeout(() => this.#processPendingBatches());
76
+ defer(() => this.#processPendingBatches());
74
77
  });
75
78
  });
76
79
  }
@@ -126,8 +129,9 @@ class BatchLinkPlugin {
126
129
  this.#executeBatch(method, group, second);
127
130
  return;
128
131
  }
132
+ const mode = value(this.mode, options);
129
133
  const lazyResponse = await options[0].next({
130
- request: { ...batchRequest, headers: { ...batchRequest.headers, "x-orpc-batch": "1" } },
134
+ request: { ...batchRequest, headers: { ...batchRequest.headers, "x-orpc-batch": mode } },
131
135
  signal: batchRequest.signal,
132
136
  context: group.context,
133
137
  input: group.input,
@@ -146,6 +150,101 @@ class BatchLinkPlugin {
146
150
  }
147
151
  }
148
152
 
153
+ class DedupeRequestsPlugin {
154
+ #groups;
155
+ #filter;
156
+ order = 4e6;
157
+ // make sure execute before batch plugin
158
+ #queue = /* @__PURE__ */ new Map();
159
+ constructor(options) {
160
+ this.#groups = options.groups;
161
+ this.#filter = options.filter ?? (({ request }) => request.method === "GET");
162
+ }
163
+ init(options) {
164
+ options.clientInterceptors ??= [];
165
+ options.clientInterceptors.push((options2) => {
166
+ if (options2.request.body instanceof Blob || options2.request.body instanceof FormData || options2.request.body instanceof URLSearchParams || isAsyncIteratorObject(options2.request.body) || !this.#filter(options2)) {
167
+ return options2.next();
168
+ }
169
+ const group = this.#groups.find((group2) => group2.condition(options2));
170
+ if (!group) {
171
+ return options2.next();
172
+ }
173
+ return new Promise((resolve, reject) => {
174
+ this.#enqueue(group, options2, resolve, reject);
175
+ defer(() => this.#dequeue());
176
+ });
177
+ });
178
+ }
179
+ #enqueue(group, options, resolve, reject) {
180
+ let queue = this.#queue.get(group);
181
+ if (!queue) {
182
+ this.#queue.set(group, queue = []);
183
+ }
184
+ const matched = queue.find((item) => {
185
+ const requestString1 = stringifyJSON({
186
+ body: item.options.request.body,
187
+ headers: item.options.request.headers,
188
+ method: item.options.request.method,
189
+ url: item.options.request.url
190
+ });
191
+ const requestString2 = stringifyJSON({
192
+ body: options.request.body,
193
+ headers: options.request.headers,
194
+ method: options.request.method,
195
+ url: options.request.url
196
+ });
197
+ return requestString1 === requestString2;
198
+ });
199
+ if (matched) {
200
+ matched.signals.push(options.request.signal);
201
+ matched.resolves.push(resolve);
202
+ matched.rejects.push(reject);
203
+ } else {
204
+ queue.push({
205
+ options,
206
+ signals: [options.request.signal],
207
+ resolves: [resolve],
208
+ rejects: [reject]
209
+ });
210
+ }
211
+ }
212
+ async #dequeue() {
213
+ const promises = [];
214
+ for (const [group, items] of this.#queue) {
215
+ for (const { options, signals, resolves, rejects } of items) {
216
+ promises.push(
217
+ this.#execute(group, options, signals, resolves, rejects)
218
+ );
219
+ }
220
+ }
221
+ this.#queue.clear();
222
+ await Promise.all(promises);
223
+ }
224
+ async #execute(group, options, signals, resolves, rejects) {
225
+ try {
226
+ const dedupedRequest = {
227
+ ...options.request,
228
+ signal: toBatchAbortSignal(signals)
229
+ };
230
+ const response = await options.next({
231
+ ...options,
232
+ request: dedupedRequest,
233
+ signal: dedupedRequest.signal,
234
+ context: group.context
235
+ });
236
+ const replicatedResponses = replicateStandardLazyResponse(response, resolves.length);
237
+ for (const resolve of resolves) {
238
+ resolve(replicatedResponses.shift());
239
+ }
240
+ } catch (error) {
241
+ for (const reject of rejects) {
242
+ reject(error);
243
+ }
244
+ }
245
+ }
246
+ }
247
+
149
248
  class ClientRetryPluginInvalidEventIteratorRetryResponse extends Error {
150
249
  }
151
250
  class ClientRetryPlugin {
@@ -174,20 +273,20 @@ class ClientRetryPlugin {
174
273
  }
175
274
  let lastEventId = interceptorOptions.lastEventId;
176
275
  let lastEventRetry;
177
- let unsubscribe;
276
+ let callback;
178
277
  let attemptIndex = 0;
179
- const next = async (initial) => {
180
- let current = initial;
278
+ const next = async (initialError) => {
279
+ let currentError = initialError;
181
280
  while (true) {
182
281
  const updatedInterceptorOptions = { ...interceptorOptions, lastEventId };
183
- if (current) {
282
+ if (currentError) {
184
283
  if (attemptIndex >= maxAttempts) {
185
- throw current.error;
284
+ throw currentError.error;
186
285
  }
187
286
  const attemptOptions = {
188
287
  ...updatedInterceptorOptions,
189
288
  attemptIndex,
190
- error: current.error,
289
+ error: currentError.error,
191
290
  lastEventRetry
192
291
  };
193
292
  const shouldRetryBool = await value(
@@ -195,23 +294,24 @@ class ClientRetryPlugin {
195
294
  attemptOptions
196
295
  );
197
296
  if (!shouldRetryBool) {
198
- throw current.error;
297
+ throw currentError.error;
199
298
  }
200
- unsubscribe = onRetry?.(attemptOptions);
299
+ callback = onRetry?.(attemptOptions);
201
300
  const retryDelayMs = await value(retryDelay, attemptOptions);
202
301
  await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
203
302
  attemptIndex++;
204
303
  }
205
304
  try {
305
+ currentError = void 0;
206
306
  return await interceptorOptions.next(updatedInterceptorOptions);
207
307
  } catch (error) {
308
+ currentError = { error };
208
309
  if (updatedInterceptorOptions.signal?.aborted === true) {
209
310
  throw error;
210
311
  }
211
- current = { error };
212
312
  } finally {
213
- unsubscribe?.();
214
- unsubscribe = void 0;
313
+ callback?.(!currentError);
314
+ callback = void 0;
215
315
  }
216
316
  }
217
317
  };
@@ -253,4 +353,37 @@ class ClientRetryPlugin {
253
353
  }
254
354
  }
255
355
 
256
- export { BatchLinkPlugin, ClientRetryPlugin, ClientRetryPluginInvalidEventIteratorRetryResponse };
356
+ class SimpleCsrfProtectionLinkPlugin {
357
+ headerName;
358
+ headerValue;
359
+ exclude;
360
+ constructor(options = {}) {
361
+ this.headerName = options.headerName ?? "x-csrf-token";
362
+ this.headerValue = options.headerValue ?? "orpc";
363
+ this.exclude = options.exclude ?? false;
364
+ }
365
+ order = 8e6;
366
+ init(options) {
367
+ options.clientInterceptors ??= [];
368
+ options.clientInterceptors.push(async (options2) => {
369
+ const excluded = await value(this.exclude, options2);
370
+ if (excluded) {
371
+ return options2.next();
372
+ }
373
+ const headerName = await value(this.headerName, options2);
374
+ const headerValue = await value(this.headerValue, options2);
375
+ return options2.next({
376
+ ...options2,
377
+ request: {
378
+ ...options2.request,
379
+ headers: {
380
+ ...options2.request.headers,
381
+ [headerName]: headerValue
382
+ }
383
+ }
384
+ });
385
+ });
386
+ }
387
+ }
388
+
389
+ export { BatchLinkPlugin, ClientRetryPlugin, ClientRetryPluginInvalidEventIteratorRetryResponse, DedupeRequestsPlugin, SimpleCsrfProtectionLinkPlugin };
@@ -1,7 +1,7 @@
1
1
  import { PromiseWithError } from '@orpc/shared';
2
2
 
3
3
  type HTTPPath = `/${string}`;
4
- type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
4
+ type HTTPMethod = 'HEAD' | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
5
5
  type ClientContext = Record<PropertyKey, any>;
6
6
  interface ClientOptions<T extends ClientContext> {
7
7
  signal?: AbortSignal;
@@ -1,7 +1,7 @@
1
1
  import { PromiseWithError } from '@orpc/shared';
2
2
 
3
3
  type HTTPPath = `/${string}`;
4
- type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
4
+ type HTTPMethod = 'HEAD' | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
5
5
  type ClientContext = Record<PropertyKey, any>;
6
6
  interface ClientOptions<T extends ClientContext> {
7
7
  signal?: AbortSignal;
@@ -1,6 +1,6 @@
1
- import { a as ClientContext, d as HTTPMethod, b as ClientOptions } from './client.CipPQkhk.js';
2
- import { c as StandardLinkInterceptorOptions, e as StandardLinkCodec, b as StandardLinkOptions } from './client.p3ON_yzu.js';
3
- import { Segment, Value } from '@orpc/shared';
1
+ import { a as ClientContext, b as ClientOptions, d as HTTPMethod } from './client.4TS_0JaO.js';
2
+ import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.C0KbSWlC.js';
3
+ import { Segment, Value, Promisable } from '@orpc/shared';
4
4
  import { StandardHeaders, StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
5
5
 
6
6
  declare const STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES: {
@@ -44,30 +44,30 @@ interface StandardRPCLinkCodecOptions<T extends ClientContext> {
44
44
  /**
45
45
  * Base url for all requests.
46
46
  */
47
- url: Value<string | URL, [StandardLinkInterceptorOptions<T>]>;
47
+ url: Value<Promisable<string | URL>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
48
48
  /**
49
49
  * The maximum length of the URL.
50
50
  *
51
51
  * @default 2083
52
52
  */
53
- maxUrlLength?: Value<number, [StandardLinkInterceptorOptions<T>]>;
53
+ maxUrlLength?: Value<Promisable<number>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
54
54
  /**
55
55
  * The method used to make the request.
56
56
  *
57
57
  * @default 'POST'
58
58
  */
59
- method?: Value<HTTPMethod, [StandardLinkInterceptorOptions<T>]>;
59
+ method?: Value<Promisable<Exclude<HTTPMethod, 'HEAD'>>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
60
60
  /**
61
61
  * The method to use when the payload cannot safely pass to the server with method return from method function.
62
62
  * GET is not allowed, it's very dangerous.
63
63
  *
64
64
  * @default 'POST'
65
65
  */
66
- fallbackMethod?: Exclude<HTTPMethod, 'GET'>;
66
+ fallbackMethod?: Exclude<HTTPMethod, 'HEAD' | 'GET'>;
67
67
  /**
68
68
  * Inject headers to the request.
69
69
  */
70
- headers?: Value<StandardHeaders, [StandardLinkInterceptorOptions<T>]>;
70
+ headers?: Value<Promisable<StandardHeaders>, [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;
@@ -83,5 +83,9 @@ declare class StandardRPCLinkCodec<T extends ClientContext> implements StandardL
83
83
 
84
84
  interface StandardRPCLinkOptions<T extends ClientContext> extends StandardLinkOptions<T>, StandardRPCLinkCodecOptions<T>, StandardRPCJsonSerializerOptions {
85
85
  }
86
+ declare class StandardRPCLink<T extends ClientContext> extends StandardLink<T> {
87
+ constructor(linkClient: StandardLinkClient<T>, options: StandardRPCLinkOptions<T>);
88
+ }
86
89
 
87
- export { STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as S, type StandardRPCJsonSerializedMetaItem as a, type StandardRPCJsonSerialized as b, type StandardRPCCustomJsonSerializer as c, type StandardRPCJsonSerializerOptions as d, StandardRPCJsonSerializer as e, type StandardRPCLinkOptions as f, type StandardRPCLinkCodecOptions as g, StandardRPCLinkCodec as h, StandardRPCSerializer as i };
90
+ export { STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as S, StandardRPCJsonSerializer as e, StandardRPCLink as g, StandardRPCLinkCodec as i, StandardRPCSerializer as j };
91
+ export type { StandardRPCJsonSerializedMetaItem as a, StandardRPCJsonSerialized as b, StandardRPCCustomJsonSerializer as c, StandardRPCJsonSerializerOptions as d, StandardRPCLinkOptions as f, StandardRPCLinkCodecOptions as h };
@@ -1,6 +1,16 @@
1
- import { Interceptor, ThrowableError } from '@orpc/shared';
1
+ import { Interceptor } from '@orpc/shared';
2
2
  import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
3
- import { a as ClientContext, b as ClientOptions, C as ClientLink } from './client.CipPQkhk.js';
3
+ import { a as ClientContext, b as ClientOptions, C as ClientLink } from './client.4TS_0JaO.mjs';
4
+
5
+ interface StandardLinkPlugin<T extends ClientContext> {
6
+ order?: number;
7
+ init?(options: StandardLinkOptions<T>): void;
8
+ }
9
+ declare class CompositeStandardLinkPlugin<T extends ClientContext, TPlugin extends StandardLinkPlugin<T>> implements StandardLinkPlugin<T> {
10
+ protected readonly plugins: TPlugin[];
11
+ constructor(plugins?: readonly TPlugin[]);
12
+ init(options: StandardLinkOptions<T>): void;
13
+ }
4
14
 
5
15
  interface StandardLinkCodec<T extends ClientContext> {
6
16
  encode(path: readonly string[], input: unknown, options: ClientOptions<T>): Promise<StandardRequest>;
@@ -10,11 +20,6 @@ interface StandardLinkClient<T extends ClientContext> {
10
20
  call(request: StandardRequest, options: ClientOptions<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse>;
11
21
  }
12
22
 
13
- declare class InvalidEventIteratorRetryResponse extends Error {
14
- }
15
- interface StandardLinkPlugin<T extends ClientContext> {
16
- init?(options: StandardLinkOptions<T>): void;
17
- }
18
23
  interface StandardLinkInterceptorOptions<T extends ClientContext> extends ClientOptions<T> {
19
24
  path: readonly string[];
20
25
  input: unknown;
@@ -23,8 +28,8 @@ interface StandardLinkClientInterceptorOptions<T extends ClientContext> extends
23
28
  request: StandardRequest;
24
29
  }
25
30
  interface StandardLinkOptions<T extends ClientContext> {
26
- interceptors?: Interceptor<StandardLinkInterceptorOptions<T>, unknown, ThrowableError>[];
27
- clientInterceptors?: Interceptor<StandardLinkClientInterceptorOptions<T>, StandardLazyResponse, ThrowableError>[];
31
+ interceptors?: Interceptor<StandardLinkInterceptorOptions<T>, Promise<unknown>>[];
32
+ clientInterceptors?: Interceptor<StandardLinkClientInterceptorOptions<T>, Promise<StandardLazyResponse>>[];
28
33
  plugins?: StandardLinkPlugin<T>[];
29
34
  }
30
35
  declare class StandardLink<T extends ClientContext> implements ClientLink<T> {
@@ -37,4 +42,5 @@ declare class StandardLink<T extends ClientContext> implements ClientLink<T> {
37
42
  call(path: readonly string[], input: unknown, options: ClientOptions<T>): Promise<unknown>;
38
43
  }
39
44
 
40
- export { InvalidEventIteratorRetryResponse as I, type StandardLinkClientInterceptorOptions as S, type StandardLinkPlugin as a, type StandardLinkOptions as b, type StandardLinkInterceptorOptions as c, StandardLink as d, type StandardLinkCodec as e, type StandardLinkClient as f };
45
+ export { CompositeStandardLinkPlugin as C, StandardLink as d };
46
+ export type { StandardLinkClientInterceptorOptions as S, StandardLinkPlugin as a, StandardLinkOptions as b, StandardLinkInterceptorOptions as c, StandardLinkCodec as e, StandardLinkClient as f };
@@ -1,4 +1,4 @@
1
- import { isObject, isTypescriptObject } from '@orpc/shared';
1
+ import { isObject, AsyncIteratorClass, isTypescriptObject } from '@orpc/shared';
2
2
  import { getEventMeta, withEventMeta } from '@orpc/standard-server';
3
3
 
4
4
  const COMMON_ORPC_ERROR_DEFS = {
@@ -110,22 +110,6 @@ class ORPCError extends Error {
110
110
  data: this.data
111
111
  };
112
112
  }
113
- static fromJSON(json, options) {
114
- return new ORPCError(json.code, {
115
- ...options,
116
- ...json
117
- });
118
- }
119
- static isValidJSON(json) {
120
- if (!isObject(json)) {
121
- return false;
122
- }
123
- const validKeys = ["defined", "code", "status", "message", "data"];
124
- if (Object.keys(json).some((k) => !validKeys.includes(k))) {
125
- return false;
126
- }
127
- return "defined" in json && typeof json.defined === "boolean" && "code" in json && typeof json.code === "string" && "status" in json && typeof json.status === "number" && "message" in json && typeof json.message === "string";
128
- }
129
113
  }
130
114
  function isDefinedError(error) {
131
115
  return error instanceof ORPCError && error.defined;
@@ -139,24 +123,35 @@ function toORPCError(error) {
139
123
  function isORPCErrorStatus(status) {
140
124
  return status < 200 || status >= 400;
141
125
  }
126
+ function isORPCErrorJson(json) {
127
+ if (!isObject(json)) {
128
+ return false;
129
+ }
130
+ const validKeys = ["defined", "code", "status", "message", "data"];
131
+ if (Object.keys(json).some((k) => !validKeys.includes(k))) {
132
+ return false;
133
+ }
134
+ return "defined" in json && typeof json.defined === "boolean" && "code" in json && typeof json.code === "string" && "status" in json && typeof json.status === "number" && isORPCErrorStatus(json.status) && "message" in json && typeof json.message === "string";
135
+ }
136
+ function createORPCErrorFromJson(json, options = {}) {
137
+ return new ORPCError(json.code, {
138
+ ...options,
139
+ ...json
140
+ });
141
+ }
142
142
 
143
143
  function mapEventIterator(iterator, maps) {
144
- return async function* () {
144
+ return new AsyncIteratorClass(async () => {
145
145
  try {
146
- while (true) {
147
- const { done, value } = await iterator.next();
148
- let mappedValue = await maps.value(value, done);
149
- if (mappedValue !== value) {
150
- const meta = getEventMeta(value);
151
- if (meta && isTypescriptObject(mappedValue)) {
152
- mappedValue = withEventMeta(mappedValue, meta);
153
- }
146
+ const { done, value } = await iterator.next();
147
+ let mappedValue = await maps.value(value, done);
148
+ if (mappedValue !== value) {
149
+ const meta = getEventMeta(value);
150
+ if (meta && isTypescriptObject(mappedValue)) {
151
+ mappedValue = withEventMeta(mappedValue, meta);
154
152
  }
155
- if (done) {
156
- return mappedValue;
157
- }
158
- yield mappedValue;
159
153
  }
154
+ return { done, value: mappedValue };
160
155
  } catch (error) {
161
156
  let mappedError = await maps.error(error);
162
157
  if (mappedError !== error) {
@@ -166,10 +161,12 @@ function mapEventIterator(iterator, maps) {
166
161
  }
167
162
  }
168
163
  throw mappedError;
169
- } finally {
164
+ }
165
+ }, async (reason) => {
166
+ if (reason !== "next") {
170
167
  await iterator.return?.();
171
168
  }
172
- }();
169
+ });
173
170
  }
174
171
 
175
- export { COMMON_ORPC_ERROR_DEFS as C, ORPCError as O, fallbackORPCErrorMessage as a, isORPCErrorStatus as b, fallbackORPCErrorStatus as f, isDefinedError as i, mapEventIterator as m, toORPCError as t };
172
+ export { COMMON_ORPC_ERROR_DEFS as C, ORPCError as O, fallbackORPCErrorMessage as a, isORPCErrorStatus as b, isORPCErrorJson as c, createORPCErrorFromJson as d, fallbackORPCErrorStatus as f, isDefinedError as i, mapEventIterator as m, toORPCError as t };
@@ -1,6 +1,6 @@
1
- import { a as ClientContext, d as HTTPMethod, b as ClientOptions } from './client.CipPQkhk.mjs';
2
- import { c as StandardLinkInterceptorOptions, e as StandardLinkCodec, b as StandardLinkOptions } from './client.C7z5zk4v.mjs';
3
- import { Segment, Value } from '@orpc/shared';
1
+ import { a as ClientContext, b as ClientOptions, d as HTTPMethod } from './client.4TS_0JaO.mjs';
2
+ import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.BMoG_EdN.mjs';
3
+ import { Segment, Value, Promisable } from '@orpc/shared';
4
4
  import { StandardHeaders, StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
5
5
 
6
6
  declare const STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES: {
@@ -44,30 +44,30 @@ interface StandardRPCLinkCodecOptions<T extends ClientContext> {
44
44
  /**
45
45
  * Base url for all requests.
46
46
  */
47
- url: Value<string | URL, [StandardLinkInterceptorOptions<T>]>;
47
+ url: Value<Promisable<string | URL>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
48
48
  /**
49
49
  * The maximum length of the URL.
50
50
  *
51
51
  * @default 2083
52
52
  */
53
- maxUrlLength?: Value<number, [StandardLinkInterceptorOptions<T>]>;
53
+ maxUrlLength?: Value<Promisable<number>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
54
54
  /**
55
55
  * The method used to make the request.
56
56
  *
57
57
  * @default 'POST'
58
58
  */
59
- method?: Value<HTTPMethod, [StandardLinkInterceptorOptions<T>]>;
59
+ method?: Value<Promisable<Exclude<HTTPMethod, 'HEAD'>>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
60
60
  /**
61
61
  * The method to use when the payload cannot safely pass to the server with method return from method function.
62
62
  * GET is not allowed, it's very dangerous.
63
63
  *
64
64
  * @default 'POST'
65
65
  */
66
- fallbackMethod?: Exclude<HTTPMethod, 'GET'>;
66
+ fallbackMethod?: Exclude<HTTPMethod, 'HEAD' | 'GET'>;
67
67
  /**
68
68
  * Inject headers to the request.
69
69
  */
70
- headers?: Value<StandardHeaders, [StandardLinkInterceptorOptions<T>]>;
70
+ headers?: Value<Promisable<StandardHeaders>, [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;
@@ -83,5 +83,9 @@ declare class StandardRPCLinkCodec<T extends ClientContext> implements StandardL
83
83
 
84
84
  interface StandardRPCLinkOptions<T extends ClientContext> extends StandardLinkOptions<T>, StandardRPCLinkCodecOptions<T>, StandardRPCJsonSerializerOptions {
85
85
  }
86
+ declare class StandardRPCLink<T extends ClientContext> extends StandardLink<T> {
87
+ constructor(linkClient: StandardLinkClient<T>, options: StandardRPCLinkOptions<T>);
88
+ }
86
89
 
87
- export { STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as S, type StandardRPCJsonSerializedMetaItem as a, type StandardRPCJsonSerialized as b, type StandardRPCCustomJsonSerializer as c, type StandardRPCJsonSerializerOptions as d, StandardRPCJsonSerializer as e, type StandardRPCLinkOptions as f, type StandardRPCLinkCodecOptions as g, StandardRPCLinkCodec as h, StandardRPCSerializer as i };
90
+ export { STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as S, StandardRPCJsonSerializer as e, StandardRPCLink as g, StandardRPCLinkCodec as i, StandardRPCSerializer as j };
91
+ export type { StandardRPCJsonSerializedMetaItem as a, StandardRPCJsonSerialized as b, StandardRPCCustomJsonSerializer as c, StandardRPCJsonSerializerOptions as d, StandardRPCLinkOptions as f, StandardRPCLinkCodecOptions as h };
@@ -1,6 +1,16 @@
1
- import { Interceptor, ThrowableError } from '@orpc/shared';
1
+ import { Interceptor } from '@orpc/shared';
2
2
  import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
3
- import { a as ClientContext, b as ClientOptions, C as ClientLink } from './client.CipPQkhk.mjs';
3
+ import { a as ClientContext, b as ClientOptions, C as ClientLink } from './client.4TS_0JaO.js';
4
+
5
+ interface StandardLinkPlugin<T extends ClientContext> {
6
+ order?: number;
7
+ init?(options: StandardLinkOptions<T>): void;
8
+ }
9
+ declare class CompositeStandardLinkPlugin<T extends ClientContext, TPlugin extends StandardLinkPlugin<T>> implements StandardLinkPlugin<T> {
10
+ protected readonly plugins: TPlugin[];
11
+ constructor(plugins?: readonly TPlugin[]);
12
+ init(options: StandardLinkOptions<T>): void;
13
+ }
4
14
 
5
15
  interface StandardLinkCodec<T extends ClientContext> {
6
16
  encode(path: readonly string[], input: unknown, options: ClientOptions<T>): Promise<StandardRequest>;
@@ -10,11 +20,6 @@ interface StandardLinkClient<T extends ClientContext> {
10
20
  call(request: StandardRequest, options: ClientOptions<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse>;
11
21
  }
12
22
 
13
- declare class InvalidEventIteratorRetryResponse extends Error {
14
- }
15
- interface StandardLinkPlugin<T extends ClientContext> {
16
- init?(options: StandardLinkOptions<T>): void;
17
- }
18
23
  interface StandardLinkInterceptorOptions<T extends ClientContext> extends ClientOptions<T> {
19
24
  path: readonly string[];
20
25
  input: unknown;
@@ -23,8 +28,8 @@ interface StandardLinkClientInterceptorOptions<T extends ClientContext> extends
23
28
  request: StandardRequest;
24
29
  }
25
30
  interface StandardLinkOptions<T extends ClientContext> {
26
- interceptors?: Interceptor<StandardLinkInterceptorOptions<T>, unknown, ThrowableError>[];
27
- clientInterceptors?: Interceptor<StandardLinkClientInterceptorOptions<T>, StandardLazyResponse, ThrowableError>[];
31
+ interceptors?: Interceptor<StandardLinkInterceptorOptions<T>, Promise<unknown>>[];
32
+ clientInterceptors?: Interceptor<StandardLinkClientInterceptorOptions<T>, Promise<StandardLazyResponse>>[];
28
33
  plugins?: StandardLinkPlugin<T>[];
29
34
  }
30
35
  declare class StandardLink<T extends ClientContext> implements ClientLink<T> {
@@ -37,4 +42,5 @@ declare class StandardLink<T extends ClientContext> implements ClientLink<T> {
37
42
  call(path: readonly string[], input: unknown, options: ClientOptions<T>): Promise<unknown>;
38
43
  }
39
44
 
40
- export { InvalidEventIteratorRetryResponse as I, type StandardLinkClientInterceptorOptions as S, type StandardLinkPlugin as a, type StandardLinkOptions as b, type StandardLinkInterceptorOptions as c, StandardLink as d, type StandardLinkCodec as e, type StandardLinkClient as f };
45
+ export { CompositeStandardLinkPlugin as C, StandardLink as d };
46
+ export type { StandardLinkClientInterceptorOptions as S, StandardLinkPlugin as a, StandardLinkOptions as b, StandardLinkInterceptorOptions as c, StandardLinkCodec as e, StandardLinkClient as f };
@@ -1,16 +1,25 @@
1
1
  import { toArray, intercept, isObject, value, isAsyncIteratorObject, stringifyJSON } from '@orpc/shared';
2
2
  import { mergeStandardHeaders, ErrorEvent } from '@orpc/standard-server';
3
- import { C as COMMON_ORPC_ERROR_DEFS, b as isORPCErrorStatus, O as ORPCError, m as mapEventIterator, t as toORPCError } from './client.jKEwIsRd.mjs';
3
+ import { C as COMMON_ORPC_ERROR_DEFS, b as isORPCErrorStatus, c as isORPCErrorJson, d as createORPCErrorFromJson, O as ORPCError, m as mapEventIterator, t as toORPCError } from './client.BX0_8bnM.mjs';
4
4
 
5
- class InvalidEventIteratorRetryResponse extends Error {
5
+ class CompositeStandardLinkPlugin {
6
+ plugins;
7
+ constructor(plugins = []) {
8
+ this.plugins = [...plugins].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
9
+ }
10
+ init(options) {
11
+ for (const plugin of this.plugins) {
12
+ plugin.init?.(options);
13
+ }
14
+ }
6
15
  }
16
+
7
17
  class StandardLink {
8
18
  constructor(codec, sender, options = {}) {
9
19
  this.codec = codec;
10
20
  this.sender = sender;
11
- for (const plugin of toArray(options.plugins)) {
12
- plugin.init?.(options);
13
- }
21
+ const plugin = new CompositeStandardLinkPlugin(options.plugins);
22
+ plugin.init(options);
14
23
  this.interceptors = toArray(options.interceptors);
15
24
  this.clientInterceptors = toArray(options.clientInterceptors);
16
25
  }
@@ -202,10 +211,9 @@ class StandardRPCLinkCodec {
202
211
  expectedMethod;
203
212
  headers;
204
213
  async encode(path, input, options) {
205
- const generalOptions = { ...options, path, input };
206
- const expectedMethod = await value(this.expectedMethod, generalOptions);
207
- let headers = await value(this.headers, generalOptions);
208
- const baseUrl = await value(this.baseUrl, generalOptions);
214
+ const expectedMethod = await value(this.expectedMethod, options, path, input);
215
+ let headers = await value(this.headers, options, path, input);
216
+ const baseUrl = await value(this.baseUrl, options, path, input);
209
217
  const url = new URL(baseUrl);
210
218
  url.pathname = `${url.pathname.replace(/\/$/, "")}${toHttpPath(path)}`;
211
219
  if (options.lastEventId !== void 0) {
@@ -213,7 +221,7 @@ class StandardRPCLinkCodec {
213
221
  }
214
222
  const serialized = this.serializer.serialize(input);
215
223
  if (expectedMethod === "GET" && !(serialized instanceof FormData) && !isAsyncIteratorObject(serialized)) {
216
- const maxUrlLength = await value(this.maxUrlLength, generalOptions);
224
+ const maxUrlLength = await value(this.maxUrlLength, options, path, input);
217
225
  const getUrl = new URL(url);
218
226
  getUrl.searchParams.append("data", stringifyJSON(serialized));
219
227
  if (getUrl.toString().length <= maxUrlLength) {
@@ -254,12 +262,12 @@ class StandardRPCLinkCodec {
254
262
  }
255
263
  })();
256
264
  if (!isOk) {
257
- if (ORPCError.isValidJSON(deserialized)) {
258
- throw ORPCError.fromJSON(deserialized);
265
+ if (isORPCErrorJson(deserialized)) {
266
+ throw createORPCErrorFromJson(deserialized);
259
267
  }
260
268
  throw new ORPCError(getMalformedResponseErrorCode(response.status), {
261
269
  status: response.status,
262
- data: deserialized
270
+ data: { ...response, body: deserialized }
263
271
  });
264
272
  }
265
273
  return deserialized;
@@ -309,8 +317,8 @@ class StandardRPCSerializer {
309
317
  return e;
310
318
  }
311
319
  const deserialized = this.#deserialize(e.data);
312
- if (ORPCError.isValidJSON(deserialized)) {
313
- return ORPCError.fromJSON(deserialized, { cause: e });
320
+ if (isORPCErrorJson(deserialized)) {
321
+ return createORPCErrorFromJson(deserialized, { cause: e });
314
322
  }
315
323
  return new ErrorEvent({
316
324
  data: deserialized,
@@ -335,4 +343,13 @@ class StandardRPCSerializer {
335
343
  }
336
344
  }
337
345
 
338
- export { InvalidEventIteratorRetryResponse as I, StandardLink as S, STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as a, StandardRPCJsonSerializer as b, StandardRPCLinkCodec as c, StandardRPCSerializer as d, getMalformedResponseErrorCode as g, toHttpPath as t };
346
+ class StandardRPCLink extends StandardLink {
347
+ constructor(linkClient, options) {
348
+ const jsonSerializer = new StandardRPCJsonSerializer(options);
349
+ const serializer = new StandardRPCSerializer(jsonSerializer);
350
+ const linkCodec = new StandardRPCLinkCodec(serializer, options);
351
+ super(linkCodec, linkClient, options);
352
+ }
353
+ }
354
+
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 };