@orpc/client 0.0.0-next.0f0c680 → 0.0.0-next.0fa86b5
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 +29 -22
- package/dist/adapters/fetch/index.d.mts +16 -12
- package/dist/adapters/fetch/index.d.ts +16 -12
- package/dist/adapters/fetch/index.mjs +6 -13
- package/dist/adapters/message-port/index.d.mts +59 -0
- package/dist/adapters/message-port/index.d.ts +59 -0
- package/dist/adapters/message-port/index.mjs +71 -0
- package/dist/adapters/standard/index.d.mts +8 -152
- package/dist/adapters/standard/index.d.ts +8 -152
- package/dist/adapters/standard/index.mjs +2 -2
- package/dist/adapters/websocket/index.d.mts +29 -0
- package/dist/adapters/websocket/index.d.ts +29 -0
- package/dist/adapters/websocket/index.mjs +45 -0
- package/dist/index.d.mts +62 -32
- package/dist/index.d.ts +62 -32
- package/dist/index.mjs +54 -35
- package/dist/plugins/index.d.mts +202 -0
- package/dist/plugins/index.d.ts +202 -0
- package/dist/plugins/index.mjs +400 -0
- package/dist/shared/client.BG98rYdO.d.ts +45 -0
- package/dist/shared/client.BOYsZIRq.d.mts +29 -0
- package/dist/shared/client.BOYsZIRq.d.ts +29 -0
- package/dist/shared/client.Bwgm6dgk.d.mts +45 -0
- package/dist/shared/client.C176log5.d.ts +91 -0
- package/dist/shared/{client.Cwx-UcH5.mjs → client.DKmRtVO2.mjs} +151 -83
- package/dist/shared/client.Ycwr4Tuo.d.mts +91 -0
- package/dist/shared/client.txdq_i5V.mjs +180 -0
- package/package.json +21 -5
- package/dist/shared/client.D_CzLDyB.d.mts +0 -42
- package/dist/shared/client.D_CzLDyB.d.ts +0 -42
- package/dist/shared/client.XAn8cDTM.mjs +0 -266
|
@@ -1,108 +1,148 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { toArray, runWithSpan, ORPC_NAME, isAsyncIteratorObject, asyncIteratorWithSpan, intercept, getGlobalOtelConfig, isObject, value, stringifyJSON } from '@orpc/shared';
|
|
2
|
+
import { mergeStandardHeaders, ErrorEvent } from '@orpc/standard-server';
|
|
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.txdq_i5V.mjs';
|
|
4
4
|
|
|
5
|
-
class
|
|
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
|
-
constructor(codec, sender, options) {
|
|
18
|
+
constructor(codec, sender, options = {}) {
|
|
9
19
|
this.codec = codec;
|
|
10
20
|
this.sender = sender;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
this.
|
|
14
|
-
this.
|
|
15
|
-
this.clientInterceptors = options.clientInterceptors ?? [];
|
|
21
|
+
const plugin = new CompositeStandardLinkPlugin(options.plugins);
|
|
22
|
+
plugin.init(options);
|
|
23
|
+
this.interceptors = toArray(options.interceptors);
|
|
24
|
+
this.clientInterceptors = toArray(options.clientInterceptors);
|
|
16
25
|
}
|
|
17
|
-
eventIteratorMaxRetries;
|
|
18
|
-
eventIteratorRetryDelay;
|
|
19
|
-
eventIteratorShouldRetry;
|
|
20
26
|
interceptors;
|
|
21
27
|
clientInterceptors;
|
|
22
28
|
call(path, input, options) {
|
|
23
|
-
return
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const shouldRetry = await value(this.eventIteratorShouldRetry, reconnectOptions, options2, path2, input2);
|
|
34
|
-
if (!shouldRetry) {
|
|
35
|
-
return null;
|
|
29
|
+
return runWithSpan(
|
|
30
|
+
{ name: `${ORPC_NAME}.${path.join("/")}`, signal: options.signal },
|
|
31
|
+
(span) => {
|
|
32
|
+
span?.setAttribute("rpc.system", ORPC_NAME);
|
|
33
|
+
span?.setAttribute("rpc.method", path.join("."));
|
|
34
|
+
if (isAsyncIteratorObject(input)) {
|
|
35
|
+
input = asyncIteratorWithSpan(
|
|
36
|
+
{ name: "consume_event_iterator_input", signal: options.signal },
|
|
37
|
+
input
|
|
38
|
+
);
|
|
36
39
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
40
|
+
return intercept(this.interceptors, { ...options, path, input }, async ({ path: path2, input: input2, ...options2 }) => {
|
|
41
|
+
const otelConfig = getGlobalOtelConfig();
|
|
42
|
+
let otelContext;
|
|
43
|
+
const currentSpan = otelConfig?.trace.getActiveSpan() ?? span;
|
|
44
|
+
if (currentSpan && otelConfig) {
|
|
45
|
+
otelContext = otelConfig?.trace.setSpan(otelConfig.context.active(), currentSpan);
|
|
46
|
+
}
|
|
47
|
+
const request = await runWithSpan(
|
|
48
|
+
{ name: "encode_request", context: otelContext },
|
|
49
|
+
() => this.codec.encode(path2, input2, options2)
|
|
50
|
+
);
|
|
51
|
+
const response = await intercept(
|
|
52
|
+
this.clientInterceptors,
|
|
53
|
+
{ ...options2, input: input2, path: path2, request },
|
|
54
|
+
({ input: input3, path: path3, request: request2, ...options3 }) => {
|
|
55
|
+
return runWithSpan(
|
|
56
|
+
{ name: "send_request", signal: options3.signal, context: otelContext },
|
|
57
|
+
() => this.sender.call(request2, options3, path3, input3)
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
const output = await runWithSpan(
|
|
62
|
+
{ name: "decode_response", context: otelContext },
|
|
63
|
+
() => this.codec.decode(response, options2, path2, input2)
|
|
64
|
+
);
|
|
65
|
+
if (isAsyncIteratorObject(output)) {
|
|
66
|
+
return asyncIteratorWithSpan(
|
|
67
|
+
{ name: "consume_event_iterator_output", signal: options2.signal },
|
|
68
|
+
output
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
return output;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
54
74
|
);
|
|
55
|
-
const output = await this.codec.decode(response, options, path, input);
|
|
56
|
-
return output;
|
|
57
75
|
}
|
|
58
76
|
}
|
|
59
77
|
|
|
78
|
+
const STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES = {
|
|
79
|
+
BIGINT: 0,
|
|
80
|
+
DATE: 1,
|
|
81
|
+
NAN: 2,
|
|
82
|
+
UNDEFINED: 3,
|
|
83
|
+
URL: 4,
|
|
84
|
+
REGEXP: 5,
|
|
85
|
+
SET: 6,
|
|
86
|
+
MAP: 7
|
|
87
|
+
};
|
|
60
88
|
class StandardRPCJsonSerializer {
|
|
61
|
-
|
|
89
|
+
customSerializers;
|
|
90
|
+
constructor(options = {}) {
|
|
91
|
+
this.customSerializers = options.customJsonSerializers ?? [];
|
|
92
|
+
if (this.customSerializers.length !== new Set(this.customSerializers.map((custom) => custom.type)).size) {
|
|
93
|
+
throw new Error("Custom serializer type must be unique.");
|
|
94
|
+
}
|
|
62
95
|
}
|
|
63
96
|
serialize(data, segments = [], meta = [], maps = [], blobs = []) {
|
|
97
|
+
for (const custom of this.customSerializers) {
|
|
98
|
+
if (custom.condition(data)) {
|
|
99
|
+
const result = this.serialize(custom.serialize(data), segments, meta, maps, blobs);
|
|
100
|
+
meta.push([custom.type, ...segments]);
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
64
104
|
if (data instanceof Blob) {
|
|
65
105
|
maps.push(segments);
|
|
66
106
|
blobs.push(data);
|
|
67
107
|
return [data, meta, maps, blobs];
|
|
68
108
|
}
|
|
69
109
|
if (typeof data === "bigint") {
|
|
70
|
-
meta.push([
|
|
110
|
+
meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.BIGINT, ...segments]);
|
|
71
111
|
return [data.toString(), meta, maps, blobs];
|
|
72
112
|
}
|
|
73
113
|
if (data instanceof Date) {
|
|
74
|
-
meta.push([
|
|
114
|
+
meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.DATE, ...segments]);
|
|
75
115
|
if (Number.isNaN(data.getTime())) {
|
|
76
116
|
return [null, meta, maps, blobs];
|
|
77
117
|
}
|
|
78
118
|
return [data.toISOString(), meta, maps, blobs];
|
|
79
119
|
}
|
|
80
120
|
if (Number.isNaN(data)) {
|
|
81
|
-
meta.push([
|
|
121
|
+
meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.NAN, ...segments]);
|
|
82
122
|
return [null, meta, maps, blobs];
|
|
83
123
|
}
|
|
84
124
|
if (data instanceof URL) {
|
|
85
|
-
meta.push([
|
|
125
|
+
meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.URL, ...segments]);
|
|
86
126
|
return [data.toString(), meta, maps, blobs];
|
|
87
127
|
}
|
|
88
128
|
if (data instanceof RegExp) {
|
|
89
|
-
meta.push([
|
|
129
|
+
meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.REGEXP, ...segments]);
|
|
90
130
|
return [data.toString(), meta, maps, blobs];
|
|
91
131
|
}
|
|
92
132
|
if (data instanceof Set) {
|
|
93
133
|
const result = this.serialize(Array.from(data), segments, meta, maps, blobs);
|
|
94
|
-
meta.push([
|
|
134
|
+
meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.SET, ...segments]);
|
|
95
135
|
return result;
|
|
96
136
|
}
|
|
97
137
|
if (data instanceof Map) {
|
|
98
138
|
const result = this.serialize(Array.from(data.entries()), segments, meta, maps, blobs);
|
|
99
|
-
meta.push([
|
|
139
|
+
meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.MAP, ...segments]);
|
|
100
140
|
return result;
|
|
101
141
|
}
|
|
102
142
|
if (Array.isArray(data)) {
|
|
103
143
|
const json = data.map((v, i) => {
|
|
104
144
|
if (v === void 0) {
|
|
105
|
-
meta.push([
|
|
145
|
+
meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.UNDEFINED, ...segments, i]);
|
|
106
146
|
return v;
|
|
107
147
|
}
|
|
108
148
|
return this.serialize(v, [...segments, i], meta, maps, blobs)[0];
|
|
@@ -112,6 +152,9 @@ class StandardRPCJsonSerializer {
|
|
|
112
152
|
if (isObject(data)) {
|
|
113
153
|
const json = {};
|
|
114
154
|
for (const k in data) {
|
|
155
|
+
if (k === "toJSON" && typeof data[k] === "function") {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
115
158
|
json[k] = this.serialize(data[k], [...segments, k], meta, maps, blobs)[0];
|
|
116
159
|
}
|
|
117
160
|
return [json, meta, maps, blobs];
|
|
@@ -131,38 +174,45 @@ class StandardRPCJsonSerializer {
|
|
|
131
174
|
currentRef[preSegment] = getBlob(i);
|
|
132
175
|
});
|
|
133
176
|
}
|
|
134
|
-
for (const
|
|
177
|
+
for (const item of meta) {
|
|
178
|
+
const type = item[0];
|
|
135
179
|
let currentRef = ref;
|
|
136
180
|
let preSegment = "data";
|
|
137
|
-
|
|
181
|
+
for (let i = 1; i < item.length; i++) {
|
|
138
182
|
currentRef = currentRef[preSegment];
|
|
139
|
-
preSegment =
|
|
140
|
-
}
|
|
183
|
+
preSegment = item[i];
|
|
184
|
+
}
|
|
185
|
+
for (const custom of this.customSerializers) {
|
|
186
|
+
if (custom.type === type) {
|
|
187
|
+
currentRef[preSegment] = custom.deserialize(currentRef[preSegment]);
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
141
191
|
switch (type) {
|
|
142
|
-
case
|
|
192
|
+
case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.BIGINT:
|
|
143
193
|
currentRef[preSegment] = BigInt(currentRef[preSegment]);
|
|
144
194
|
break;
|
|
145
|
-
case
|
|
195
|
+
case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.DATE:
|
|
146
196
|
currentRef[preSegment] = new Date(currentRef[preSegment] ?? "Invalid Date");
|
|
147
197
|
break;
|
|
148
|
-
case
|
|
198
|
+
case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.NAN:
|
|
149
199
|
currentRef[preSegment] = Number.NaN;
|
|
150
200
|
break;
|
|
151
|
-
case
|
|
201
|
+
case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.UNDEFINED:
|
|
152
202
|
currentRef[preSegment] = void 0;
|
|
153
203
|
break;
|
|
154
|
-
case
|
|
204
|
+
case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.URL:
|
|
155
205
|
currentRef[preSegment] = new URL(currentRef[preSegment]);
|
|
156
206
|
break;
|
|
157
|
-
case
|
|
207
|
+
case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.REGEXP: {
|
|
158
208
|
const [, pattern, flags] = currentRef[preSegment].match(/^\/(.*)\/([a-z]*)$/);
|
|
159
209
|
currentRef[preSegment] = new RegExp(pattern, flags);
|
|
160
210
|
break;
|
|
161
211
|
}
|
|
162
|
-
case
|
|
212
|
+
case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.SET:
|
|
163
213
|
currentRef[preSegment] = new Set(currentRef[preSegment]);
|
|
164
214
|
break;
|
|
165
|
-
case
|
|
215
|
+
case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.MAP:
|
|
166
216
|
currentRef[preSegment] = new Map(currentRef[preSegment]);
|
|
167
217
|
break;
|
|
168
218
|
}
|
|
@@ -171,6 +221,13 @@ class StandardRPCJsonSerializer {
|
|
|
171
221
|
}
|
|
172
222
|
}
|
|
173
223
|
|
|
224
|
+
function toHttpPath(path) {
|
|
225
|
+
return `/${path.map(encodeURIComponent).join("/")}`;
|
|
226
|
+
}
|
|
227
|
+
function getMalformedResponseErrorCode(status) {
|
|
228
|
+
return Object.entries(COMMON_ORPC_ERROR_DEFS).find(([, def]) => def.status === status)?.[0] ?? "MALFORMED_ORPC_ERROR_RESPONSE";
|
|
229
|
+
}
|
|
230
|
+
|
|
174
231
|
class StandardRPCLinkCodec {
|
|
175
232
|
constructor(serializer, options) {
|
|
176
233
|
this.serializer = serializer;
|
|
@@ -187,14 +244,18 @@ class StandardRPCLinkCodec {
|
|
|
187
244
|
headers;
|
|
188
245
|
async encode(path, input, options) {
|
|
189
246
|
const expectedMethod = await value(this.expectedMethod, options, path, input);
|
|
190
|
-
|
|
247
|
+
let headers = await value(this.headers, options, path, input);
|
|
191
248
|
const baseUrl = await value(this.baseUrl, options, path, input);
|
|
192
|
-
const url = new URL(
|
|
249
|
+
const url = new URL(baseUrl);
|
|
250
|
+
url.pathname = `${url.pathname.replace(/\/$/, "")}${toHttpPath(path)}`;
|
|
251
|
+
if (options.lastEventId !== void 0) {
|
|
252
|
+
headers = mergeStandardHeaders(headers, { "last-event-id": options.lastEventId });
|
|
253
|
+
}
|
|
193
254
|
const serialized = this.serializer.serialize(input);
|
|
194
|
-
if (expectedMethod === "GET" && !(serialized instanceof FormData) && !
|
|
255
|
+
if (expectedMethod === "GET" && !(serialized instanceof FormData) && !isAsyncIteratorObject(serialized)) {
|
|
195
256
|
const maxUrlLength = await value(this.maxUrlLength, options, path, input);
|
|
196
257
|
const getUrl = new URL(url);
|
|
197
|
-
getUrl.searchParams.append("data", stringifyJSON(serialized)
|
|
258
|
+
getUrl.searchParams.append("data", stringifyJSON(serialized));
|
|
198
259
|
if (getUrl.toString().length <= maxUrlLength) {
|
|
199
260
|
return {
|
|
200
261
|
body: void 0,
|
|
@@ -214,7 +275,7 @@ class StandardRPCLinkCodec {
|
|
|
214
275
|
};
|
|
215
276
|
}
|
|
216
277
|
async decode(response) {
|
|
217
|
-
const isOk = response.status
|
|
278
|
+
const isOk = !isORPCErrorStatus(response.status);
|
|
218
279
|
const deserialized = await (async () => {
|
|
219
280
|
let isBodyOk = false;
|
|
220
281
|
try {
|
|
@@ -233,11 +294,12 @@ class StandardRPCLinkCodec {
|
|
|
233
294
|
}
|
|
234
295
|
})();
|
|
235
296
|
if (!isOk) {
|
|
236
|
-
if (
|
|
237
|
-
throw
|
|
297
|
+
if (isORPCErrorJson(deserialized)) {
|
|
298
|
+
throw createORPCErrorFromJson(deserialized);
|
|
238
299
|
}
|
|
239
|
-
throw new
|
|
240
|
-
|
|
300
|
+
throw new ORPCError(getMalformedResponseErrorCode(response.status), {
|
|
301
|
+
status: response.status,
|
|
302
|
+
data: { ...response, body: deserialized }
|
|
241
303
|
});
|
|
242
304
|
}
|
|
243
305
|
return deserialized;
|
|
@@ -263,9 +325,6 @@ class StandardRPCSerializer {
|
|
|
263
325
|
return this.#serialize(data, true);
|
|
264
326
|
}
|
|
265
327
|
#serialize(data, enableFormData) {
|
|
266
|
-
if (data === void 0 || data instanceof Blob) {
|
|
267
|
-
return data;
|
|
268
|
-
}
|
|
269
328
|
const [json, meta_, maps, blobs] = this.jsonSerializer.serialize(data);
|
|
270
329
|
const meta = meta_.length === 0 ? void 0 : meta_;
|
|
271
330
|
if (!enableFormData || blobs.length === 0) {
|
|
@@ -290,8 +349,8 @@ class StandardRPCSerializer {
|
|
|
290
349
|
return e;
|
|
291
350
|
}
|
|
292
351
|
const deserialized = this.#deserialize(e.data);
|
|
293
|
-
if (
|
|
294
|
-
return
|
|
352
|
+
if (isORPCErrorJson(deserialized)) {
|
|
353
|
+
return createORPCErrorFromJson(deserialized, { cause: e });
|
|
295
354
|
}
|
|
296
355
|
return new ErrorEvent({
|
|
297
356
|
data: deserialized,
|
|
@@ -303,8 +362,8 @@ class StandardRPCSerializer {
|
|
|
303
362
|
return this.#deserialize(data);
|
|
304
363
|
}
|
|
305
364
|
#deserialize(data) {
|
|
306
|
-
if (data === void 0
|
|
307
|
-
return
|
|
365
|
+
if (data === void 0) {
|
|
366
|
+
return void 0;
|
|
308
367
|
}
|
|
309
368
|
if (!(data instanceof FormData)) {
|
|
310
369
|
return this.jsonSerializer.deserialize(data.json, data.meta ?? []);
|
|
@@ -319,4 +378,13 @@ class StandardRPCSerializer {
|
|
|
319
378
|
}
|
|
320
379
|
}
|
|
321
380
|
|
|
322
|
-
|
|
381
|
+
class StandardRPCLink extends StandardLink {
|
|
382
|
+
constructor(linkClient, options) {
|
|
383
|
+
const jsonSerializer = new StandardRPCJsonSerializer(options);
|
|
384
|
+
const serializer = new StandardRPCSerializer(jsonSerializer);
|
|
385
|
+
const linkCodec = new StandardRPCLinkCodec(serializer, options);
|
|
386
|
+
super(linkCodec, linkClient, options);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
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 };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { b as ClientContext, c as ClientOptions, f as HTTPMethod } from './client.BOYsZIRq.mjs';
|
|
2
|
+
import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.Bwgm6dgk.mjs';
|
|
3
|
+
import { Segment, Value, Promisable } from '@orpc/shared';
|
|
4
|
+
import { StandardHeaders, StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
|
|
5
|
+
|
|
6
|
+
declare const STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES: {
|
|
7
|
+
readonly BIGINT: 0;
|
|
8
|
+
readonly DATE: 1;
|
|
9
|
+
readonly NAN: 2;
|
|
10
|
+
readonly UNDEFINED: 3;
|
|
11
|
+
readonly URL: 4;
|
|
12
|
+
readonly REGEXP: 5;
|
|
13
|
+
readonly SET: 6;
|
|
14
|
+
readonly MAP: 7;
|
|
15
|
+
};
|
|
16
|
+
type StandardRPCJsonSerializedMetaItem = readonly [type: number, ...path: Segment[]];
|
|
17
|
+
type StandardRPCJsonSerialized = [json: unknown, meta: StandardRPCJsonSerializedMetaItem[], maps: Segment[][], blobs: Blob[]];
|
|
18
|
+
interface StandardRPCCustomJsonSerializer {
|
|
19
|
+
type: number;
|
|
20
|
+
condition(data: unknown): boolean;
|
|
21
|
+
serialize(data: any): unknown;
|
|
22
|
+
deserialize(serialized: any): unknown;
|
|
23
|
+
}
|
|
24
|
+
interface StandardRPCJsonSerializerOptions {
|
|
25
|
+
customJsonSerializers?: readonly StandardRPCCustomJsonSerializer[];
|
|
26
|
+
}
|
|
27
|
+
declare class StandardRPCJsonSerializer {
|
|
28
|
+
private readonly customSerializers;
|
|
29
|
+
constructor(options?: StandardRPCJsonSerializerOptions);
|
|
30
|
+
serialize(data: unknown, segments?: Segment[], meta?: StandardRPCJsonSerializedMetaItem[], maps?: Segment[][], blobs?: Blob[]): StandardRPCJsonSerialized;
|
|
31
|
+
deserialize(json: unknown, meta: readonly StandardRPCJsonSerializedMetaItem[]): unknown;
|
|
32
|
+
deserialize(json: unknown, meta: readonly StandardRPCJsonSerializedMetaItem[], maps: readonly Segment[][], getBlob: (index: number) => Blob): unknown;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
declare class StandardRPCSerializer {
|
|
36
|
+
#private;
|
|
37
|
+
private readonly jsonSerializer;
|
|
38
|
+
constructor(jsonSerializer: StandardRPCJsonSerializer);
|
|
39
|
+
serialize(data: unknown): object;
|
|
40
|
+
deserialize(data: unknown): unknown;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface StandardRPCLinkCodecOptions<T extends ClientContext> {
|
|
44
|
+
/**
|
|
45
|
+
* Base url for all requests.
|
|
46
|
+
*/
|
|
47
|
+
url: Value<Promisable<string | URL>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
|
|
48
|
+
/**
|
|
49
|
+
* The maximum length of the URL.
|
|
50
|
+
*
|
|
51
|
+
* @default 2083
|
|
52
|
+
*/
|
|
53
|
+
maxUrlLength?: Value<Promisable<number>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
|
|
54
|
+
/**
|
|
55
|
+
* The method used to make the request.
|
|
56
|
+
*
|
|
57
|
+
* @default 'POST'
|
|
58
|
+
*/
|
|
59
|
+
method?: Value<Promisable<Exclude<HTTPMethod, 'HEAD'>>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
|
|
60
|
+
/**
|
|
61
|
+
* The method to use when the payload cannot safely pass to the server with method return from method function.
|
|
62
|
+
* GET is not allowed, it's very dangerous.
|
|
63
|
+
*
|
|
64
|
+
* @default 'POST'
|
|
65
|
+
*/
|
|
66
|
+
fallbackMethod?: Exclude<HTTPMethod, 'HEAD' | 'GET'>;
|
|
67
|
+
/**
|
|
68
|
+
* Inject headers to the request.
|
|
69
|
+
*/
|
|
70
|
+
headers?: Value<Promisable<StandardHeaders>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
|
|
71
|
+
}
|
|
72
|
+
declare class StandardRPCLinkCodec<T extends ClientContext> implements StandardLinkCodec<T> {
|
|
73
|
+
private readonly serializer;
|
|
74
|
+
private readonly baseUrl;
|
|
75
|
+
private readonly maxUrlLength;
|
|
76
|
+
private readonly fallbackMethod;
|
|
77
|
+
private readonly expectedMethod;
|
|
78
|
+
private readonly headers;
|
|
79
|
+
constructor(serializer: StandardRPCSerializer, options: StandardRPCLinkCodecOptions<T>);
|
|
80
|
+
encode(path: readonly string[], input: unknown, options: ClientOptions<T>): Promise<StandardRequest>;
|
|
81
|
+
decode(response: StandardLazyResponse): Promise<unknown>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface StandardRPCLinkOptions<T extends ClientContext> extends StandardLinkOptions<T>, StandardRPCLinkCodecOptions<T>, StandardRPCJsonSerializerOptions {
|
|
85
|
+
}
|
|
86
|
+
declare class StandardRPCLink<T extends ClientContext> extends StandardLink<T> {
|
|
87
|
+
constructor(linkClient: StandardLinkClient<T>, options: StandardRPCLinkOptions<T>);
|
|
88
|
+
}
|
|
89
|
+
|
|
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 };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { resolveMaybeOptionalOptions, isObject, AsyncIteratorClass, isTypescriptObject } from '@orpc/shared';
|
|
2
|
+
import { getEventMeta, withEventMeta } from '@orpc/standard-server';
|
|
3
|
+
|
|
4
|
+
const COMMON_ORPC_ERROR_DEFS = {
|
|
5
|
+
BAD_REQUEST: {
|
|
6
|
+
status: 400,
|
|
7
|
+
message: "Bad Request"
|
|
8
|
+
},
|
|
9
|
+
UNAUTHORIZED: {
|
|
10
|
+
status: 401,
|
|
11
|
+
message: "Unauthorized"
|
|
12
|
+
},
|
|
13
|
+
FORBIDDEN: {
|
|
14
|
+
status: 403,
|
|
15
|
+
message: "Forbidden"
|
|
16
|
+
},
|
|
17
|
+
NOT_FOUND: {
|
|
18
|
+
status: 404,
|
|
19
|
+
message: "Not Found"
|
|
20
|
+
},
|
|
21
|
+
METHOD_NOT_SUPPORTED: {
|
|
22
|
+
status: 405,
|
|
23
|
+
message: "Method Not Supported"
|
|
24
|
+
},
|
|
25
|
+
NOT_ACCEPTABLE: {
|
|
26
|
+
status: 406,
|
|
27
|
+
message: "Not Acceptable"
|
|
28
|
+
},
|
|
29
|
+
TIMEOUT: {
|
|
30
|
+
status: 408,
|
|
31
|
+
message: "Request Timeout"
|
|
32
|
+
},
|
|
33
|
+
CONFLICT: {
|
|
34
|
+
status: 409,
|
|
35
|
+
message: "Conflict"
|
|
36
|
+
},
|
|
37
|
+
PRECONDITION_FAILED: {
|
|
38
|
+
status: 412,
|
|
39
|
+
message: "Precondition Failed"
|
|
40
|
+
},
|
|
41
|
+
PAYLOAD_TOO_LARGE: {
|
|
42
|
+
status: 413,
|
|
43
|
+
message: "Payload Too Large"
|
|
44
|
+
},
|
|
45
|
+
UNSUPPORTED_MEDIA_TYPE: {
|
|
46
|
+
status: 415,
|
|
47
|
+
message: "Unsupported Media Type"
|
|
48
|
+
},
|
|
49
|
+
UNPROCESSABLE_CONTENT: {
|
|
50
|
+
status: 422,
|
|
51
|
+
message: "Unprocessable Content"
|
|
52
|
+
},
|
|
53
|
+
TOO_MANY_REQUESTS: {
|
|
54
|
+
status: 429,
|
|
55
|
+
message: "Too Many Requests"
|
|
56
|
+
},
|
|
57
|
+
CLIENT_CLOSED_REQUEST: {
|
|
58
|
+
status: 499,
|
|
59
|
+
message: "Client Closed Request"
|
|
60
|
+
},
|
|
61
|
+
INTERNAL_SERVER_ERROR: {
|
|
62
|
+
status: 500,
|
|
63
|
+
message: "Internal Server Error"
|
|
64
|
+
},
|
|
65
|
+
NOT_IMPLEMENTED: {
|
|
66
|
+
status: 501,
|
|
67
|
+
message: "Not Implemented"
|
|
68
|
+
},
|
|
69
|
+
BAD_GATEWAY: {
|
|
70
|
+
status: 502,
|
|
71
|
+
message: "Bad Gateway"
|
|
72
|
+
},
|
|
73
|
+
SERVICE_UNAVAILABLE: {
|
|
74
|
+
status: 503,
|
|
75
|
+
message: "Service Unavailable"
|
|
76
|
+
},
|
|
77
|
+
GATEWAY_TIMEOUT: {
|
|
78
|
+
status: 504,
|
|
79
|
+
message: "Gateway Timeout"
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
function fallbackORPCErrorStatus(code, status) {
|
|
83
|
+
return status ?? COMMON_ORPC_ERROR_DEFS[code]?.status ?? 500;
|
|
84
|
+
}
|
|
85
|
+
function fallbackORPCErrorMessage(code, message) {
|
|
86
|
+
return message || COMMON_ORPC_ERROR_DEFS[code]?.message || code;
|
|
87
|
+
}
|
|
88
|
+
class ORPCError extends Error {
|
|
89
|
+
defined;
|
|
90
|
+
code;
|
|
91
|
+
status;
|
|
92
|
+
data;
|
|
93
|
+
constructor(code, ...rest) {
|
|
94
|
+
const options = resolveMaybeOptionalOptions(rest);
|
|
95
|
+
if (options.status !== void 0 && !isORPCErrorStatus(options.status)) {
|
|
96
|
+
throw new Error("[ORPCError] Invalid error status code.");
|
|
97
|
+
}
|
|
98
|
+
const message = fallbackORPCErrorMessage(code, options.message);
|
|
99
|
+
super(message, options);
|
|
100
|
+
this.code = code;
|
|
101
|
+
this.status = fallbackORPCErrorStatus(code, options.status);
|
|
102
|
+
this.defined = options.defined ?? false;
|
|
103
|
+
this.data = options.data;
|
|
104
|
+
}
|
|
105
|
+
toJSON() {
|
|
106
|
+
return {
|
|
107
|
+
defined: this.defined,
|
|
108
|
+
code: this.code,
|
|
109
|
+
status: this.status,
|
|
110
|
+
message: this.message,
|
|
111
|
+
data: this.data
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function isDefinedError(error) {
|
|
116
|
+
return error instanceof ORPCError && error.defined;
|
|
117
|
+
}
|
|
118
|
+
function toORPCError(error) {
|
|
119
|
+
return error instanceof ORPCError ? error : new ORPCError("INTERNAL_SERVER_ERROR", {
|
|
120
|
+
message: "Internal server error",
|
|
121
|
+
cause: error
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function isORPCErrorStatus(status) {
|
|
125
|
+
return status < 200 || status >= 400;
|
|
126
|
+
}
|
|
127
|
+
function isORPCErrorJson(json) {
|
|
128
|
+
if (!isObject(json)) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
const validKeys = ["defined", "code", "status", "message", "data"];
|
|
132
|
+
if (Object.keys(json).some((k) => !validKeys.includes(k))) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
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";
|
|
136
|
+
}
|
|
137
|
+
function createORPCErrorFromJson(json, options = {}) {
|
|
138
|
+
return new ORPCError(json.code, {
|
|
139
|
+
...options,
|
|
140
|
+
...json
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function mapEventIterator(iterator, maps) {
|
|
145
|
+
const mapError = async (error) => {
|
|
146
|
+
let mappedError = await maps.error(error);
|
|
147
|
+
if (mappedError !== error) {
|
|
148
|
+
const meta = getEventMeta(error);
|
|
149
|
+
if (meta && isTypescriptObject(mappedError)) {
|
|
150
|
+
mappedError = withEventMeta(mappedError, meta);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return mappedError;
|
|
154
|
+
};
|
|
155
|
+
return new AsyncIteratorClass(async () => {
|
|
156
|
+
const { done, value } = await (async () => {
|
|
157
|
+
try {
|
|
158
|
+
return await iterator.next();
|
|
159
|
+
} catch (error) {
|
|
160
|
+
throw await mapError(error);
|
|
161
|
+
}
|
|
162
|
+
})();
|
|
163
|
+
let mappedValue = await maps.value(value, done);
|
|
164
|
+
if (mappedValue !== value) {
|
|
165
|
+
const meta = getEventMeta(value);
|
|
166
|
+
if (meta && isTypescriptObject(mappedValue)) {
|
|
167
|
+
mappedValue = withEventMeta(mappedValue, meta);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return { done, value: mappedValue };
|
|
171
|
+
}, async () => {
|
|
172
|
+
try {
|
|
173
|
+
await iterator.return?.();
|
|
174
|
+
} catch (error) {
|
|
175
|
+
throw await mapError(error);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
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 };
|