@orpc/client 2.0.0-beta.36 → 2.0.0-beta.37

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,17 +1,11 @@
1
1
  import { ClientContext, ClientOptions } from '../../index.mjs';
2
- import { Value, Promisable, Interceptor } from '@orpc/shared';
2
+ import { Value, Promisable } from '@orpc/shared';
3
3
  import { StandardRequest, StandardLazyResponse } from '@standard-server/core';
4
4
  import { ToFetchBodyOptions } from '@standard-server/fetch';
5
- import { StandardLinkTransport, StandardLinkPlugin, StandardLink, StandardLinkOptions } from '../standard/index.mjs';
5
+ import { StandardLinkTransport, StandardLink, StandardLinkOptions } from '../standard/index.mjs';
6
6
  import { RPCLinkCodecOptions } from '../standard/index.mjs';
7
- import '../../shared/client.DPi5reJh.mjs';
7
+ import '../../shared/client.n8K9dFhY.mjs';
8
8
 
9
- interface FetchLinkTransportFetchInterceptorOptions<T extends ClientContext> extends ClientOptions<T> {
10
- path: string[];
11
- url: string;
12
- init: RequestInit;
13
- }
14
- type FetchLinkTransportFetchInterceptor<T extends ClientContext> = Interceptor<FetchLinkTransportFetchInterceptorOptions<T>, Promise<Response>>;
15
9
  interface FetchLinkTransportOptions<T extends ClientContext> {
16
10
  /**
17
11
  * The origin to prepend to all request URLs, useful for CORS requests.
@@ -30,32 +24,16 @@ interface FetchLinkTransportOptions<T extends ClientContext> {
30
24
  * @default (url, init) => globalThis.fetch(url, init)
31
25
  */
32
26
  fetch?(url: string, init: RequestInit, options: ClientOptions<T>, path: string[]): Promise<Response>;
33
- /**
34
- * Interceptors that execute before the actual fetch call, useful for modifying the fetch parameters, adding logging, etc.
35
- */
36
- fetchInterceptors?: FetchLinkTransportFetchInterceptor<T>[];
37
- plugins?: FetchLinkTransportPlugin<T>[];
38
27
  }
39
28
  declare class FetchLinkTransport<T extends ClientContext> implements StandardLinkTransport<T> {
40
29
  private readonly origin;
41
30
  private readonly fetch;
42
31
  private readonly toFetchRequestOptions;
43
- private readonly fetchInterceptors;
44
32
  constructor(options: FetchLinkTransportOptions<T>);
45
33
  send(standardRequest: StandardRequest, path: string[], options: ClientOptions<T>): Promise<StandardLazyResponse>;
46
34
  }
47
35
 
48
- interface FetchLinkTransportPlugin<T extends ClientContext> extends StandardLinkPlugin<T> {
49
- initFetchLinkTransportOptions?(options: FetchLinkTransportOptions<T>): FetchLinkTransportOptions<T>;
50
- }
51
- declare class CompositeFetchLinkTransportPlugin<T extends ClientContext> implements FetchLinkTransportPlugin<T> {
52
- protected readonly plugins: FetchLinkTransportPlugin<T>[];
53
- name: string;
54
- constructor(plugins?: FetchLinkTransportPlugin<T>[]);
55
- initFetchLinkTransportOptions(options: FetchLinkTransportOptions<T>): FetchLinkTransportOptions<T>;
56
- }
57
-
58
- interface RPCLinkOptions<T extends ClientContext> extends Omit<StandardLinkOptions<T>, 'plugins'>, FetchLinkTransportOptions<T>, RPCLinkCodecOptions<T> {
36
+ interface RPCLinkOptions<T extends ClientContext> extends StandardLinkOptions<T>, FetchLinkTransportOptions<T>, RPCLinkCodecOptions<T> {
59
37
  }
60
38
  /**
61
39
  * Client link that communicates with an RPC Handler over the Fetch API (HTTP).
@@ -66,5 +44,5 @@ declare class RPCLink<T extends ClientContext> extends StandardLink<T> {
66
44
  constructor(options: RPCLinkOptions<T>);
67
45
  }
68
46
 
69
- export { CompositeFetchLinkTransportPlugin, FetchLinkTransport, RPCLink };
70
- export type { FetchLinkTransportFetchInterceptor, FetchLinkTransportFetchInterceptorOptions, FetchLinkTransportOptions, FetchLinkTransportPlugin, RPCLinkOptions };
47
+ export { FetchLinkTransport, RPCLink };
48
+ export type { FetchLinkTransportOptions, RPCLinkOptions };
@@ -1,17 +1,11 @@
1
1
  import { ClientContext, ClientOptions } from '../../index.js';
2
- import { Value, Promisable, Interceptor } from '@orpc/shared';
2
+ import { Value, Promisable } from '@orpc/shared';
3
3
  import { StandardRequest, StandardLazyResponse } from '@standard-server/core';
4
4
  import { ToFetchBodyOptions } from '@standard-server/fetch';
5
- import { StandardLinkTransport, StandardLinkPlugin, StandardLink, StandardLinkOptions } from '../standard/index.js';
5
+ import { StandardLinkTransport, StandardLink, StandardLinkOptions } from '../standard/index.js';
6
6
  import { RPCLinkCodecOptions } from '../standard/index.js';
7
- import '../../shared/client.DPi5reJh.js';
7
+ import '../../shared/client.n8K9dFhY.js';
8
8
 
9
- interface FetchLinkTransportFetchInterceptorOptions<T extends ClientContext> extends ClientOptions<T> {
10
- path: string[];
11
- url: string;
12
- init: RequestInit;
13
- }
14
- type FetchLinkTransportFetchInterceptor<T extends ClientContext> = Interceptor<FetchLinkTransportFetchInterceptorOptions<T>, Promise<Response>>;
15
9
  interface FetchLinkTransportOptions<T extends ClientContext> {
16
10
  /**
17
11
  * The origin to prepend to all request URLs, useful for CORS requests.
@@ -30,32 +24,16 @@ interface FetchLinkTransportOptions<T extends ClientContext> {
30
24
  * @default (url, init) => globalThis.fetch(url, init)
31
25
  */
32
26
  fetch?(url: string, init: RequestInit, options: ClientOptions<T>, path: string[]): Promise<Response>;
33
- /**
34
- * Interceptors that execute before the actual fetch call, useful for modifying the fetch parameters, adding logging, etc.
35
- */
36
- fetchInterceptors?: FetchLinkTransportFetchInterceptor<T>[];
37
- plugins?: FetchLinkTransportPlugin<T>[];
38
27
  }
39
28
  declare class FetchLinkTransport<T extends ClientContext> implements StandardLinkTransport<T> {
40
29
  private readonly origin;
41
30
  private readonly fetch;
42
31
  private readonly toFetchRequestOptions;
43
- private readonly fetchInterceptors;
44
32
  constructor(options: FetchLinkTransportOptions<T>);
45
33
  send(standardRequest: StandardRequest, path: string[], options: ClientOptions<T>): Promise<StandardLazyResponse>;
46
34
  }
47
35
 
48
- interface FetchLinkTransportPlugin<T extends ClientContext> extends StandardLinkPlugin<T> {
49
- initFetchLinkTransportOptions?(options: FetchLinkTransportOptions<T>): FetchLinkTransportOptions<T>;
50
- }
51
- declare class CompositeFetchLinkTransportPlugin<T extends ClientContext> implements FetchLinkTransportPlugin<T> {
52
- protected readonly plugins: FetchLinkTransportPlugin<T>[];
53
- name: string;
54
- constructor(plugins?: FetchLinkTransportPlugin<T>[]);
55
- initFetchLinkTransportOptions(options: FetchLinkTransportOptions<T>): FetchLinkTransportOptions<T>;
56
- }
57
-
58
- interface RPCLinkOptions<T extends ClientContext> extends Omit<StandardLinkOptions<T>, 'plugins'>, FetchLinkTransportOptions<T>, RPCLinkCodecOptions<T> {
36
+ interface RPCLinkOptions<T extends ClientContext> extends StandardLinkOptions<T>, FetchLinkTransportOptions<T>, RPCLinkCodecOptions<T> {
59
37
  }
60
38
  /**
61
39
  * Client link that communicates with an RPC Handler over the Fetch API (HTTP).
@@ -66,5 +44,5 @@ declare class RPCLink<T extends ClientContext> extends StandardLink<T> {
66
44
  constructor(options: RPCLinkOptions<T>);
67
45
  }
68
46
 
69
- export { CompositeFetchLinkTransportPlugin, FetchLinkTransport, RPCLink };
70
- export type { FetchLinkTransportFetchInterceptor, FetchLinkTransportFetchInterceptorOptions, FetchLinkTransportOptions, FetchLinkTransportPlugin, RPCLinkOptions };
47
+ export { FetchLinkTransport, RPCLink };
48
+ export type { FetchLinkTransportOptions, RPCLinkOptions };
@@ -1,26 +1,10 @@
1
- import { sortPlugins, value, intercept, once } from '@orpc/shared';
1
+ import { value, once } from '@orpc/shared';
2
2
  import { toFetchBody, toFetchHeaders, toStandardLazyResponse } from '@standard-server/fetch';
3
- import { S as StandardLink, R as RPCLinkCodec } from '../../shared/client.DmnKF1vQ.mjs';
3
+ import { S as StandardLink, R as RPCLinkCodec } from '../../shared/client.BtJ-utP9.mjs';
4
4
  import '@standard-server/core';
5
- import '../../shared/client.BcRcwiif.mjs';
5
+ import '../../shared/client.CUxLdmiH.mjs';
6
6
  import '../../shared/client.Dtv1JPkU.mjs';
7
7
 
8
- class CompositeFetchLinkTransportPlugin {
9
- constructor(plugins = []) {
10
- this.plugins = plugins;
11
- this.plugins = sortPlugins(plugins);
12
- }
13
- name = "~composite/fetch";
14
- initFetchLinkTransportOptions(options) {
15
- for (const plugin of this.plugins) {
16
- if (plugin.initFetchLinkTransportOptions) {
17
- options = plugin.initFetchLinkTransportOptions(options);
18
- }
19
- }
20
- return options;
21
- }
22
- }
23
-
24
8
  const GET_SUPPORTED_DUPLEX_MODE = once(() => {
25
9
  try {
26
10
  let duplex;
@@ -44,13 +28,10 @@ class FetchLinkTransport {
44
28
  origin;
45
29
  fetch;
46
30
  toFetchRequestOptions;
47
- fetchInterceptors;
48
31
  constructor(options) {
49
- options = new CompositeFetchLinkTransportPlugin(options.plugins).initFetchLinkTransportOptions(options);
50
32
  this.origin = options.origin;
51
33
  this.fetch = options.fetch ?? ((url, init) => globalThis.fetch(url, init));
52
34
  this.toFetchRequestOptions = options.toFetchRequest;
53
- this.fetchInterceptors = options.fetchInterceptors;
54
35
  }
55
36
  async send(standardRequest, path, options) {
56
37
  let origin = await value(this.origin, options, path);
@@ -72,11 +53,7 @@ class FetchLinkTransport {
72
53
  init.duplex = duplex;
73
54
  }
74
55
  }
75
- const response = await intercept(
76
- this.fetchInterceptors,
77
- { ...options, url, path, init },
78
- ({ url: url2, path: path2, init: init2, ...options2 }) => this.fetch(url2, init2, options2, path2)
79
- );
56
+ const response = await this.fetch(url, init, options, path);
80
57
  const standardResponse = toStandardLazyResponse(response);
81
58
  return standardResponse;
82
59
  }
@@ -90,4 +67,4 @@ class RPCLink extends StandardLink {
90
67
  }
91
68
  }
92
69
 
93
- export { CompositeFetchLinkTransportPlugin, FetchLinkTransport, RPCLink };
70
+ export { FetchLinkTransport, RPCLink };
@@ -4,7 +4,7 @@ import { StandardRequest, StandardLazyResponse } from '@standard-server/core';
4
4
  import { ClientPeer, EncodePeerMessageOptions, DecodePeerMessageOptions } from '@standard-server/peer';
5
5
  import { StandardLinkTransport, StandardLink, StandardLinkOptions } from '../standard/index.mjs';
6
6
  import { RPCLinkCodecOptions } from '../standard/index.mjs';
7
- import '../../shared/client.DPi5reJh.mjs';
7
+ import '../../shared/client.n8K9dFhY.mjs';
8
8
 
9
9
  /**
10
10
  * The message port used by electron in main process
@@ -4,7 +4,7 @@ import { StandardRequest, StandardLazyResponse } from '@standard-server/core';
4
4
  import { ClientPeer, EncodePeerMessageOptions, DecodePeerMessageOptions } from '@standard-server/peer';
5
5
  import { StandardLinkTransport, StandardLink, StandardLinkOptions } from '../standard/index.js';
6
6
  import { RPCLinkCodecOptions } from '../standard/index.js';
7
- import '../../shared/client.DPi5reJh.js';
7
+ import '../../shared/client.n8K9dFhY.js';
8
8
 
9
9
  /**
10
10
  * The message port used by electron in main process
@@ -1,9 +1,9 @@
1
1
  import { value } from '@orpc/shared';
2
2
  import { ClientPeer, encodePeerMessage, decodePeerMessage, isServerPeerSendMessage, isPeerMessage } from '@standard-server/peer';
3
- import { S as StandardLink, R as RPCLinkCodec } from '../../shared/client.DmnKF1vQ.mjs';
3
+ import { S as StandardLink, R as RPCLinkCodec } from '../../shared/client.BtJ-utP9.mjs';
4
4
  import '@standard-server/core';
5
5
  import '@standard-server/fetch';
6
- import '../../shared/client.BcRcwiif.mjs';
6
+ import '../../shared/client.CUxLdmiH.mjs';
7
7
  import '../../shared/client.Dtv1JPkU.mjs';
8
8
 
9
9
  function postMessagePortMessage(port, data, transfer) {
@@ -1,6 +1,6 @@
1
- export { C as CompositeStandardLinkPlugin, R as RPCLinkCodec, S as StandardLink } from '../../shared/client.DmnKF1vQ.mjs';
1
+ export { C as CompositeStandardLinkPlugin, R as RPCLinkCodec, S as StandardLink } from '../../shared/client.BtJ-utP9.mjs';
2
2
  import '@orpc/shared';
3
3
  import '@standard-server/core';
4
4
  import '@standard-server/fetch';
5
- import '../../shared/client.BcRcwiif.mjs';
5
+ import '../../shared/client.CUxLdmiH.mjs';
6
6
  import '../../shared/client.Dtv1JPkU.mjs';
@@ -4,7 +4,7 @@ import { StandardRequest, StandardLazyResponse } from '@standard-server/core';
4
4
  import { EncodePeerMessageOptions, DecodePeerMessageOptions } from '@standard-server/peer';
5
5
  import { StandardLinkTransport, StandardLink, StandardLinkOptions } from '../standard/index.mjs';
6
6
  import { RPCLinkCodecOptions } from '../standard/index.mjs';
7
- import '../../shared/client.DPi5reJh.mjs';
7
+ import '../../shared/client.n8K9dFhY.mjs';
8
8
 
9
9
  type WebSocketLike = Pick<WebSocket, 'addEventListener' | 'removeEventListener' | 'send' | 'readyState'>;
10
10
  interface WebSocketLinkTransportAttemptInfo {
@@ -4,7 +4,7 @@ import { StandardRequest, StandardLazyResponse } from '@standard-server/core';
4
4
  import { EncodePeerMessageOptions, DecodePeerMessageOptions } from '@standard-server/peer';
5
5
  import { StandardLinkTransport, StandardLink, StandardLinkOptions } from '../standard/index.js';
6
6
  import { RPCLinkCodecOptions } from '../standard/index.js';
7
- import '../../shared/client.DPi5reJh.js';
7
+ import '../../shared/client.n8K9dFhY.js';
8
8
 
9
9
  type WebSocketLike = Pick<WebSocket, 'addEventListener' | 'removeEventListener' | 'send' | 'readyState'>;
10
10
  interface WebSocketLinkTransportAttemptInfo {
@@ -1,9 +1,9 @@
1
1
  import { runWithSignal, AbortError, sleep, promiseWithResolvers, sequential, loadBytes, toStringOrBytes } from '@orpc/shared';
2
2
  import { ClientPeer, encodePeerMessage, decodePeerMessage, isServerPeerSendMessage } from '@standard-server/peer';
3
- import { S as StandardLink, R as RPCLinkCodec } from '../../shared/client.DmnKF1vQ.mjs';
3
+ import { S as StandardLink, R as RPCLinkCodec } from '../../shared/client.BtJ-utP9.mjs';
4
4
  import '@standard-server/core';
5
5
  import '@standard-server/fetch';
6
- import '../../shared/client.BcRcwiif.mjs';
6
+ import '../../shared/client.CUxLdmiH.mjs';
7
7
  import '../../shared/client.Dtv1JPkU.mjs';
8
8
 
9
9
  const WEBSOCKET_CONNECTING = 0;
package/dist/index.d.mts CHANGED
@@ -4,7 +4,7 @@ import { C as ClientContext, a as ClientOptions, c as AnyNestedClient, I as Infe
4
4
  export { i as AnyORPCErrorJSON, j as COMMON_ERROR_STATUS_MAP, k as InferClientBodyInputs, l as InferClientBodyOutputs, m as InferClientErrors, n as InferClientInputs, o as InferClientOutputs, p as MalformedResponseError, N as NestedClient, q as ORPCErrorOptions } from './shared/client.BoXZCzuS.mjs';
5
5
  import { StandardResponse } from '@standard-server/core';
6
6
  export { ErrorEvent, EventMeta, StandardBody, StandardBodyHint, StandardHeaders, StandardLazyRequest, StandardLazyResponse, StandardMethod, StandardRequest, StandardResponse, StandardUrl, getEventMeta, unwrapEvent, withEventMeta } from '@standard-server/core';
7
- export { R as RPCJsonSerialization, a as RPCJsonSerializationMeta, b as RPCJsonSerializer, c as RPCJsonSerializerHandler, d as RPCJsonSerializerOptions, e as RPCSerializer, f as RPCSerializerOptions, g as RPCSerializerSerializeOptions } from './shared/client.DPi5reJh.mjs';
7
+ export { R as RPCJsonSerialization, a as RPCJsonSerializationMeta, b as RPCJsonSerializer, c as RPCJsonSerializerHandler, d as RPCJsonSerializerOptions, e as RPCSerializer, f as RPCSerializerOptions, g as RPCSerializerSerializeOptions } from './shared/client.n8K9dFhY.mjs';
8
8
 
9
9
  declare function wrapAsyncIteratorPreservingEventMeta<TYield, TReturn, TMappedYield = TYield, TMappedReturn = TReturn>(iterator: AsyncIterator<TYield, TReturn>, { mapResult, mapError, ...rest }: WrapAsyncIteratorOptions<TYield, TReturn, TMappedYield, TMappedReturn>): AsyncIteratorClass<TMappedYield, TMappedReturn>;
10
10
 
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { C as ClientContext, a as ClientOptions, c as AnyNestedClient, I as Infe
4
4
  export { i as AnyORPCErrorJSON, j as COMMON_ERROR_STATUS_MAP, k as InferClientBodyInputs, l as InferClientBodyOutputs, m as InferClientErrors, n as InferClientInputs, o as InferClientOutputs, p as MalformedResponseError, N as NestedClient, q as ORPCErrorOptions } from './shared/client.BoXZCzuS.js';
5
5
  import { StandardResponse } from '@standard-server/core';
6
6
  export { ErrorEvent, EventMeta, StandardBody, StandardBodyHint, StandardHeaders, StandardLazyRequest, StandardLazyResponse, StandardMethod, StandardRequest, StandardResponse, StandardUrl, getEventMeta, unwrapEvent, withEventMeta } from '@standard-server/core';
7
- export { R as RPCJsonSerialization, a as RPCJsonSerializationMeta, b as RPCJsonSerializer, c as RPCJsonSerializerHandler, d as RPCJsonSerializerOptions, e as RPCSerializer, f as RPCSerializerOptions, g as RPCSerializerSerializeOptions } from './shared/client.DPi5reJh.js';
7
+ export { R as RPCJsonSerialization, a as RPCJsonSerializationMeta, b as RPCJsonSerializer, c as RPCJsonSerializerHandler, d as RPCJsonSerializerOptions, e as RPCSerializer, f as RPCSerializerOptions, g as RPCSerializerSerializeOptions } from './shared/client.n8K9dFhY.js';
8
8
 
9
9
  declare function wrapAsyncIteratorPreservingEventMeta<TYield, TReturn, TMappedYield = TYield, TMappedReturn = TReturn>(iterator: AsyncIterator<TYield, TReturn>, { mapResult, mapError, ...rest }: WrapAsyncIteratorOptions<TYield, TReturn, TMappedYield, TMappedReturn>): AsyncIteratorClass<TMappedYield, TMappedReturn>;
10
10
 
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { b as isDefinedError } from './shared/client.BcRcwiif.mjs';
2
- export { d as RPCJsonSerializer, R as RPCSerializer, e as cloneORPCError, a as createORPCErrorFromJson, c as createORPCErrorFromMalformedResponse, i as isORPCErrorJson, t as toORPCError, w as wrapAsyncIteratorPreservingEventMeta } from './shared/client.BcRcwiif.mjs';
1
+ import { b as isDefinedError } from './shared/client.CUxLdmiH.mjs';
2
+ export { d as RPCJsonSerializer, R as RPCSerializer, e as cloneORPCError, a as createORPCErrorFromJson, c as createORPCErrorFromMalformedResponse, i as isORPCErrorJson, t as toORPCError, w as wrapAsyncIteratorPreservingEventMeta } from './shared/client.CUxLdmiH.mjs';
3
3
  import { toArray, intercept, isTypescriptObject } from '@orpc/shared';
4
4
  export { AsyncIteratorClass, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, consumeAsyncIterator, consumeAsyncIterator as consumeEventIterator, asyncIteratorToStream as eventIteratorToStream, asyncIteratorToUnproxiedDataStream as eventIteratorToUnproxiedDataStream, onAsyncIteratorObjectError, onError, onFinish, onReadableStreamError, onStart, onSuccess, streamToAsyncIteratorObject, streamToAsyncIteratorObject as streamToEventIterator } from '@orpc/shared';
5
5
  export { C as COMMON_ERROR_STATUS_MAP, M as MalformedResponseError, O as ORPCError } from './shared/client.Dtv1JPkU.mjs';
@@ -30,7 +30,8 @@ class BatchLinkPlugin {
30
30
  const headersList = options2.map((o) => o.request.headers);
31
31
  const commonHeaders = {};
32
32
  for (const headers of headersList) {
33
- for (const [key, value2] of Object.entries(headers)) {
33
+ for (const key of Object.keys(headers)) {
34
+ const value2 = headers[key];
34
35
  if (headersList.every((h) => h[key] === value2)) {
35
36
  commonHeaders[key] = value2;
36
37
  }
@@ -40,7 +41,8 @@ class BatchLinkPlugin {
40
41
  });
41
42
  this.mapSubrequest = options.mapSubrequest ?? (({ request }, { headers }) => {
42
43
  const subHeaders = { ...request.headers };
43
- for (const [key, value2] of Object.entries(headers)) {
44
+ for (const key of Object.keys(headers)) {
45
+ const value2 = headers[key];
44
46
  if (subHeaders[key] === value2) {
45
47
  subHeaders[key] = void 0;
46
48
  }
@@ -1,7 +1,7 @@
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 { R as RPCSerializer, c as createORPCErrorFromMalformedResponse, i as isORPCErrorJson, a as createORPCErrorFromJson } from './client.BcRcwiif.mjs';
4
+ import { R as RPCSerializer, c as createORPCErrorFromMalformedResponse, i as isORPCErrorJson, a as createORPCErrorFromJson } from './client.CUxLdmiH.mjs';
5
5
 
6
6
  class CompositeStandardLinkPlugin {
7
7
  name = "~composite";
@@ -87,7 +87,14 @@ function wrapAsyncIteratorPreservingEventMeta(iterator, { mapResult, mapError, .
87
87
  });
88
88
  }
89
89
 
90
- const REGEX_STRING_PATTERN = /^\/([\s\S]*)\/([a-z]*)$/;
90
+ function invalidSerializedData(detail) {
91
+ return new TypeError(`Invalid RPC serialized data: ${detail}`);
92
+ }
93
+ function assertSerializedType(ok, type, expected) {
94
+ if (!ok) {
95
+ throw invalidSerializedData(`type "${type}" expects ${expected}.`);
96
+ }
97
+ }
91
98
  const DEFAULT_RPC_JSON_SERIALIZER_HANDLERS = {
92
99
  undefined: {
93
100
  condition(data) {
@@ -96,7 +103,8 @@ const DEFAULT_RPC_JSON_SERIALIZER_HANDLERS = {
96
103
  serialize() {
97
104
  return null;
98
105
  },
99
- deserialize() {
106
+ deserialize(serialized) {
107
+ assertSerializedType(serialized === null, "undefined", "null");
100
108
  return void 0;
101
109
  },
102
110
  isTerminal: true
@@ -109,6 +117,7 @@ const DEFAULT_RPC_JSON_SERIALIZER_HANDLERS = {
109
117
  return data.toString();
110
118
  },
111
119
  deserialize(serialized) {
120
+ assertSerializedType(typeof serialized === "string", "bigint", "a string");
112
121
  return BigInt(serialized);
113
122
  },
114
123
  isTerminal: true
@@ -124,7 +133,8 @@ const DEFAULT_RPC_JSON_SERIALIZER_HANDLERS = {
124
133
  return data.toISOString();
125
134
  },
126
135
  deserialize(serialized) {
127
- return new Date(serialized ?? "Invalid Date");
136
+ assertSerializedType(typeof serialized === "string" || serialized === null, "date", "a string or null");
137
+ return new Date(serialized ?? Number.NaN);
128
138
  },
129
139
  isTerminal: true
130
140
  },
@@ -135,7 +145,8 @@ const DEFAULT_RPC_JSON_SERIALIZER_HANDLERS = {
135
145
  serialize() {
136
146
  return null;
137
147
  },
138
- deserialize() {
148
+ deserialize(serialized) {
149
+ assertSerializedType(serialized === null, "nan", "null");
139
150
  return Number.NaN;
140
151
  },
141
152
  isTerminal: true
@@ -148,23 +159,11 @@ const DEFAULT_RPC_JSON_SERIALIZER_HANDLERS = {
148
159
  return data.toString();
149
160
  },
150
161
  deserialize(serialized) {
162
+ assertSerializedType(typeof serialized === "string", "url", "a string");
151
163
  return new URL(serialized);
152
164
  },
153
165
  isTerminal: true
154
166
  },
155
- regexp: {
156
- condition(data) {
157
- return data instanceof RegExp;
158
- },
159
- serialize(data) {
160
- return data.toString();
161
- },
162
- deserialize(serialized) {
163
- const [, pattern, flags] = serialized.match(REGEX_STRING_PATTERN);
164
- return new RegExp(pattern, flags);
165
- },
166
- isTerminal: true
167
- },
168
167
  set: {
169
168
  condition(data) {
170
169
  return data instanceof Set;
@@ -173,6 +172,7 @@ const DEFAULT_RPC_JSON_SERIALIZER_HANDLERS = {
173
172
  return Array.from(data);
174
173
  },
175
174
  deserialize(serialized) {
175
+ assertSerializedType(Array.isArray(serialized), "set", "an array");
176
176
  return new Set(serialized);
177
177
  }
178
178
  },
@@ -184,6 +184,7 @@ const DEFAULT_RPC_JSON_SERIALIZER_HANDLERS = {
184
184
  return Array.from(data.entries());
185
185
  },
186
186
  deserialize(serialized) {
187
+ assertSerializedType(Array.isArray(serialized), "map", "an array");
187
188
  return new Map(serialized);
188
189
  }
189
190
  }
@@ -203,7 +204,8 @@ class RPCJsonSerializer {
203
204
  }
204
205
  let inlineBuiltInHandlers = true;
205
206
  let handlerEntries = [];
206
- for (const [key, handler] of Object.entries(customHandlers)) {
207
+ for (const key of Object.keys(customHandlers)) {
208
+ const handler = customHandlers[key];
207
209
  this.handlers[key] = handler;
208
210
  if (inlineBuiltInHandlers && key in DEFAULT_RPC_JSON_SERIALIZER_HANDLERS) {
209
211
  inlineBuiltInHandlers = false;
@@ -214,7 +216,8 @@ class RPCJsonSerializer {
214
216
  }
215
217
  if (!inlineBuiltInHandlers) {
216
218
  handlerEntries = [];
217
- for (const [key, handler] of Object.entries(this.handlers)) {
219
+ for (const key of Object.keys(this.handlers)) {
220
+ const handler = this.handlers[key];
218
221
  if (handler !== void 0) {
219
222
  handlerEntries.push([key, handler]);
220
223
  }
@@ -268,10 +271,6 @@ class RPCJsonSerializer {
268
271
  meta.push(["url", ...segments]);
269
272
  return data.toString();
270
273
  }
271
- if (data instanceof RegExp) {
272
- meta.push(["regexp", ...segments]);
273
- return data.toString();
274
- }
275
274
  if (data instanceof Set) {
276
275
  const result = this.serializeValue(Array.from(data), segments, meta, maps, blobs);
277
276
  meta.push(["set", ...segments]);
@@ -322,7 +321,8 @@ class RPCJsonSerializer {
322
321
  }
323
322
  if (isPlainObject(data)) {
324
323
  const json = new NullProtoObj();
325
- for (const [k, v] of Object.entries(data)) {
324
+ for (const k of Object.keys(data)) {
325
+ const v = data[k];
326
326
  if (k === "toJSON" && typeof v === "function") {
327
327
  continue;
328
328
  }
@@ -348,7 +348,7 @@ class RPCJsonSerializer {
348
348
  currentRef = currentRef[preSegment];
349
349
  preSegment = segments[j];
350
350
  if (!Object.hasOwn(currentRef, preSegment)) {
351
- throw new Error(`Security error: Invalid serialized data. Segment "${preSegment}" does not exist.`);
351
+ throw invalidSerializedData(`segment "${preSegment}" does not exist.`);
352
352
  }
353
353
  }
354
354
  currentRef[preSegment] = serialized.blobs[i];
@@ -357,16 +357,20 @@ class RPCJsonSerializer {
357
357
  if (serialized.meta) {
358
358
  for (const item of serialized.meta) {
359
359
  const type = item[0];
360
+ const handler = this.handlers[type];
361
+ if (handler === void 0) {
362
+ throw invalidSerializedData(`type "${type}" is not supported.`);
363
+ }
360
364
  let currentRef = ref;
361
365
  let preSegment = "data";
362
366
  for (let i = 1; i < item.length; i++) {
363
367
  currentRef = currentRef[preSegment];
364
368
  preSegment = item[i];
365
369
  if (!Object.hasOwn(currentRef, preSegment)) {
366
- throw new Error(`Security error: Invalid serialized data. Segment "${preSegment}" does not exist.`);
370
+ throw invalidSerializedData(`segment "${preSegment}" does not exist.`);
367
371
  }
368
372
  }
369
- currentRef[preSegment] = this.handlers[type].deserialize(currentRef[preSegment]);
373
+ currentRef[preSegment] = handler.deserialize(currentRef[preSegment]);
370
374
  }
371
375
  }
372
376
  return ref.data;
@@ -16,7 +16,10 @@ type RPCJsonSerialization = {
16
16
  interface RPCJsonSerializerHandler {
17
17
  condition(value: unknown): boolean;
18
18
  serialize(value: any): unknown;
19
- deserialize(serialized: any): unknown;
19
+ /**
20
+ * `serialized` comes from the wire, so validate its type and throw on mismatch.
21
+ */
22
+ deserialize(serialized: unknown): unknown;
20
23
  /**
21
24
  * If false, the result of this serializer will not be further processed by other serializers,
22
25
  * even if it matches their conditions and treat it as final serialized value.
@@ -60,10 +63,10 @@ interface RPCJsonSerializerOptions {
60
63
  *
61
64
  * **Disabling:** Set a key to `undefined` to remove a built-in handler:
62
65
  * ```ts
63
- * handlers: { regexp: undefined }
66
+ * handlers: { url: undefined }
64
67
  * ```
65
68
  *
66
- * Built-in type keys: `undefined`, `bigint`, `date`, `nan`, `url`, `regexp`, `set`, `map`.
69
+ * Built-in type keys: `undefined`, `bigint`, `date`, `nan`, `url`, `set`, `map`.
67
70
  */
68
71
  handlers?: Record<string, undefined | RPCJsonSerializerHandler> | undefined;
69
72
  /**
@@ -16,7 +16,10 @@ type RPCJsonSerialization = {
16
16
  interface RPCJsonSerializerHandler {
17
17
  condition(value: unknown): boolean;
18
18
  serialize(value: any): unknown;
19
- deserialize(serialized: any): unknown;
19
+ /**
20
+ * `serialized` comes from the wire, so validate its type and throw on mismatch.
21
+ */
22
+ deserialize(serialized: unknown): unknown;
20
23
  /**
21
24
  * If false, the result of this serializer will not be further processed by other serializers,
22
25
  * even if it matches their conditions and treat it as final serialized value.
@@ -60,10 +63,10 @@ interface RPCJsonSerializerOptions {
60
63
  *
61
64
  * **Disabling:** Set a key to `undefined` to remove a built-in handler:
62
65
  * ```ts
63
- * handlers: { regexp: undefined }
66
+ * handlers: { url: undefined }
64
67
  * ```
65
68
  *
66
- * Built-in type keys: `undefined`, `bigint`, `date`, `nan`, `url`, `regexp`, `set`, `map`.
69
+ * Built-in type keys: `undefined`, `bigint`, `date`, `nan`, `url`, `set`, `map`.
67
70
  */
68
71
  handlers?: Record<string, undefined | RPCJsonSerializerHandler> | undefined;
69
72
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/client",
3
3
  "type": "module",
4
- "version": "2.0.0-beta.36",
4
+ "version": "2.0.0-beta.37",
5
5
  "description": "Consume oRPC and OpenAPI APIs with end-to-end type safety over HTTP, WebSocket, or message ports",
6
6
  "license": "MIT",
7
7
  "funding": [
@@ -63,10 +63,10 @@
63
63
  "dist"
64
64
  ],
65
65
  "dependencies": {
66
- "@orpc/shared": "2.0.0-beta.36",
67
- "@standard-server/core": "~0.9.0",
68
- "@standard-server/fetch": "~0.9.0",
69
- "@standard-server/peer": "~0.9.0"
66
+ "@orpc/shared": "2.0.0-beta.37",
67
+ "@standard-server/core": "~0.9.2",
68
+ "@standard-server/fetch": "~0.9.2",
69
+ "@standard-server/peer": "~0.9.2"
70
70
  },
71
71
  "devDependencies": {
72
72
  "zod": "^4.5.4"