@orpc/server 0.0.0-next.c6c659d → 0.0.0-next.ccd4e42

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