@orpc/server 0.0.0-next.649534d → 0.0.0-next.67ca77c

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
1
7
  // src/utils.ts
2
8
  function mergeContext(a, b) {
3
9
  if (!a)
@@ -168,6 +174,7 @@ function getRouterChild(router, ...path) {
168
174
  }
169
175
 
170
176
  export {
177
+ __export,
171
178
  mergeContext,
172
179
  Procedure,
173
180
  isProcedure,
@@ -179,4 +186,4 @@ export {
179
186
  createProcedureClient,
180
187
  getRouterChild
181
188
  };
182
- //# sourceMappingURL=chunk-37HIYNDO.js.map
189
+ //# sourceMappingURL=chunk-6A7XHEBH.js.map
@@ -0,0 +1,303 @@
1
+ import {
2
+ __export,
3
+ createProcedureClient,
4
+ getRouterChild,
5
+ isProcedure,
6
+ unlazy
7
+ } from "./chunk-6A7XHEBH.js";
8
+
9
+ // src/adapters/fetch/super-json.ts
10
+ var super_json_exports = {};
11
+ __export(super_json_exports, {
12
+ deserialize: () => deserialize,
13
+ serialize: () => serialize
14
+ });
15
+
16
+ // ../../node_modules/.pnpm/is-what@5.0.2/node_modules/is-what/dist/getType.js
17
+ function getType(payload) {
18
+ return Object.prototype.toString.call(payload).slice(8, -1);
19
+ }
20
+
21
+ // ../../node_modules/.pnpm/is-what@5.0.2/node_modules/is-what/dist/isPlainObject.js
22
+ function isPlainObject(payload) {
23
+ if (getType(payload) !== "Object")
24
+ return false;
25
+ const prototype = Object.getPrototypeOf(payload);
26
+ return !!prototype && prototype.constructor === Object && prototype === Object.prototype;
27
+ }
28
+
29
+ // src/adapters/fetch/super-json.ts
30
+ function serialize(value, segments = [], meta = []) {
31
+ if (typeof value === "bigint") {
32
+ meta.push(["bigint", segments]);
33
+ return { data: value.toString(), meta };
34
+ }
35
+ if (value instanceof Date) {
36
+ meta.push(["date", segments]);
37
+ const data = Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString();
38
+ return { data, meta };
39
+ }
40
+ if (Number.isNaN(value)) {
41
+ meta.push(["nan", segments]);
42
+ return { data: "NaN", meta };
43
+ }
44
+ if (value instanceof RegExp) {
45
+ meta.push(["regexp", segments]);
46
+ return { data: value.toString(), meta };
47
+ }
48
+ if (value instanceof URL) {
49
+ meta.push(["url", segments]);
50
+ return { data: value.toString(), meta };
51
+ }
52
+ if (isPlainObject(value)) {
53
+ const data = {};
54
+ for (const k in value) {
55
+ data[k] = serialize(value[k], [...segments, k], meta).data;
56
+ }
57
+ return { data, meta };
58
+ }
59
+ if (Array.isArray(value)) {
60
+ const data = value.map((v, i) => {
61
+ if (v === void 0) {
62
+ meta.push(["undefined", [...segments, i]]);
63
+ return null;
64
+ }
65
+ return serialize(v, [...segments, i], meta).data;
66
+ });
67
+ return { data, meta };
68
+ }
69
+ if (value instanceof Set) {
70
+ const result = serialize(Array.from(value), segments, meta);
71
+ meta.push(["set", segments]);
72
+ return result;
73
+ }
74
+ if (value instanceof Map) {
75
+ const result = serialize(Array.from(value.entries()), segments, meta);
76
+ meta.push(["map", segments]);
77
+ return result;
78
+ }
79
+ return { data: value, meta };
80
+ }
81
+ function deserialize({
82
+ data,
83
+ meta
84
+ }) {
85
+ if (meta.length === 0) {
86
+ return data;
87
+ }
88
+ const ref = { data };
89
+ for (const [type, segments] of meta) {
90
+ let currentRef = ref;
91
+ let preSegment = "data";
92
+ for (let i = 0; i < segments.length; i++) {
93
+ currentRef = currentRef[preSegment];
94
+ preSegment = segments[i];
95
+ }
96
+ switch (type) {
97
+ case "nan":
98
+ currentRef[preSegment] = Number.NaN;
99
+ break;
100
+ case "bigint":
101
+ currentRef[preSegment] = BigInt(currentRef[preSegment]);
102
+ break;
103
+ case "date":
104
+ currentRef[preSegment] = new Date(currentRef[preSegment]);
105
+ break;
106
+ case "regexp": {
107
+ const [, pattern, flags] = currentRef[preSegment].match(/^\/(.*)\/([a-z]*)$/);
108
+ currentRef[preSegment] = new RegExp(pattern, flags);
109
+ break;
110
+ }
111
+ case "url":
112
+ currentRef[preSegment] = new URL(currentRef[preSegment]);
113
+ break;
114
+ case "undefined":
115
+ currentRef[preSegment] = void 0;
116
+ break;
117
+ case "map":
118
+ currentRef[preSegment] = new Map(currentRef[preSegment]);
119
+ break;
120
+ case "set":
121
+ currentRef[preSegment] = new Set(currentRef[preSegment]);
122
+ break;
123
+ /* v8 ignore next 3 */
124
+ default: {
125
+ const _expected = type;
126
+ }
127
+ }
128
+ }
129
+ return ref.data;
130
+ }
131
+
132
+ // src/adapters/fetch/orpc-payload-codec.ts
133
+ import { findDeepMatches, set } from "@orpc/shared";
134
+ import { ORPCError } from "@orpc/shared/error";
135
+ var ORPCPayloadCodec = class {
136
+ /**
137
+ * If method is GET, the payload will be encoded as query string.
138
+ * If method is GET and payload contain file, the method will be fallback to fallbackMethod. (fallbackMethod = GET will force to use GET method)
139
+ */
140
+ encode(payload, method = "POST", fallbackMethod = "POST") {
141
+ const { data, meta } = serialize(payload);
142
+ const { maps, values } = findDeepMatches((v) => v instanceof Blob, data);
143
+ if (method === "GET" && (values.length === 0 || fallbackMethod === "GET")) {
144
+ const query = new URLSearchParams({
145
+ data: JSON.stringify(data),
146
+ meta: JSON.stringify(meta)
147
+ });
148
+ return {
149
+ query,
150
+ method: "GET"
151
+ };
152
+ }
153
+ const nonGETMethod = method === "GET" ? fallbackMethod : method;
154
+ if (values.length > 0) {
155
+ const form = new FormData();
156
+ if (data !== void 0) {
157
+ form.append("data", JSON.stringify(data));
158
+ }
159
+ form.append("meta", JSON.stringify(meta));
160
+ form.append("maps", JSON.stringify(maps));
161
+ for (const i in values) {
162
+ const value = values[i];
163
+ form.append(i, value);
164
+ }
165
+ return {
166
+ body: form,
167
+ method: nonGETMethod
168
+ };
169
+ }
170
+ return {
171
+ body: JSON.stringify({ data, meta }),
172
+ headers: new Headers({
173
+ "content-type": "application/json"
174
+ }),
175
+ method: nonGETMethod
176
+ };
177
+ }
178
+ async decode(re) {
179
+ try {
180
+ if ("method" in re && re.method === "GET") {
181
+ const url = new URL(re.url);
182
+ const query = url.searchParams;
183
+ const data = JSON.parse(query.getAll("data").at(-1));
184
+ const meta = JSON.parse(query.getAll("meta").at(-1));
185
+ return deserialize({
186
+ data,
187
+ meta
188
+ });
189
+ }
190
+ if (re.headers.get("content-type")?.startsWith("multipart/form-data")) {
191
+ const form = await re.formData();
192
+ const rawData = form.get("data");
193
+ const rawMeta = form.get("meta");
194
+ const rawMaps = form.get("maps");
195
+ let data = JSON.parse(rawData);
196
+ const meta = JSON.parse(rawMeta);
197
+ const maps = JSON.parse(rawMaps);
198
+ for (const i in maps) {
199
+ data = set(data, maps[i], form.get(i));
200
+ }
201
+ return deserialize({
202
+ data,
203
+ meta
204
+ });
205
+ }
206
+ const json = await re.json();
207
+ return deserialize(json);
208
+ } catch (e) {
209
+ throw new ORPCError({
210
+ code: "BAD_REQUEST",
211
+ message: "Cannot parse request/response. Please check the request/response body and Content-Type header.",
212
+ cause: e
213
+ });
214
+ }
215
+ }
216
+ };
217
+
218
+ // src/adapters/fetch/orpc-procedure-matcher.ts
219
+ import { trim } from "@orpc/shared";
220
+ var ORPCProcedureMatcher = class {
221
+ constructor(router) {
222
+ this.router = router;
223
+ }
224
+ async match(pathname) {
225
+ const path = trim(pathname, "/").split("/").map(decodeURIComponent);
226
+ const match = getRouterChild(this.router, ...path);
227
+ const { default: maybeProcedure } = await unlazy(match);
228
+ if (!isProcedure(maybeProcedure)) {
229
+ return void 0;
230
+ }
231
+ return {
232
+ procedure: maybeProcedure,
233
+ path
234
+ };
235
+ }
236
+ };
237
+
238
+ // src/adapters/fetch/orpc-handler.ts
239
+ import { executeWithHooks, ORPC_HANDLER_HEADER, ORPC_HANDLER_VALUE, trim as trim2 } from "@orpc/shared";
240
+ import { ORPCError as ORPCError2 } from "@orpc/shared/error";
241
+ var ORPCHandler = class {
242
+ constructor(router, options) {
243
+ this.router = router;
244
+ this.options = options;
245
+ this.procedureMatcher = options?.procedureMatcher ?? new ORPCProcedureMatcher(router);
246
+ this.payloadCodec = options?.payloadCodec ?? new ORPCPayloadCodec();
247
+ }
248
+ procedureMatcher;
249
+ payloadCodec;
250
+ condition(request) {
251
+ return Boolean(request.headers.get(ORPC_HANDLER_HEADER)?.includes(ORPC_HANDLER_VALUE));
252
+ }
253
+ async fetch(request, ...[options]) {
254
+ const context = options?.context;
255
+ const execute = async () => {
256
+ const url = new URL(request.url);
257
+ const pathname = `/${trim2(url.pathname.replace(options?.prefix ?? "", ""), "/")}`;
258
+ const match = await this.procedureMatcher.match(pathname);
259
+ if (!match) {
260
+ throw new ORPCError2({ code: "NOT_FOUND", message: "Not found" });
261
+ }
262
+ const input = await this.payloadCodec.decode(request);
263
+ const client = createProcedureClient({
264
+ context,
265
+ procedure: match.procedure,
266
+ path: match.path
267
+ });
268
+ const output = await client(input, { signal: options?.signal });
269
+ const { body, headers } = this.payloadCodec.encode(output);
270
+ return new Response(body, { headers });
271
+ };
272
+ try {
273
+ return await executeWithHooks({
274
+ context,
275
+ execute,
276
+ input: request,
277
+ hooks: this.options,
278
+ meta: {
279
+ signal: options?.signal
280
+ }
281
+ });
282
+ } catch (e) {
283
+ const error = e instanceof ORPCError2 ? e : new ORPCError2({
284
+ code: "INTERNAL_SERVER_ERROR",
285
+ message: "Internal server error",
286
+ cause: e
287
+ });
288
+ const { body, headers } = this.payloadCodec.encode(error.toJSON());
289
+ return new Response(body, {
290
+ headers,
291
+ status: error.status
292
+ });
293
+ }
294
+ }
295
+ };
296
+
297
+ export {
298
+ super_json_exports,
299
+ ORPCPayloadCodec,
300
+ ORPCProcedureMatcher,
301
+ ORPCHandler
302
+ };
303
+ //# sourceMappingURL=chunk-B2EZJB7X.js.map
package/dist/fetch.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import {
2
- createProcedureClient,
3
- getRouterChild,
4
- isProcedure,
5
- unlazy
6
- } from "./chunk-37HIYNDO.js";
2
+ ORPCHandler,
3
+ ORPCPayloadCodec,
4
+ ORPCProcedureMatcher,
5
+ super_json_exports
6
+ } from "./chunk-B2EZJB7X.js";
7
+ import "./chunk-6A7XHEBH.js";
7
8
 
8
- // src/fetch/composite-handler.ts
9
+ // src/adapters/fetch/composite-handler.ts
9
10
  var CompositeHandler = class {
10
11
  constructor(handlers) {
11
12
  this.handlers = handlers;
@@ -21,295 +22,11 @@ var CompositeHandler = class {
21
22
  });
22
23
  }
23
24
  };
24
-
25
- // src/fetch/orpc-handler.ts
26
- import { executeWithHooks, ORPC_HANDLER_HEADER, ORPC_HANDLER_VALUE, trim as trim2 } from "@orpc/shared";
27
- import { ORPCError as ORPCError2 } from "@orpc/shared/error";
28
-
29
- // src/fetch/orpc-payload-codec.ts
30
- import { findDeepMatches, set } from "@orpc/shared";
31
- import { ORPCError } from "@orpc/shared/error";
32
-
33
- // ../../node_modules/.pnpm/is-what@5.0.2/node_modules/is-what/dist/getType.js
34
- function getType(payload) {
35
- return Object.prototype.toString.call(payload).slice(8, -1);
36
- }
37
-
38
- // ../../node_modules/.pnpm/is-what@5.0.2/node_modules/is-what/dist/isPlainObject.js
39
- function isPlainObject(payload) {
40
- if (getType(payload) !== "Object")
41
- return false;
42
- const prototype = Object.getPrototypeOf(payload);
43
- return !!prototype && prototype.constructor === Object && prototype === Object.prototype;
44
- }
45
-
46
- // src/fetch/super-json.ts
47
- function serialize(value, segments = [], meta = []) {
48
- if (typeof value === "bigint") {
49
- meta.push(["bigint", segments]);
50
- return { data: value.toString(), meta };
51
- }
52
- if (value instanceof Date) {
53
- meta.push(["date", segments]);
54
- const data = Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString();
55
- return { data, meta };
56
- }
57
- if (Number.isNaN(value)) {
58
- meta.push(["nan", segments]);
59
- return { data: "NaN", meta };
60
- }
61
- if (value instanceof RegExp) {
62
- meta.push(["regexp", segments]);
63
- return { data: value.toString(), meta };
64
- }
65
- if (value instanceof URL) {
66
- meta.push(["url", segments]);
67
- return { data: value.toString(), meta };
68
- }
69
- if (isPlainObject(value)) {
70
- const data = {};
71
- for (const k in value) {
72
- data[k] = serialize(value[k], [...segments, k], meta).data;
73
- }
74
- return { data, meta };
75
- }
76
- if (Array.isArray(value)) {
77
- const data = value.map((v, i) => {
78
- if (v === void 0) {
79
- meta.push(["undefined", [...segments, i]]);
80
- return null;
81
- }
82
- return serialize(v, [...segments, i], meta).data;
83
- });
84
- return { data, meta };
85
- }
86
- if (value instanceof Set) {
87
- const result = serialize(Array.from(value), segments, meta);
88
- meta.push(["set", segments]);
89
- return result;
90
- }
91
- if (value instanceof Map) {
92
- const result = serialize(Array.from(value.entries()), segments, meta);
93
- meta.push(["map", segments]);
94
- return result;
95
- }
96
- return { data: value, meta };
97
- }
98
- function deserialize({
99
- data,
100
- meta
101
- }) {
102
- if (meta.length === 0) {
103
- return data;
104
- }
105
- const ref = { data };
106
- for (const [type, segments] of meta) {
107
- let currentRef = ref;
108
- let preSegment = "data";
109
- for (let i = 0; i < segments.length; i++) {
110
- currentRef = currentRef[preSegment];
111
- preSegment = segments[i];
112
- }
113
- switch (type) {
114
- case "nan":
115
- currentRef[preSegment] = Number.NaN;
116
- break;
117
- case "bigint":
118
- currentRef[preSegment] = BigInt(currentRef[preSegment]);
119
- break;
120
- case "date":
121
- currentRef[preSegment] = new Date(currentRef[preSegment]);
122
- break;
123
- case "regexp": {
124
- const [, pattern, flags] = currentRef[preSegment].match(/^\/(.*)\/([a-z]*)$/);
125
- currentRef[preSegment] = new RegExp(pattern, flags);
126
- break;
127
- }
128
- case "url":
129
- currentRef[preSegment] = new URL(currentRef[preSegment]);
130
- break;
131
- case "undefined":
132
- currentRef[preSegment] = void 0;
133
- break;
134
- case "map":
135
- currentRef[preSegment] = new Map(currentRef[preSegment]);
136
- break;
137
- case "set":
138
- currentRef[preSegment] = new Set(currentRef[preSegment]);
139
- break;
140
- /* v8 ignore next 3 */
141
- default: {
142
- const _expected = type;
143
- }
144
- }
145
- }
146
- return ref.data;
147
- }
148
-
149
- // src/fetch/orpc-payload-codec.ts
150
- var ORPCPayloadCodec = class {
151
- /**
152
- * If method is GET, the payload will be encoded as query string.
153
- * If method is GET and payload contain file, the method will be fallback to fallbackMethod. (fallbackMethod = GET will force to use GET method)
154
- */
155
- encode(payload, method = "POST", fallbackMethod = "POST") {
156
- const { data, meta } = serialize(payload);
157
- const { maps, values } = findDeepMatches((v) => v instanceof Blob, data);
158
- if (method === "GET" && (values.length === 0 || fallbackMethod === "GET")) {
159
- const query = new URLSearchParams({
160
- data: JSON.stringify(data),
161
- meta: JSON.stringify(meta)
162
- });
163
- return {
164
- query,
165
- method: "GET"
166
- };
167
- }
168
- const nonGETMethod = method === "GET" ? fallbackMethod : method;
169
- if (values.length > 0) {
170
- const form = new FormData();
171
- if (data !== void 0) {
172
- form.append("data", JSON.stringify(data));
173
- }
174
- form.append("meta", JSON.stringify(meta));
175
- form.append("maps", JSON.stringify(maps));
176
- for (const i in values) {
177
- const value = values[i];
178
- form.append(i, value);
179
- }
180
- return {
181
- body: form,
182
- method: nonGETMethod
183
- };
184
- }
185
- return {
186
- body: JSON.stringify({ data, meta }),
187
- headers: new Headers({
188
- "content-type": "application/json"
189
- }),
190
- method: nonGETMethod
191
- };
192
- }
193
- async decode(re) {
194
- try {
195
- if ("method" in re && re.method === "GET") {
196
- const url = new URL(re.url);
197
- const query = url.searchParams;
198
- const data = JSON.parse(query.getAll("data").at(-1));
199
- const meta = JSON.parse(query.getAll("meta").at(-1));
200
- return deserialize({
201
- data,
202
- meta
203
- });
204
- }
205
- if (re.headers.get("content-type")?.startsWith("multipart/form-data")) {
206
- const form = await re.formData();
207
- const rawData = form.get("data");
208
- const rawMeta = form.get("meta");
209
- const rawMaps = form.get("maps");
210
- let data = JSON.parse(rawData);
211
- const meta = JSON.parse(rawMeta);
212
- const maps = JSON.parse(rawMaps);
213
- for (const i in maps) {
214
- data = set(data, maps[i], form.get(i));
215
- }
216
- return deserialize({
217
- data,
218
- meta
219
- });
220
- }
221
- const json = await re.json();
222
- return deserialize(json);
223
- } catch (e) {
224
- throw new ORPCError({
225
- code: "BAD_REQUEST",
226
- message: "Cannot parse request/response. Please check the request/response body and Content-Type header.",
227
- cause: e
228
- });
229
- }
230
- }
231
- };
232
-
233
- // src/fetch/orpc-procedure-matcher.ts
234
- import { trim } from "@orpc/shared";
235
- var ORPCProcedureMatcher = class {
236
- constructor(router) {
237
- this.router = router;
238
- }
239
- async match(pathname) {
240
- const path = trim(pathname, "/").split("/").map(decodeURIComponent);
241
- const match = getRouterChild(this.router, ...path);
242
- const { default: maybeProcedure } = await unlazy(match);
243
- if (!isProcedure(maybeProcedure)) {
244
- return void 0;
245
- }
246
- return {
247
- procedure: maybeProcedure,
248
- path
249
- };
250
- }
251
- };
252
-
253
- // src/fetch/orpc-handler.ts
254
- var ORPCHandler = class {
255
- constructor(router, options) {
256
- this.router = router;
257
- this.options = options;
258
- this.procedureMatcher = options?.procedureMatcher ?? new ORPCProcedureMatcher(router);
259
- this.payloadCodec = options?.payloadCodec ?? new ORPCPayloadCodec();
260
- }
261
- procedureMatcher;
262
- payloadCodec;
263
- condition(request) {
264
- return Boolean(request.headers.get(ORPC_HANDLER_HEADER)?.includes(ORPC_HANDLER_VALUE));
265
- }
266
- async fetch(request, ...[options]) {
267
- const context = options?.context;
268
- const execute = async () => {
269
- const url = new URL(request.url);
270
- const pathname = `/${trim2(url.pathname.replace(options?.prefix ?? "", ""), "/")}`;
271
- const match = await this.procedureMatcher.match(pathname);
272
- if (!match) {
273
- throw new ORPCError2({ code: "NOT_FOUND", message: "Not found" });
274
- }
275
- const input = await this.payloadCodec.decode(request);
276
- const client = createProcedureClient({
277
- context,
278
- procedure: match.procedure,
279
- path: match.path
280
- });
281
- const output = await client(input, { signal: options?.signal });
282
- const { body, headers } = this.payloadCodec.encode(output);
283
- return new Response(body, { headers });
284
- };
285
- try {
286
- return await executeWithHooks({
287
- context,
288
- execute,
289
- input: request,
290
- hooks: this.options,
291
- meta: {
292
- signal: options?.signal
293
- }
294
- });
295
- } catch (e) {
296
- const error = e instanceof ORPCError2 ? e : new ORPCError2({
297
- code: "INTERNAL_SERVER_ERROR",
298
- message: "Internal server error",
299
- cause: e
300
- });
301
- const { body, headers } = this.payloadCodec.encode(error.toJSON());
302
- return new Response(body, {
303
- headers,
304
- status: error.status
305
- });
306
- }
307
- }
308
- };
309
25
  export {
310
26
  CompositeHandler,
311
27
  ORPCHandler,
312
28
  ORPCPayloadCodec,
313
- ORPCProcedureMatcher
29
+ ORPCProcedureMatcher,
30
+ super_json_exports as SuperJSON
314
31
  };
315
32
  //# sourceMappingURL=fetch.js.map
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  lazy,
10
10
  mergeContext,
11
11
  unlazy
12
- } from "./chunk-37HIYNDO.js";
12
+ } from "./chunk-6A7XHEBH.js";
13
13
 
14
14
  // src/builder.ts
15
15
  import { ContractProcedure } from "@orpc/contract";
@@ -486,6 +486,7 @@ function createRouterClient(options) {
486
486
  }
487
487
 
488
488
  // src/index.ts
489
+ import { configGlobal, fallbackToGlobalConfig } from "@orpc/contract";
489
490
  export * from "@orpc/shared/error";
490
491
  var os = new Builder({});
491
492
  export {
@@ -496,6 +497,7 @@ export {
496
497
  ProcedureImplementer,
497
498
  RouterBuilder,
498
499
  RouterImplementer,
500
+ configGlobal,
499
501
  createChainableImplementer,
500
502
  createProcedureClient,
501
503
  createRouterClient,
@@ -503,6 +505,7 @@ export {
503
505
  decorateMiddleware,
504
506
  decorateProcedure,
505
507
  deepSetLazyRouterPrefix,
508
+ fallbackToGlobalConfig,
506
509
  flatLazy,
507
510
  getLazyRouterPrefix,
508
511
  getRouterChild,
package/dist/node.js ADDED
@@ -0,0 +1,45 @@
1
+ import {
2
+ ORPCHandler
3
+ } from "./chunk-B2EZJB7X.js";
4
+ import "./chunk-6A7XHEBH.js";
5
+
6
+ // src/adapters/node/composite-handler.ts
7
+ var CompositeHandler = class {
8
+ constructor(handlers) {
9
+ this.handlers = handlers;
10
+ }
11
+ async handle(req, res, ...opt) {
12
+ for (const handler of this.handlers) {
13
+ if (handler.condition(req)) {
14
+ return handler.handle(req, res, ...opt);
15
+ }
16
+ }
17
+ res.statusCode = 404;
18
+ res.end("None of the handlers can handle the request.");
19
+ }
20
+ };
21
+
22
+ // src/adapters/node/orpc-handler.ts
23
+ import { createRequest, sendResponse } from "@mjackson/node-fetch-server";
24
+ import { ORPC_HANDLER_HEADER, ORPC_HANDLER_VALUE } from "@orpc/shared";
25
+ var ORPCHandler2 = class {
26
+ orpcFetchHandler;
27
+ constructor(router, options) {
28
+ this.orpcFetchHandler = new ORPCHandler(router, options);
29
+ }
30
+ condition(request) {
31
+ return Boolean(request.headers[ORPC_HANDLER_HEADER]?.includes(ORPC_HANDLER_VALUE));
32
+ }
33
+ async handle(req, res, ...[options]) {
34
+ const request = createRequest(req, res, options);
35
+ const castedOptions = options ?? {};
36
+ const response = await this.orpcFetchHandler.fetch(request, castedOptions);
37
+ await options?.beforeSend?.(response, castedOptions.context);
38
+ return await sendResponse(res, response);
39
+ }
40
+ };
41
+ export {
42
+ CompositeHandler,
43
+ ORPCHandler2 as ORPCHandler
44
+ };
45
+ //# sourceMappingURL=node.js.map
@@ -1,4 +1,4 @@
1
- import type { Context } from '../types';
1
+ import type { Context } from '../../types';
2
2
  import type { ConditionalFetchHandler, FetchHandler, FetchOptions } from './types';
3
3
  export declare class CompositeHandler<T extends Context> implements FetchHandler<T> {
4
4
  private readonly handlers;
@@ -2,5 +2,6 @@ export * from './composite-handler';
2
2
  export * from './orpc-handler';
3
3
  export * from './orpc-payload-codec';
4
4
  export * from './orpc-procedure-matcher';
5
+ export * as SuperJSON from './super-json';
5
6
  export * from './types';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import type { Hooks } from '@orpc/shared';
2
- import type { Router } from '../router';
3
- import type { Context, WithSignal } from '../types';
2
+ import type { Router } from '../../router';
3
+ import type { Context, WithSignal } from '../../types';
4
4
  import type { ConditionalFetchHandler, FetchOptions } from './types';
5
5
  import { type PublicORPCPayloadCodec } from './orpc-payload-codec';
6
6
  import { type PublicORPCProcedureMatcher } from './orpc-procedure-matcher';
@@ -1,5 +1,5 @@
1
- import type { ANY_PROCEDURE } from '../procedure';
2
- import { type ANY_ROUTER } from '../router';
1
+ import type { ANY_PROCEDURE } from '../../procedure';
2
+ import { type ANY_ROUTER } from '../../router';
3
3
  export declare class ORPCProcedureMatcher {
4
4
  private readonly router;
5
5
  constructor(router: ANY_ROUTER);
@@ -1,5 +1,5 @@
1
1
  import type { HTTPPath } from '@orpc/contract';
2
- import type { Context, WithSignal } from '../types';
2
+ import type { Context, WithSignal } from '../../types';
3
3
  export type FetchOptions<T extends Context> = WithSignal & {
4
4
  prefix?: HTTPPath;
5
5
  } & (undefined extends T ? {
@@ -0,0 +1,9 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { Context } from '../../types';
3
+ import type { ConditionalRequestHandler, RequestHandler, RequestOptions } from './types';
4
+ export declare class CompositeHandler<T extends Context> implements RequestHandler<T> {
5
+ private readonly handlers;
6
+ constructor(handlers: ConditionalRequestHandler<T>[]);
7
+ handle(req: IncomingMessage, res: ServerResponse, ...opt: [options: RequestOptions<T>] | (undefined extends T ? [] : never)): Promise<void>;
8
+ }
9
+ //# sourceMappingURL=composite-handler.d.ts.map
@@ -0,0 +1,5 @@
1
+ export * from './composite-handler';
2
+ export * from './orpc-handler';
3
+ export * from './orpc-handler';
4
+ export * from './types';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { Router } from '../../router';
3
+ import type { Context } from '../../types';
4
+ import type { ORPCHandlerOptions } from '../fetch/orpc-handler';
5
+ import type { ConditionalRequestHandler, RequestOptions } from './types';
6
+ export declare class ORPCHandler<T extends Context> implements ConditionalRequestHandler<T> {
7
+ private readonly orpcFetchHandler;
8
+ constructor(router: Router<T, any>, options?: NoInfer<ORPCHandlerOptions<T>>);
9
+ condition(request: IncomingMessage): boolean;
10
+ handle(req: IncomingMessage, res: ServerResponse, ...[options]: [options: RequestOptions<T>] | (undefined extends T ? [] : never)): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=orpc-handler.d.ts.map
@@ -0,0 +1,21 @@
1
+ import type { RequestOptions as BaseRequestOptions } from '@mjackson/node-fetch-server';
2
+ import type { HTTPPath } from '@orpc/contract';
3
+ import type { Promisable } from '@orpc/shared';
4
+ import type { IncomingMessage, ServerResponse } from 'node:http';
5
+ import type { Context, WithSignal } from '../../types';
6
+ export type RequestOptions<T extends Context> = BaseRequestOptions & WithSignal & {
7
+ prefix?: HTTPPath;
8
+ } & (undefined extends T ? {
9
+ context?: T;
10
+ } : {
11
+ context: T;
12
+ }) & {
13
+ beforeSend?: (response: Response, context: T) => Promisable<void>;
14
+ };
15
+ export interface RequestHandler<T extends Context> {
16
+ handle: (req: IncomingMessage, res: ServerResponse, ...opt: [options: RequestOptions<T>] | (undefined extends T ? [] : never)) => void;
17
+ }
18
+ export interface ConditionalRequestHandler<T extends Context> extends RequestHandler<T> {
19
+ condition: (request: IncomingMessage) => boolean;
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -18,6 +18,7 @@ export * from './router-client';
18
18
  export * from './router-implementer';
19
19
  export * from './types';
20
20
  export * from './utils';
21
+ export { configGlobal, fallbackToGlobalConfig } from '@orpc/contract';
21
22
  export * from '@orpc/shared/error';
22
23
  export declare const os: Builder<WELL_CONTEXT, undefined>;
23
24
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/server",
3
3
  "type": "module",
4
- "version": "0.0.0-next.649534d",
4
+ "version": "0.0.0-next.67ca77c",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -20,10 +20,15 @@
20
20
  "default": "./dist/index.js"
21
21
  },
22
22
  "./fetch": {
23
- "types": "./dist/src/fetch/index.d.ts",
23
+ "types": "./dist/src/adapters/fetch/index.d.ts",
24
24
  "import": "./dist/fetch.js",
25
25
  "default": "./dist/fetch.js"
26
26
  },
27
+ "./node": {
28
+ "types": "./dist/src/adapters/node/index.d.ts",
29
+ "import": "./dist/node.js",
30
+ "default": "./dist/node.js"
31
+ },
27
32
  "./🔒/*": {
28
33
  "types": "./dist/src/*.d.ts"
29
34
  }
@@ -34,14 +39,15 @@
34
39
  "dist"
35
40
  ],
36
41
  "dependencies": {
37
- "@orpc/contract": "0.0.0-next.649534d",
38
- "@orpc/shared": "0.0.0-next.649534d"
42
+ "@mjackson/node-fetch-server": "^0.5.0",
43
+ "@orpc/contract": "0.0.0-next.67ca77c",
44
+ "@orpc/shared": "0.0.0-next.67ca77c"
39
45
  },
40
46
  "devDependencies": {
41
47
  "zod": "^3.24.1"
42
48
  },
43
49
  "scripts": {
44
- "build": "tsup --clean --sourcemap --entry.index=src/index.ts --entry.fetch=src/fetch/index.ts --format=esm --onSuccess='tsc -b --noCheck'",
50
+ "build": "tsup --clean --sourcemap --entry.index=src/index.ts --entry.fetch=src/adapters/fetch/index.ts --entry.node=src/adapters/node/index.ts --format=esm --onSuccess='tsc -b --noCheck'",
45
51
  "build:watch": "pnpm run build --watch",
46
52
  "type:check": "tsc -b"
47
53
  }