@orpc/server 0.12.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,272 @@
1
+ // src/utils.ts
2
+ function mergeContext(a, b) {
3
+ if (!a)
4
+ return b;
5
+ if (!b)
6
+ return a;
7
+ return {
8
+ ...a,
9
+ ...b
10
+ };
11
+ }
12
+
13
+ // src/middleware.ts
14
+ var decoratedMiddlewareSymbol = Symbol("\u{1F512}decoratedMiddleware");
15
+ function decorateMiddleware(middleware) {
16
+ if (Reflect.get(middleware, decoratedMiddlewareSymbol)) {
17
+ return middleware;
18
+ }
19
+ const concat = (concatMiddleware, mapInput2) => {
20
+ const concatMiddleware_ = mapInput2 ? decorateMiddleware(concatMiddleware).mapInput(mapInput2) : concatMiddleware;
21
+ return decorateMiddleware(async (input, context, meta, ...rest) => {
22
+ const input_ = input;
23
+ const context_ = context;
24
+ const meta_ = meta;
25
+ const next = async (options) => {
26
+ return concatMiddleware_(input_, mergeContext(context_, options.context), meta_, ...rest);
27
+ };
28
+ const m1 = await middleware(input_, context_, {
29
+ ...meta_,
30
+ next
31
+ }, ...rest);
32
+ return m1;
33
+ });
34
+ };
35
+ const mapInput = (map) => {
36
+ return decorateMiddleware(
37
+ (input, ...rest) => middleware(map(input), ...rest)
38
+ );
39
+ };
40
+ return Object.assign(middleware, {
41
+ [decoratedMiddlewareSymbol]: true,
42
+ concat,
43
+ mapInput
44
+ });
45
+ }
46
+
47
+ // src/procedure-caller.ts
48
+ import { executeWithHooks, trim, value } from "@orpc/shared";
49
+ import { ORPCError } from "@orpc/shared/error";
50
+
51
+ // src/procedure.ts
52
+ import {
53
+ DecoratedContractProcedure,
54
+ isContractProcedure
55
+ } from "@orpc/contract";
56
+ var Procedure = class {
57
+ constructor(zz$p) {
58
+ this.zz$p = zz$p;
59
+ }
60
+ };
61
+ var DECORATED_PROCEDURE_SYMBOL = Symbol("DECORATED_PROCEDURE");
62
+ function decorateProcedure(procedure) {
63
+ if (DECORATED_PROCEDURE_SYMBOL in procedure) {
64
+ return procedure;
65
+ }
66
+ return Object.assign(createProcedureCaller({
67
+ procedure,
68
+ context: void 0
69
+ }), {
70
+ [DECORATED_PROCEDURE_SYMBOL]: true,
71
+ zz$p: procedure.zz$p,
72
+ prefix(prefix) {
73
+ return decorateProcedure({
74
+ zz$p: {
75
+ ...procedure.zz$p,
76
+ contract: DecoratedContractProcedure.decorate(
77
+ procedure.zz$p.contract
78
+ ).prefix(prefix)
79
+ }
80
+ });
81
+ },
82
+ route(opts) {
83
+ return decorateProcedure({
84
+ zz$p: {
85
+ ...procedure.zz$p,
86
+ contract: DecoratedContractProcedure.decorate(
87
+ procedure.zz$p.contract
88
+ ).route(opts)
89
+ }
90
+ });
91
+ },
92
+ use(middleware, mapInput) {
93
+ const middleware_ = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
94
+ return decorateProcedure({
95
+ zz$p: {
96
+ ...procedure.zz$p,
97
+ middlewares: [middleware_, ...procedure.zz$p.middlewares ?? []]
98
+ }
99
+ });
100
+ }
101
+ });
102
+ }
103
+ function isProcedure(item) {
104
+ if (item instanceof Procedure)
105
+ return true;
106
+ return (typeof item === "object" || typeof item === "function") && item !== null && "zz$p" in item && typeof item.zz$p === "object" && item.zz$p !== null && "contract" in item.zz$p && isContractProcedure(item.zz$p.contract) && "func" in item.zz$p && typeof item.zz$p.func === "function";
107
+ }
108
+
109
+ // src/procedure-caller.ts
110
+ function createProcedureCaller(options) {
111
+ const caller = async (input) => {
112
+ const path = options.path ?? [];
113
+ const procedure = await loadProcedure(options.procedure);
114
+ const context = await value(options.context);
115
+ const execute = async () => {
116
+ const validInput = (() => {
117
+ const schema = procedure.zz$p.contract.zz$cp.InputSchema;
118
+ if (!schema) {
119
+ return input;
120
+ }
121
+ try {
122
+ return schema.parse(input);
123
+ } catch (e) {
124
+ throw new ORPCError({
125
+ message: "Validation input failed",
126
+ code: "BAD_REQUEST",
127
+ cause: e
128
+ });
129
+ }
130
+ })();
131
+ const middlewares = procedure.zz$p.middlewares ?? [];
132
+ let currentMidIndex = 0;
133
+ let currentContext = context;
134
+ const next = async (nextOptions) => {
135
+ const mid = middlewares[currentMidIndex];
136
+ currentMidIndex += 1;
137
+ currentContext = mergeContext(currentContext, nextOptions.context);
138
+ if (mid) {
139
+ return await mid(validInput, currentContext, {
140
+ path,
141
+ procedure,
142
+ next,
143
+ output: (output3) => ({ output: output3, context: void 0 })
144
+ });
145
+ } else {
146
+ return {
147
+ output: await await procedure.zz$p.func(validInput, currentContext, {
148
+ path,
149
+ procedure
150
+ }),
151
+ context: currentContext
152
+ };
153
+ }
154
+ };
155
+ const output2 = (await next({})).output;
156
+ const validOutput = await (async () => {
157
+ const schema = procedure.zz$p.contract.zz$cp.OutputSchema;
158
+ if (!schema) {
159
+ return output2;
160
+ }
161
+ const result = await schema.safeParseAsync(output2);
162
+ if (result.error) {
163
+ throw new ORPCError({
164
+ message: "Validation output failed",
165
+ code: "INTERNAL_SERVER_ERROR",
166
+ cause: result.error
167
+ });
168
+ }
169
+ return result.data;
170
+ })();
171
+ return validOutput;
172
+ };
173
+ const output = await executeWithHooks({
174
+ hooks: options,
175
+ input,
176
+ context,
177
+ meta: {
178
+ path,
179
+ procedure
180
+ },
181
+ execute
182
+ });
183
+ return output;
184
+ };
185
+ return caller;
186
+ }
187
+ async function loadProcedure(procedure) {
188
+ let loadedProcedure;
189
+ if (isLazy(procedure)) {
190
+ loadedProcedure = (await loadLazy(procedure)).default;
191
+ } else {
192
+ loadedProcedure = procedure;
193
+ }
194
+ if (!isProcedure(loadedProcedure)) {
195
+ throw new ORPCError({
196
+ code: "NOT_FOUND",
197
+ message: "Not found",
198
+ cause: new Error(trim(`
199
+ This error should be caught by the typescript compiler.
200
+ But if you still see this error, it means that you trying to call a lazy router (expected to be a lazy procedure).
201
+ `))
202
+ });
203
+ }
204
+ return loadedProcedure;
205
+ }
206
+
207
+ // src/lazy.ts
208
+ var LAZY_LOADER_SYMBOL = Symbol("ORPC_LAZY_LOADER");
209
+ function createLazy(loader) {
210
+ return {
211
+ [LAZY_LOADER_SYMBOL]: loader
212
+ };
213
+ }
214
+ function loadLazy(lazy) {
215
+ return lazy[LAZY_LOADER_SYMBOL]();
216
+ }
217
+ function isLazy(item) {
218
+ return (typeof item === "object" || typeof item === "function") && item !== null && LAZY_LOADER_SYMBOL in item && typeof item[LAZY_LOADER_SYMBOL] === "function";
219
+ }
220
+ function createFlattenLazy(lazy) {
221
+ const flattenLoader = async () => {
222
+ let current = await loadLazy(lazy);
223
+ while (true) {
224
+ if (!isLazy(current.default)) {
225
+ break;
226
+ }
227
+ current = await loadLazy(current.default);
228
+ }
229
+ return current;
230
+ };
231
+ const flattenLazy = {
232
+ [LAZY_LOADER_SYMBOL]: flattenLoader
233
+ };
234
+ return flattenLazy;
235
+ }
236
+ function decorateLazy(lazy) {
237
+ const flattenLazy = createFlattenLazy(lazy);
238
+ const procedureCaller = createProcedureCaller({
239
+ procedure: flattenLazy,
240
+ context: void 0
241
+ });
242
+ Object.assign(procedureCaller, flattenLazy);
243
+ const recursive = new Proxy(procedureCaller, {
244
+ get(target, key) {
245
+ if (typeof key !== "string") {
246
+ return Reflect.get(target, key);
247
+ }
248
+ return decorateLazy(createLazy(async () => {
249
+ const current = await loadLazy(flattenLazy);
250
+ return { default: current.default[key] };
251
+ }));
252
+ }
253
+ });
254
+ return recursive;
255
+ }
256
+
257
+ export {
258
+ mergeContext,
259
+ decorateMiddleware,
260
+ LAZY_LOADER_SYMBOL,
261
+ createLazy,
262
+ loadLazy,
263
+ isLazy,
264
+ createFlattenLazy,
265
+ decorateLazy,
266
+ createProcedureCaller,
267
+ loadProcedure,
268
+ Procedure,
269
+ decorateProcedure,
270
+ isProcedure
271
+ };
272
+ //# sourceMappingURL=chunk-MZXEMHFS.js.map
package/dist/fetch.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  createProcedureCaller,
3
+ isLazy,
3
4
  isProcedure
4
- } from "./chunk-CVLK2PBB.js";
5
+ } from "./chunk-MZXEMHFS.js";
5
6
 
6
7
  // src/fetch/handle.ts
7
8
  import { ORPCError } from "@orpc/shared/error";
@@ -23,7 +24,7 @@ async function handleFetchRequest(options) {
23
24
 
24
25
  // src/fetch/handler.ts
25
26
  import { ORPC_HEADER, ORPC_HEADER_VALUE } from "@orpc/contract";
26
- import { trim, value } from "@orpc/shared";
27
+ import { executeWithHooks, trim, value } from "@orpc/shared";
27
28
  import { ORPCError as ORPCError2 } from "@orpc/shared/error";
28
29
  import { ORPCDeserializer, ORPCSerializer } from "@orpc/transformer";
29
30
  var serializer = new ORPCSerializer();
@@ -55,10 +56,13 @@ function createORPCHandler() {
55
56
  });
56
57
  };
57
58
  try {
58
- return await options.hooks?.(
59
+ return await executeWithHooks({
60
+ hooks: options,
59
61
  context,
60
- { next: handler, response: (response) => response }
61
- ) ?? await handler();
62
+ execute: handler,
63
+ input: options.request,
64
+ meta: void 0
65
+ });
62
66
  } catch (e) {
63
67
  const error = e instanceof ORPCError2 ? e : new ORPCError2({
64
68
  code: "INTERNAL_SERVER_ERROR",
@@ -77,13 +81,13 @@ function resolveORPCRouter(router, pathname) {
77
81
  const path = trim(pathname, "/").split("/").map(decodeURIComponent);
78
82
  let current = router;
79
83
  for (const segment of path) {
80
- if ((typeof current !== "object" || current === null) && typeof current !== "function") {
84
+ if (typeof current !== "object" && typeof current !== "function" || !current) {
81
85
  current = void 0;
82
86
  break;
83
87
  }
84
88
  current = current[segment];
85
89
  }
86
- return isProcedure(current) ? {
90
+ return isProcedure(current) || isLazy(current) ? {
87
91
  procedure: current,
88
92
  path
89
93
  } : void 0;
@@ -103,3 +107,4 @@ export {
103
107
  createORPCHandler,
104
108
  handleFetchRequest
105
109
  };
110
+ //# sourceMappingURL=fetch.js.map
package/dist/index.js CHANGED
@@ -1,11 +1,18 @@
1
1
  import {
2
+ LAZY_LOADER_SYMBOL,
2
3
  Procedure,
4
+ createFlattenLazy,
5
+ createLazy,
3
6
  createProcedureCaller,
7
+ decorateLazy,
4
8
  decorateMiddleware,
5
9
  decorateProcedure,
10
+ isLazy,
6
11
  isProcedure,
12
+ loadLazy,
13
+ loadProcedure,
7
14
  mergeContext
8
- } from "./chunk-CVLK2PBB.js";
15
+ } from "./chunk-MZXEMHFS.js";
9
16
 
10
17
  // src/builder.ts
11
18
  import {
@@ -15,9 +22,138 @@ import {
15
22
 
16
23
  // src/procedure-builder.ts
17
24
  import {
18
- DecoratedContractProcedure
25
+ DecoratedContractProcedure as DecoratedContractProcedure2
19
26
  } from "@orpc/contract";
20
27
 
28
+ // src/router-builder.ts
29
+ import { DecoratedContractProcedure, prefixHTTPPath } from "@orpc/contract";
30
+ var LAZY_ROUTER_PREFIX_SYMBOL = Symbol("ORPC_LAZY_ROUTER_PREFIX");
31
+ var RouterBuilder = class _RouterBuilder {
32
+ constructor(zz$rb) {
33
+ this.zz$rb = zz$rb;
34
+ if (zz$rb.prefix && zz$rb.prefix.includes("{")) {
35
+ throw new Error('Prefix cannot contain "{" for dynamic routing');
36
+ }
37
+ }
38
+ prefix(prefix) {
39
+ return new _RouterBuilder({
40
+ ...this.zz$rb,
41
+ prefix: `${this.zz$rb.prefix ?? ""}${prefix}`
42
+ });
43
+ }
44
+ tags(...tags) {
45
+ if (!tags.length)
46
+ return this;
47
+ return new _RouterBuilder({
48
+ ...this.zz$rb,
49
+ tags: [...this.zz$rb.tags ?? [], ...tags]
50
+ });
51
+ }
52
+ use(middleware, mapInput) {
53
+ const middleware_ = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
54
+ return new _RouterBuilder({
55
+ ...this.zz$rb,
56
+ middlewares: [...this.zz$rb.middlewares || [], middleware_]
57
+ });
58
+ }
59
+ router(router) {
60
+ const handled = adaptRouter({
61
+ routerOrChild: router,
62
+ middlewares: this.zz$rb.middlewares,
63
+ tags: this.zz$rb.tags,
64
+ prefix: this.zz$rb.prefix
65
+ });
66
+ return handled;
67
+ }
68
+ lazy(loader) {
69
+ const lazy = adaptLazyRouter({
70
+ current: createLazy(loader),
71
+ middlewares: this.zz$rb.middlewares,
72
+ tags: this.zz$rb.tags,
73
+ prefix: this.zz$rb.prefix
74
+ });
75
+ return lazy;
76
+ }
77
+ };
78
+ function adaptRouter(options) {
79
+ if (isProcedure(options.routerOrChild)) {
80
+ return adaptProcedure({
81
+ ...options,
82
+ procedure: options.routerOrChild
83
+ });
84
+ }
85
+ if (isLazy(options.routerOrChild)) {
86
+ return adaptLazyRouter({
87
+ ...options,
88
+ current: options.routerOrChild
89
+ });
90
+ }
91
+ const handled = {};
92
+ for (const key in options.routerOrChild) {
93
+ handled[key] = adaptRouter({
94
+ ...options,
95
+ routerOrChild: options.routerOrChild[key]
96
+ });
97
+ }
98
+ return handled;
99
+ }
100
+ function adaptLazyRouter(options) {
101
+ const loader = async () => {
102
+ const current = (await loadLazy(options.current)).default;
103
+ return {
104
+ default: adaptRouter({
105
+ ...options,
106
+ routerOrChild: current
107
+ })
108
+ };
109
+ };
110
+ let lazyRouterPrefix = options.prefix;
111
+ if (LAZY_ROUTER_PREFIX_SYMBOL in options.current && typeof options.current[LAZY_ROUTER_PREFIX_SYMBOL] === "string") {
112
+ lazyRouterPrefix = lazyRouterPrefix ? prefixHTTPPath(options.current[LAZY_ROUTER_PREFIX_SYMBOL], lazyRouterPrefix) : options.current[LAZY_ROUTER_PREFIX_SYMBOL];
113
+ }
114
+ const decoratedLazy = Object.assign(decorateLazy(createLazy(loader)), {
115
+ [LAZY_ROUTER_PREFIX_SYMBOL]: lazyRouterPrefix
116
+ });
117
+ const recursive = new Proxy(decoratedLazy, {
118
+ get(target, key) {
119
+ if (typeof key !== "string") {
120
+ return Reflect.get(target, key);
121
+ }
122
+ return adaptLazyRouter({
123
+ ...options,
124
+ current: createLazy(async () => {
125
+ const current = (await loadLazy(options.current)).default;
126
+ return { default: current[key] };
127
+ })
128
+ });
129
+ }
130
+ });
131
+ return recursive;
132
+ }
133
+ function adaptProcedure(options) {
134
+ const builderMiddlewares = options.middlewares ?? [];
135
+ const procedureMiddlewares = options.procedure.zz$p.middlewares ?? [];
136
+ const middlewares = [
137
+ ...builderMiddlewares,
138
+ ...procedureMiddlewares.filter(
139
+ (item) => !builderMiddlewares.includes(item)
140
+ )
141
+ ];
142
+ let contract = DecoratedContractProcedure.decorate(
143
+ options.procedure.zz$p.contract
144
+ ).addTags(...options.tags ?? []);
145
+ if (options.prefix) {
146
+ contract = contract.prefix(options.prefix);
147
+ }
148
+ return decorateProcedure({
149
+ zz$p: {
150
+ ...options.procedure.zz$p,
151
+ contract,
152
+ middlewares
153
+ }
154
+ });
155
+ }
156
+
21
157
  // src/procedure-implementer.ts
22
158
  var ProcedureImplementer = class _ProcedureImplementer {
23
159
  constructor(zz$pi) {
@@ -39,6 +175,9 @@ var ProcedureImplementer = class _ProcedureImplementer {
39
175
  }
40
176
  });
41
177
  }
178
+ lazy(loader) {
179
+ return new RouterBuilder(this.zz$pi).lazy(loader);
180
+ }
42
181
  };
43
182
 
44
183
  // src/procedure-builder.ts
@@ -52,7 +191,7 @@ var ProcedureBuilder = class _ProcedureBuilder {
52
191
  route(opts) {
53
192
  return new _ProcedureBuilder({
54
193
  ...this.zz$pb,
55
- contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).route(
194
+ contract: DecoratedContractProcedure2.decorate(this.zz$pb.contract).route(
56
195
  opts
57
196
  )
58
197
  });
@@ -60,7 +199,7 @@ var ProcedureBuilder = class _ProcedureBuilder {
60
199
  input(schema, example) {
61
200
  return new _ProcedureBuilder({
62
201
  ...this.zz$pb,
63
- contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).input(
202
+ contract: DecoratedContractProcedure2.decorate(this.zz$pb.contract).input(
64
203
  schema,
65
204
  example
66
205
  )
@@ -69,7 +208,7 @@ var ProcedureBuilder = class _ProcedureBuilder {
69
208
  output(schema, example) {
70
209
  return new _ProcedureBuilder({
71
210
  ...this.zz$pb,
72
- contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).output(
211
+ contract: DecoratedContractProcedure2.decorate(this.zz$pb.contract).output(
73
212
  schema,
74
213
  example
75
214
  )
@@ -101,75 +240,24 @@ var ProcedureBuilder = class _ProcedureBuilder {
101
240
  }
102
241
  };
103
242
 
104
- // src/router-builder.ts
105
- import { DecoratedContractProcedure as DecoratedContractProcedure2 } from "@orpc/contract";
106
- var RouterBuilder = class _RouterBuilder {
107
- constructor(zz$rb) {
108
- this.zz$rb = zz$rb;
109
- }
110
- prefix(prefix) {
111
- return new _RouterBuilder({
112
- ...this.zz$rb,
113
- prefix: `${this.zz$rb.prefix ?? ""}${prefix}`
114
- });
115
- }
116
- tags(...tags) {
117
- if (!tags.length)
118
- return this;
119
- return new _RouterBuilder({
120
- ...this.zz$rb,
121
- tags: [...this.zz$rb.tags ?? [], ...tags]
122
- });
123
- }
124
- use(middleware, mapInput) {
125
- const middleware_ = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
126
- return new _RouterBuilder({
127
- ...this.zz$rb,
128
- middlewares: [...this.zz$rb.middlewares || [], middleware_]
129
- });
130
- }
131
- router(router) {
132
- const handled = {};
133
- for (const key in router) {
134
- const item = router[key];
135
- if (isProcedure(item)) {
136
- const builderMiddlewares = this.zz$rb.middlewares ?? [];
137
- const itemMiddlewares = item.zz$p.middlewares ?? [];
138
- const middlewares = [
139
- ...builderMiddlewares,
140
- ...itemMiddlewares.filter(
141
- (item2) => !builderMiddlewares.includes(item2)
142
- )
143
- ];
144
- const contract = DecoratedContractProcedure2.decorate(
145
- item.zz$p.contract
146
- ).addTags(...this.zz$rb.tags ?? []);
147
- handled[key] = decorateProcedure({
148
- zz$p: {
149
- ...item.zz$p,
150
- contract: this.zz$rb.prefix ? contract.prefix(this.zz$rb.prefix) : contract,
151
- middlewares
152
- }
153
- });
154
- } else {
155
- handled[key] = this.router(item);
156
- }
157
- }
158
- return handled;
159
- }
160
- };
161
-
162
243
  // src/router-implementer.ts
163
- import {
164
- isContractProcedure
165
- } from "@orpc/contract";
244
+ import { isContractProcedure } from "@orpc/contract";
245
+ var ROUTER_CONTRACT_SYMBOL = Symbol("ORPC_ROUTER_CONTRACT");
166
246
  var RouterImplementer = class {
167
247
  constructor(zz$ri) {
168
248
  this.zz$ri = zz$ri;
169
249
  }
170
250
  router(router) {
171
- assertRouterImplementation(this.zz$ri.contract, router);
172
- return router;
251
+ return Object.assign(new RouterBuilder({}).router(router), {
252
+ [ROUTER_CONTRACT_SYMBOL]: this.zz$ri.contract
253
+ });
254
+ }
255
+ lazy(loader) {
256
+ const lazy = createLazy(loader);
257
+ const decorated = decorateLazy(lazy);
258
+ return Object.assign(decorated, {
259
+ [ROUTER_CONTRACT_SYMBOL]: this.zz$ri.contract
260
+ });
173
261
  }
174
262
  };
175
263
  function chainRouterImplementer(contract, middlewares) {
@@ -188,37 +276,6 @@ function chainRouterImplementer(contract, middlewares) {
188
276
  const implementer = new RouterImplementer({ contract });
189
277
  return Object.assign(implementer, result);
190
278
  }
191
- function assertRouterImplementation(contract, router, path = []) {
192
- for (const key in contract) {
193
- const currentPath = [...path, key];
194
- const contractItem = contract[key];
195
- const routerItem = router[key];
196
- if (!routerItem) {
197
- throw new Error(
198
- `Missing implementation for procedure at [${currentPath.join(".")}]`
199
- );
200
- }
201
- if (isContractProcedure(contractItem)) {
202
- if (isProcedure(routerItem)) {
203
- if (routerItem.zz$p.contract !== contractItem) {
204
- throw new Error(
205
- `Mismatch implementation for procedure at [${currentPath.join(".")}]`
206
- );
207
- }
208
- } else {
209
- throw new Error(
210
- `Mismatch implementation for procedure at [${currentPath.join(".")}]`
211
- );
212
- }
213
- } else {
214
- assertRouterImplementation(
215
- contractItem,
216
- routerItem,
217
- currentPath
218
- );
219
- }
220
- }
221
- }
222
279
 
223
280
  // src/builder.ts
224
281
  var Builder = class _Builder {
@@ -327,6 +384,9 @@ var Builder = class _Builder {
327
384
  router(router) {
328
385
  return new RouterBuilder(this.zz$b).router(router);
329
386
  }
387
+ lazy(loader) {
388
+ return new RouterBuilder(this.zz$b).lazy(loader);
389
+ }
330
390
  };
331
391
 
332
392
  // src/router.ts
@@ -350,25 +410,29 @@ function toContractRouter(router) {
350
410
 
351
411
  // src/router-caller.ts
352
412
  function createRouterCaller(options) {
353
- const caller = {};
354
- for (const key in options.router) {
355
- const path = [...options.basePath ?? [], key];
356
- const item = options.router[key];
357
- if (isProcedure(item)) {
358
- caller[key] = createProcedureCaller({
359
- procedure: item,
360
- context: options.context,
361
- path
362
- });
363
- } else {
364
- caller[key] = createRouterCaller({
365
- router: item,
366
- context: options.context,
367
- basePath: path
413
+ return createRouterCallerInternal(options);
414
+ }
415
+ function createRouterCallerInternal(options) {
416
+ const procedureCaller = isLazy(options.router) || isProcedure(options.router) ? createProcedureCaller({
417
+ ...options,
418
+ procedure: options.router,
419
+ context: options.context,
420
+ path: options.basePath
421
+ }) : {};
422
+ const recursive = new Proxy(procedureCaller, {
423
+ get(target, key) {
424
+ if (typeof key !== "string") {
425
+ return Reflect.get(target, key);
426
+ }
427
+ const next = options.router[key];
428
+ return createRouterCallerInternal({
429
+ ...options,
430
+ router: next,
431
+ basePath: [...options.basePath ?? [], key]
368
432
  });
369
433
  }
370
- }
371
- return caller;
434
+ });
435
+ return recursive;
372
436
  }
373
437
 
374
438
  // src/index.ts
@@ -376,18 +440,28 @@ export * from "@orpc/shared/error";
376
440
  var os = new Builder();
377
441
  export {
378
442
  Builder,
443
+ LAZY_LOADER_SYMBOL,
444
+ LAZY_ROUTER_PREFIX_SYMBOL,
379
445
  Procedure,
380
446
  ProcedureBuilder,
381
447
  ProcedureImplementer,
448
+ ROUTER_CONTRACT_SYMBOL,
449
+ RouterBuilder,
382
450
  RouterImplementer,
383
- assertRouterImplementation,
384
451
  chainRouterImplementer,
452
+ createFlattenLazy,
453
+ createLazy,
385
454
  createProcedureCaller,
386
455
  createRouterCaller,
456
+ decorateLazy,
387
457
  decorateMiddleware,
388
458
  decorateProcedure,
459
+ isLazy,
389
460
  isProcedure,
461
+ loadLazy,
462
+ loadProcedure,
390
463
  mergeContext,
391
464
  os,
392
465
  toContractRouter
393
466
  };
467
+ //# sourceMappingURL=index.js.map
@@ -1,9 +1,10 @@
1
1
  import type { IsEqual } from '@orpc/shared';
2
+ import type { DecoratedLazy } from './lazy';
3
+ import type { DecoratedProcedure, Procedure, ProcedureFunc } from './procedure';
2
4
  import type { HandledRouter, Router } from './router';
3
5
  import type { Context, MergeContext } from './types';
4
6
  import { ContractProcedure, type ContractRouter, type HTTPPath, type RouteOptions, type Schema, type SchemaInput, type SchemaOutput } from '@orpc/contract';
5
7
  import { type DecoratedMiddleware, type MapInputMiddleware, type Middleware } from './middleware';
6
- import { type DecoratedProcedure, type ProcedureFunc } from './procedure';
7
8
  import { ProcedureBuilder } from './procedure-builder';
8
9
  import { ProcedureImplementer } from './procedure-implementer';
9
10
  import { RouterBuilder } from './router-builder';
@@ -45,4 +46,8 @@ export declare class Builder<TContext extends Context, TExtraContext extends Con
45
46
  * Create DecoratedRouter
46
47
  */
47
48
  router<URouter extends Router<TContext>>(router: URouter): HandledRouter<URouter>;
49
+ lazy<U extends Router<TContext> | Procedure<TContext, any, any, any, any>>(loader: () => Promise<{
50
+ default: U;
51
+ }>): DecoratedLazy<U>;
48
52
  }
53
+ //# sourceMappingURL=builder.d.ts.map
@@ -4,3 +4,4 @@ export type HandleFetchRequestOptions<TRouter extends Router<any>> = FetchHandle
4
4
  handlers: readonly [FetchHandler, ...FetchHandler[]];
5
5
  };
6
6
  export declare function handleFetchRequest<TRouter extends Router<any>>(options: HandleFetchRequestOptions<TRouter>): Promise<Response>;
7
+ //# sourceMappingURL=handle.d.ts.map
@@ -1,2 +1,3 @@
1
1
  import type { FetchHandler } from './types';
2
2
  export declare function createORPCHandler(): FetchHandler;
3
+ //# sourceMappingURL=handler.d.ts.map
@@ -1,3 +1,4 @@
1
1
  export * from './handle';
2
2
  export * from './handler';
3
3
  export * from './types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -1,9 +1,5 @@
1
- import type { PartialOnUndefinedDeep, Promisable, Value } from '@orpc/shared';
1
+ import type { Hooks, PartialOnUndefinedDeep, Value } from '@orpc/shared';
2
2
  import type { Router } from '../router';
3
- export interface FetchHandlerHooks {
4
- next: () => Promise<Response>;
5
- response: (response: Response) => Response;
6
- }
7
3
  export type FetchHandlerOptions<TRouter extends Router<any>> = {
8
4
  /**
9
5
  * The `router` used for handling the request and routing,
@@ -21,14 +17,11 @@ export type FetchHandlerOptions<TRouter extends Router<any>> = {
21
17
  * @example /api
22
18
  */
23
19
  prefix?: string;
24
- /**
25
- * Hooks for executing logics on lifecycle events.
26
- */
27
- hooks?: (context: TRouter extends Router<infer UContext> ? UContext : never, hooks: FetchHandlerHooks) => Promisable<Response>;
28
20
  } & PartialOnUndefinedDeep<{
29
21
  /**
30
22
  * The context used to handle the request.
31
23
  */
32
24
  context: Value<TRouter extends Router<infer UContext> ? UContext : never>;
33
- }>;
25
+ }> & Hooks<Request, Response, TRouter extends Router<infer UContext> ? UContext : never, undefined>;
34
26
  export type FetchHandler = <TRouter extends Router<any>>(options: FetchHandlerOptions<TRouter>) => Promise<Response | undefined>;
27
+ //# sourceMappingURL=types.d.ts.map
@@ -1,14 +1,17 @@
1
1
  import { Builder } from './builder';
2
2
  export * from './builder';
3
+ export * from './lazy';
3
4
  export * from './middleware';
4
5
  export * from './procedure';
5
6
  export * from './procedure-builder';
6
7
  export * from './procedure-caller';
7
8
  export * from './procedure-implementer';
8
9
  export * from './router';
10
+ export * from './router-builder';
9
11
  export * from './router-caller';
10
12
  export * from './router-implementer';
11
13
  export * from './types';
12
14
  export * from './utils';
13
15
  export * from '@orpc/shared/error';
14
16
  export declare const os: Builder<Record<string, unknown> | undefined, undefined>;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,23 @@
1
+ import type { Procedure } from './procedure';
2
+ import type { ProcedureCaller } from './procedure-caller';
3
+ export declare const LAZY_LOADER_SYMBOL: unique symbol;
4
+ export interface Lazy<T> {
5
+ [LAZY_LOADER_SYMBOL]: () => Promise<{
6
+ default: T;
7
+ }>;
8
+ }
9
+ export type ANY_LAZY = Lazy<any>;
10
+ export declare function createLazy<T>(loader: () => Promise<{
11
+ default: T;
12
+ }>): Lazy<T>;
13
+ export declare function loadLazy<T>(lazy: Lazy<T>): Promise<{
14
+ default: T;
15
+ }>;
16
+ export declare function isLazy(item: unknown): item is ANY_LAZY;
17
+ export type FlattenLazy<T> = T extends Lazy<infer U> ? FlattenLazy<U> : Lazy<T>;
18
+ export declare function createFlattenLazy<T>(lazy: Lazy<T>): FlattenLazy<T>;
19
+ export type DecoratedLazy<T> = T extends Lazy<infer U> ? DecoratedLazy<U> : (T extends Procedure<infer UContext, any, any, any, any> ? Lazy<T> & (undefined extends UContext ? ProcedureCaller<T> : unknown) : T extends Record<any, any> ? {
20
+ [K in keyof T]: DecoratedLazy<T[K]>;
21
+ } /** Notice: this still a lazy, but type not work when I & Lazy<T>, maybe it's a bug, should improve */ : Lazy<T>);
22
+ export declare function decorateLazy<T>(lazy: Lazy<T>): DecoratedLazy<T>;
23
+ //# sourceMappingURL=lazy.d.ts.map
@@ -23,3 +23,4 @@ export interface DecoratedMiddleware<TContext extends Context, TExtraContext ext
23
23
  mapInput: <UInput = unknown>(map: MapInputMiddleware<UInput, TInput>) => DecoratedMiddleware<TContext, TExtraContext, UInput, TOutput>;
24
24
  }
25
25
  export declare function decorateMiddleware<TContext extends Context, TExtraContext extends Context, TInput, TOutput>(middleware: Middleware<TContext, TExtraContext, TInput, TOutput>): DecoratedMiddleware<TContext, TExtraContext, TInput, TOutput>;
26
+ //# sourceMappingURL=middleware.d.ts.map
@@ -28,3 +28,4 @@ export declare class ProcedureBuilder<TContext extends Context, TExtraContext ex
28
28
  */
29
29
  func<UFuncOutput extends SchemaOutput<TOutputSchema>>(func: ProcedureFunc<TContext, TExtraContext, TInputSchema, TOutputSchema, UFuncOutput>): DecoratedProcedure<TContext, TExtraContext, TInputSchema, TOutputSchema, UFuncOutput>;
30
30
  }
31
+ //# sourceMappingURL=procedure-builder.d.ts.map
@@ -1,18 +1,25 @@
1
1
  import type { SchemaInput, SchemaOutput } from '@orpc/contract';
2
- import type { Procedure } from './procedure';
3
- import { type Value } from '@orpc/shared';
4
- export interface CreateProcedureCallerOptions<TProcedure extends Procedure<any, any, any, any, any>> {
5
- procedure: TProcedure;
6
- /**
7
- * The context used when calling the procedure.
8
- */
9
- context: Value<TProcedure extends Procedure<infer UContext, any, any, any, any> ? UContext : never>;
2
+ import type { Hooks, PartialOnUndefinedDeep, Value } from '@orpc/shared';
3
+ import type { Lazy } from './lazy';
4
+ import type { ANY_LAZY_PROCEDURE, ANY_PROCEDURE, Procedure } from './procedure';
5
+ export type CreateProcedureCallerOptions<T extends ANY_PROCEDURE | ANY_LAZY_PROCEDURE> = T extends Procedure<infer UContext, any, any, infer UOutputSchema, infer UFuncOutput> | Lazy<Procedure<infer UContext, any, any, infer UOutputSchema, infer UFuncOutput>> ? {
6
+ procedure: T;
10
7
  /**
11
8
  * This is helpful for logging and analytics.
12
9
  *
13
10
  * @internal
14
11
  */
15
12
  path?: string[];
16
- }
17
- export type ProcedureCaller<TProcedure extends Procedure<any, any, any, any, any>> = TProcedure extends Procedure<any, any, infer UInputSchema, infer UOutputSchema, infer UFuncOutput> ? (...input: [input: SchemaInput<UInputSchema> | FormData] | (undefined extends SchemaInput<UInputSchema> ? [] : never)) => Promise<SchemaOutput<UOutputSchema, UFuncOutput>> : never;
18
- export declare function createProcedureCaller<TProcedure extends Procedure<any, any, any, any, any>>(options: CreateProcedureCallerOptions<TProcedure>): ProcedureCaller<TProcedure>;
13
+ } & PartialOnUndefinedDeep<{
14
+ /**
15
+ * The context used when calling the procedure.
16
+ */
17
+ context: Value<UContext>;
18
+ }> & Hooks<unknown, SchemaOutput<UOutputSchema, UFuncOutput>, UContext, {
19
+ path: string[];
20
+ procedure: ANY_PROCEDURE;
21
+ }> : never;
22
+ export type ProcedureCaller<TProcedure extends ANY_PROCEDURE | ANY_LAZY_PROCEDURE> = TProcedure extends Procedure<any, any, infer UInputSchema, infer UOutputSchema, infer UFuncOutput> | Lazy<Procedure<any, any, infer UInputSchema, infer UOutputSchema, infer UFuncOutput>> ? (...input: [input: SchemaInput<UInputSchema>] | (undefined extends SchemaInput<UInputSchema> ? [] : never)) => Promise<SchemaOutput<UOutputSchema, UFuncOutput>> : never;
23
+ export declare function createProcedureCaller<TProcedure extends ANY_PROCEDURE | ANY_LAZY_PROCEDURE>(options: CreateProcedureCallerOptions<TProcedure>): ProcedureCaller<TProcedure>;
24
+ export declare function loadProcedure(procedure: ANY_PROCEDURE | ANY_LAZY_PROCEDURE): Promise<ANY_PROCEDURE>;
25
+ //# sourceMappingURL=procedure-caller.d.ts.map
@@ -1,7 +1,8 @@
1
1
  import type { ContractProcedure, Schema, SchemaInput, SchemaOutput } from '@orpc/contract';
2
+ import type { DecoratedLazy } from './lazy';
3
+ import type { DecoratedProcedure, Procedure, ProcedureFunc } from './procedure';
2
4
  import type { Context, MergeContext } from './types';
3
5
  import { type MapInputMiddleware, type Middleware } from './middleware';
4
- import { type DecoratedProcedure, type ProcedureFunc } from './procedure';
5
6
  export declare class ProcedureImplementer<TContext extends Context, TExtraContext extends Context, TInputSchema extends Schema, TOutputSchema extends Schema> {
6
7
  zz$pi: {
7
8
  contract: ContractProcedure<TInputSchema, TOutputSchema>;
@@ -14,4 +15,8 @@ export declare class ProcedureImplementer<TContext extends Context, TExtraContex
14
15
  use<UExtraContext extends Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>> | undefined = undefined>(middleware: Middleware<MergeContext<TContext, TExtraContext>, UExtraContext, SchemaOutput<TInputSchema>, SchemaInput<TOutputSchema>>): ProcedureImplementer<TContext, MergeContext<TExtraContext, UExtraContext>, TInputSchema, TOutputSchema>;
15
16
  use<UExtraContext extends Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>> | undefined = undefined, UMappedInput = unknown>(middleware: Middleware<MergeContext<TContext, TExtraContext>, UExtraContext, UMappedInput, SchemaInput<TOutputSchema>>, mapInput: MapInputMiddleware<SchemaOutput<TInputSchema>, UMappedInput>): ProcedureImplementer<TContext, MergeContext<TExtraContext, UExtraContext>, TInputSchema, TOutputSchema>;
16
17
  func<UFuncOutput extends SchemaOutput<TOutputSchema>>(func: ProcedureFunc<TContext, TExtraContext, TInputSchema, TOutputSchema, UFuncOutput>): DecoratedProcedure<TContext, TExtraContext, TInputSchema, TOutputSchema, UFuncOutput>;
18
+ lazy<U extends Procedure<TContext, TExtraContext, TInputSchema, TOutputSchema, SchemaOutput<TOutputSchema>>>(loader: () => Promise<{
19
+ default: U;
20
+ }>): DecoratedLazy<U>;
17
21
  }
22
+ //# sourceMappingURL=procedure-implementer.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import type { Promisable } from '@orpc/shared';
2
+ import type { Lazy } from './lazy';
2
3
  import type { ProcedureCaller } from './procedure-caller';
3
4
  import type { Context, MergeContext, Meta } from './types';
4
5
  import { type ContractProcedure, type HTTPPath, type RouteOptions, type Schema, type SchemaInput, type SchemaOutput } from '@orpc/contract';
@@ -15,6 +16,9 @@ export declare class Procedure<TContext extends Context, TExtraContext extends C
15
16
  func: ProcedureFunc<TContext, TExtraContext, TInputSchema, TOutputSchema, TFuncOutput>;
16
17
  });
17
18
  }
19
+ export type ANY_PROCEDURE = Procedure<any, any, any, any, any>;
20
+ export type WELL_DEFINED_PROCEDURE = Procedure<Context, Context, Schema, Schema, unknown>;
21
+ export type ANY_LAZY_PROCEDURE = Lazy<ANY_PROCEDURE>;
18
22
  export type DecoratedProcedure<TContext extends Context, TExtraContext extends Context, TInputSchema extends Schema, TOutputSchema extends Schema, TFuncOutput extends SchemaOutput<TOutputSchema>> = Procedure<TContext, TExtraContext, TInputSchema, TOutputSchema, TFuncOutput> & {
19
23
  prefix: (prefix: HTTPPath) => DecoratedProcedure<TContext, TExtraContext, TInputSchema, TOutputSchema, TFuncOutput>;
20
24
  route: (opts: RouteOptions) => DecoratedProcedure<TContext, TExtraContext, TInputSchema, TOutputSchema, TFuncOutput>;
@@ -24,5 +28,5 @@ export interface ProcedureFunc<TContext extends Context, TExtraContext extends C
24
28
  (input: SchemaOutput<TInputSchema>, context: MergeContext<TContext, TExtraContext>, meta: Meta): Promisable<SchemaInput<TOutputSchema, TOutput>>;
25
29
  }
26
30
  export declare function decorateProcedure<TContext extends Context, TExtraContext extends Context, TInputSchema extends Schema, TOutputSchema extends Schema, TFuncOutput extends SchemaOutput<TOutputSchema>>(procedure: Procedure<TContext, TExtraContext, TInputSchema, TOutputSchema, TFuncOutput>): DecoratedProcedure<TContext, TExtraContext, TInputSchema, TOutputSchema, TFuncOutput>;
27
- export type WELL_DEFINED_PROCEDURE = Procedure<Context, Context, Schema, Schema, unknown>;
28
- export declare function isProcedure(item: unknown): item is WELL_DEFINED_PROCEDURE;
31
+ export declare function isProcedure(item: unknown): item is ANY_PROCEDURE;
32
+ //# sourceMappingURL=procedure.d.ts.map
@@ -1,7 +1,9 @@
1
+ import type { DecoratedLazy } from './lazy';
1
2
  import type { HandledRouter, Router } from './router';
2
3
  import type { Context, MergeContext } from './types';
3
4
  import { type HTTPPath } from '@orpc/contract';
4
5
  import { type MapInputMiddleware, type Middleware } from './middleware';
6
+ export declare const LAZY_ROUTER_PREFIX_SYMBOL: unique symbol;
5
7
  export declare class RouterBuilder<TContext extends Context, TExtraContext extends Context> {
6
8
  zz$rb: {
7
9
  prefix?: HTTPPath;
@@ -18,4 +20,8 @@ export declare class RouterBuilder<TContext extends Context, TExtraContext exten
18
20
  use<UExtraContext extends Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>> | undefined = undefined>(middleware: Middleware<MergeContext<TContext, TExtraContext>, UExtraContext, unknown, unknown>): RouterBuilder<TContext, MergeContext<TExtraContext, UExtraContext>>;
19
21
  use<UExtraContext extends Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>> | undefined = undefined, UMappedInput = unknown>(middleware: Middleware<MergeContext<TContext, TExtraContext>, UExtraContext, UMappedInput, unknown>, mapInput: MapInputMiddleware<unknown, UMappedInput>): RouterBuilder<TContext, MergeContext<TExtraContext, UExtraContext>>;
20
22
  router<URouter extends Router<TContext>>(router: URouter): HandledRouter<URouter>;
23
+ lazy<U extends Router<TContext>>(loader: () => Promise<{
24
+ default: U;
25
+ }>): DecoratedLazy<U>;
21
26
  }
27
+ //# sourceMappingURL=router-builder.d.ts.map
@@ -1,8 +1,11 @@
1
- import type { Value } from '@orpc/shared';
1
+ import type { Hooks, Value } from '@orpc/shared';
2
+ import type { ANY_LAZY_PROCEDURE, ANY_PROCEDURE } from './procedure';
2
3
  import type { Router } from './router';
3
- import { type Procedure } from './procedure';
4
4
  import { type ProcedureCaller } from './procedure-caller';
5
- export interface CreateRouterCallerOptions<TRouter extends Router<any>> {
5
+ export interface CreateRouterCallerOptions<TRouter extends Router<any>> extends Hooks<unknown, unknown, TRouter extends Router<infer UContext> ? UContext : never, {
6
+ path: string[];
7
+ procedure: ANY_PROCEDURE;
8
+ }> {
6
9
  router: TRouter;
7
10
  /**
8
11
  * The context used when calling the procedure.
@@ -16,6 +19,7 @@ export interface CreateRouterCallerOptions<TRouter extends Router<any>> {
16
19
  basePath?: string[];
17
20
  }
18
21
  export type RouterCaller<TRouter extends Router<any>> = {
19
- [K in keyof TRouter]: TRouter[K] extends Procedure<any, any, any, any, any> ? ProcedureCaller<TRouter[K]> : TRouter[K] extends Router<any> ? RouterCaller<TRouter[K]> : never;
22
+ [K in keyof TRouter]: TRouter[K] extends ANY_PROCEDURE | ANY_LAZY_PROCEDURE ? ProcedureCaller<TRouter[K]> : TRouter[K] extends Router<any> ? RouterCaller<TRouter[K]> : never;
20
23
  };
21
24
  export declare function createRouterCaller<TRouter extends Router<any>>(options: CreateRouterCallerOptions<TRouter>): RouterCaller<TRouter>;
25
+ //# sourceMappingURL=router-caller.d.ts.map
@@ -1,8 +1,10 @@
1
+ import type { DecoratedLazy } from './lazy';
1
2
  import type { Middleware } from './middleware';
2
- import type { RouterWithContract } from './router';
3
+ import type { HandledRouter, RouterWithContract } from './router';
3
4
  import type { Context } from './types';
4
5
  import { type ContractProcedure, type ContractRouter } from '@orpc/contract';
5
6
  import { ProcedureImplementer } from './procedure-implementer';
7
+ export declare const ROUTER_CONTRACT_SYMBOL: unique symbol;
6
8
  export declare class RouterImplementer<TContext extends Context, TContract extends ContractRouter> {
7
9
  zz$ri: {
8
10
  contract: TContract;
@@ -10,10 +12,13 @@ export declare class RouterImplementer<TContext extends Context, TContract exten
10
12
  constructor(zz$ri: {
11
13
  contract: TContract;
12
14
  });
13
- router(router: RouterWithContract<TContext, TContract>): RouterWithContract<TContext, TContract>;
15
+ router(router: RouterWithContract<TContext, TContract>): HandledRouter<RouterWithContract<TContext, TContract>>;
16
+ lazy(loader: () => Promise<{
17
+ default: RouterWithContract<TContext, TContract>;
18
+ }>): DecoratedLazy<RouterWithContract<TContext, TContract>>;
14
19
  }
15
20
  export type ChainedRouterImplementer<TContext extends Context, TContract extends ContractRouter, TExtraContext extends Context> = {
16
21
  [K in keyof TContract]: TContract[K] extends ContractProcedure<infer UInputSchema, infer UOutputSchema> ? ProcedureImplementer<TContext, TExtraContext, UInputSchema, UOutputSchema> : TContract[K] extends ContractRouter ? ChainedRouterImplementer<TContext, TContract[K], TExtraContext> : never;
17
22
  } & RouterImplementer<TContext, TContract>;
18
23
  export declare function chainRouterImplementer<TContext extends Context, TContract extends ContractRouter, TExtraContext extends Context>(contract: TContract, middlewares?: Middleware<any, any, any, any>[]): ChainedRouterImplementer<TContext, TContract, TExtraContext>;
19
- export declare function assertRouterImplementation(contract: ContractRouter, router: RouterWithContract<any, any>, path?: string[]): void;
24
+ //# sourceMappingURL=router-implementer.d.ts.map
@@ -1,19 +1,21 @@
1
1
  import type { ContractProcedure, ContractRouter, SchemaInput, SchemaOutput } from '@orpc/contract';
2
+ import type { ANY_LAZY, DecoratedLazy, Lazy } from './lazy';
2
3
  import type { Context } from './types';
3
4
  import { type DecoratedProcedure, type Procedure } from './procedure';
4
5
  export interface Router<TContext extends Context> {
5
- [k: string]: Procedure<TContext, any, any, any, any> | Router<TContext>;
6
+ [k: string]: Procedure<TContext, any, any, any, any> | Lazy<Procedure<TContext, any, any, any, any>> | Router<TContext> | Lazy<Router<TContext>>;
6
7
  }
7
8
  export type HandledRouter<TRouter extends Router<any>> = {
8
- [K in keyof TRouter]: TRouter[K] extends Procedure<infer UContext, infer UExtraContext, infer UInputSchema, infer UOutputSchema, infer UFuncOutput> ? DecoratedProcedure<UContext, UExtraContext, UInputSchema, UOutputSchema, UFuncOutput> : TRouter[K] extends Router<any> ? HandledRouter<TRouter[K]> : never;
9
+ [K in keyof TRouter]: TRouter[K] extends Procedure<infer UContext, infer UExtraContext, infer UInputSchema, infer UOutputSchema, infer UFuncOutput> ? DecoratedProcedure<UContext, UExtraContext, UInputSchema, UOutputSchema, UFuncOutput> : TRouter[K] extends ANY_LAZY ? DecoratedLazy<TRouter[K]> : TRouter[K] extends Router<any> ? HandledRouter<TRouter[K]> : never;
9
10
  };
10
11
  export type RouterWithContract<TContext extends Context, TContract extends ContractRouter> = {
11
- [K in keyof TContract]: TContract[K] extends ContractProcedure<infer UInputSchema, infer UOutputSchema> ? Procedure<TContext, any, UInputSchema, UOutputSchema, any> : TContract[K] extends ContractRouter ? RouterWithContract<TContext, TContract[K]> : never;
12
+ [K in keyof TContract]: TContract[K] extends ContractProcedure<infer UInputSchema, infer UOutputSchema> ? Procedure<TContext, any, UInputSchema, UOutputSchema, any> | Lazy<Procedure<TContext, any, UInputSchema, UOutputSchema, any>> : TContract[K] extends ContractRouter ? RouterWithContract<TContext, TContract[K]> | Lazy<RouterWithContract<TContext, TContract[K]>> : never;
12
13
  };
13
14
  export declare function toContractRouter(router: ContractRouter | Router<any>): ContractRouter;
14
15
  export type InferRouterInputs<T extends Router<any>> = {
15
- [K in keyof T]: T[K] extends Procedure<any, any, infer UInputSchema, any, any> ? SchemaInput<UInputSchema> : T[K] extends Router<any> ? InferRouterInputs<T[K]> : never;
16
+ [K in keyof T]: T[K] extends Procedure<any, any, infer UInputSchema, any, any> | Lazy<Procedure<any, any, infer UInputSchema, any, any>> ? SchemaInput<UInputSchema> : T[K] extends Router<any> ? InferRouterInputs<T[K]> : never;
16
17
  };
17
18
  export type InferRouterOutputs<T extends Router<any>> = {
18
- [K in keyof T]: T[K] extends Procedure<any, any, any, infer UOutputSchema, infer UFuncOutput> ? SchemaOutput<UOutputSchema, UFuncOutput> : T[K] extends Router<any> ? InferRouterOutputs<T[K]> : never;
19
+ [K in keyof T]: T[K] extends Procedure<any, any, any, infer UOutputSchema, infer UFuncOutput> | Lazy<Procedure<any, any, any, infer UOutputSchema, infer UFuncOutput>> ? SchemaOutput<UOutputSchema, UFuncOutput> : T[K] extends Router<any> ? InferRouterOutputs<T[K]> : never;
19
20
  };
21
+ //# sourceMappingURL=router.d.ts.map
@@ -5,3 +5,4 @@ export interface Meta {
5
5
  path: string[];
6
6
  procedure: WELL_DEFINED_PROCEDURE;
7
7
  }
8
+ //# sourceMappingURL=types.d.ts.map
@@ -1,2 +1,3 @@
1
1
  import type { Context, MergeContext } from './types';
2
2
  export declare function mergeContext<A extends Context, B extends Context>(a: A, b: B): MergeContext<A, B>;
3
+ //# sourceMappingURL=utils.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.12.0",
4
+ "version": "0.14.0",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -29,23 +29,24 @@
29
29
  }
30
30
  },
31
31
  "files": [
32
- "!dist/*.tsbuildinfo",
32
+ "!**/*.map",
33
+ "!**/*.tsbuildinfo",
33
34
  "dist"
34
35
  ],
35
36
  "peerDependencies": {
36
37
  "zod": ">=3.23.0",
37
- "@orpc/zod": "0.12.0"
38
+ "@orpc/zod": "0.14.0"
38
39
  },
39
40
  "dependencies": {
40
- "@orpc/contract": "0.12.0",
41
- "@orpc/transformer": "0.12.0",
42
- "@orpc/shared": "0.12.0"
41
+ "@orpc/shared": "0.14.0",
42
+ "@orpc/transformer": "0.14.0",
43
+ "@orpc/contract": "0.14.0"
43
44
  },
44
45
  "devDependencies": {
45
- "@orpc/openapi": "0.12.0"
46
+ "@orpc/openapi": "0.14.0"
46
47
  },
47
48
  "scripts": {
48
- "build": "tsup --clean --entry.index=src/index.ts --entry.fetch=src/fetch/index.ts --format=esm --onSuccess='tsc -b --noCheck'",
49
+ "build": "tsup --clean --sourcemap --entry.index=src/index.ts --entry.fetch=src/fetch/index.ts --format=esm --onSuccess='tsc -b --noCheck'",
49
50
  "build:watch": "pnpm run build --watch",
50
51
  "type:check": "tsc -b"
51
52
  }
@@ -1,189 +0,0 @@
1
- // src/utils.ts
2
- function mergeContext(a, b) {
3
- if (!a)
4
- return b;
5
- if (!b)
6
- return a;
7
- return {
8
- ...a,
9
- ...b
10
- };
11
- }
12
-
13
- // src/middleware.ts
14
- var decoratedMiddlewareSymbol = Symbol("\u{1F512}decoratedMiddleware");
15
- function decorateMiddleware(middleware) {
16
- if (Reflect.get(middleware, decoratedMiddlewareSymbol)) {
17
- return middleware;
18
- }
19
- const concat = (concatMiddleware, mapInput2) => {
20
- const concatMiddleware_ = mapInput2 ? decorateMiddleware(concatMiddleware).mapInput(mapInput2) : concatMiddleware;
21
- return decorateMiddleware(async (input, context, meta, ...rest) => {
22
- const input_ = input;
23
- const context_ = context;
24
- const meta_ = meta;
25
- const next = async (options) => {
26
- return concatMiddleware_(input_, mergeContext(context_, options.context), meta_, ...rest);
27
- };
28
- const m1 = await middleware(input_, context_, {
29
- ...meta_,
30
- next
31
- }, ...rest);
32
- return m1;
33
- });
34
- };
35
- const mapInput = (map) => {
36
- return decorateMiddleware(
37
- (input, ...rest) => middleware(map(input), ...rest)
38
- );
39
- };
40
- return Object.assign(middleware, {
41
- [decoratedMiddlewareSymbol]: true,
42
- concat,
43
- mapInput
44
- });
45
- }
46
-
47
- // src/procedure-caller.ts
48
- import { value } from "@orpc/shared";
49
- import { ORPCError } from "@orpc/shared/error";
50
- import { OpenAPIDeserializer } from "@orpc/transformer";
51
- function createProcedureCaller(options) {
52
- const path = options.path ?? [];
53
- const procedure = options.procedure;
54
- const caller = async (input) => {
55
- const input_ = (() => {
56
- if (!(input instanceof FormData)) {
57
- return input;
58
- }
59
- const transformer = new OpenAPIDeserializer({
60
- schema: procedure.zz$p.contract.zz$cp.InputSchema
61
- });
62
- return transformer.deserializeAsFormData(input);
63
- })();
64
- const validInput = (() => {
65
- const schema = procedure.zz$p.contract.zz$cp.InputSchema;
66
- if (!schema) {
67
- return input_;
68
- }
69
- try {
70
- return schema.parse(input_);
71
- } catch (e) {
72
- throw new ORPCError({
73
- message: "Validation input failed",
74
- code: "BAD_REQUEST",
75
- cause: e
76
- });
77
- }
78
- })();
79
- const middlewares = procedure.zz$p.middlewares ?? [];
80
- let currentMidIndex = 0;
81
- let currentContext = await value(options.context);
82
- const next = async (nextOptions) => {
83
- const mid = middlewares[currentMidIndex];
84
- currentMidIndex += 1;
85
- currentContext = mergeContext(currentContext, nextOptions.context);
86
- if (mid) {
87
- return await mid(validInput, currentContext, {
88
- path,
89
- procedure,
90
- next,
91
- output: (output2) => ({ output: output2, context: void 0 })
92
- });
93
- } else {
94
- return {
95
- output: await await procedure.zz$p.func(validInput, currentContext, {
96
- path,
97
- procedure
98
- }),
99
- context: currentContext
100
- };
101
- }
102
- };
103
- const output = (await next({})).output;
104
- const validOutput = await (async () => {
105
- const schema = procedure.zz$p.contract.zz$cp.OutputSchema;
106
- if (!schema) {
107
- return output;
108
- }
109
- const result = await schema.safeParseAsync(output);
110
- if (result.error) {
111
- throw new ORPCError({
112
- message: "Validation output failed",
113
- code: "INTERNAL_SERVER_ERROR",
114
- cause: result.error
115
- });
116
- }
117
- return result.data;
118
- })();
119
- return validOutput;
120
- };
121
- return caller;
122
- }
123
-
124
- // src/procedure.ts
125
- import {
126
- DecoratedContractProcedure,
127
- isContractProcedure
128
- } from "@orpc/contract";
129
- var Procedure = class {
130
- constructor(zz$p) {
131
- this.zz$p = zz$p;
132
- }
133
- };
134
- var DECORATED_PROCEDURE_SYMBOL = Symbol("DECORATED_PROCEDURE");
135
- function decorateProcedure(procedure) {
136
- if (DECORATED_PROCEDURE_SYMBOL in procedure) {
137
- return procedure;
138
- }
139
- return Object.assign(createProcedureCaller({
140
- procedure,
141
- context: void 0
142
- }), {
143
- [DECORATED_PROCEDURE_SYMBOL]: true,
144
- zz$p: procedure.zz$p,
145
- prefix(prefix) {
146
- return decorateProcedure({
147
- zz$p: {
148
- ...procedure.zz$p,
149
- contract: DecoratedContractProcedure.decorate(
150
- procedure.zz$p.contract
151
- ).prefix(prefix)
152
- }
153
- });
154
- },
155
- route(opts) {
156
- return decorateProcedure({
157
- zz$p: {
158
- ...procedure.zz$p,
159
- contract: DecoratedContractProcedure.decorate(
160
- procedure.zz$p.contract
161
- ).route(opts)
162
- }
163
- });
164
- },
165
- use(middleware, mapInput) {
166
- const middleware_ = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
167
- return decorateProcedure({
168
- zz$p: {
169
- ...procedure.zz$p,
170
- middlewares: [middleware_, ...procedure.zz$p.middlewares ?? []]
171
- }
172
- });
173
- }
174
- });
175
- }
176
- function isProcedure(item) {
177
- if (item instanceof Procedure)
178
- return true;
179
- return (typeof item === "object" || typeof item === "function") && item !== null && "zz$p" in item && typeof item.zz$p === "object" && item.zz$p !== null && "contract" in item.zz$p && isContractProcedure(item.zz$p.contract) && "func" in item.zz$p && typeof item.zz$p.func === "function";
180
- }
181
-
182
- export {
183
- mergeContext,
184
- decorateMiddleware,
185
- createProcedureCaller,
186
- Procedure,
187
- decorateProcedure,
188
- isProcedure
189
- };