@orpc/openapi 0.0.0-next.55d0b4f → 0.0.0-next.56e31fa

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,53 @@
1
+ // src/utils.ts
2
+ import { isContractProcedure } from "@orpc/contract";
3
+ import { isLazy, isProcedure, ROUTER_CONTRACT_SYMBOL } from "@orpc/server";
4
+ function eachContractProcedureLeaf(options, callback, result = [], isCurrentRouterContract = false) {
5
+ if (!isCurrentRouterContract && ROUTER_CONTRACT_SYMBOL in options.router && options.router[ROUTER_CONTRACT_SYMBOL]) {
6
+ return eachContractProcedureLeaf(
7
+ {
8
+ path: options.path,
9
+ router: options.router[ROUTER_CONTRACT_SYMBOL]
10
+ },
11
+ callback,
12
+ result,
13
+ true
14
+ );
15
+ }
16
+ if (isLazy(options.router)) {
17
+ result.push({
18
+ lazy: options.router,
19
+ path: options.path
20
+ });
21
+ } else if (isProcedure(options.router)) {
22
+ callback({
23
+ contract: options.router.zz$p.contract,
24
+ path: options.path
25
+ });
26
+ } else if (isContractProcedure(options.router)) {
27
+ callback({
28
+ contract: options.router,
29
+ path: options.path
30
+ });
31
+ } else {
32
+ for (const key in options.router) {
33
+ eachContractProcedureLeaf(
34
+ {
35
+ router: options.router[key],
36
+ path: [...options.path, key]
37
+ },
38
+ callback,
39
+ result
40
+ );
41
+ }
42
+ }
43
+ return result;
44
+ }
45
+ function standardizeHTTPPath(path) {
46
+ return `/${path.replace(/\/{2,}/g, "/").replace(/^\/|\/$/g, "")}`;
47
+ }
48
+
49
+ export {
50
+ eachContractProcedureLeaf,
51
+ standardizeHTTPPath
52
+ };
53
+ //# sourceMappingURL=chunk-7HD5IZWG.js.map
package/dist/fetch.js CHANGED
@@ -1,12 +1,16 @@
1
+ import {
2
+ eachContractProcedureLeaf,
3
+ standardizeHTTPPath
4
+ } from "./chunk-7HD5IZWG.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 { createProcedureCaller, isLazy, isProcedure, LAZY_LOADER_SYMBOL, LAZY_ROUTER_PREFIX_SYMBOL, ORPCError } 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,14 +21,20 @@ 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;
28
+ const procedure = isLazy(match.procedure) ? (await match.procedure[LAZY_LOADER_SYMBOL]()).default : match.procedure;
25
29
  const path = match.path;
26
- const params = procedure.zz$p.contract.zz$cp.InputSchema ? zodCoerce(
27
- procedure.zz$p.contract.zz$cp.InputSchema,
30
+ if (!isProcedure(procedure)) {
31
+ throw new ORPCError({
32
+ code: "NOT_FOUND",
33
+ message: "Not found"
34
+ });
35
+ }
36
+ const params = procedure.zz$p.contract["~orpc"].InputSchema ? zodCoerce(
37
+ procedure.zz$p.contract["~orpc"].InputSchema,
28
38
  match.params,
29
39
  { bracketNotation: true }
30
40
  ) : match.params;
@@ -35,7 +45,7 @@ function createOpenAPIHandler(createHonoRouter) {
35
45
  procedure,
36
46
  path
37
47
  });
38
- const output = await caller(mergedInput);
48
+ const output = await caller(mergedInput, { signal: options.signal });
39
49
  const { body, headers } = serializer.serialize(output);
40
50
  return new Response(body, {
41
51
  status: 200,
@@ -43,10 +53,15 @@ function createOpenAPIHandler(createHonoRouter) {
43
53
  });
44
54
  };
45
55
  try {
46
- return await options.hooks?.(context, {
47
- next: handler,
48
- response: (response) => response
49
- }) ?? await handler();
56
+ return await executeWithHooks({
57
+ context,
58
+ hooks: options,
59
+ execute: handler,
60
+ input: options.request,
61
+ meta: {
62
+ signal: options.signal
63
+ }
64
+ });
50
65
  } catch (e) {
51
66
  const error = toORPCError(e);
52
67
  try {
@@ -69,27 +84,44 @@ function createOpenAPIHandler(createHonoRouter) {
69
84
  };
70
85
  }
71
86
  var routingCache = /* @__PURE__ */ new Map();
87
+ var pendingCache = /* @__PURE__ */ new Map();
72
88
  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);
89
+ const addRoutes = (routing, pending, options) => {
90
+ const lazies = eachContractProcedureLeaf(options, ({ path, contract }) => {
91
+ const method = contract["~orpc"].route?.method ?? "POST";
92
+ const httpPath = contract["~orpc"].route?.path ? openAPIPathToRouterPath(contract["~orpc"].route?.path) : `/${path.map(encodeURIComponent).join("/")}`;
93
+ routing.add(method, httpPath, path);
94
+ });
95
+ pending.ref.push(...lazies);
96
+ };
97
+ return async (router, method, pathname) => {
98
+ const pending = (() => {
99
+ let pending2 = pendingCache.get(router);
100
+ if (!pending2) {
101
+ pending2 = { ref: [] };
102
+ pendingCache.set(router, pending2);
103
+ }
104
+ return pending2;
105
+ })();
106
+ const routing = (() => {
107
+ let routing2 = routingCache.get(router);
108
+ if (!routing2) {
109
+ routing2 = createHonoRouter();
110
+ routingCache.set(router, routing2);
111
+ addRoutes(routing2, pending, { router, path: [] });
112
+ }
113
+ return routing2;
114
+ })();
115
+ const newPending = [];
116
+ for (const item of pending.ref) {
117
+ if (LAZY_ROUTER_PREFIX_SYMBOL in item.lazy && item.lazy[LAZY_ROUTER_PREFIX_SYMBOL] && !pathname.startsWith(item.lazy[LAZY_ROUTER_PREFIX_SYMBOL]) && !pathname.startsWith(`/${item.path.map(encodeURIComponent).join("/")}`)) {
118
+ newPending.push(item);
119
+ continue;
120
+ }
121
+ const router2 = (await item.lazy[LAZY_LOADER_SYMBOL]()).default;
122
+ addRoutes(routing, pending, { path: item.path, router: router2 });
92
123
  }
124
+ pending.ref = newPending;
93
125
  const [matches, params_] = routing.match(method, pathname);
94
126
  const [match] = matches.sort((a, b) => {
95
127
  return Object.keys(a[1]).length - Object.keys(b[1]).length;
@@ -97,18 +129,25 @@ function createResolveRouter(createHonoRouter) {
97
129
  if (!match) {
98
130
  return void 0;
99
131
  }
100
- const path = match[0][0];
101
- const procedure = match[0][1];
132
+ const path = match[0];
102
133
  const params = params_ ? mapValues(
103
134
  match[1],
104
135
  (v) => params_[v]
105
136
  ) : match[1];
106
- return {
137
+ let current = router;
138
+ for (const segment of path) {
139
+ if (typeof current !== "object" && typeof current !== "function" || !current) {
140
+ current = void 0;
141
+ break;
142
+ }
143
+ current = current[segment];
144
+ }
145
+ return isProcedure(current) || isLazy(current) ? {
107
146
  path,
108
- procedure,
147
+ procedure: current,
109
148
  params: { ...params }
110
149
  // params from hono not a normal object, so we need spread here
111
- };
150
+ } : void 0;
112
151
  };
113
152
  }
114
153
  function mergeParamsAndInput(coercedParams, input) {
@@ -125,7 +164,7 @@ function mergeParamsAndInput(coercedParams, input) {
125
164
  }
126
165
  async function deserializeInput(request, procedure) {
127
166
  const deserializer = new OpenAPIDeserializer({
128
- schema: procedure.zz$p.contract.zz$cp.InputSchema
167
+ schema: procedure.zz$p.contract["~orpc"].InputSchema
129
168
  });
130
169
  try {
131
170
  return await deserializer.deserialize(request);
@@ -148,13 +187,13 @@ function openAPIPathToRouterPath(path) {
148
187
  return standardizeHTTPPath(path).replace(/\{([^}]+)\}/g, ":$1");
149
188
  }
150
189
 
151
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router.js
190
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router.js
152
191
  var METHOD_NAME_ALL = "ALL";
153
192
  var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
154
193
  var UnsupportedPathError = class extends Error {
155
194
  };
156
195
 
157
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/utils/url.js
196
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/utils/url.js
158
197
  var checkOptionalParameter = (path) => {
159
198
  if (!path.match(/\:.+\?$/)) {
160
199
  return null;
@@ -183,7 +222,7 @@ var checkOptionalParameter = (path) => {
183
222
  return results.filter((v, i, a) => a.indexOf(v) === i);
184
223
  };
185
224
 
186
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/reg-exp-router/node.js
225
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/reg-exp-router/node.js
187
226
  var LABEL_REG_EXP_STR = "[^/]+";
188
227
  var ONLY_WILDCARD_REG_EXP_STR = ".*";
189
228
  var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
@@ -288,7 +327,7 @@ var Node = class {
288
327
  }
289
328
  };
290
329
 
291
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/reg-exp-router/trie.js
330
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/reg-exp-router/trie.js
292
331
  var Trie = class {
293
332
  #context = { varIndex: 0 };
294
333
  #root = new Node();
@@ -344,7 +383,7 @@ var Trie = class {
344
383
  }
345
384
  };
346
385
 
347
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/reg-exp-router/router.js
386
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/reg-exp-router/router.js
348
387
  var emptyParam = [];
349
388
  var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
350
389
  var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
@@ -545,7 +584,7 @@ function createOpenAPIServerHandler() {
545
584
  return createOpenAPIHandler(() => new RegExpRouter());
546
585
  }
547
586
 
548
- // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/linear-router/router.js
587
+ // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/linear-router/router.js
549
588
  var emptyParams = /* @__PURE__ */ Object.create(null);
550
589
  var splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g;
551
590
  var splitByStarRe = /\*/;
@@ -663,7 +702,6 @@ export {
663
702
  createOpenAPIHandler,
664
703
  createOpenAPIServerHandler,
665
704
  createOpenAPIServerlessHandler,
666
- createResolveRouter,
667
- openAPIPathToRouterPath
705
+ createResolveRouter
668
706
  };
669
707
  //# sourceMappingURL=fetch.js.map