@orpc/client 1.14.10 → 1.14.11
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 +52 -68
- package/dist/adapters/fetch/index.d.mts +54 -35
- package/dist/adapters/fetch/index.d.ts +54 -35
- package/dist/adapters/fetch/index.mjs +74 -27
- package/dist/adapters/message-port/index.d.mts +25 -30
- package/dist/adapters/message-port/index.d.ts +25 -30
- package/dist/adapters/message-port/index.mjs +39 -30
- package/dist/adapters/standard/index.d.mts +59 -9
- package/dist/adapters/standard/index.d.ts +59 -9
- package/dist/adapters/standard/index.mjs +5 -5
- package/dist/adapters/websocket/index.d.mts +113 -21
- package/dist/adapters/websocket/index.d.ts +113 -21
- package/dist/adapters/websocket/index.mjs +95 -37
- package/dist/index.d.mts +75 -184
- package/dist/index.d.ts +75 -184
- package/dist/index.mjs +74 -63
- package/dist/plugins/index.d.mts +191 -122
- package/dist/plugins/index.d.ts +191 -122
- package/dist/plugins/index.mjs +627 -281
- package/dist/shared/client.8f4DNmdE.d.mts +96 -0
- package/dist/shared/client.BBZBQID8.d.mts +167 -0
- package/dist/shared/client.BBZBQID8.d.ts +167 -0
- package/dist/shared/client.BMKYqpdy.d.ts +96 -0
- package/dist/shared/client.BRJnOJ0R.mjs +174 -0
- package/dist/shared/client.BdItY5DT.d.mts +111 -0
- package/dist/shared/client.BdItY5DT.d.ts +111 -0
- package/dist/shared/client.Dnfj8jnT.mjs +92 -0
- package/dist/shared/client.DqYwRDUO.mjs +343 -0
- package/package.json +7 -7
- package/dist/shared/client.2jUAqzYU.d.ts +0 -45
- package/dist/shared/client.B3pNRBih.d.ts +0 -91
- package/dist/shared/client.BFAVy68H.d.mts +0 -91
- package/dist/shared/client.BLtwTQUg.mjs +0 -40
- package/dist/shared/client.CpCa3si8.d.mts +0 -45
- package/dist/shared/client.DsgfctKs.mjs +0 -174
- package/dist/shared/client.i2uoJbEp.d.mts +0 -83
- package/dist/shared/client.i2uoJbEp.d.ts +0 -83
- package/dist/shared/client.wv-wJnEy.mjs +0 -404
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { sortPlugins, runWithSpan, ORPC_NAME, isAsyncIteratorObject, override, traceAsyncIterator, intercept, getOpenTelemetryConfig, value, pathToHttpPath, stringifyJSON } from '@orpc/shared';
|
|
2
|
+
import { mergeStandardHeaders, parseStandardUrl } from '@standardserver/core';
|
|
3
|
+
import { toStandardHeaders } from '@standardserver/fetch';
|
|
4
|
+
import { O as ORPCError } from './client.Dnfj8jnT.mjs';
|
|
5
|
+
import { R as RPCSerializer, i as isORPCErrorJson, c as createORPCErrorFromJson } from './client.DqYwRDUO.mjs';
|
|
6
|
+
|
|
7
|
+
class CompositeStandardLinkPlugin {
|
|
8
|
+
name = "~composite";
|
|
9
|
+
plugins;
|
|
10
|
+
constructor(plugins = []) {
|
|
11
|
+
this.plugins = sortPlugins(plugins);
|
|
12
|
+
}
|
|
13
|
+
init(options) {
|
|
14
|
+
for (const plugin of this.plugins) {
|
|
15
|
+
if (plugin.init) {
|
|
16
|
+
options = plugin.init(options);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return options;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class StandardLink {
|
|
24
|
+
constructor(codec, transport, options = {}) {
|
|
25
|
+
this.codec = codec;
|
|
26
|
+
this.transport = transport;
|
|
27
|
+
options = new CompositeStandardLinkPlugin(options.plugins).init(options);
|
|
28
|
+
this.interceptors = options.interceptors;
|
|
29
|
+
this.transportInterceptors = options.transportInterceptors;
|
|
30
|
+
}
|
|
31
|
+
interceptors;
|
|
32
|
+
transportInterceptors;
|
|
33
|
+
/**
|
|
34
|
+
* @throws ORPCError, transport-level errors (network failures, timeouts, etc.)
|
|
35
|
+
*/
|
|
36
|
+
call(path, input, options) {
|
|
37
|
+
return runWithSpan(`${ORPC_NAME}.${path.join("/")}`, (span) => {
|
|
38
|
+
span?.setAttribute("rpc.system", ORPC_NAME);
|
|
39
|
+
span?.setAttribute("rpc.method", path.join("."));
|
|
40
|
+
if (isAsyncIteratorObject(input)) {
|
|
41
|
+
input = override(input, traceAsyncIterator("consume_async_iterator_object_input", input));
|
|
42
|
+
}
|
|
43
|
+
return intercept(this.interceptors, { ...options, path, input }, async ({ path: path2, input: input2, ...options2 }) => {
|
|
44
|
+
const otel = getOpenTelemetryConfig();
|
|
45
|
+
let activeContext;
|
|
46
|
+
const activeSpan = otel?.trace.getActiveSpan() ?? span;
|
|
47
|
+
if (activeSpan && otel) {
|
|
48
|
+
activeContext = otel.trace.setSpan(otel.context.active(), activeSpan);
|
|
49
|
+
}
|
|
50
|
+
let request = await runWithSpan(
|
|
51
|
+
{ name: "encode_input", context: activeContext },
|
|
52
|
+
() => this.codec.encodeInput(input2, path2, options2)
|
|
53
|
+
);
|
|
54
|
+
if (activeContext && otel?.propagation) {
|
|
55
|
+
const headers = { ...request.headers };
|
|
56
|
+
otel.propagation.inject(activeContext, headers);
|
|
57
|
+
request = { ...request, headers };
|
|
58
|
+
}
|
|
59
|
+
const response = await intercept(
|
|
60
|
+
this.transportInterceptors,
|
|
61
|
+
{ ...options2, path: path2, request },
|
|
62
|
+
({ path: path3, request: request2, ...options3 }) => {
|
|
63
|
+
let activeTransportContext;
|
|
64
|
+
const activeTransportSpan = otel?.trace.getActiveSpan() ?? activeSpan;
|
|
65
|
+
if (activeTransportSpan && otel) {
|
|
66
|
+
activeTransportContext = otel.trace.setSpan(otel.context.active(), activeTransportSpan);
|
|
67
|
+
}
|
|
68
|
+
return runWithSpan(
|
|
69
|
+
{ name: "send_request", context: activeTransportContext },
|
|
70
|
+
() => this.transport.send(request2, path3, options3)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
const decodedResult = await runWithSpan(
|
|
75
|
+
{ name: "decode_response", context: activeContext },
|
|
76
|
+
() => this.codec.decodeResponse(response, path2, options2)
|
|
77
|
+
);
|
|
78
|
+
if (decodedResult.kind === "error") {
|
|
79
|
+
throw decodedResult.error;
|
|
80
|
+
}
|
|
81
|
+
const output = decodedResult.output;
|
|
82
|
+
if (isAsyncIteratorObject(output)) {
|
|
83
|
+
return override(output, traceAsyncIterator("consume_async_iterator_object_output", output));
|
|
84
|
+
}
|
|
85
|
+
return output;
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const END_SLASH_REGEX = /\/$/;
|
|
92
|
+
class RPCLinkCodec {
|
|
93
|
+
baseUrl;
|
|
94
|
+
maxUrlLength;
|
|
95
|
+
fallbackMethod;
|
|
96
|
+
expectedMethod;
|
|
97
|
+
headers;
|
|
98
|
+
serializer;
|
|
99
|
+
constructor(options) {
|
|
100
|
+
this.baseUrl = options.url ?? "/";
|
|
101
|
+
this.maxUrlLength = options.maxUrlLength ?? 2083;
|
|
102
|
+
this.fallbackMethod = options.fallbackMethod ?? "POST";
|
|
103
|
+
this.expectedMethod = options.method ?? this.fallbackMethod;
|
|
104
|
+
this.headers = options.headers ?? {};
|
|
105
|
+
this.serializer = options.serializer ?? new RPCSerializer();
|
|
106
|
+
}
|
|
107
|
+
async encodeInput(input, path, options) {
|
|
108
|
+
let headers = toResolvedStandardHeaders(await value(this.headers, options, path, input));
|
|
109
|
+
if (options.lastEventId !== void 0) {
|
|
110
|
+
headers = mergeStandardHeaders(headers, { "last-event-id": options.lastEventId });
|
|
111
|
+
}
|
|
112
|
+
const expectedMethod = await value(this.expectedMethod, options, path, input);
|
|
113
|
+
const baseUrl = await value(this.baseUrl, options, path, input);
|
|
114
|
+
const [pathname, search, hash] = parseStandardUrl(baseUrl);
|
|
115
|
+
const newPathname = `${pathname.replace(END_SLASH_REGEX, "")}${pathToHttpPath(path)}`;
|
|
116
|
+
const serialized = this.serializer.serialize(input);
|
|
117
|
+
if (expectedMethod === "GET" && !(serialized instanceof Blob) && !(serialized instanceof ReadableStream) && !(serialized instanceof FormData) && !isAsyncIteratorObject(serialized)) {
|
|
118
|
+
const maxUrlLength = await value(this.maxUrlLength, options, path, input);
|
|
119
|
+
const mergedSearch = new URLSearchParams(search);
|
|
120
|
+
mergedSearch.append("data", stringifyJSON(serialized) ?? "");
|
|
121
|
+
const url2 = `${newPathname}?${mergedSearch}${hash ?? ""}`;
|
|
122
|
+
if (url2.length <= maxUrlLength) {
|
|
123
|
+
return {
|
|
124
|
+
body: void 0,
|
|
125
|
+
method: expectedMethod,
|
|
126
|
+
headers,
|
|
127
|
+
url: url2,
|
|
128
|
+
signal: options.signal
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const url = `${newPathname}${search ?? ""}${hash ?? ""}`;
|
|
133
|
+
return {
|
|
134
|
+
url,
|
|
135
|
+
method: expectedMethod === "GET" ? this.fallbackMethod : expectedMethod,
|
|
136
|
+
headers,
|
|
137
|
+
body: serialized,
|
|
138
|
+
signal: options.signal
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
async decodeResponse(response) {
|
|
142
|
+
const isOk = response.status < 400;
|
|
143
|
+
const body = await response.resolveBody();
|
|
144
|
+
const deserialized = await (async () => {
|
|
145
|
+
try {
|
|
146
|
+
return this.serializer.deserialize(body);
|
|
147
|
+
} catch (cause) {
|
|
148
|
+
throw new Error("Invalid RPC response format.", {
|
|
149
|
+
cause
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
})();
|
|
153
|
+
if (!isOk) {
|
|
154
|
+
if (isORPCErrorJson(deserialized)) {
|
|
155
|
+
return { kind: "error", error: createORPCErrorFromJson(deserialized) };
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
kind: "error",
|
|
159
|
+
error: new ORPCError("MALFORMED_ORPC_ERROR_RESPONSE", {
|
|
160
|
+
data: { headers: response.headers, status: response.status, body: deserialized }
|
|
161
|
+
})
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return { kind: "output", output: deserialized };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function toResolvedStandardHeaders(headers) {
|
|
168
|
+
if (typeof headers.forEach === "function") {
|
|
169
|
+
return toStandardHeaders(headers);
|
|
170
|
+
}
|
|
171
|
+
return headers;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export { CompositeStandardLinkPlugin as C, RPCLinkCodec as R, StandardLink as S };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { StandardBody } from '@standardserver/core';
|
|
2
|
+
import { Segment } from '@orpc/shared';
|
|
3
|
+
|
|
4
|
+
type RPCJsonSerializationMeta = [type: string, ...path: Segment[]];
|
|
5
|
+
type RPCJsonSerialization = {
|
|
6
|
+
json: unknown;
|
|
7
|
+
meta?: RPCJsonSerializationMeta[] | undefined;
|
|
8
|
+
maps?: undefined;
|
|
9
|
+
blobs?: undefined;
|
|
10
|
+
} | {
|
|
11
|
+
json: unknown;
|
|
12
|
+
meta?: RPCJsonSerializationMeta[] | undefined;
|
|
13
|
+
maps: Segment[][];
|
|
14
|
+
blobs: Blob[];
|
|
15
|
+
};
|
|
16
|
+
interface RPCJsonSerializerHandler {
|
|
17
|
+
condition(value: unknown): boolean;
|
|
18
|
+
serialize(value: any): unknown;
|
|
19
|
+
deserialize(serialized: any): unknown;
|
|
20
|
+
/**
|
|
21
|
+
* If false, the result of this serializer will not be further processed by other serializers,
|
|
22
|
+
* even if it matches their conditions and treat it as final serialized value.
|
|
23
|
+
* This can be useful for serializers that return primitive values, which should not be further processed.
|
|
24
|
+
* to improve performance and avoid potential issues with other serializers.
|
|
25
|
+
*
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
isTerminal?: boolean;
|
|
29
|
+
}
|
|
30
|
+
interface RPCJsonSerializerOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Extend or override the built-in type handlers used during serialization and deserialization.
|
|
33
|
+
*
|
|
34
|
+
* Each key is a unique type identifier (e.g. `"date"`, `"bigint"`) and maps to a handler
|
|
35
|
+
* that defines how to detect, serialize, and deserialize values of that type.
|
|
36
|
+
*
|
|
37
|
+
* **Extending:** Add new keys to support custom types:
|
|
38
|
+
* ```ts
|
|
39
|
+
* handlers: {
|
|
40
|
+
* buffer: {
|
|
41
|
+
* condition: (v) => v instanceof Buffer,
|
|
42
|
+
* serialize: (v: Buffer) => v.toString('base64'),
|
|
43
|
+
* deserialize: (s: string) => Buffer.from(s, 'base64'),
|
|
44
|
+
* isTerminal: true,
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* **Overriding:** Use an existing key to replace a built-in handler:
|
|
50
|
+
* ```ts
|
|
51
|
+
* handlers: {
|
|
52
|
+
* date: {
|
|
53
|
+
* condition: (v) => v instanceof Date,
|
|
54
|
+
* serialize: (v: Date) => v.getTime(),
|
|
55
|
+
* deserialize: (n: number) => new Date(n),
|
|
56
|
+
* isTerminal: true,
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* **Disabling:** Set a key to `undefined` to remove a built-in handler:
|
|
62
|
+
* ```ts
|
|
63
|
+
* handlers: { regexp: undefined }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* Built-in type keys: `undefined`, `bigint`, `date`, `nan`, `url`, `regexp`, `set`, `map`.
|
|
67
|
+
*/
|
|
68
|
+
handlers?: Record<string, undefined | RPCJsonSerializerHandler> | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* If true, properties with undefined values will be omitted during serialization.
|
|
71
|
+
*
|
|
72
|
+
* @default true
|
|
73
|
+
*/
|
|
74
|
+
omitUndefinedProperties?: boolean | undefined;
|
|
75
|
+
}
|
|
76
|
+
declare class RPCJsonSerializer {
|
|
77
|
+
private readonly handlers;
|
|
78
|
+
private readonly omitUndefinedProperties;
|
|
79
|
+
constructor(options?: RPCJsonSerializerOptions);
|
|
80
|
+
serialize(data: unknown): RPCJsonSerialization;
|
|
81
|
+
private serializeValue;
|
|
82
|
+
deserialize(serialized: RPCJsonSerialization): unknown;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface RPCSerializerSerializeOptions {
|
|
86
|
+
/**
|
|
87
|
+
* Use FormData for serialization when nested blobs are present.
|
|
88
|
+
* Does not apply to root-level Blob values.
|
|
89
|
+
*
|
|
90
|
+
* @default true
|
|
91
|
+
*/
|
|
92
|
+
useFormDataForBlobFields?: boolean;
|
|
93
|
+
}
|
|
94
|
+
interface RPCSerializerOptions extends RPCJsonSerializerOptions {
|
|
95
|
+
/**
|
|
96
|
+
* Default options for serialize method
|
|
97
|
+
*/
|
|
98
|
+
serialize?: RPCSerializerSerializeOptions | undefined;
|
|
99
|
+
}
|
|
100
|
+
declare class RPCSerializer {
|
|
101
|
+
private readonly jsonSerializer;
|
|
102
|
+
private readonly defaultSerializeOptions;
|
|
103
|
+
constructor(options?: RPCSerializerOptions);
|
|
104
|
+
serialize(data: unknown, options?: RPCSerializerSerializeOptions): StandardBody;
|
|
105
|
+
private serializeValue;
|
|
106
|
+
deserialize(data: StandardBody): unknown;
|
|
107
|
+
private deserializeValue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export { RPCJsonSerializer as b, RPCSerializer as e };
|
|
111
|
+
export type { RPCJsonSerialization as R, RPCJsonSerializationMeta as a, RPCJsonSerializerHandler as c, RPCJsonSerializerOptions as d, RPCSerializerOptions as f, RPCSerializerSerializeOptions as g };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { StandardBody } from '@standardserver/core';
|
|
2
|
+
import { Segment } from '@orpc/shared';
|
|
3
|
+
|
|
4
|
+
type RPCJsonSerializationMeta = [type: string, ...path: Segment[]];
|
|
5
|
+
type RPCJsonSerialization = {
|
|
6
|
+
json: unknown;
|
|
7
|
+
meta?: RPCJsonSerializationMeta[] | undefined;
|
|
8
|
+
maps?: undefined;
|
|
9
|
+
blobs?: undefined;
|
|
10
|
+
} | {
|
|
11
|
+
json: unknown;
|
|
12
|
+
meta?: RPCJsonSerializationMeta[] | undefined;
|
|
13
|
+
maps: Segment[][];
|
|
14
|
+
blobs: Blob[];
|
|
15
|
+
};
|
|
16
|
+
interface RPCJsonSerializerHandler {
|
|
17
|
+
condition(value: unknown): boolean;
|
|
18
|
+
serialize(value: any): unknown;
|
|
19
|
+
deserialize(serialized: any): unknown;
|
|
20
|
+
/**
|
|
21
|
+
* If false, the result of this serializer will not be further processed by other serializers,
|
|
22
|
+
* even if it matches their conditions and treat it as final serialized value.
|
|
23
|
+
* This can be useful for serializers that return primitive values, which should not be further processed.
|
|
24
|
+
* to improve performance and avoid potential issues with other serializers.
|
|
25
|
+
*
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
isTerminal?: boolean;
|
|
29
|
+
}
|
|
30
|
+
interface RPCJsonSerializerOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Extend or override the built-in type handlers used during serialization and deserialization.
|
|
33
|
+
*
|
|
34
|
+
* Each key is a unique type identifier (e.g. `"date"`, `"bigint"`) and maps to a handler
|
|
35
|
+
* that defines how to detect, serialize, and deserialize values of that type.
|
|
36
|
+
*
|
|
37
|
+
* **Extending:** Add new keys to support custom types:
|
|
38
|
+
* ```ts
|
|
39
|
+
* handlers: {
|
|
40
|
+
* buffer: {
|
|
41
|
+
* condition: (v) => v instanceof Buffer,
|
|
42
|
+
* serialize: (v: Buffer) => v.toString('base64'),
|
|
43
|
+
* deserialize: (s: string) => Buffer.from(s, 'base64'),
|
|
44
|
+
* isTerminal: true,
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* **Overriding:** Use an existing key to replace a built-in handler:
|
|
50
|
+
* ```ts
|
|
51
|
+
* handlers: {
|
|
52
|
+
* date: {
|
|
53
|
+
* condition: (v) => v instanceof Date,
|
|
54
|
+
* serialize: (v: Date) => v.getTime(),
|
|
55
|
+
* deserialize: (n: number) => new Date(n),
|
|
56
|
+
* isTerminal: true,
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* **Disabling:** Set a key to `undefined` to remove a built-in handler:
|
|
62
|
+
* ```ts
|
|
63
|
+
* handlers: { regexp: undefined }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* Built-in type keys: `undefined`, `bigint`, `date`, `nan`, `url`, `regexp`, `set`, `map`.
|
|
67
|
+
*/
|
|
68
|
+
handlers?: Record<string, undefined | RPCJsonSerializerHandler> | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* If true, properties with undefined values will be omitted during serialization.
|
|
71
|
+
*
|
|
72
|
+
* @default true
|
|
73
|
+
*/
|
|
74
|
+
omitUndefinedProperties?: boolean | undefined;
|
|
75
|
+
}
|
|
76
|
+
declare class RPCJsonSerializer {
|
|
77
|
+
private readonly handlers;
|
|
78
|
+
private readonly omitUndefinedProperties;
|
|
79
|
+
constructor(options?: RPCJsonSerializerOptions);
|
|
80
|
+
serialize(data: unknown): RPCJsonSerialization;
|
|
81
|
+
private serializeValue;
|
|
82
|
+
deserialize(serialized: RPCJsonSerialization): unknown;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface RPCSerializerSerializeOptions {
|
|
86
|
+
/**
|
|
87
|
+
* Use FormData for serialization when nested blobs are present.
|
|
88
|
+
* Does not apply to root-level Blob values.
|
|
89
|
+
*
|
|
90
|
+
* @default true
|
|
91
|
+
*/
|
|
92
|
+
useFormDataForBlobFields?: boolean;
|
|
93
|
+
}
|
|
94
|
+
interface RPCSerializerOptions extends RPCJsonSerializerOptions {
|
|
95
|
+
/**
|
|
96
|
+
* Default options for serialize method
|
|
97
|
+
*/
|
|
98
|
+
serialize?: RPCSerializerSerializeOptions | undefined;
|
|
99
|
+
}
|
|
100
|
+
declare class RPCSerializer {
|
|
101
|
+
private readonly jsonSerializer;
|
|
102
|
+
private readonly defaultSerializeOptions;
|
|
103
|
+
constructor(options?: RPCSerializerOptions);
|
|
104
|
+
serialize(data: unknown, options?: RPCSerializerSerializeOptions): StandardBody;
|
|
105
|
+
private serializeValue;
|
|
106
|
+
deserialize(data: StandardBody): unknown;
|
|
107
|
+
private deserializeValue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export { RPCJsonSerializer as b, RPCSerializer as e };
|
|
111
|
+
export type { RPCJsonSerialization as R, RPCJsonSerializationMeta as a, RPCJsonSerializerHandler as c, RPCJsonSerializerOptions as d, RPCSerializerOptions as f, RPCSerializerSerializeOptions as g };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { resolveMaybeOptionalOptions, getConstructor } from '@orpc/shared';
|
|
2
|
+
|
|
3
|
+
const COMMON_ERROR_STATUS_MAP = {
|
|
4
|
+
BAD_REQUEST: 400,
|
|
5
|
+
UNAUTHORIZED: 401,
|
|
6
|
+
PAYMENT_REQUIRED: 402,
|
|
7
|
+
FORBIDDEN: 403,
|
|
8
|
+
NOT_FOUND: 404,
|
|
9
|
+
METHOD_NOT_SUPPORTED: 405,
|
|
10
|
+
NOT_ACCEPTABLE: 406,
|
|
11
|
+
TIMEOUT: 408,
|
|
12
|
+
CONFLICT: 409,
|
|
13
|
+
GONE: 410,
|
|
14
|
+
PRECONDITION_FAILED: 412,
|
|
15
|
+
PAYLOAD_TOO_LARGE: 413,
|
|
16
|
+
UNSUPPORTED_MEDIA_TYPE: 415,
|
|
17
|
+
UNPROCESSABLE_CONTENT: 422,
|
|
18
|
+
PRECONDITION_REQUIRED: 428,
|
|
19
|
+
TOO_MANY_REQUESTS: 429,
|
|
20
|
+
CLIENT_CLOSED_REQUEST: 499,
|
|
21
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
22
|
+
NOT_IMPLEMENTED: 501,
|
|
23
|
+
BAD_GATEWAY: 502,
|
|
24
|
+
SERVICE_UNAVAILABLE: 503,
|
|
25
|
+
GATEWAY_TIMEOUT: 504
|
|
26
|
+
};
|
|
27
|
+
let ORPCErrorConstructors;
|
|
28
|
+
class ORPCError extends Error {
|
|
29
|
+
static {
|
|
30
|
+
const ORPC_ERROR_CONSTRUCTORS_SYMBOL = Symbol.for("ORPC_ERROR_CONSTRUCTORS");
|
|
31
|
+
void (globalThis[ORPC_ERROR_CONSTRUCTORS_SYMBOL] ??= /* @__PURE__ */ new WeakSet());
|
|
32
|
+
ORPCErrorConstructors = globalThis[ORPC_ERROR_CONSTRUCTORS_SYMBOL];
|
|
33
|
+
ORPCErrorConstructors.add(ORPCError);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* @info
|
|
37
|
+
* The `__branch` property is used for type branding, helping TypeScript distinguish
|
|
38
|
+
* an `ORPCError` instance from plain objects with a similar structure.
|
|
39
|
+
*/
|
|
40
|
+
name = "ORPCError";
|
|
41
|
+
/**
|
|
42
|
+
* Indicates whether the error matches a definition in the procedure's `.errors` map.
|
|
43
|
+
*/
|
|
44
|
+
defined = false;
|
|
45
|
+
/**
|
|
46
|
+
* Indicates whether the error's type is inferable at the TypeScript level.
|
|
47
|
+
* This is typically true when the error is explicitly defined or returned within a handler.
|
|
48
|
+
*/
|
|
49
|
+
inferable = false;
|
|
50
|
+
code;
|
|
51
|
+
data;
|
|
52
|
+
constructor(code, ...rest) {
|
|
53
|
+
const options = resolveMaybeOptionalOptions(rest);
|
|
54
|
+
const message = options.message ?? code.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
55
|
+
super(message, options);
|
|
56
|
+
this.code = code;
|
|
57
|
+
this.data = options.data;
|
|
58
|
+
}
|
|
59
|
+
toJSON() {
|
|
60
|
+
return {
|
|
61
|
+
defined: this.defined,
|
|
62
|
+
inferable: this.inferable,
|
|
63
|
+
code: this.code,
|
|
64
|
+
message: this.message,
|
|
65
|
+
data: this.data
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Workaround for Next.js where different contexts use separate
|
|
70
|
+
* dependency graphs, causing multiple ORPCError constructors existing and breaking
|
|
71
|
+
* `instanceof` checks across contexts.
|
|
72
|
+
*
|
|
73
|
+
* This is particularly problematic with "Optimized SSR", where orpc-client
|
|
74
|
+
* executes in one context but is invoked from another. When an error is thrown
|
|
75
|
+
* in the execution context, `instanceof ORPCError` checks fail in the
|
|
76
|
+
* invocation context due to separate class constructors.
|
|
77
|
+
*
|
|
78
|
+
* @todo Remove this and related code if Next.js resolves the multiple dependency graph issue.
|
|
79
|
+
*/
|
|
80
|
+
static [Symbol.hasInstance](instance) {
|
|
81
|
+
if (!ORPCErrorConstructors.has(this)) {
|
|
82
|
+
return super[Symbol.hasInstance](instance);
|
|
83
|
+
}
|
|
84
|
+
const constructor = getConstructor(instance);
|
|
85
|
+
if (constructor && ORPCErrorConstructors.has(constructor)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
return super[Symbol.hasInstance](instance);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { COMMON_ERROR_STATUS_MAP as C, ORPCError as O };
|