@orpc/openapi 0.0.0-next.8f9385e → 0.0.0-next.97446ff

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,54 @@
1
+ // src/utils.ts
2
+ import { isContractProcedure } from "@orpc/contract";
3
+ import { flatLazy, getRouterContract, isLazy, isProcedure } from "@orpc/server";
4
+ function eachContractProcedureLeaf(options, callback, result = [], isCurrentRouterContract = false) {
5
+ const hiddenContract = getRouterContract(options.router);
6
+ if (!isCurrentRouterContract && hiddenContract) {
7
+ return eachContractProcedureLeaf(
8
+ {
9
+ path: options.path,
10
+ router: hiddenContract
11
+ },
12
+ callback,
13
+ result,
14
+ true
15
+ );
16
+ }
17
+ if (isLazy(options.router)) {
18
+ result.push({
19
+ lazy: flatLazy(options.router),
20
+ path: options.path
21
+ });
22
+ } else if (isProcedure(options.router)) {
23
+ callback({
24
+ contract: options.router["~orpc"].contract,
25
+ path: options.path
26
+ });
27
+ } else if (isContractProcedure(options.router)) {
28
+ callback({
29
+ contract: options.router,
30
+ path: options.path
31
+ });
32
+ } else {
33
+ for (const key in options.router) {
34
+ eachContractProcedureLeaf(
35
+ {
36
+ router: options.router[key],
37
+ path: [...options.path, key]
38
+ },
39
+ callback,
40
+ result
41
+ );
42
+ }
43
+ }
44
+ return result;
45
+ }
46
+ function standardizeHTTPPath(path) {
47
+ return `/${path.replace(/\/{2,}/g, "/").replace(/^\/|\/$/g, "")}`;
48
+ }
49
+
50
+ export {
51
+ eachContractProcedureLeaf,
52
+ standardizeHTTPPath
53
+ };
54
+ //# sourceMappingURL=chunk-CMRY2Z4J.js.map
package/dist/fetch.js CHANGED
@@ -1,12 +1,16 @@
1
+ import {
2
+ eachContractProcedureLeaf,
3
+ standardizeHTTPPath
4
+ } from "./chunk-CMRY2Z4J.js";
5
+
1
6
  // src/fetch/base-handler.ts
2
- import { ORPC_HEADER, standardizeHTTPPath } from "@orpc/contract";
3
- import { createProcedureCaller, isProcedure, ORPCError } from "@orpc/server";
4
- import { isPlainObject, mapValues, trim, value } from "@orpc/shared";
7
+ import { createProcedureClient, getLazyRouterPrefix, getRouterChild, isProcedure, LAZY_LOADER_SYMBOL, ORPCError, unlazy } from "@orpc/server";
8
+ import { executeWithHooks, isPlainObject, mapValues, ORPC_PROTOCOL_HEADER, ORPC_PROTOCOL_VALUE, trim, value } from "@orpc/shared";
5
9
  import { OpenAPIDeserializer, OpenAPISerializer, zodCoerce } from "@orpc/transformer";
6
10
  function createOpenAPIHandler(createHonoRouter) {
7
11
  const resolveRouter = createResolveRouter(createHonoRouter);
8
12
  return async (options) => {
9
- if (options.request.headers.get(ORPC_HEADER) !== null) {
13
+ if (options.request.headers.get(ORPC_PROTOCOL_HEADER)?.includes(ORPC_PROTOCOL_VALUE)) {
10
14
  return void 0;
11
15
  }
12
16
  const context = await value(options.context);
@@ -17,25 +21,24 @@ function createOpenAPIHandler(createHonoRouter) {
17
21
  const pathname = `/${trim(url.pathname.replace(options.prefix ?? "", ""), "/")}`;
18
22
  const customMethod = options.request.method === "POST" ? url.searchParams.get("method")?.toUpperCase() : void 0;
19
23
  const method = customMethod || options.request.method;
20
- const match = resolveRouter(options.router, method, pathname);
24
+ const match = await resolveRouter(options.router, method, pathname);
21
25
  if (!match) {
22
26
  throw new ORPCError({ code: "NOT_FOUND", message: "Not found" });
23
27
  }
24
- const procedure = match.procedure;
25
- const path = match.path;
26
- const params = procedure.zz$p.contract.zz$cp.InputSchema ? zodCoerce(
27
- procedure.zz$p.contract.zz$cp.InputSchema,
28
+ const { path, procedure } = match;
29
+ const params = procedure["~orpc"].contract["~orpc"].InputSchema ? zodCoerce(
30
+ procedure["~orpc"].contract["~orpc"].InputSchema,
28
31
  match.params,
29
32
  { bracketNotation: true }
30
33
  ) : match.params;
31
34
  const input = await deserializeInput(options.request, procedure);
32
35
  const mergedInput = mergeParamsAndInput(params, input);
33
- const caller = createProcedureCaller({
36
+ const caller = createProcedureClient({
34
37
  context,
35
38
  procedure,
36
39
  path
37
40
  });
38
- const output = await caller(mergedInput);
41
+ const output = await caller(mergedInput, { signal: options.signal });
39
42
  const { body, headers } = serializer.serialize(output);
40
43
  return new Response(body, {
41
44
  status: 200,
@@ -43,10 +46,15 @@ function createOpenAPIHandler(createHonoRouter) {
43
46
  });
44
47
  };
45
48
  try {
46
- return await options.hooks?.(context, {
47
- next: handler,
48
- response: (response) => response
49
- }) ?? await handler();
49
+ return await executeWithHooks({
50
+ context,
51
+ hooks: options,
52
+ execute: handler,
53
+ input: options.request,
54
+ meta: {
55
+ signal: options.signal
56
+ }
57
+ });
50
58
  } catch (e) {
51
59
  const error = toORPCError(e);
52
60
  try {
@@ -69,27 +77,45 @@ function createOpenAPIHandler(createHonoRouter) {
69
77
  };
70
78
  }
71
79
  var routingCache = /* @__PURE__ */ new Map();
80
+ var pendingCache = /* @__PURE__ */ new Map();
72
81
  function createResolveRouter(createHonoRouter) {
73
- return (router, method, pathname) => {
74
- let routing = routingCache.get(router);
75
- if (!routing) {
76
- routing = createHonoRouter();
77
- const addRouteRecursively = (routing2, router2, basePath) => {
78
- for (const key in router2) {
79
- const currentPath = [...basePath, key];
80
- const item = router2[key];
81
- if (isProcedure(item)) {
82
- const method2 = item.zz$p.contract.zz$cp.method ?? "POST";
83
- const path2 = item.zz$p.contract.zz$cp.path ? openAPIPathToRouterPath(item.zz$p.contract.zz$cp.path) : `/${currentPath.map(encodeURIComponent).join("/")}`;
84
- routing2.add(method2, path2, [currentPath, item]);
85
- } else {
86
- addRouteRecursively(routing2, item, currentPath);
87
- }
88
- }
89
- };
90
- addRouteRecursively(routing, router, []);
91
- routingCache.set(router, routing);
82
+ const addRoutes = (routing, pending, options) => {
83
+ const lazies = eachContractProcedureLeaf(options, ({ path, contract }) => {
84
+ const method = contract["~orpc"].route?.method ?? "POST";
85
+ const httpPath = contract["~orpc"].route?.path ? openAPIPathToRouterPath(contract["~orpc"].route?.path) : `/${path.map(encodeURIComponent).join("/")}`;
86
+ routing.add(method, httpPath, path);
87
+ });
88
+ pending.ref.push(...lazies);
89
+ };
90
+ return async (router, method, pathname) => {
91
+ const pending = (() => {
92
+ let pending2 = pendingCache.get(router);
93
+ if (!pending2) {
94
+ pending2 = { ref: [] };
95
+ pendingCache.set(router, pending2);
96
+ }
97
+ return pending2;
98
+ })();
99
+ const routing = (() => {
100
+ let routing2 = routingCache.get(router);
101
+ if (!routing2) {
102
+ routing2 = createHonoRouter();
103
+ routingCache.set(router, routing2);
104
+ addRoutes(routing2, pending, { router, path: [] });
105
+ }
106
+ return routing2;
107
+ })();
108
+ const newPending = [];
109
+ for (const item of pending.ref) {
110
+ const lazyPrefix = getLazyRouterPrefix(item.lazy);
111
+ if (lazyPrefix && !pathname.startsWith(lazyPrefix) && !pathname.startsWith(`/${item.path.map(encodeURIComponent).join("/")}`)) {
112
+ newPending.push(item);
113
+ continue;
114
+ }
115
+ const router2 = (await item.lazy[LAZY_LOADER_SYMBOL]()).default;
116
+ addRoutes(routing, pending, { path: item.path, router: router2 });
92
117
  }
118
+ pending.ref = newPending;
93
119
  const [matches, params_] = routing.match(method, pathname);
94
120
  const [match] = matches.sort((a, b) => {
95
121
  return Object.keys(a[1]).length - Object.keys(b[1]).length;
@@ -97,15 +123,18 @@ function createResolveRouter(createHonoRouter) {
97
123
  if (!match) {
98
124
  return void 0;
99
125
  }
100
- const path = match[0][0];
101
- const procedure = match[0][1];
126
+ const path = match[0];
102
127
  const params = params_ ? mapValues(
103
128
  match[1],
104
129
  (v) => params_[v]
105
130
  ) : match[1];
131
+ const { default: maybeProcedure } = await unlazy(getRouterChild(router, ...path));
132
+ if (!isProcedure(maybeProcedure)) {
133
+ return void 0;
134
+ }
106
135
  return {
107
136
  path,
108
- procedure,
137
+ procedure: maybeProcedure,
109
138
  params: { ...params }
110
139
  // params from hono not a normal object, so we need spread here
111
140
  };
@@ -125,7 +154,7 @@ function mergeParamsAndInput(coercedParams, input) {
125
154
  }
126
155
  async function deserializeInput(request, procedure) {
127
156
  const deserializer = new OpenAPIDeserializer({
128
- schema: procedure.zz$p.contract.zz$cp.InputSchema
157
+ schema: procedure["~orpc"].contract["~orpc"].InputSchema
129
158
  });
130
159
  try {
131
160
  return await deserializer.deserialize(request);
@@ -148,13 +177,13 @@ function openAPIPathToRouterPath(path) {
148
177
  return standardizeHTTPPath(path).replace(/\{([^}]+)\}/g, ":$1");
149
178
  }
150
179
 
151
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router.js
180
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router.js
152
181
  var METHOD_NAME_ALL = "ALL";
153
182
  var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
154
183
  var UnsupportedPathError = class extends Error {
155
184
  };
156
185
 
157
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/utils/url.js
186
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/utils/url.js
158
187
  var checkOptionalParameter = (path) => {
159
188
  if (!path.match(/\:.+\?$/)) {
160
189
  return null;
@@ -183,7 +212,7 @@ var checkOptionalParameter = (path) => {
183
212
  return results.filter((v, i, a) => a.indexOf(v) === i);
184
213
  };
185
214
 
186
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/reg-exp-router/node.js
215
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/reg-exp-router/node.js
187
216
  var LABEL_REG_EXP_STR = "[^/]+";
188
217
  var ONLY_WILDCARD_REG_EXP_STR = ".*";
189
218
  var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
@@ -288,7 +317,7 @@ var Node = class {
288
317
  }
289
318
  };
290
319
 
291
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/reg-exp-router/trie.js
320
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/reg-exp-router/trie.js
292
321
  var Trie = class {
293
322
  #context = { varIndex: 0 };
294
323
  #root = new Node();
@@ -344,7 +373,7 @@ var Trie = class {
344
373
  }
345
374
  };
346
375
 
347
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/reg-exp-router/router.js
376
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/reg-exp-router/router.js
348
377
  var emptyParam = [];
349
378
  var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
350
379
  var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
@@ -545,7 +574,7 @@ function createOpenAPIServerHandler() {
545
574
  return createOpenAPIHandler(() => new RegExpRouter());
546
575
  }
547
576
 
548
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/linear-router/router.js
577
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/linear-router/router.js
549
578
  var emptyParams = /* @__PURE__ */ Object.create(null);
550
579
  var splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g;
551
580
  var splitByStarRe = /\*/;
@@ -663,7 +692,6 @@ export {
663
692
  createOpenAPIHandler,
664
693
  createOpenAPIServerHandler,
665
694
  createOpenAPIServerlessHandler,
666
- createResolveRouter,
667
- openAPIPathToRouterPath
695
+ createResolveRouter
668
696
  };
669
697
  //# sourceMappingURL=fetch.js.map