@orpc/server 0.0.0-next.2ba0691 → 0.0.0-next.31590a1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. package/dist/chunk-CVIWJKJC.js +308 -0
  2. package/dist/chunk-EYGVJA7A.js +136 -0
  3. package/dist/chunk-NOA3GBJQ.js +380 -0
  4. package/dist/chunk-OXB4YX67.js +111 -0
  5. package/dist/fetch.js +14 -299
  6. package/dist/hono.js +42 -0
  7. package/dist/index.js +269 -383
  8. package/dist/next.js +39 -0
  9. package/dist/node.js +175 -0
  10. package/dist/plugins.js +11 -0
  11. package/dist/src/adapters/fetch/index.d.ts +4 -0
  12. package/dist/src/adapters/fetch/rpc-handler.d.ts +10 -0
  13. package/dist/src/adapters/fetch/types.d.ts +13 -0
  14. package/dist/src/adapters/fetch/utils.d.ts +6 -0
  15. package/dist/src/adapters/hono/index.d.ts +3 -0
  16. package/dist/src/adapters/hono/middleware.d.ts +13 -0
  17. package/dist/src/adapters/next/index.d.ts +3 -0
  18. package/dist/src/adapters/next/serve.d.ts +20 -0
  19. package/dist/src/adapters/node/index.d.ts +4 -0
  20. package/dist/src/adapters/node/rpc-handler.d.ts +10 -0
  21. package/dist/src/adapters/node/types.d.ts +21 -0
  22. package/dist/src/adapters/node/utils.d.ts +5 -0
  23. package/dist/src/adapters/standard/handler.d.ts +47 -0
  24. package/dist/src/adapters/standard/index.d.ts +7 -0
  25. package/dist/src/adapters/standard/rpc-codec.d.ts +15 -0
  26. package/dist/src/adapters/standard/rpc-handler.d.ts +8 -0
  27. package/dist/src/adapters/standard/rpc-matcher.d.ts +10 -0
  28. package/dist/src/adapters/standard/rpc-serializer.d.ts +16 -0
  29. package/dist/src/adapters/standard/types.d.ts +44 -0
  30. package/dist/src/builder-variants.d.ts +74 -0
  31. package/dist/src/builder.d.ts +52 -30
  32. package/dist/src/config.d.ts +6 -0
  33. package/dist/src/context.d.ts +9 -0
  34. package/dist/src/hidden.d.ts +6 -4
  35. package/dist/src/implementer-procedure.d.ts +30 -0
  36. package/dist/src/implementer-variants.d.ts +17 -0
  37. package/dist/src/implementer.d.ts +28 -0
  38. package/dist/src/index.d.ts +11 -11
  39. package/dist/src/lazy-utils.d.ts +4 -2
  40. package/dist/src/lazy.d.ts +9 -5
  41. package/dist/src/middleware-decorated.d.ts +7 -5
  42. package/dist/src/middleware-utils.d.ts +5 -0
  43. package/dist/src/middleware.d.ts +28 -14
  44. package/dist/src/plugins/base.d.ts +11 -0
  45. package/dist/src/plugins/cors.d.ts +18 -0
  46. package/dist/src/plugins/index.d.ts +4 -0
  47. package/dist/src/plugins/response-headers.d.ts +10 -0
  48. package/dist/src/procedure-client.d.ts +8 -22
  49. package/dist/src/procedure-decorated.d.ts +18 -11
  50. package/dist/src/procedure-utils.d.ts +17 -0
  51. package/dist/src/procedure.d.ts +24 -18
  52. package/dist/src/router-accessible-lazy.d.ts +8 -0
  53. package/dist/src/router-client.d.ts +7 -10
  54. package/dist/src/router.d.ts +25 -12
  55. package/dist/src/utils.d.ts +23 -2
  56. package/dist/standard.js +17 -0
  57. package/package.json +36 -6
  58. package/dist/chunk-37HIYNDO.js +0 -182
  59. package/dist/src/fetch/composite-handler.d.ts +0 -8
  60. package/dist/src/fetch/index.d.ts +0 -6
  61. package/dist/src/fetch/orpc-handler.d.ts +0 -20
  62. package/dist/src/fetch/orpc-payload-codec.d.ts +0 -11
  63. package/dist/src/fetch/orpc-procedure-matcher.d.ts +0 -12
  64. package/dist/src/fetch/super-json.d.ts +0 -12
  65. package/dist/src/fetch/types.d.ts +0 -16
  66. package/dist/src/implementer-chainable.d.ts +0 -10
  67. package/dist/src/lazy-decorated.d.ts +0 -10
  68. package/dist/src/procedure-builder.d.ts +0 -22
  69. package/dist/src/procedure-implementer.d.ts +0 -18
  70. package/dist/src/router-builder.d.ts +0 -29
  71. package/dist/src/router-implementer.d.ts +0 -21
  72. package/dist/src/types.d.ts +0 -12
@@ -0,0 +1,308 @@
1
+ import {
2
+ convertPathToHttpPath,
3
+ createContractedProcedure,
4
+ createProcedureClient,
5
+ eachContractProcedure,
6
+ getRouterChild,
7
+ isProcedure,
8
+ unlazy
9
+ } from "./chunk-NOA3GBJQ.js";
10
+ import {
11
+ CompositePlugin
12
+ } from "./chunk-OXB4YX67.js";
13
+
14
+ // src/adapters/standard/handler.ts
15
+ import { toORPCError } from "@orpc/contract";
16
+ import { intercept, trim } from "@orpc/shared";
17
+ var StandardHandler = class {
18
+ constructor(router, matcher, codec, options = {}) {
19
+ this.matcher = matcher;
20
+ this.codec = codec;
21
+ this.options = options;
22
+ this.plugin = new CompositePlugin(options?.plugins);
23
+ this.plugin.init(this.options);
24
+ this.matcher.init(router);
25
+ }
26
+ plugin;
27
+ handle(request, ...[options]) {
28
+ const handleOptions = options ?? {};
29
+ handleOptions.context ??= {};
30
+ return intercept(
31
+ this.options.interceptorsRoot ?? [],
32
+ { request, ...handleOptions },
33
+ async (interceptorRootOptions) => {
34
+ try {
35
+ return await intercept(
36
+ this.options.interceptors ?? [],
37
+ interceptorRootOptions,
38
+ async ({ request: request2, context }) => {
39
+ const method = request2.method;
40
+ const url = request2.url;
41
+ const pathname = `/${trim(url.pathname.replace(options?.prefix ?? "", ""), "/")}`;
42
+ const match = await this.matcher.match(method, pathname);
43
+ if (!match) {
44
+ return { matched: false, response: void 0 };
45
+ }
46
+ const client = createProcedureClient(match.procedure, {
47
+ context,
48
+ path: match.path
49
+ });
50
+ const input = await this.codec.decode(request2, match.params, match.procedure);
51
+ const output = await client(input, { signal: request2.signal });
52
+ const response = this.codec.encode(output, match.procedure);
53
+ return {
54
+ matched: true,
55
+ response
56
+ };
57
+ }
58
+ );
59
+ } catch (e) {
60
+ const error = toORPCError(e);
61
+ const response = this.codec.encodeError(error);
62
+ return {
63
+ matched: true,
64
+ response
65
+ };
66
+ }
67
+ }
68
+ );
69
+ }
70
+ };
71
+
72
+ // src/adapters/standard/rpc-serializer.ts
73
+ import { findDeepMatches, isPlainObject, set } from "@orpc/shared";
74
+ var RPCSerializer = class {
75
+ serialize(data) {
76
+ if (data instanceof Blob) {
77
+ return data;
78
+ }
79
+ const serializedJSON = serializeRPCJson(data);
80
+ const { maps, values: blobs } = findDeepMatches((v) => v instanceof Blob, serializedJSON.json);
81
+ if (blobs.length === 0) {
82
+ return serializedJSON;
83
+ }
84
+ const form = new FormData();
85
+ form.set("data", JSON.stringify(serializedJSON));
86
+ form.set("maps", JSON.stringify(maps));
87
+ for (const i in blobs) {
88
+ form.set(i, blobs[i]);
89
+ }
90
+ return form;
91
+ }
92
+ deserialize(serialized) {
93
+ if (serialized instanceof Blob) {
94
+ return serialized;
95
+ }
96
+ if (!(serialized instanceof FormData)) {
97
+ return deserializeRPCJson(serialized);
98
+ }
99
+ const data = JSON.parse(serialized.get("data"));
100
+ const maps = JSON.parse(serialized.get("maps"));
101
+ for (const i in maps) {
102
+ data.json = set(data.json, maps[i], serialized.get(i));
103
+ }
104
+ return deserializeRPCJson(data);
105
+ }
106
+ };
107
+ function serializeRPCJson(value, segments = [], meta = []) {
108
+ if (typeof value === "bigint") {
109
+ meta.push(["bigint", segments]);
110
+ return { json: value.toString(), meta };
111
+ }
112
+ if (value instanceof Date) {
113
+ meta.push(["date", segments]);
114
+ const data = Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString();
115
+ return { json: data, meta };
116
+ }
117
+ if (Number.isNaN(value)) {
118
+ meta.push(["nan", segments]);
119
+ return { json: "NaN", meta };
120
+ }
121
+ if (value instanceof RegExp) {
122
+ meta.push(["regexp", segments]);
123
+ return { json: value.toString(), meta };
124
+ }
125
+ if (value instanceof URL) {
126
+ meta.push(["url", segments]);
127
+ return { json: value.toString(), meta };
128
+ }
129
+ if (isPlainObject(value)) {
130
+ const json = {};
131
+ for (const k in value) {
132
+ json[k] = serializeRPCJson(value[k], [...segments, k], meta).json;
133
+ }
134
+ return { json, meta };
135
+ }
136
+ if (Array.isArray(value)) {
137
+ const json = value.map((v, i) => {
138
+ if (v === void 0) {
139
+ meta.push(["undefined", [...segments, i]]);
140
+ return null;
141
+ }
142
+ return serializeRPCJson(v, [...segments, i], meta).json;
143
+ });
144
+ return { json, meta };
145
+ }
146
+ if (value instanceof Set) {
147
+ const result = serializeRPCJson(Array.from(value), segments, meta);
148
+ meta.push(["set", segments]);
149
+ return result;
150
+ }
151
+ if (value instanceof Map) {
152
+ const result = serializeRPCJson(Array.from(value.entries()), segments, meta);
153
+ meta.push(["map", segments]);
154
+ return result;
155
+ }
156
+ return { json: value, meta };
157
+ }
158
+ function deserializeRPCJson({
159
+ json,
160
+ meta
161
+ }) {
162
+ if (meta.length === 0) {
163
+ return json;
164
+ }
165
+ const ref = { data: json };
166
+ for (const [type, segments] of meta) {
167
+ let currentRef = ref;
168
+ let preSegment = "data";
169
+ for (let i = 0; i < segments.length; i++) {
170
+ currentRef = currentRef[preSegment];
171
+ preSegment = segments[i];
172
+ }
173
+ switch (type) {
174
+ case "nan":
175
+ currentRef[preSegment] = Number.NaN;
176
+ break;
177
+ case "bigint":
178
+ currentRef[preSegment] = BigInt(currentRef[preSegment]);
179
+ break;
180
+ case "date":
181
+ currentRef[preSegment] = new Date(currentRef[preSegment]);
182
+ break;
183
+ case "regexp": {
184
+ const [, pattern, flags] = currentRef[preSegment].match(/^\/(.*)\/([a-z]*)$/);
185
+ currentRef[preSegment] = new RegExp(pattern, flags);
186
+ break;
187
+ }
188
+ case "url":
189
+ currentRef[preSegment] = new URL(currentRef[preSegment]);
190
+ break;
191
+ case "undefined":
192
+ currentRef[preSegment] = void 0;
193
+ break;
194
+ case "map":
195
+ currentRef[preSegment] = new Map(currentRef[preSegment]);
196
+ break;
197
+ case "set":
198
+ currentRef[preSegment] = new Set(currentRef[preSegment]);
199
+ break;
200
+ /* v8 ignore next 3 */
201
+ default: {
202
+ const _expected = type;
203
+ }
204
+ }
205
+ }
206
+ return ref.data;
207
+ }
208
+
209
+ // src/adapters/standard/rpc-codec.ts
210
+ var RPCCodec = class {
211
+ serializer;
212
+ constructor(options = {}) {
213
+ this.serializer = options.serializer ?? new RPCSerializer();
214
+ }
215
+ async decode(request, _params, _procedure) {
216
+ const serialized = request.method === "GET" ? JSON.parse(request.url.searchParams.getAll("data").at(-1)) : await request.body();
217
+ return this.serializer.deserialize(serialized);
218
+ }
219
+ encode(output, _procedure) {
220
+ return {
221
+ status: 200,
222
+ headers: {},
223
+ body: this.serializer.serialize(output)
224
+ };
225
+ }
226
+ encodeError(error) {
227
+ return {
228
+ status: error.status,
229
+ headers: {},
230
+ body: this.serializer.serialize(error.toJSON())
231
+ };
232
+ }
233
+ };
234
+
235
+ // src/adapters/standard/rpc-matcher.ts
236
+ var RPCMatcher = class {
237
+ tree = {};
238
+ pendingRouters = [];
239
+ init(router, path = []) {
240
+ const laziedOptions = eachContractProcedure({
241
+ router,
242
+ path
243
+ }, ({ path: path2, contract }) => {
244
+ const httpPath = convertPathToHttpPath(path2);
245
+ if (isProcedure(contract)) {
246
+ this.tree[httpPath] = {
247
+ path: path2,
248
+ contract,
249
+ procedure: contract,
250
+ // this mean dev not used contract-first so we can used contract as procedure directly
251
+ router
252
+ };
253
+ } else {
254
+ this.tree[httpPath] = {
255
+ path: path2,
256
+ contract,
257
+ procedure: void 0,
258
+ router
259
+ };
260
+ }
261
+ });
262
+ this.pendingRouters.push(...laziedOptions.map((option) => ({
263
+ ...option,
264
+ httpPathPrefix: convertPathToHttpPath(option.path)
265
+ })));
266
+ }
267
+ async match(_method, pathname) {
268
+ if (this.pendingRouters.length) {
269
+ const newPendingRouters = [];
270
+ for (const pendingRouter of this.pendingRouters) {
271
+ if (pathname.startsWith(pendingRouter.httpPathPrefix)) {
272
+ const { default: router } = await unlazy(pendingRouter.lazied);
273
+ this.init(router, pendingRouter.path);
274
+ } else {
275
+ newPendingRouters.push(pendingRouter);
276
+ }
277
+ }
278
+ this.pendingRouters = newPendingRouters;
279
+ }
280
+ const match = this.tree[pathname];
281
+ if (!match) {
282
+ return void 0;
283
+ }
284
+ if (!match.procedure) {
285
+ const { default: maybeProcedure } = await unlazy(getRouterChild(match.router, ...match.path));
286
+ if (!isProcedure(maybeProcedure)) {
287
+ throw new Error(`
288
+ [Contract-First] Missing or invalid implementation for procedure at path: ${convertPathToHttpPath(match.path)}.
289
+ Ensure that the procedure is correctly defined and matches the expected contract.
290
+ `);
291
+ }
292
+ match.procedure = createContractedProcedure(match.contract, maybeProcedure);
293
+ }
294
+ return {
295
+ path: match.path,
296
+ procedure: match.procedure
297
+ };
298
+ }
299
+ };
300
+
301
+ export {
302
+ StandardHandler,
303
+ RPCSerializer,
304
+ serializeRPCJson,
305
+ RPCCodec,
306
+ RPCMatcher
307
+ };
308
+ //# sourceMappingURL=chunk-CVIWJKJC.js.map
@@ -0,0 +1,136 @@
1
+ import {
2
+ RPCCodec,
3
+ RPCMatcher,
4
+ StandardHandler
5
+ } from "./chunk-CVIWJKJC.js";
6
+
7
+ // src/adapters/fetch/utils.ts
8
+ import { once } from "@orpc/shared";
9
+ import cd from "content-disposition";
10
+ function fetchHeadersToStandardHeaders(headers) {
11
+ const standardHeaders = {};
12
+ for (const [key, value] of headers) {
13
+ if (Array.isArray(standardHeaders[key])) {
14
+ standardHeaders[key].push(value);
15
+ } else if (standardHeaders[key] !== void 0) {
16
+ standardHeaders[key] = [standardHeaders[key], value];
17
+ } else {
18
+ standardHeaders[key] = value;
19
+ }
20
+ }
21
+ return standardHeaders;
22
+ }
23
+ async function fetchReToStandardBody(re) {
24
+ if (!re.body) {
25
+ return void 0;
26
+ }
27
+ const contentDisposition = re.headers.get("content-disposition");
28
+ const fileName = contentDisposition ? cd.parse(contentDisposition).parameters.filename : void 0;
29
+ if (fileName) {
30
+ const blob2 = await re.blob();
31
+ return new File([blob2], fileName, {
32
+ type: blob2.type
33
+ });
34
+ }
35
+ const contentType = re.headers.get("content-type");
36
+ if (!contentType || contentType.startsWith("application/json")) {
37
+ const text = await re.text();
38
+ if (!text) {
39
+ return void 0;
40
+ }
41
+ return JSON.parse(text);
42
+ }
43
+ if (contentType.startsWith("multipart/form-data")) {
44
+ return await re.formData();
45
+ }
46
+ if (contentType.startsWith("application/x-www-form-urlencoded")) {
47
+ return new URLSearchParams(await re.text());
48
+ }
49
+ if (contentType.startsWith("text/")) {
50
+ return await re.text();
51
+ }
52
+ const blob = await re.blob();
53
+ return new File([blob], "blob", {
54
+ type: blob.type
55
+ });
56
+ }
57
+ function fetchRequestToStandardRequest(request) {
58
+ const url = new URL(request.url);
59
+ return {
60
+ raw: { request },
61
+ url,
62
+ signal: request.signal,
63
+ method: request.method,
64
+ body: once(() => {
65
+ return fetchReToStandardBody(request);
66
+ }),
67
+ get headers() {
68
+ const headers = fetchHeadersToStandardHeaders(request.headers);
69
+ Object.defineProperty(this, "headers", { value: headers, writable: true });
70
+ return headers;
71
+ },
72
+ set headers(value) {
73
+ Object.defineProperty(this, "headers", { value, writable: true });
74
+ }
75
+ };
76
+ }
77
+ function standardResponseToFetchHeaders(response) {
78
+ const fetchHeaders = new Headers();
79
+ for (const [key, value] of Object.entries(response.headers)) {
80
+ if (Array.isArray(value)) {
81
+ for (const v of value) {
82
+ fetchHeaders.append(key, v);
83
+ }
84
+ } else if (value !== void 0) {
85
+ fetchHeaders.append(key, value);
86
+ }
87
+ }
88
+ if (response.body instanceof Blob && !fetchHeaders.has("content-disposition")) {
89
+ fetchHeaders.set("content-disposition", cd(response.body instanceof File ? response.body.name : "blob"));
90
+ } else if (!(response.body instanceof Blob) && !(response.body instanceof URLSearchParams) && !(response.body instanceof FormData) && response.body !== void 0 && !fetchHeaders.has("content-type")) {
91
+ fetchHeaders.set("content-type", "application/json");
92
+ }
93
+ return fetchHeaders;
94
+ }
95
+ function standardBodyToFetchBody(body) {
96
+ if (body instanceof Blob || body instanceof FormData || body instanceof URLSearchParams) {
97
+ return body;
98
+ }
99
+ return JSON.stringify(body);
100
+ }
101
+ function standardResponseToFetchResponse(response) {
102
+ return new Response(standardBodyToFetchBody(response.body), {
103
+ headers: standardResponseToFetchHeaders(response),
104
+ status: response.status
105
+ });
106
+ }
107
+
108
+ // src/adapters/fetch/rpc-handler.ts
109
+ var RPCHandler = class {
110
+ standardHandler;
111
+ constructor(router, options) {
112
+ const matcher = options?.matcher ?? new RPCMatcher();
113
+ const codec = options?.codec ?? new RPCCodec();
114
+ this.standardHandler = new StandardHandler(router, matcher, codec, options);
115
+ }
116
+ async handle(request, ...rest) {
117
+ const standardRequest = fetchRequestToStandardRequest(request);
118
+ const result = await this.standardHandler.handle(standardRequest, ...rest);
119
+ if (!result.matched) {
120
+ return result;
121
+ }
122
+ return {
123
+ matched: true,
124
+ response: standardResponseToFetchResponse(result.response)
125
+ };
126
+ }
127
+ };
128
+
129
+ export {
130
+ fetchReToStandardBody,
131
+ fetchRequestToStandardRequest,
132
+ standardBodyToFetchBody,
133
+ standardResponseToFetchResponse,
134
+ RPCHandler
135
+ };
136
+ //# sourceMappingURL=chunk-EYGVJA7A.js.map