@orpc/openapi 0.0.0-next.ee0aeaf → 0.0.0-next.fd1db03

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.
Files changed (34) hide show
  1. package/dist/chunk-KNYXLM77.js +107 -0
  2. package/dist/fetch.js +585 -631
  3. package/dist/index.js +383 -4487
  4. package/dist/src/fetch/bracket-notation.d.ts +84 -0
  5. package/dist/src/fetch/index.d.ts +9 -3
  6. package/dist/src/fetch/input-structure-compact.d.ts +6 -0
  7. package/dist/src/fetch/input-structure-detailed.d.ts +11 -0
  8. package/dist/src/fetch/openapi-handler-server.d.ts +7 -0
  9. package/dist/src/fetch/openapi-handler-serverless.d.ts +7 -0
  10. package/dist/src/fetch/openapi-handler.d.ts +33 -0
  11. package/dist/src/fetch/openapi-payload-codec.d.ts +15 -0
  12. package/dist/src/fetch/openapi-procedure-matcher.d.ts +19 -0
  13. package/dist/src/fetch/schema-coercer.d.ts +10 -0
  14. package/dist/src/index.d.ts +10 -1
  15. package/dist/src/json-serializer.d.ts +5 -0
  16. package/dist/src/openapi-content-builder.d.ts +10 -0
  17. package/dist/src/openapi-error.d.ts +3 -0
  18. package/dist/src/openapi-generator.d.ts +56 -0
  19. package/dist/src/openapi-input-structure-parser.d.ts +22 -0
  20. package/dist/src/openapi-output-structure-parser.d.ts +18 -0
  21. package/dist/src/openapi-parameters-builder.d.ts +12 -0
  22. package/dist/src/openapi-path-parser.d.ts +8 -0
  23. package/dist/src/openapi.d.ts +3 -0
  24. package/dist/src/schema-converter.d.ts +16 -0
  25. package/dist/src/schema-utils.d.ts +11 -0
  26. package/dist/src/schema.d.ts +12 -0
  27. package/dist/src/utils.d.ts +6 -5
  28. package/package.json +9 -7
  29. package/dist/chunk-7HD5IZWG.js +0 -53
  30. package/dist/src/fetch/base-handler.d.ts +0 -13
  31. package/dist/src/fetch/server-handler.d.ts +0 -3
  32. package/dist/src/fetch/serverless-handler.d.ts +0 -3
  33. package/dist/src/generator.d.ts +0 -24
  34. package/dist/src/zod-to-json-schema.d.ts +0 -43
package/dist/fetch.js CHANGED
@@ -1,707 +1,661 @@
1
1
  import {
2
- eachContractProcedureLeaf,
2
+ JSONSerializer,
3
+ forEachContractProcedure,
3
4
  standardizeHTTPPath
4
- } from "./chunk-7HD5IZWG.js";
5
+ } from "./chunk-KNYXLM77.js";
5
6
 
6
- // src/fetch/base-handler.ts
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";
9
- import { OpenAPIDeserializer, OpenAPISerializer, zodCoerce } from "@orpc/transformer";
10
- function createOpenAPIHandler(createHonoRouter) {
11
- const resolveRouter = createResolveRouter(createHonoRouter);
12
- return async (options) => {
13
- if (options.request.headers.get(ORPC_PROTOCOL_HEADER)?.includes(ORPC_PROTOCOL_VALUE)) {
14
- return void 0;
15
- }
16
- const context = await value(options.context);
17
- const accept = options.request.headers.get("Accept") || void 0;
18
- const serializer = new OpenAPISerializer({ accept });
19
- const handler = async () => {
20
- const url = new URL(options.request.url);
21
- const pathname = `/${trim(url.pathname.replace(options.prefix ?? "", ""), "/")}`;
22
- const customMethod = options.request.method === "POST" ? url.searchParams.get("method")?.toUpperCase() : void 0;
23
- const method = customMethod || options.request.method;
24
- const match = await resolveRouter(options.router, method, pathname);
25
- if (!match) {
26
- throw new ORPCError({ code: "NOT_FOUND", message: "Not found" });
27
- }
28
- const procedure = isLazy(match.procedure) ? (await match.procedure[LAZY_LOADER_SYMBOL]()).default : match.procedure;
29
- const path = match.path;
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,
38
- match.params,
39
- { bracketNotation: true }
40
- ) : match.params;
41
- const input = await deserializeInput(options.request, procedure);
42
- const mergedInput = mergeParamsAndInput(params, input);
43
- const caller = createProcedureCaller({
44
- context,
45
- procedure,
46
- path
47
- });
48
- const output = await caller(mergedInput, { signal: options.signal });
49
- const { body, headers } = serializer.serialize(output);
50
- return new Response(body, {
51
- status: 200,
52
- headers
53
- });
54
- };
55
- try {
56
- return await executeWithHooks({
57
- context,
58
- hooks: options,
59
- execute: handler,
60
- input: options.request,
61
- meta: {
62
- signal: options.signal
63
- }
7
+ // src/fetch/bracket-notation.ts
8
+ import { isPlainObject } from "@orpc/shared";
9
+ function serialize(payload, parentKey = "") {
10
+ if (!Array.isArray(payload) && !isPlainObject(payload))
11
+ return [["", payload]];
12
+ const result = [];
13
+ function helper(value, path) {
14
+ if (Array.isArray(value)) {
15
+ value.forEach((item, index) => {
16
+ helper(item, [...path, String(index)]);
64
17
  });
65
- } catch (e) {
66
- const error = toORPCError(e);
67
- try {
68
- const { body, headers } = serializer.serialize(error.toJSON());
69
- return new Response(body, {
70
- status: error.status,
71
- headers
72
- });
73
- } catch (e2) {
74
- const error2 = toORPCError(e2);
75
- const { body, headers } = new OpenAPISerializer().serialize(
76
- error2.toJSON()
77
- );
78
- return new Response(body, {
79
- status: error2.status,
80
- headers
81
- });
18
+ } else if (isPlainObject(value)) {
19
+ for (const [key, val] of Object.entries(value)) {
20
+ helper(val, [...path, key]);
82
21
  }
22
+ } else {
23
+ result.push([stringifyPath(path), value]);
83
24
  }
84
- };
25
+ }
26
+ helper(payload, parentKey ? [parentKey] : []);
27
+ return result;
85
28
  }
86
- var routingCache = /* @__PURE__ */ new Map();
87
- var pendingCache = /* @__PURE__ */ new Map();
88
- function createResolveRouter(createHonoRouter) {
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 });
29
+ function deserialize(entities) {
30
+ if (entities.length === 0) {
31
+ return void 0;
32
+ }
33
+ const isRootArray = entities.every(([path]) => path === "");
34
+ const result = isRootArray ? [] : {};
35
+ const arrayPushPaths = /* @__PURE__ */ new Set();
36
+ for (const [path, _] of entities) {
37
+ const segments = parsePath(path);
38
+ const base = segments.slice(0, -1).join(".");
39
+ const last = segments[segments.length - 1];
40
+ if (last === "") {
41
+ arrayPushPaths.add(base);
42
+ } else {
43
+ arrayPushPaths.delete(base);
123
44
  }
124
- pending.ref = newPending;
125
- const [matches, params_] = routing.match(method, pathname);
126
- const [match] = matches.sort((a, b) => {
127
- return Object.keys(a[1]).length - Object.keys(b[1]).length;
128
- });
129
- if (!match) {
130
- return void 0;
45
+ }
46
+ function setValue(obj, segments, value, fullPath) {
47
+ const [first, ...rest_] = segments;
48
+ if (Array.isArray(obj) && first === "") {
49
+ ;
50
+ obj.push(value);
51
+ return;
131
52
  }
132
- const path = match[0];
133
- const params = params_ ? mapValues(
134
- match[1],
135
- (v) => params_[v]
136
- ) : match[1];
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;
53
+ const objAsRecord = obj;
54
+ if (rest_.length === 0) {
55
+ objAsRecord[first] = value;
56
+ return;
57
+ }
58
+ const rest = rest_;
59
+ if (rest[0] === "") {
60
+ const pathToCheck = segments.slice(0, -1).join(".");
61
+ if (rest.length === 1 && arrayPushPaths.has(pathToCheck)) {
62
+ if (!(first in objAsRecord)) {
63
+ objAsRecord[first] = [];
64
+ }
65
+ if (Array.isArray(objAsRecord[first])) {
66
+ ;
67
+ objAsRecord[first].push(value);
68
+ return;
69
+ }
142
70
  }
143
- current = current[segment];
71
+ if (!(first in objAsRecord)) {
72
+ objAsRecord[first] = {};
73
+ }
74
+ const target = objAsRecord[first];
75
+ target[""] = value;
76
+ return;
144
77
  }
145
- return isProcedure(current) || isLazy(current) ? {
146
- path,
147
- procedure: current,
148
- params: { ...params }
149
- // params from hono not a normal object, so we need spread here
150
- } : void 0;
151
- };
152
- }
153
- function mergeParamsAndInput(coercedParams, input) {
154
- if (Object.keys(coercedParams).length === 0) {
155
- return input;
156
- }
157
- if (!isPlainObject(input)) {
158
- return coercedParams;
78
+ if (!(first in objAsRecord)) {
79
+ objAsRecord[first] = {};
80
+ }
81
+ setValue(
82
+ objAsRecord[first],
83
+ rest,
84
+ value,
85
+ fullPath
86
+ );
159
87
  }
160
- return {
161
- ...coercedParams,
162
- ...input
163
- };
164
- }
165
- async function deserializeInput(request, procedure) {
166
- const deserializer = new OpenAPIDeserializer({
167
- schema: procedure.zz$p.contract["~orpc"].InputSchema
168
- });
169
- try {
170
- return await deserializer.deserialize(request);
171
- } catch (e) {
172
- throw new ORPCError({
173
- code: "BAD_REQUEST",
174
- message: "Cannot parse request. Please check the request body and Content-Type header.",
175
- cause: e
176
- });
88
+ for (const [path, value] of entities) {
89
+ const segments = parsePath(path);
90
+ setValue(result, segments, value, path);
177
91
  }
92
+ return result;
178
93
  }
179
- function toORPCError(e) {
180
- return e instanceof ORPCError ? e : new ORPCError({
181
- code: "INTERNAL_SERVER_ERROR",
182
- message: "Internal server error",
183
- cause: e
94
+ function escapeSegment(segment) {
95
+ return segment.replace(/[\\[\]]/g, (match) => {
96
+ switch (match) {
97
+ case "\\":
98
+ return "\\\\";
99
+ case "[":
100
+ return "\\[";
101
+ case "]":
102
+ return "\\]";
103
+ default:
104
+ return match;
105
+ }
184
106
  });
185
107
  }
186
- function openAPIPathToRouterPath(path) {
187
- return standardizeHTTPPath(path).replace(/\{([^}]+)\}/g, ":$1");
108
+ function stringifyPath(path) {
109
+ const [first, ...rest] = path;
110
+ const firstSegment = escapeSegment(first);
111
+ const base = first === "" ? "" : firstSegment;
112
+ return rest.reduce(
113
+ (result, segment) => `${result}[${escapeSegment(segment)}]`,
114
+ base
115
+ );
188
116
  }
189
-
190
- // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router.js
191
- var METHOD_NAME_ALL = "ALL";
192
- var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
193
- var UnsupportedPathError = class extends Error {
194
- };
195
-
196
- // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/utils/url.js
197
- var checkOptionalParameter = (path) => {
198
- if (!path.match(/\:.+\?$/)) {
199
- return null;
200
- }
201
- const segments = path.split("/");
202
- const results = [];
203
- let basePath = "";
204
- segments.forEach((segment) => {
205
- if (segment !== "" && !/\:/.test(segment)) {
206
- basePath += "/" + segment;
207
- } else if (/\:/.test(segment)) {
208
- if (/\?/.test(segment)) {
209
- if (results.length === 0 && basePath === "") {
210
- results.push("/");
117
+ function parsePath(path) {
118
+ if (path === "")
119
+ return [""];
120
+ const result = [];
121
+ let currentSegment = "";
122
+ let inBracket = false;
123
+ let bracketContent = "";
124
+ let backslashCount = 0;
125
+ for (let i = 0; i < path.length; i++) {
126
+ const char = path[i];
127
+ if (char === "\\") {
128
+ backslashCount++;
129
+ continue;
130
+ }
131
+ if (backslashCount > 0) {
132
+ const literalBackslashes = "\\".repeat(Math.floor(backslashCount / 2));
133
+ if (char === "[" || char === "]") {
134
+ if (backslashCount % 2 === 1) {
135
+ if (inBracket) {
136
+ bracketContent += literalBackslashes + char;
137
+ } else {
138
+ currentSegment += literalBackslashes + char;
139
+ }
211
140
  } else {
212
- results.push(basePath);
141
+ if (inBracket) {
142
+ bracketContent += literalBackslashes;
143
+ } else {
144
+ currentSegment += literalBackslashes;
145
+ }
146
+ if (char === "[" && !inBracket) {
147
+ if (currentSegment !== "" || result.length === 0) {
148
+ result.push(currentSegment);
149
+ }
150
+ inBracket = true;
151
+ bracketContent = "";
152
+ currentSegment = "";
153
+ } else if (char === "]" && inBracket) {
154
+ result.push(bracketContent);
155
+ inBracket = false;
156
+ bracketContent = "";
157
+ } else {
158
+ if (inBracket) {
159
+ bracketContent += char;
160
+ } else {
161
+ currentSegment += char;
162
+ }
163
+ }
213
164
  }
214
- const optionalSegment = segment.replace("?", "");
215
- basePath += "/" + optionalSegment;
216
- results.push(basePath);
217
165
  } else {
218
- basePath += "/" + segment;
166
+ const allBackslashes = "\\".repeat(backslashCount);
167
+ if (inBracket) {
168
+ bracketContent += allBackslashes + char;
169
+ } else {
170
+ currentSegment += allBackslashes + char;
171
+ }
219
172
  }
173
+ backslashCount = 0;
174
+ continue;
220
175
  }
221
- });
222
- return results.filter((v, i, a) => a.indexOf(v) === i);
223
- };
224
-
225
- // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/reg-exp-router/node.js
226
- var LABEL_REG_EXP_STR = "[^/]+";
227
- var ONLY_WILDCARD_REG_EXP_STR = ".*";
228
- var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
229
- var PATH_ERROR = Symbol();
230
- var regExpMetaChars = new Set(".\\+*[^]$()");
231
- function compareKey(a, b) {
232
- if (a.length === 1) {
233
- return b.length === 1 ? a < b ? -1 : 1 : -1;
234
- }
235
- if (b.length === 1) {
236
- return 1;
237
- }
238
- if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
239
- return 1;
240
- } else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
241
- return -1;
242
- }
243
- if (a === LABEL_REG_EXP_STR) {
244
- return 1;
245
- } else if (b === LABEL_REG_EXP_STR) {
246
- return -1;
247
- }
248
- return a.length === b.length ? a < b ? -1 : 1 : b.length - a.length;
249
- }
250
- var Node = class {
251
- #index;
252
- #varIndex;
253
- #children = /* @__PURE__ */ Object.create(null);
254
- insert(tokens, index, paramMap, context, pathErrorCheckOnly) {
255
- if (tokens.length === 0) {
256
- if (this.#index !== void 0) {
257
- throw PATH_ERROR;
258
- }
259
- if (pathErrorCheckOnly) {
260
- return;
176
+ if (char === "[" && !inBracket) {
177
+ if (currentSegment !== "" || result.length === 0) {
178
+ result.push(currentSegment);
261
179
  }
262
- this.#index = index;
263
- return;
180
+ inBracket = true;
181
+ bracketContent = "";
182
+ currentSegment = "";
183
+ continue;
264
184
  }
265
- const [token, ...restTokens] = tokens;
266
- const pattern = token === "*" ? restTokens.length === 0 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
267
- let node;
268
- if (pattern) {
269
- const name = pattern[1];
270
- let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
271
- if (name && pattern[2]) {
272
- regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
273
- if (/\((?!\?:)/.test(regexpStr)) {
274
- throw PATH_ERROR;
275
- }
276
- }
277
- node = this.#children[regexpStr];
278
- if (!node) {
279
- if (Object.keys(this.#children).some(
280
- (k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
281
- )) {
282
- throw PATH_ERROR;
283
- }
284
- if (pathErrorCheckOnly) {
285
- return;
286
- }
287
- node = this.#children[regexpStr] = new Node();
288
- if (name !== "") {
289
- node.#varIndex = context.varIndex++;
290
- }
291
- }
292
- if (!pathErrorCheckOnly && name !== "") {
293
- paramMap.push([name, node.#varIndex]);
294
- }
185
+ if (char === "]" && inBracket) {
186
+ result.push(bracketContent);
187
+ inBracket = false;
188
+ bracketContent = "";
189
+ continue;
190
+ }
191
+ if (inBracket) {
192
+ bracketContent += char;
295
193
  } else {
296
- node = this.#children[token];
297
- if (!node) {
298
- if (Object.keys(this.#children).some(
299
- (k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
300
- )) {
301
- throw PATH_ERROR;
302
- }
303
- if (pathErrorCheckOnly) {
304
- return;
305
- }
306
- node = this.#children[token] = new Node();
307
- }
194
+ currentSegment += char;
308
195
  }
309
- node.insert(restTokens, index, paramMap, context, pathErrorCheckOnly);
310
196
  }
311
- buildRegExpStr() {
312
- const childKeys = Object.keys(this.#children).sort(compareKey);
313
- const strList = childKeys.map((k) => {
314
- const c = this.#children[k];
315
- return (typeof c.#varIndex === "number" ? `(${k})@${c.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr();
316
- });
317
- if (typeof this.#index === "number") {
318
- strList.unshift(`#${this.#index}`);
197
+ if (backslashCount > 0) {
198
+ const remainingBackslashes = "\\".repeat(backslashCount);
199
+ if (inBracket) {
200
+ bracketContent += remainingBackslashes;
201
+ } else {
202
+ currentSegment += remainingBackslashes;
319
203
  }
320
- if (strList.length === 0) {
321
- return "";
204
+ }
205
+ if (inBracket) {
206
+ if (currentSegment !== "" || result.length === 0) {
207
+ result.push(currentSegment);
322
208
  }
323
- if (strList.length === 1) {
324
- return strList[0];
209
+ result.push(`[${bracketContent}`);
210
+ } else if (currentSegment !== "" || result.length === 0) {
211
+ result.push(currentSegment);
212
+ }
213
+ return result;
214
+ }
215
+
216
+ // src/fetch/input-structure-compact.ts
217
+ import { isPlainObject as isPlainObject2 } from "@orpc/shared";
218
+ var InputStructureCompact = class {
219
+ build(params, payload) {
220
+ if (Object.keys(params).length === 0) {
221
+ return payload;
325
222
  }
326
- return "(?:" + strList.join("|") + ")";
223
+ if (!isPlainObject2(payload)) {
224
+ return params;
225
+ }
226
+ return {
227
+ ...params,
228
+ ...payload
229
+ };
327
230
  }
328
231
  };
329
232
 
330
- // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/reg-exp-router/trie.js
331
- var Trie = class {
332
- #context = { varIndex: 0 };
333
- #root = new Node();
334
- insert(path, index, pathErrorCheckOnly) {
335
- const paramAssoc = [];
336
- const groups = [];
337
- for (let i = 0; ; ) {
338
- let replaced = false;
339
- path = path.replace(/\{[^}]+\}/g, (m) => {
340
- const mark = `@\\${i}`;
341
- groups[i] = [mark, m];
342
- i++;
343
- replaced = true;
344
- return mark;
345
- });
346
- if (!replaced) {
347
- break;
233
+ // src/fetch/input-structure-detailed.ts
234
+ var InputStructureDetailed = class {
235
+ build(params, query, headers, body) {
236
+ return {
237
+ params,
238
+ query,
239
+ headers,
240
+ body
241
+ };
242
+ }
243
+ };
244
+
245
+ // src/fetch/openapi-handler.ts
246
+ import { createProcedureClient, ORPCError as ORPCError2 } from "@orpc/server";
247
+ import { executeWithHooks, isPlainObject as isPlainObject3, ORPC_HANDLER_HEADER, trim } from "@orpc/shared";
248
+
249
+ // src/fetch/openapi-payload-codec.ts
250
+ import { ORPCError } from "@orpc/server";
251
+ import { findDeepMatches } from "@orpc/shared";
252
+ import cd from "content-disposition";
253
+ import { safeParse } from "fast-content-type-parse";
254
+ import wcmatch from "wildcard-match";
255
+ var OpenAPIPayloadCodec = class {
256
+ constructor(jsonSerializer) {
257
+ this.jsonSerializer = jsonSerializer;
258
+ }
259
+ encode(payload, accept) {
260
+ const typeMatchers = (accept?.split(",").map(safeParse) ?? [{ type: "*/*" }]).map(({ type }) => wcmatch(type));
261
+ if (payload instanceof Blob) {
262
+ const contentType = payload.type || "application/octet-stream";
263
+ if (typeMatchers.some((isMatch) => isMatch(contentType))) {
264
+ const headers = new Headers({
265
+ "Content-Type": contentType
266
+ });
267
+ if (payload instanceof File && payload.name) {
268
+ headers.append("Content-Disposition", cd(payload.name));
269
+ }
270
+ return {
271
+ body: payload,
272
+ headers
273
+ };
348
274
  }
349
275
  }
350
- const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
351
- for (let i = groups.length - 1; i >= 0; i--) {
352
- const [mark] = groups[i];
353
- for (let j = tokens.length - 1; j >= 0; j--) {
354
- if (tokens[j].indexOf(mark) !== -1) {
355
- tokens[j] = tokens[j].replace(mark, groups[i][1]);
356
- break;
357
- }
276
+ const handledPayload = this.jsonSerializer.serialize(payload);
277
+ const hasBlobs = findDeepMatches((v) => v instanceof Blob, handledPayload).values.length > 0;
278
+ const isExpectedMultipartFormData = typeMatchers.some(
279
+ (isMatch) => isMatch("multipart/form-data")
280
+ );
281
+ if (hasBlobs && isExpectedMultipartFormData) {
282
+ return this.encodeAsFormData(handledPayload);
283
+ }
284
+ if (typeMatchers.some((isMatch) => isMatch("application/json"))) {
285
+ return this.encodeAsJSON(handledPayload);
286
+ }
287
+ if (typeMatchers.some(
288
+ (isMatch) => isMatch("application/x-www-form-urlencoded")
289
+ )) {
290
+ return this.encodeAsURLSearchParams(handledPayload);
291
+ }
292
+ if (isExpectedMultipartFormData) {
293
+ return this.encodeAsFormData(handledPayload);
294
+ }
295
+ throw new ORPCError({
296
+ code: "NOT_ACCEPTABLE",
297
+ message: `Unsupported content-type: ${accept}`
298
+ });
299
+ }
300
+ encodeAsJSON(payload) {
301
+ if (payload === void 0) {
302
+ return {
303
+ body: void 0,
304
+ headers: new Headers({
305
+ "content-type": "application/json"
306
+ })
307
+ };
308
+ }
309
+ return {
310
+ body: JSON.stringify(payload),
311
+ headers: new Headers({
312
+ "content-type": "application/json"
313
+ })
314
+ };
315
+ }
316
+ encodeAsFormData(payload) {
317
+ const form = new FormData();
318
+ for (const [path, value] of serialize(payload)) {
319
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
320
+ form.append(path, value.toString());
321
+ } else if (value === null) {
322
+ form.append(path, "null");
323
+ } else if (value instanceof Date) {
324
+ form.append(
325
+ path,
326
+ Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString()
327
+ );
328
+ } else if (value instanceof Blob) {
329
+ form.append(path, value);
358
330
  }
359
331
  }
360
- this.#root.insert(tokens, index, paramAssoc, this.#context, pathErrorCheckOnly);
361
- return paramAssoc;
362
- }
363
- buildRegExp() {
364
- let regexp = this.#root.buildRegExpStr();
365
- if (regexp === "") {
366
- return [/^$/, [], []];
367
- }
368
- let captureIndex = 0;
369
- const indexReplacementMap = [];
370
- const paramReplacementMap = [];
371
- regexp = regexp.replace(/#(\d+)|@(\d+)|\.\*\$/g, (_, handlerIndex, paramIndex) => {
372
- if (handlerIndex !== void 0) {
373
- indexReplacementMap[++captureIndex] = Number(handlerIndex);
374
- return "$()";
332
+ return {
333
+ body: form
334
+ };
335
+ }
336
+ encodeAsURLSearchParams(payload) {
337
+ const params = new URLSearchParams();
338
+ for (const [path, value] of serialize(payload)) {
339
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
340
+ params.append(path, value.toString());
341
+ } else if (value === null) {
342
+ params.append(path, "null");
343
+ } else if (value instanceof Date) {
344
+ params.append(
345
+ path,
346
+ Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString()
347
+ );
375
348
  }
376
- if (paramIndex !== void 0) {
377
- paramReplacementMap[Number(paramIndex)] = ++captureIndex;
378
- return "";
349
+ }
350
+ return {
351
+ body: params.toString(),
352
+ headers: new Headers({
353
+ "content-type": "application/x-www-form-urlencoded"
354
+ })
355
+ };
356
+ }
357
+ async decode(re) {
358
+ if (re instanceof Headers || re instanceof URLSearchParams || re instanceof FormData) {
359
+ return deserialize([...re.entries()]);
360
+ }
361
+ const contentType = re.headers.get("content-type");
362
+ const contentDisposition = re.headers.get("content-disposition");
363
+ const fileName = contentDisposition ? cd.parse(contentDisposition).parameters.filename : void 0;
364
+ if (fileName) {
365
+ const blob2 = await re.blob();
366
+ const file = new File([blob2], fileName, {
367
+ type: blob2.type
368
+ });
369
+ return file;
370
+ }
371
+ if (!contentType || contentType.startsWith("application/json")) {
372
+ if (!re.body) {
373
+ return void 0;
379
374
  }
380
- return "";
375
+ return await re.json();
376
+ }
377
+ if (contentType.startsWith("application/x-www-form-urlencoded")) {
378
+ const params = new URLSearchParams(await re.text());
379
+ return this.decode(params);
380
+ }
381
+ if (contentType.startsWith("text/")) {
382
+ const text = await re.text();
383
+ return text;
384
+ }
385
+ if (contentType.startsWith("multipart/form-data")) {
386
+ const form = await re.formData();
387
+ return this.decode(form);
388
+ }
389
+ const blob = await re.blob();
390
+ return new File([blob], "blob", {
391
+ type: blob.type
381
392
  });
382
- return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
383
393
  }
384
394
  };
385
395
 
386
- // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/reg-exp-router/router.js
387
- var emptyParam = [];
388
- var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
389
- var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
390
- function buildWildcardRegExp(path) {
391
- return wildcardRegExpCache[path] ??= new RegExp(
392
- path === "*" ? "" : `^${path.replace(
393
- /\/\*$|([.\\+*[^\]$()])/g,
394
- (_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)"
395
- )}$`
396
- );
397
- }
398
- function clearWildcardRegExpCache() {
399
- wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
400
- }
401
- function buildMatcherFromPreprocessedRoutes(routes) {
402
- const trie = new Trie();
403
- const handlerData = [];
404
- if (routes.length === 0) {
405
- return nullMatcher;
406
- }
407
- const routesWithStaticPathFlag = routes.map(
408
- (route) => [!/\*|\/:/.test(route[0]), ...route]
409
- ).sort(
410
- ([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
411
- );
412
- const staticMap = /* @__PURE__ */ Object.create(null);
413
- for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
414
- const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
415
- if (pathErrorCheckOnly) {
416
- staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
417
- } else {
418
- j++;
419
- }
420
- let paramAssoc;
421
- try {
422
- paramAssoc = trie.insert(path, j, pathErrorCheckOnly);
423
- } catch (e) {
424
- throw e === PATH_ERROR ? new UnsupportedPathError(path) : e;
396
+ // src/fetch/openapi-procedure-matcher.ts
397
+ import { getLazyRouterPrefix, getRouterChild, isProcedure, unlazy } from "@orpc/server";
398
+ import { mapValues } from "@orpc/shared";
399
+ var OpenAPIProcedureMatcher = class {
400
+ constructor(hono, router) {
401
+ this.hono = hono;
402
+ this.router = router;
403
+ this.pendingRouters = [{ path: [], router }];
404
+ }
405
+ pendingRouters;
406
+ async match(method, pathname) {
407
+ await this.handlePendingRouters(pathname);
408
+ const [matches, paramStash] = this.hono.match(method, pathname);
409
+ const [match] = matches.sort((a, b) => {
410
+ const slashCountA = a[0][0].split("/").length;
411
+ const slashCountB = b[0][0].split("/").length;
412
+ if (slashCountA !== slashCountB) {
413
+ return slashCountB - slashCountA;
414
+ }
415
+ const paramsCountA = Object.keys(a[1]).length;
416
+ const paramsCountB = Object.keys(b[1]).length;
417
+ return paramsCountA - paramsCountB;
418
+ });
419
+ if (!match) {
420
+ return void 0;
425
421
  }
426
- if (pathErrorCheckOnly) {
427
- continue;
422
+ const path = match[0][1];
423
+ const params = paramStash ? mapValues(
424
+ match[1],
425
+ // if paramStash is defined, then match[1] is ParamIndexMap
426
+ (v) => paramStash[v]
427
+ ) : match[1];
428
+ const { default: maybeProcedure } = await unlazy(getRouterChild(this.router, ...path));
429
+ if (!isProcedure(maybeProcedure)) {
430
+ return void 0;
428
431
  }
429
- handlerData[j] = handlers.map(([h, paramCount]) => {
430
- const paramIndexMap = /* @__PURE__ */ Object.create(null);
431
- paramCount -= 1;
432
- for (; paramCount >= 0; paramCount--) {
433
- const [key, value2] = paramAssoc[paramCount];
434
- paramIndexMap[key] = value2;
435
- }
436
- return [h, paramIndexMap];
432
+ return {
433
+ path,
434
+ procedure: maybeProcedure,
435
+ params: { ...params }
436
+ // normalize params from hono
437
+ };
438
+ }
439
+ add(path, router) {
440
+ const lazies = forEachContractProcedure({ path, router }, ({ path: path2, contract }) => {
441
+ const method = contract["~orpc"].route?.method ?? "POST";
442
+ const httpPath = contract["~orpc"].route?.path ? this.convertOpenAPIPathToRouterPath(contract["~orpc"].route?.path) : `/${path2.map(encodeURIComponent).join("/")}`;
443
+ this.hono.add(method, httpPath, [httpPath, path2]);
437
444
  });
445
+ this.pendingRouters.push(...lazies);
438
446
  }
439
- const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
440
- for (let i = 0, len = handlerData.length; i < len; i++) {
441
- for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
442
- const map = handlerData[i][j]?.[1];
443
- if (!map) {
447
+ async handlePendingRouters(pathname) {
448
+ const newPendingLazyRouters = [];
449
+ for (const item of this.pendingRouters) {
450
+ const lazyPrefix = getLazyRouterPrefix(item.router);
451
+ if (lazyPrefix && !pathname.startsWith(lazyPrefix) && !pathname.startsWith(`/${item.path.map(encodeURIComponent).join("/")}`)) {
452
+ newPendingLazyRouters.push(item);
444
453
  continue;
445
454
  }
446
- const keys = Object.keys(map);
447
- for (let k = 0, len3 = keys.length; k < len3; k++) {
448
- map[keys[k]] = paramReplacementMap[map[keys[k]]];
449
- }
455
+ const { default: router } = await unlazy(item.router);
456
+ this.add(item.path, router);
450
457
  }
458
+ this.pendingRouters = newPendingLazyRouters;
451
459
  }
452
- const handlerMap = [];
453
- for (const i in indexReplacementMap) {
454
- handlerMap[i] = handlerData[indexReplacementMap[i]];
460
+ convertOpenAPIPathToRouterPath(path) {
461
+ return standardizeHTTPPath(path).replace(/\{([^}]+)\}/g, ":$1");
455
462
  }
456
- return [regexp, handlerMap, staticMap];
457
- }
458
- function findMiddleware(middleware, path) {
459
- if (!middleware) {
460
- return void 0;
463
+ };
464
+
465
+ // src/fetch/schema-coercer.ts
466
+ var CompositeSchemaCoercer = class {
467
+ constructor(coercers) {
468
+ this.coercers = coercers;
461
469
  }
462
- for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
463
- if (buildWildcardRegExp(k).test(path)) {
464
- return [...middleware[k]];
470
+ coerce(schema, value) {
471
+ let current = value;
472
+ for (const coercer of this.coercers) {
473
+ current = coercer.coerce(schema, current);
465
474
  }
475
+ return current;
466
476
  }
467
- return void 0;
468
- }
469
- var RegExpRouter = class {
470
- name = "RegExpRouter";
471
- #middleware;
472
- #routes;
473
- constructor() {
474
- this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
475
- this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
476
- }
477
- add(method, path, handler) {
478
- const middleware = this.#middleware;
479
- const routes = this.#routes;
480
- if (!middleware || !routes) {
481
- throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
482
- }
483
- if (!middleware[method]) {
484
- ;
485
- [middleware, routes].forEach((handlerMap) => {
486
- handlerMap[method] = /* @__PURE__ */ Object.create(null);
487
- Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p) => {
488
- handlerMap[method][p] = [...handlerMap[METHOD_NAME_ALL][p]];
489
- });
490
- });
491
- }
492
- if (path === "/*") {
493
- path = "*";
494
- }
495
- const paramCount = (path.match(/\/:/g) || []).length;
496
- if (/\*$/.test(path)) {
497
- const re = buildWildcardRegExp(path);
498
- if (method === METHOD_NAME_ALL) {
499
- Object.keys(middleware).forEach((m) => {
500
- middleware[m][path] ||= findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
501
- });
502
- } else {
503
- middleware[method][path] ||= findMiddleware(middleware[method], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
477
+ };
478
+
479
+ // src/fetch/openapi-handler.ts
480
+ var OpenAPIHandler = class {
481
+ constructor(hono, router, options) {
482
+ this.options = options;
483
+ const jsonSerializer = options?.jsonSerializer ?? new JSONSerializer();
484
+ this.procedureMatcher = options?.procedureMatcher ?? new OpenAPIProcedureMatcher(hono, router);
485
+ this.payloadCodec = options?.payloadCodec ?? new OpenAPIPayloadCodec(jsonSerializer);
486
+ this.inputStructureCompact = options?.inputBuilderSimple ?? new InputStructureCompact();
487
+ this.inputStructureDetailed = options?.inputBuilderFull ?? new InputStructureDetailed();
488
+ this.compositeSchemaCoercer = new CompositeSchemaCoercer(options?.schemaCoercers ?? []);
489
+ }
490
+ procedureMatcher;
491
+ payloadCodec;
492
+ inputStructureCompact;
493
+ inputStructureDetailed;
494
+ compositeSchemaCoercer;
495
+ condition(request) {
496
+ return request.headers.get(ORPC_HANDLER_HEADER) === null;
497
+ }
498
+ async fetch(request, ...[options]) {
499
+ const context = options?.context;
500
+ const headers = request.headers;
501
+ const accept = headers.get("Accept") || void 0;
502
+ const execute = async () => {
503
+ const url = new URL(request.url);
504
+ const pathname = `/${trim(url.pathname.replace(options?.prefix ?? "", ""), "/")}`;
505
+ const query = url.searchParams;
506
+ const customMethod = request.method === "POST" ? query.get("method")?.toUpperCase() : void 0;
507
+ const matchedMethod = customMethod || request.method;
508
+ const matched = await this.procedureMatcher.match(matchedMethod, pathname);
509
+ if (!matched) {
510
+ throw new ORPCError2({ code: "NOT_FOUND", message: "Not found" });
504
511
  }
505
- Object.keys(middleware).forEach((m) => {
506
- if (method === METHOD_NAME_ALL || method === m) {
507
- Object.keys(middleware[m]).forEach((p) => {
508
- re.test(p) && middleware[m][p].push([handler, paramCount]);
509
- });
510
- }
512
+ const contractDef = matched.procedure["~orpc"].contract["~orpc"];
513
+ const input = await this.decodeInput(matched.procedure, matched.params, request);
514
+ const coercedInput = this.compositeSchemaCoercer.coerce(contractDef.InputSchema, input);
515
+ const client = createProcedureClient({
516
+ context,
517
+ procedure: matched.procedure,
518
+ path: matched.path
511
519
  });
512
- Object.keys(routes).forEach((m) => {
513
- if (method === METHOD_NAME_ALL || method === m) {
514
- Object.keys(routes[m]).forEach(
515
- (p) => re.test(p) && routes[m][p].push([handler, paramCount])
516
- );
517
- }
520
+ const output = await client(coercedInput, { signal: options?.signal });
521
+ const { body, headers: resHeaders } = this.encodeOutput(matched.procedure, output, accept);
522
+ return new Response(body, {
523
+ headers: resHeaders,
524
+ status: contractDef.route?.successStatus ?? 200
518
525
  });
519
- return;
520
- }
521
- const paths = checkOptionalParameter(path) || [path];
522
- for (let i = 0, len = paths.length; i < len; i++) {
523
- const path2 = paths[i];
524
- Object.keys(routes).forEach((m) => {
525
- if (method === METHOD_NAME_ALL || method === m) {
526
- routes[m][path2] ||= [
527
- ...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || []
528
- ];
529
- routes[m][path2].push([handler, paramCount - len + i + 1]);
526
+ };
527
+ try {
528
+ return await executeWithHooks({
529
+ context,
530
+ execute,
531
+ input: request,
532
+ hooks: this.options,
533
+ meta: {
534
+ signal: options?.signal
530
535
  }
531
536
  });
537
+ } catch (e) {
538
+ const error = this.convertToORPCError(e);
539
+ try {
540
+ const { body, headers: headers2 } = this.payloadCodec.encode(error.toJSON(), accept);
541
+ return new Response(body, {
542
+ status: error.status,
543
+ headers: headers2
544
+ });
545
+ } catch (e2) {
546
+ const error2 = this.convertToORPCError(e2);
547
+ const { body, headers: headers2 } = this.payloadCodec.encode(error2.toJSON(), void 0);
548
+ return new Response(body, {
549
+ status: error2.status,
550
+ headers: headers2
551
+ });
552
+ }
553
+ }
554
+ }
555
+ async decodeInput(procedure, params, request) {
556
+ const inputStructure = procedure["~orpc"].contract["~orpc"].route?.inputStructure;
557
+ const url = new URL(request.url);
558
+ const query = url.searchParams;
559
+ const headers = request.headers;
560
+ if (!inputStructure || inputStructure === "compact") {
561
+ return this.inputStructureCompact.build(
562
+ params,
563
+ request.method === "GET" ? await this.payloadCodec.decode(query) : await this.payloadCodec.decode(request)
564
+ );
532
565
  }
566
+ const _expect = inputStructure;
567
+ const decodedQuery = await this.payloadCodec.decode(query);
568
+ const decodedHeaders = await this.payloadCodec.decode(headers);
569
+ const decodedBody = await this.payloadCodec.decode(request);
570
+ return this.inputStructureDetailed.build(params, decodedQuery, decodedHeaders, decodedBody);
533
571
  }
534
- match(method, path) {
535
- clearWildcardRegExpCache();
536
- const matchers = this.#buildAllMatchers();
537
- this.match = (method2, path2) => {
538
- const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
539
- const staticMatch = matcher[2][path2];
540
- if (staticMatch) {
541
- return staticMatch;
572
+ encodeOutput(procedure, output, accept) {
573
+ const outputStructure = procedure["~orpc"].contract["~orpc"].route?.outputStructure;
574
+ if (!outputStructure || outputStructure === "compact") {
575
+ return this.payloadCodec.encode(output, accept);
576
+ }
577
+ const _expect = outputStructure;
578
+ this.assertDetailedOutput(output);
579
+ const headers = new Headers();
580
+ if (output.headers) {
581
+ for (const [key, value] of Object.entries(output.headers)) {
582
+ headers.append(key, value);
542
583
  }
543
- const match = path2.match(matcher[0]);
544
- if (!match) {
545
- return [[], emptyParam];
584
+ }
585
+ const { body, headers: encodedHeaders } = this.payloadCodec.encode(output.body, accept);
586
+ if (encodedHeaders) {
587
+ for (const [key, value] of encodedHeaders.entries()) {
588
+ headers.append(key, value);
546
589
  }
547
- const index = match.indexOf("", 1);
548
- return [matcher[1][index], match];
549
- };
550
- return this.match(method, path);
590
+ }
591
+ return { body, headers };
551
592
  }
552
- #buildAllMatchers() {
553
- const matchers = /* @__PURE__ */ Object.create(null);
554
- Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => {
555
- matchers[method] ||= this.#buildMatcher(method);
556
- });
557
- this.#middleware = this.#routes = void 0;
558
- return matchers;
559
- }
560
- #buildMatcher(method) {
561
- const routes = [];
562
- let hasOwnRoute = method === METHOD_NAME_ALL;
563
- [this.#middleware, this.#routes].forEach((r) => {
564
- const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : [];
565
- if (ownRoute.length !== 0) {
566
- hasOwnRoute ||= true;
567
- routes.push(...ownRoute);
568
- } else if (method !== METHOD_NAME_ALL) {
569
- routes.push(
570
- ...Object.keys(r[METHOD_NAME_ALL]).map((path) => [path, r[METHOD_NAME_ALL][path]])
571
- );
593
+ assertDetailedOutput(output) {
594
+ const error = new Error(`
595
+ Invalid output structure for 'detailed' output.
596
+ Expected format:
597
+ {
598
+ body?: unknown; // The main response content (optional)
599
+ headers?: { // Additional headers (optional)
600
+ [key: string]: string;
601
+ };
572
602
  }
573
- });
574
- if (!hasOwnRoute) {
575
- return null;
576
- } else {
577
- return buildMatcherFromPreprocessedRoutes(routes);
603
+
604
+ Example:
605
+ {
606
+ body: { message: "Success" },
607
+ headers: { "X-Custom-Header": "Custom-Value" },
608
+ }
609
+
610
+ Fix: Ensure your output matches the expected structure.
611
+ `);
612
+ if (!isPlainObject3(output) || Object.keys(output).some((key) => key !== "body" && key !== "headers")) {
613
+ throw error;
614
+ }
615
+ if (output.headers !== void 0 && !isPlainObject3(output.headers)) {
616
+ throw error;
617
+ }
618
+ if (output.headers && Object.entries(output.headers).some(([key, value]) => typeof key !== "string" || typeof value !== "string")) {
619
+ throw error;
578
620
  }
579
621
  }
622
+ convertToORPCError(e) {
623
+ return e instanceof ORPCError2 ? e : new ORPCError2({
624
+ code: "INTERNAL_SERVER_ERROR",
625
+ message: "Internal server error",
626
+ cause: e
627
+ });
628
+ }
580
629
  };
581
630
 
582
- // src/fetch/server-handler.ts
583
- function createOpenAPIServerHandler() {
584
- return createOpenAPIHandler(() => new RegExpRouter());
585
- }
586
-
587
- // ../../node_modules/.pnpm/hono@4.6.13/node_modules/hono/dist/router/linear-router/router.js
588
- var emptyParams = /* @__PURE__ */ Object.create(null);
589
- var splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g;
590
- var splitByStarRe = /\*/;
591
- var LinearRouter = class {
592
- name = "LinearRouter";
593
- #routes = [];
594
- add(method, path, handler) {
595
- for (let i = 0, paths = checkOptionalParameter(path) || [path], len = paths.length; i < len; i++) {
596
- this.#routes.push([method, paths[i], handler]);
597
- }
598
- }
599
- match(method, path) {
600
- const handlers = [];
601
- ROUTES_LOOP:
602
- for (let i = 0, len = this.#routes.length; i < len; i++) {
603
- const [routeMethod, routePath, handler] = this.#routes[i];
604
- if (routeMethod === method || routeMethod === METHOD_NAME_ALL) {
605
- if (routePath === "*" || routePath === "/*") {
606
- handlers.push([handler, emptyParams]);
607
- continue;
608
- }
609
- const hasStar = routePath.indexOf("*") !== -1;
610
- const hasLabel = routePath.indexOf(":") !== -1;
611
- if (!hasStar && !hasLabel) {
612
- if (routePath === path || routePath + "/" === path) {
613
- handlers.push([handler, emptyParams]);
614
- }
615
- } else if (hasStar && !hasLabel) {
616
- const endsWithStar = routePath.charCodeAt(routePath.length - 1) === 42;
617
- const parts = (endsWithStar ? routePath.slice(0, -2) : routePath).split(splitByStarRe);
618
- const lastIndex = parts.length - 1;
619
- for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) {
620
- const part = parts[j];
621
- const index = path.indexOf(part, pos);
622
- if (index !== pos) {
623
- continue ROUTES_LOOP;
624
- }
625
- pos += part.length;
626
- if (j === lastIndex) {
627
- if (!endsWithStar && pos !== path.length && !(pos === path.length - 1 && path.charCodeAt(pos) === 47)) {
628
- continue ROUTES_LOOP;
629
- }
630
- } else {
631
- const index2 = path.indexOf("/", pos);
632
- if (index2 === -1) {
633
- continue ROUTES_LOOP;
634
- }
635
- pos = index2;
636
- }
637
- }
638
- handlers.push([handler, emptyParams]);
639
- } else if (hasLabel && !hasStar) {
640
- const params = /* @__PURE__ */ Object.create(null);
641
- const parts = routePath.match(splitPathRe);
642
- const lastIndex = parts.length - 1;
643
- for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) {
644
- if (pos === -1 || pos >= path.length) {
645
- continue ROUTES_LOOP;
646
- }
647
- const part = parts[j];
648
- if (part.charCodeAt(1) === 58) {
649
- let name = part.slice(2);
650
- let value2;
651
- if (name.charCodeAt(name.length - 1) === 125) {
652
- const openBracePos = name.indexOf("{");
653
- const pattern = name.slice(openBracePos + 1, -1);
654
- const restPath = path.slice(pos + 1);
655
- const match = new RegExp(pattern, "d").exec(restPath);
656
- if (!match || match.indices[0][0] !== 0 || match.indices[0][1] === 0) {
657
- continue ROUTES_LOOP;
658
- }
659
- name = name.slice(0, openBracePos);
660
- value2 = restPath.slice(...match.indices[0]);
661
- pos += match.indices[0][1] + 1;
662
- } else {
663
- let endValuePos = path.indexOf("/", pos + 1);
664
- if (endValuePos === -1) {
665
- if (pos + 1 === path.length) {
666
- continue ROUTES_LOOP;
667
- }
668
- endValuePos = path.length;
669
- }
670
- value2 = path.slice(pos + 1, endValuePos);
671
- pos = endValuePos;
672
- }
673
- params[name] ||= value2;
674
- } else {
675
- const index = path.indexOf(part, pos);
676
- if (index !== pos) {
677
- continue ROUTES_LOOP;
678
- }
679
- pos += part.length;
680
- }
681
- if (j === lastIndex) {
682
- if (pos !== path.length && !(pos === path.length - 1 && path.charCodeAt(pos) === 47)) {
683
- continue ROUTES_LOOP;
684
- }
685
- }
686
- }
687
- handlers.push([handler, params]);
688
- } else if (hasLabel && hasStar) {
689
- throw new UnsupportedPathError();
690
- }
691
- }
692
- }
693
- return [handlers];
631
+ // src/fetch/openapi-handler-server.ts
632
+ import { TrieRouter } from "hono/router/trie-router";
633
+ var OpenAPIServerHandler = class extends OpenAPIHandler {
634
+ constructor(router, options) {
635
+ super(new TrieRouter(), router, options);
694
636
  }
695
637
  };
696
638
 
697
- // src/fetch/serverless-handler.ts
698
- function createOpenAPIServerlessHandler() {
699
- return createOpenAPIHandler(() => new LinearRouter());
700
- }
639
+ // src/fetch/openapi-handler-serverless.ts
640
+ import { LinearRouter } from "hono/router/linear-router";
641
+ var OpenAPIServerlessHandler = class extends OpenAPIHandler {
642
+ constructor(router, options) {
643
+ super(new LinearRouter(), router, options);
644
+ }
645
+ };
701
646
  export {
702
- createOpenAPIHandler,
703
- createOpenAPIServerHandler,
704
- createOpenAPIServerlessHandler,
705
- createResolveRouter
647
+ CompositeSchemaCoercer,
648
+ InputStructureCompact,
649
+ InputStructureDetailed,
650
+ OpenAPIHandler,
651
+ OpenAPIPayloadCodec,
652
+ OpenAPIProcedureMatcher,
653
+ OpenAPIServerHandler,
654
+ OpenAPIServerlessHandler,
655
+ deserialize,
656
+ escapeSegment,
657
+ parsePath,
658
+ serialize,
659
+ stringifyPath
706
660
  };
707
661
  //# sourceMappingURL=fetch.js.map