@orpc/server 0.0.0-next.c59d67c → 0.0.0-next.db1f26d

Sign up to get free protection for your applications and to get access to all the features.
@@ -45,13 +45,92 @@ function decorateMiddleware(middleware) {
45
45
  }
46
46
 
47
47
  // src/procedure-caller.ts
48
- import { value } from "@orpc/shared";
48
+ import { trim, value } from "@orpc/shared";
49
49
  import { ORPCError } from "@orpc/shared/error";
50
50
  import { OpenAPIDeserializer } from "@orpc/transformer";
51
+
52
+ // src/procedure.ts
53
+ import {
54
+ DecoratedContractProcedure,
55
+ isContractProcedure
56
+ } from "@orpc/contract";
57
+ var Procedure = class {
58
+ constructor(zz$p) {
59
+ this.zz$p = zz$p;
60
+ }
61
+ };
62
+ var DECORATED_PROCEDURE_SYMBOL = Symbol("DECORATED_PROCEDURE");
63
+ function decorateProcedure(procedure) {
64
+ if (DECORATED_PROCEDURE_SYMBOL in procedure) {
65
+ return procedure;
66
+ }
67
+ return Object.assign(createProcedureCaller({
68
+ procedure,
69
+ context: void 0
70
+ }), {
71
+ [DECORATED_PROCEDURE_SYMBOL]: true,
72
+ zz$p: procedure.zz$p,
73
+ prefix(prefix) {
74
+ return decorateProcedure({
75
+ zz$p: {
76
+ ...procedure.zz$p,
77
+ contract: DecoratedContractProcedure.decorate(
78
+ procedure.zz$p.contract
79
+ ).prefix(prefix)
80
+ }
81
+ });
82
+ },
83
+ route(opts) {
84
+ return decorateProcedure({
85
+ zz$p: {
86
+ ...procedure.zz$p,
87
+ contract: DecoratedContractProcedure.decorate(
88
+ procedure.zz$p.contract
89
+ ).route(opts)
90
+ }
91
+ });
92
+ },
93
+ use(middleware, mapInput) {
94
+ const middleware_ = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
95
+ return decorateProcedure({
96
+ zz$p: {
97
+ ...procedure.zz$p,
98
+ middlewares: [middleware_, ...procedure.zz$p.middlewares ?? []]
99
+ }
100
+ });
101
+ }
102
+ });
103
+ }
104
+ function isProcedure(item) {
105
+ if (item instanceof Procedure)
106
+ return true;
107
+ 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";
108
+ }
109
+
110
+ // src/procedure-caller.ts
51
111
  function createProcedureCaller(options) {
52
- const path = options.path ?? [];
53
- const procedure = options.procedure;
112
+ const loadProcedure = async () => {
113
+ let procedure;
114
+ if (isLazy(options.procedure)) {
115
+ procedure = (await loadLazy(options.procedure)).default;
116
+ } else {
117
+ procedure = options.procedure;
118
+ }
119
+ if (!isProcedure(procedure)) {
120
+ throw new ORPCError({
121
+ code: "NOT_FOUND",
122
+ message: "Not found",
123
+ cause: new Error(trim(`
124
+ This error should be caught by the typescript compiler.
125
+ But if you still see this error, it means that you trying to call a lazy router (expected to be a lazy procedure).
126
+ `))
127
+ });
128
+ }
129
+ return procedure;
130
+ };
54
131
  const caller = async (input) => {
132
+ const path = options.path ?? [];
133
+ const procedure = await loadProcedure();
55
134
  const input_ = (() => {
56
135
  if (!(input instanceof FormData)) {
57
136
  return input;
@@ -121,70 +200,68 @@ function createProcedureCaller(options) {
121
200
  return caller;
122
201
  }
123
202
 
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,
203
+ // src/lazy.ts
204
+ var LAZY_LOADER_SYMBOL = Symbol("ORPC_LAZY_LOADER");
205
+ function createLazy(loader) {
206
+ return {
207
+ [LAZY_LOADER_SYMBOL]: loader
208
+ };
209
+ }
210
+ function loadLazy(lazy) {
211
+ return lazy[LAZY_LOADER_SYMBOL]();
212
+ }
213
+ function isLazy(item) {
214
+ return (typeof item === "object" || typeof item === "function") && item !== null && LAZY_LOADER_SYMBOL in item && typeof item[LAZY_LOADER_SYMBOL] === "function";
215
+ }
216
+ function createFlattenLazy(lazy) {
217
+ const flattenLoader = async () => {
218
+ let current = await loadLazy(lazy);
219
+ while (true) {
220
+ if (!isLazy(current.default)) {
221
+ break;
222
+ }
223
+ current = await loadLazy(current.default);
224
+ }
225
+ return current;
226
+ };
227
+ const flattenLazy = {
228
+ [LAZY_LOADER_SYMBOL]: flattenLoader
229
+ };
230
+ return flattenLazy;
231
+ }
232
+ function decorateLazy(lazy) {
233
+ const flattenLazy = createFlattenLazy(lazy);
234
+ const procedureCaller = createProcedureCaller({
235
+ procedure: flattenLazy,
141
236
  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
- });
237
+ });
238
+ Object.assign(procedureCaller, flattenLazy);
239
+ const recursive = new Proxy(procedureCaller, {
240
+ get(target, key) {
241
+ if (typeof key !== "string") {
242
+ return Reflect.get(target, key);
243
+ }
244
+ return decorateLazy(createLazy(async () => {
245
+ const current = await loadLazy(flattenLazy);
246
+ return { default: current.default[key] };
247
+ }));
173
248
  }
174
249
  });
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";
250
+ return recursive;
180
251
  }
181
252
 
182
253
  export {
183
254
  mergeContext,
184
255
  decorateMiddleware,
256
+ LAZY_LOADER_SYMBOL,
257
+ createLazy,
258
+ loadLazy,
259
+ isLazy,
260
+ createFlattenLazy,
261
+ decorateLazy,
185
262
  createProcedureCaller,
186
263
  Procedure,
187
264
  decorateProcedure,
188
265
  isProcedure
189
266
  };
190
- //# sourceMappingURL=chunk-TDFYNRZV.js.map
267
+ //# sourceMappingURL=chunk-FL4ZAGNE.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-TDFYNRZV.js";
5
+ } from "./chunk-FL4ZAGNE.js";
5
6
 
6
7
  // src/fetch/handle.ts
7
8
  import { ORPCError } from "@orpc/shared/error";
@@ -77,13 +78,13 @@ function resolveORPCRouter(router, pathname) {
77
78
  const path = trim(pathname, "/").split("/").map(decodeURIComponent);
78
79
  let current = router;
79
80
  for (const segment of path) {
80
- if ((typeof current !== "object" || current === null) && typeof current !== "function") {
81
+ if (typeof current !== "object" && typeof current !== "function" || !current) {
81
82
  current = void 0;
82
83
  break;
83
84
  }
84
85
  current = current[segment];
85
86
  }
86
- return isProcedure(current) ? {
87
+ return isProcedure(current) || isLazy(current) ? {
87
88
  procedure: current,
88
89
  path
89
90
  } : void 0;
package/dist/index.js CHANGED
@@ -1,11 +1,17 @@
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,
7
13
  mergeContext
8
- } from "./chunk-TDFYNRZV.js";
14
+ } from "./chunk-FL4ZAGNE.js";
9
15
 
10
16
  // src/builder.ts
11
17
  import {
@@ -15,9 +21,138 @@ import {
15
21
 
16
22
  // src/procedure-builder.ts
17
23
  import {
18
- DecoratedContractProcedure
24
+ DecoratedContractProcedure as DecoratedContractProcedure2
19
25
  } from "@orpc/contract";
20
26
 
27
+ // src/router-builder.ts
28
+ import { DecoratedContractProcedure, prefixHTTPPath } from "@orpc/contract";
29
+ var LAZY_ROUTER_PREFIX_SYMBOL = Symbol("ORPC_LAZY_ROUTER_PREFIX");
30
+ var RouterBuilder = class _RouterBuilder {
31
+ constructor(zz$rb) {
32
+ this.zz$rb = zz$rb;
33
+ if (zz$rb.prefix && zz$rb.prefix.includes("{")) {
34
+ throw new Error('Prefix cannot contain "{" for dynamic routing');
35
+ }
36
+ }
37
+ prefix(prefix) {
38
+ return new _RouterBuilder({
39
+ ...this.zz$rb,
40
+ prefix: `${this.zz$rb.prefix ?? ""}${prefix}`
41
+ });
42
+ }
43
+ tags(...tags) {
44
+ if (!tags.length)
45
+ return this;
46
+ return new _RouterBuilder({
47
+ ...this.zz$rb,
48
+ tags: [...this.zz$rb.tags ?? [], ...tags]
49
+ });
50
+ }
51
+ use(middleware, mapInput) {
52
+ const middleware_ = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
53
+ return new _RouterBuilder({
54
+ ...this.zz$rb,
55
+ middlewares: [...this.zz$rb.middlewares || [], middleware_]
56
+ });
57
+ }
58
+ router(router) {
59
+ const handled = adaptRouter({
60
+ routerOrChild: router,
61
+ middlewares: this.zz$rb.middlewares,
62
+ tags: this.zz$rb.tags,
63
+ prefix: this.zz$rb.prefix
64
+ });
65
+ return handled;
66
+ }
67
+ lazy(loader) {
68
+ const lazy = adaptLazyRouter({
69
+ current: createLazy(loader),
70
+ middlewares: this.zz$rb.middlewares,
71
+ tags: this.zz$rb.tags,
72
+ prefix: this.zz$rb.prefix
73
+ });
74
+ return lazy;
75
+ }
76
+ };
77
+ function adaptRouter(options) {
78
+ if (isProcedure(options.routerOrChild)) {
79
+ return adaptProcedure({
80
+ ...options,
81
+ procedure: options.routerOrChild
82
+ });
83
+ }
84
+ if (isLazy(options.routerOrChild)) {
85
+ return adaptLazyRouter({
86
+ ...options,
87
+ current: options.routerOrChild
88
+ });
89
+ }
90
+ const handled = {};
91
+ for (const key in options.routerOrChild) {
92
+ handled[key] = adaptRouter({
93
+ ...options,
94
+ routerOrChild: options.routerOrChild[key]
95
+ });
96
+ }
97
+ return handled;
98
+ }
99
+ function adaptLazyRouter(options) {
100
+ const loader = async () => {
101
+ const current = (await loadLazy(options.current)).default;
102
+ return {
103
+ default: adaptRouter({
104
+ ...options,
105
+ routerOrChild: current
106
+ })
107
+ };
108
+ };
109
+ let lazyRouterPrefix = options.prefix;
110
+ if (LAZY_ROUTER_PREFIX_SYMBOL in options.current && typeof options.current[LAZY_ROUTER_PREFIX_SYMBOL] === "string") {
111
+ lazyRouterPrefix = lazyRouterPrefix ? prefixHTTPPath(options.current[LAZY_ROUTER_PREFIX_SYMBOL], lazyRouterPrefix) : options.current[LAZY_ROUTER_PREFIX_SYMBOL];
112
+ }
113
+ const decoratedLazy = Object.assign(decorateLazy(createLazy(loader)), {
114
+ [LAZY_ROUTER_PREFIX_SYMBOL]: lazyRouterPrefix
115
+ });
116
+ const recursive = new Proxy(decoratedLazy, {
117
+ get(target, key) {
118
+ if (typeof key !== "string") {
119
+ return Reflect.get(target, key);
120
+ }
121
+ return adaptLazyRouter({
122
+ ...options,
123
+ current: createLazy(async () => {
124
+ const current = (await loadLazy(options.current)).default;
125
+ return { default: current[key] };
126
+ })
127
+ });
128
+ }
129
+ });
130
+ return recursive;
131
+ }
132
+ function adaptProcedure(options) {
133
+ const builderMiddlewares = options.middlewares ?? [];
134
+ const procedureMiddlewares = options.procedure.zz$p.middlewares ?? [];
135
+ const middlewares = [
136
+ ...builderMiddlewares,
137
+ ...procedureMiddlewares.filter(
138
+ (item) => !builderMiddlewares.includes(item)
139
+ )
140
+ ];
141
+ let contract = DecoratedContractProcedure.decorate(
142
+ options.procedure.zz$p.contract
143
+ ).addTags(...options.tags ?? []);
144
+ if (options.prefix) {
145
+ contract = contract.prefix(options.prefix);
146
+ }
147
+ return decorateProcedure({
148
+ zz$p: {
149
+ ...options.procedure.zz$p,
150
+ contract,
151
+ middlewares
152
+ }
153
+ });
154
+ }
155
+
21
156
  // src/procedure-implementer.ts
22
157
  var ProcedureImplementer = class _ProcedureImplementer {
23
158
  constructor(zz$pi) {
@@ -39,6 +174,9 @@ var ProcedureImplementer = class _ProcedureImplementer {
39
174
  }
40
175
  });
41
176
  }
177
+ lazy(loader) {
178
+ return new RouterBuilder(this.zz$pi).lazy(loader);
179
+ }
42
180
  };
43
181
 
44
182
  // src/procedure-builder.ts
@@ -52,7 +190,7 @@ var ProcedureBuilder = class _ProcedureBuilder {
52
190
  route(opts) {
53
191
  return new _ProcedureBuilder({
54
192
  ...this.zz$pb,
55
- contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).route(
193
+ contract: DecoratedContractProcedure2.decorate(this.zz$pb.contract).route(
56
194
  opts
57
195
  )
58
196
  });
@@ -60,7 +198,7 @@ var ProcedureBuilder = class _ProcedureBuilder {
60
198
  input(schema, example) {
61
199
  return new _ProcedureBuilder({
62
200
  ...this.zz$pb,
63
- contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).input(
201
+ contract: DecoratedContractProcedure2.decorate(this.zz$pb.contract).input(
64
202
  schema,
65
203
  example
66
204
  )
@@ -69,7 +207,7 @@ var ProcedureBuilder = class _ProcedureBuilder {
69
207
  output(schema, example) {
70
208
  return new _ProcedureBuilder({
71
209
  ...this.zz$pb,
72
- contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).output(
210
+ contract: DecoratedContractProcedure2.decorate(this.zz$pb.contract).output(
73
211
  schema,
74
212
  example
75
213
  )
@@ -101,75 +239,24 @@ var ProcedureBuilder = class _ProcedureBuilder {
101
239
  }
102
240
  };
103
241
 
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
242
  // src/router-implementer.ts
163
- import {
164
- isContractProcedure
165
- } from "@orpc/contract";
243
+ import { isContractProcedure } from "@orpc/contract";
244
+ var ROUTER_CONTRACT_SYMBOL = Symbol("ORPC_ROUTER_CONTRACT");
166
245
  var RouterImplementer = class {
167
246
  constructor(zz$ri) {
168
247
  this.zz$ri = zz$ri;
169
248
  }
170
249
  router(router) {
171
- assertRouterImplementation(this.zz$ri.contract, router);
172
- return router;
250
+ return Object.assign(new RouterBuilder({}).router(router), {
251
+ [ROUTER_CONTRACT_SYMBOL]: this.zz$ri.contract
252
+ });
253
+ }
254
+ lazy(loader) {
255
+ const lazy = createLazy(loader);
256
+ const decorated = decorateLazy(lazy);
257
+ return Object.assign(decorated, {
258
+ [ROUTER_CONTRACT_SYMBOL]: this.zz$ri.contract
259
+ });
173
260
  }
174
261
  };
175
262
  function chainRouterImplementer(contract, middlewares) {
@@ -188,37 +275,6 @@ function chainRouterImplementer(contract, middlewares) {
188
275
  const implementer = new RouterImplementer({ contract });
189
276
  return Object.assign(implementer, result);
190
277
  }
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
278
 
223
279
  // src/builder.ts
224
280
  var Builder = class _Builder {
@@ -327,6 +383,9 @@ var Builder = class _Builder {
327
383
  router(router) {
328
384
  return new RouterBuilder(this.zz$b).router(router);
329
385
  }
386
+ lazy(loader) {
387
+ return new RouterBuilder(this.zz$b).lazy(loader);
388
+ }
330
389
  };
331
390
 
332
391
  // src/router.ts
@@ -350,25 +409,32 @@ function toContractRouter(router) {
350
409
 
351
410
  // src/router-caller.ts
352
411
  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,
412
+ return createRouterCallerInternal({
413
+ current: options.router,
414
+ context: options.context,
415
+ path: options.basePath ?? []
416
+ });
417
+ }
418
+ function createRouterCallerInternal(options) {
419
+ const procedureCaller = isLazy(options.current) || isProcedure(options.current) ? createProcedureCaller({
420
+ procedure: options.current,
421
+ context: options.context,
422
+ path: options.path
423
+ }) : {};
424
+ const recursive = new Proxy(procedureCaller, {
425
+ get(target, key) {
426
+ if (typeof key !== "string") {
427
+ return Reflect.get(target, key);
428
+ }
429
+ const next = options.current[key];
430
+ return createRouterCallerInternal({
431
+ current: next,
366
432
  context: options.context,
367
- basePath: path
433
+ path: [...options.path, key]
368
434
  });
369
435
  }
370
- }
371
- return caller;
436
+ });
437
+ return recursive;
372
438
  }
373
439
 
374
440
  // src/index.ts
@@ -376,17 +442,25 @@ export * from "@orpc/shared/error";
376
442
  var os = new Builder();
377
443
  export {
378
444
  Builder,
445
+ LAZY_LOADER_SYMBOL,
446
+ LAZY_ROUTER_PREFIX_SYMBOL,
379
447
  Procedure,
380
448
  ProcedureBuilder,
381
449
  ProcedureImplementer,
450
+ ROUTER_CONTRACT_SYMBOL,
451
+ RouterBuilder,
382
452
  RouterImplementer,
383
- assertRouterImplementation,
384
453
  chainRouterImplementer,
454
+ createFlattenLazy,
455
+ createLazy,
385
456
  createProcedureCaller,
386
457
  createRouterCaller,
458
+ decorateLazy,
387
459
  decorateMiddleware,
388
460
  decorateProcedure,
461
+ isLazy,
389
462
  isProcedure,
463
+ loadLazy,
390
464
  mergeContext,
391
465
  os,
392
466
  toContractRouter
@@ -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,5 +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
  }
49
53
  //# sourceMappingURL=builder.d.ts.map
@@ -1,11 +1,13 @@
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';
@@ -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
@@ -1,12 +1,13 @@
1
1
  import type { SchemaInput, SchemaOutput } from '@orpc/contract';
2
- import type { Procedure } from './procedure';
2
+ import type { Lazy } from './lazy';
3
3
  import { type Value } from '@orpc/shared';
4
- export interface CreateProcedureCallerOptions<TProcedure extends Procedure<any, any, any, any, any>> {
4
+ import { type ANY_LAZY_PROCEDURE, type ANY_PROCEDURE, type Procedure } from './procedure';
5
+ export interface CreateProcedureCallerOptions<TProcedure extends ANY_PROCEDURE | ANY_LAZY_PROCEDURE> {
5
6
  procedure: TProcedure;
6
7
  /**
7
8
  * The context used when calling the procedure.
8
9
  */
9
- context: Value<TProcedure extends Procedure<infer UContext, any, any, any, any> ? UContext : never>;
10
+ context: Value<TProcedure extends Procedure<infer UContext, any, any, any, any> | Lazy<Procedure<infer UContext, any, any, any, any>> ? UContext : never>;
10
11
  /**
11
12
  * This is helpful for logging and analytics.
12
13
  *
@@ -14,6 +15,6 @@ export interface CreateProcedureCallerOptions<TProcedure extends Procedure<any,
14
15
  */
15
16
  path?: string[];
16
17
  }
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>;
18
+ 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> | FormData] | (undefined extends SchemaInput<UInputSchema> ? [] : never)) => Promise<SchemaOutput<UOutputSchema, UFuncOutput>> : never;
19
+ export declare function createProcedureCaller<TProcedure extends ANY_PROCEDURE | ANY_LAZY_PROCEDURE>(options: CreateProcedureCallerOptions<TProcedure>): ProcedureCaller<TProcedure>;
19
20
  //# 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,5 +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
  }
18
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,6 +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;
29
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,5 +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
  }
22
27
  //# sourceMappingURL=router-builder.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import type { 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
5
  export interface CreateRouterCallerOptions<TRouter extends Router<any>> {
6
6
  router: TRouter;
@@ -16,7 +16,7 @@ export interface CreateRouterCallerOptions<TRouter extends Router<any>> {
16
16
  basePath?: string[];
17
17
  }
18
18
  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;
19
+ [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
20
  };
21
21
  export declare function createRouterCaller<TRouter extends Router<any>>(options: CreateRouterCallerOptions<TRouter>): RouterCaller<TRouter>;
22
22
  //# 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,11 +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;
20
24
  //# sourceMappingURL=router-implementer.d.ts.map
@@ -1,14 +1,15 @@
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>> = {
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.c59d67c",
4
+ "version": "0.0.0-next.db1f26d",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -35,15 +35,15 @@
35
35
  ],
36
36
  "peerDependencies": {
37
37
  "zod": ">=3.23.0",
38
- "@orpc/zod": "0.0.0-next.c59d67c"
38
+ "@orpc/zod": "0.0.0-next.db1f26d"
39
39
  },
40
40
  "dependencies": {
41
- "@orpc/contract": "0.0.0-next.c59d67c",
42
- "@orpc/shared": "0.0.0-next.c59d67c",
43
- "@orpc/transformer": "0.0.0-next.c59d67c"
41
+ "@orpc/contract": "0.0.0-next.db1f26d",
42
+ "@orpc/shared": "0.0.0-next.db1f26d",
43
+ "@orpc/transformer": "0.0.0-next.db1f26d"
44
44
  },
45
45
  "devDependencies": {
46
- "@orpc/openapi": "0.0.0-next.c59d67c"
46
+ "@orpc/openapi": "0.0.0-next.db1f26d"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "tsup --clean --sourcemap --entry.index=src/index.ts --entry.fetch=src/fetch/index.ts --format=esm --onSuccess='tsc -b --noCheck'",