@orpc/openapi 0.11.0 → 0.13.0

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,49 @@
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
+
46
+ export {
47
+ eachContractProcedureLeaf
48
+ };
49
+ //# sourceMappingURL=chunk-KZIT2WCV.js.map
package/dist/fetch.js ADDED
@@ -0,0 +1,703 @@
1
+ import {
2
+ eachContractProcedureLeaf
3
+ } from "./chunk-KZIT2WCV.js";
4
+
5
+ // src/fetch/base-handler.ts
6
+ import { ORPC_HEADER, standardizeHTTPPath } from "@orpc/contract";
7
+ import { createProcedureCaller, isLazy, isProcedure, LAZY_LOADER_SYMBOL, LAZY_ROUTER_PREFIX_SYMBOL, ORPCError } from "@orpc/server";
8
+ import { isPlainObject, mapValues, 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_HEADER) !== null) {
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.zz$cp.InputSchema ? zodCoerce(
37
+ procedure.zz$p.contract.zz$cp.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);
49
+ const { body, headers } = serializer.serialize(output);
50
+ return new Response(body, {
51
+ status: 200,
52
+ headers
53
+ });
54
+ };
55
+ try {
56
+ return await options.hooks?.(context, {
57
+ next: handler,
58
+ response: (response) => response
59
+ }) ?? await handler();
60
+ } catch (e) {
61
+ const error = toORPCError(e);
62
+ try {
63
+ const { body, headers } = serializer.serialize(error.toJSON());
64
+ return new Response(body, {
65
+ status: error.status,
66
+ headers
67
+ });
68
+ } catch (e2) {
69
+ const error2 = toORPCError(e2);
70
+ const { body, headers } = new OpenAPISerializer().serialize(
71
+ error2.toJSON()
72
+ );
73
+ return new Response(body, {
74
+ status: error2.status,
75
+ headers
76
+ });
77
+ }
78
+ }
79
+ };
80
+ }
81
+ var routingCache = /* @__PURE__ */ new Map();
82
+ var pendingCache = /* @__PURE__ */ new Map();
83
+ function createResolveRouter(createHonoRouter) {
84
+ const addRoutes = (routing, pending, options) => {
85
+ const lazies = eachContractProcedureLeaf(options, ({ path, contract }) => {
86
+ const method = contract.zz$cp.method ?? "POST";
87
+ const httpPath = contract.zz$cp.path ? openAPIPathToRouterPath(contract.zz$cp.path) : `/${path.map(encodeURIComponent).join("/")}`;
88
+ routing.add(method, httpPath, path);
89
+ });
90
+ pending.ref.push(...lazies);
91
+ };
92
+ return async (router, method, pathname) => {
93
+ const pending = (() => {
94
+ let pending2 = pendingCache.get(router);
95
+ if (!pending2) {
96
+ pending2 = { ref: [] };
97
+ pendingCache.set(router, pending2);
98
+ }
99
+ return pending2;
100
+ })();
101
+ const routing = (() => {
102
+ let routing2 = routingCache.get(router);
103
+ if (!routing2) {
104
+ routing2 = createHonoRouter();
105
+ routingCache.set(router, routing2);
106
+ addRoutes(routing2, pending, { router, path: [] });
107
+ }
108
+ return routing2;
109
+ })();
110
+ const newPending = [];
111
+ for (const item of pending.ref) {
112
+ 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("/")}`)) {
113
+ newPending.push(item);
114
+ continue;
115
+ }
116
+ const router2 = (await item.lazy[LAZY_LOADER_SYMBOL]()).default;
117
+ addRoutes(routing, pending, { path: item.path, router: router2 });
118
+ }
119
+ pending.ref = newPending;
120
+ const [matches, params_] = routing.match(method, pathname);
121
+ const [match] = matches.sort((a, b) => {
122
+ return Object.keys(a[1]).length - Object.keys(b[1]).length;
123
+ });
124
+ if (!match) {
125
+ return void 0;
126
+ }
127
+ const path = match[0];
128
+ const params = params_ ? mapValues(
129
+ match[1],
130
+ (v) => params_[v]
131
+ ) : match[1];
132
+ let current = router;
133
+ for (const segment of path) {
134
+ if (typeof current !== "object" && typeof current !== "function" || !current) {
135
+ current = void 0;
136
+ break;
137
+ }
138
+ current = current[segment];
139
+ }
140
+ return isProcedure(current) || isLazy(current) ? {
141
+ path,
142
+ procedure: current,
143
+ params: { ...params }
144
+ // params from hono not a normal object, so we need spread here
145
+ } : void 0;
146
+ };
147
+ }
148
+ function mergeParamsAndInput(coercedParams, input) {
149
+ if (Object.keys(coercedParams).length === 0) {
150
+ return input;
151
+ }
152
+ if (!isPlainObject(input)) {
153
+ return coercedParams;
154
+ }
155
+ return {
156
+ ...coercedParams,
157
+ ...input
158
+ };
159
+ }
160
+ async function deserializeInput(request, procedure) {
161
+ const deserializer = new OpenAPIDeserializer({
162
+ schema: procedure.zz$p.contract.zz$cp.InputSchema
163
+ });
164
+ try {
165
+ return await deserializer.deserialize(request);
166
+ } catch (e) {
167
+ throw new ORPCError({
168
+ code: "BAD_REQUEST",
169
+ message: "Cannot parse request. Please check the request body and Content-Type header.",
170
+ cause: e
171
+ });
172
+ }
173
+ }
174
+ function toORPCError(e) {
175
+ return e instanceof ORPCError ? e : new ORPCError({
176
+ code: "INTERNAL_SERVER_ERROR",
177
+ message: "Internal server error",
178
+ cause: e
179
+ });
180
+ }
181
+ function openAPIPathToRouterPath(path) {
182
+ return standardizeHTTPPath(path).replace(/\{([^}]+)\}/g, ":$1");
183
+ }
184
+
185
+ // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router.js
186
+ var METHOD_NAME_ALL = "ALL";
187
+ var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
188
+ var UnsupportedPathError = class extends Error {
189
+ };
190
+
191
+ // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/utils/url.js
192
+ var checkOptionalParameter = (path) => {
193
+ if (!path.match(/\:.+\?$/)) {
194
+ return null;
195
+ }
196
+ const segments = path.split("/");
197
+ const results = [];
198
+ let basePath = "";
199
+ segments.forEach((segment) => {
200
+ if (segment !== "" && !/\:/.test(segment)) {
201
+ basePath += "/" + segment;
202
+ } else if (/\:/.test(segment)) {
203
+ if (/\?/.test(segment)) {
204
+ if (results.length === 0 && basePath === "") {
205
+ results.push("/");
206
+ } else {
207
+ results.push(basePath);
208
+ }
209
+ const optionalSegment = segment.replace("?", "");
210
+ basePath += "/" + optionalSegment;
211
+ results.push(basePath);
212
+ } else {
213
+ basePath += "/" + segment;
214
+ }
215
+ }
216
+ });
217
+ return results.filter((v, i, a) => a.indexOf(v) === i);
218
+ };
219
+
220
+ // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/reg-exp-router/node.js
221
+ var LABEL_REG_EXP_STR = "[^/]+";
222
+ var ONLY_WILDCARD_REG_EXP_STR = ".*";
223
+ var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
224
+ var PATH_ERROR = Symbol();
225
+ var regExpMetaChars = new Set(".\\+*[^]$()");
226
+ function compareKey(a, b) {
227
+ if (a.length === 1) {
228
+ return b.length === 1 ? a < b ? -1 : 1 : -1;
229
+ }
230
+ if (b.length === 1) {
231
+ return 1;
232
+ }
233
+ if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
234
+ return 1;
235
+ } else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
236
+ return -1;
237
+ }
238
+ if (a === LABEL_REG_EXP_STR) {
239
+ return 1;
240
+ } else if (b === LABEL_REG_EXP_STR) {
241
+ return -1;
242
+ }
243
+ return a.length === b.length ? a < b ? -1 : 1 : b.length - a.length;
244
+ }
245
+ var Node = class {
246
+ #index;
247
+ #varIndex;
248
+ #children = /* @__PURE__ */ Object.create(null);
249
+ insert(tokens, index, paramMap, context, pathErrorCheckOnly) {
250
+ if (tokens.length === 0) {
251
+ if (this.#index !== void 0) {
252
+ throw PATH_ERROR;
253
+ }
254
+ if (pathErrorCheckOnly) {
255
+ return;
256
+ }
257
+ this.#index = index;
258
+ return;
259
+ }
260
+ const [token, ...restTokens] = tokens;
261
+ const pattern = token === "*" ? restTokens.length === 0 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
262
+ let node;
263
+ if (pattern) {
264
+ const name = pattern[1];
265
+ let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
266
+ if (name && pattern[2]) {
267
+ regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
268
+ if (/\((?!\?:)/.test(regexpStr)) {
269
+ throw PATH_ERROR;
270
+ }
271
+ }
272
+ node = this.#children[regexpStr];
273
+ if (!node) {
274
+ if (Object.keys(this.#children).some(
275
+ (k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
276
+ )) {
277
+ throw PATH_ERROR;
278
+ }
279
+ if (pathErrorCheckOnly) {
280
+ return;
281
+ }
282
+ node = this.#children[regexpStr] = new Node();
283
+ if (name !== "") {
284
+ node.#varIndex = context.varIndex++;
285
+ }
286
+ }
287
+ if (!pathErrorCheckOnly && name !== "") {
288
+ paramMap.push([name, node.#varIndex]);
289
+ }
290
+ } else {
291
+ node = this.#children[token];
292
+ if (!node) {
293
+ if (Object.keys(this.#children).some(
294
+ (k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
295
+ )) {
296
+ throw PATH_ERROR;
297
+ }
298
+ if (pathErrorCheckOnly) {
299
+ return;
300
+ }
301
+ node = this.#children[token] = new Node();
302
+ }
303
+ }
304
+ node.insert(restTokens, index, paramMap, context, pathErrorCheckOnly);
305
+ }
306
+ buildRegExpStr() {
307
+ const childKeys = Object.keys(this.#children).sort(compareKey);
308
+ const strList = childKeys.map((k) => {
309
+ const c = this.#children[k];
310
+ return (typeof c.#varIndex === "number" ? `(${k})@${c.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr();
311
+ });
312
+ if (typeof this.#index === "number") {
313
+ strList.unshift(`#${this.#index}`);
314
+ }
315
+ if (strList.length === 0) {
316
+ return "";
317
+ }
318
+ if (strList.length === 1) {
319
+ return strList[0];
320
+ }
321
+ return "(?:" + strList.join("|") + ")";
322
+ }
323
+ };
324
+
325
+ // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/reg-exp-router/trie.js
326
+ var Trie = class {
327
+ #context = { varIndex: 0 };
328
+ #root = new Node();
329
+ insert(path, index, pathErrorCheckOnly) {
330
+ const paramAssoc = [];
331
+ const groups = [];
332
+ for (let i = 0; ; ) {
333
+ let replaced = false;
334
+ path = path.replace(/\{[^}]+\}/g, (m) => {
335
+ const mark = `@\\${i}`;
336
+ groups[i] = [mark, m];
337
+ i++;
338
+ replaced = true;
339
+ return mark;
340
+ });
341
+ if (!replaced) {
342
+ break;
343
+ }
344
+ }
345
+ const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
346
+ for (let i = groups.length - 1; i >= 0; i--) {
347
+ const [mark] = groups[i];
348
+ for (let j = tokens.length - 1; j >= 0; j--) {
349
+ if (tokens[j].indexOf(mark) !== -1) {
350
+ tokens[j] = tokens[j].replace(mark, groups[i][1]);
351
+ break;
352
+ }
353
+ }
354
+ }
355
+ this.#root.insert(tokens, index, paramAssoc, this.#context, pathErrorCheckOnly);
356
+ return paramAssoc;
357
+ }
358
+ buildRegExp() {
359
+ let regexp = this.#root.buildRegExpStr();
360
+ if (regexp === "") {
361
+ return [/^$/, [], []];
362
+ }
363
+ let captureIndex = 0;
364
+ const indexReplacementMap = [];
365
+ const paramReplacementMap = [];
366
+ regexp = regexp.replace(/#(\d+)|@(\d+)|\.\*\$/g, (_, handlerIndex, paramIndex) => {
367
+ if (handlerIndex !== void 0) {
368
+ indexReplacementMap[++captureIndex] = Number(handlerIndex);
369
+ return "$()";
370
+ }
371
+ if (paramIndex !== void 0) {
372
+ paramReplacementMap[Number(paramIndex)] = ++captureIndex;
373
+ return "";
374
+ }
375
+ return "";
376
+ });
377
+ return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
378
+ }
379
+ };
380
+
381
+ // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/reg-exp-router/router.js
382
+ var emptyParam = [];
383
+ var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
384
+ var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
385
+ function buildWildcardRegExp(path) {
386
+ return wildcardRegExpCache[path] ??= new RegExp(
387
+ path === "*" ? "" : `^${path.replace(
388
+ /\/\*$|([.\\+*[^\]$()])/g,
389
+ (_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)"
390
+ )}$`
391
+ );
392
+ }
393
+ function clearWildcardRegExpCache() {
394
+ wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
395
+ }
396
+ function buildMatcherFromPreprocessedRoutes(routes) {
397
+ const trie = new Trie();
398
+ const handlerData = [];
399
+ if (routes.length === 0) {
400
+ return nullMatcher;
401
+ }
402
+ const routesWithStaticPathFlag = routes.map(
403
+ (route) => [!/\*|\/:/.test(route[0]), ...route]
404
+ ).sort(
405
+ ([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
406
+ );
407
+ const staticMap = /* @__PURE__ */ Object.create(null);
408
+ for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
409
+ const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
410
+ if (pathErrorCheckOnly) {
411
+ staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
412
+ } else {
413
+ j++;
414
+ }
415
+ let paramAssoc;
416
+ try {
417
+ paramAssoc = trie.insert(path, j, pathErrorCheckOnly);
418
+ } catch (e) {
419
+ throw e === PATH_ERROR ? new UnsupportedPathError(path) : e;
420
+ }
421
+ if (pathErrorCheckOnly) {
422
+ continue;
423
+ }
424
+ handlerData[j] = handlers.map(([h, paramCount]) => {
425
+ const paramIndexMap = /* @__PURE__ */ Object.create(null);
426
+ paramCount -= 1;
427
+ for (; paramCount >= 0; paramCount--) {
428
+ const [key, value2] = paramAssoc[paramCount];
429
+ paramIndexMap[key] = value2;
430
+ }
431
+ return [h, paramIndexMap];
432
+ });
433
+ }
434
+ const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
435
+ for (let i = 0, len = handlerData.length; i < len; i++) {
436
+ for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
437
+ const map = handlerData[i][j]?.[1];
438
+ if (!map) {
439
+ continue;
440
+ }
441
+ const keys = Object.keys(map);
442
+ for (let k = 0, len3 = keys.length; k < len3; k++) {
443
+ map[keys[k]] = paramReplacementMap[map[keys[k]]];
444
+ }
445
+ }
446
+ }
447
+ const handlerMap = [];
448
+ for (const i in indexReplacementMap) {
449
+ handlerMap[i] = handlerData[indexReplacementMap[i]];
450
+ }
451
+ return [regexp, handlerMap, staticMap];
452
+ }
453
+ function findMiddleware(middleware, path) {
454
+ if (!middleware) {
455
+ return void 0;
456
+ }
457
+ for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
458
+ if (buildWildcardRegExp(k).test(path)) {
459
+ return [...middleware[k]];
460
+ }
461
+ }
462
+ return void 0;
463
+ }
464
+ var RegExpRouter = class {
465
+ name = "RegExpRouter";
466
+ #middleware;
467
+ #routes;
468
+ constructor() {
469
+ this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
470
+ this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
471
+ }
472
+ add(method, path, handler) {
473
+ const middleware = this.#middleware;
474
+ const routes = this.#routes;
475
+ if (!middleware || !routes) {
476
+ throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
477
+ }
478
+ if (!middleware[method]) {
479
+ ;
480
+ [middleware, routes].forEach((handlerMap) => {
481
+ handlerMap[method] = /* @__PURE__ */ Object.create(null);
482
+ Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p) => {
483
+ handlerMap[method][p] = [...handlerMap[METHOD_NAME_ALL][p]];
484
+ });
485
+ });
486
+ }
487
+ if (path === "/*") {
488
+ path = "*";
489
+ }
490
+ const paramCount = (path.match(/\/:/g) || []).length;
491
+ if (/\*$/.test(path)) {
492
+ const re = buildWildcardRegExp(path);
493
+ if (method === METHOD_NAME_ALL) {
494
+ Object.keys(middleware).forEach((m) => {
495
+ middleware[m][path] ||= findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
496
+ });
497
+ } else {
498
+ middleware[method][path] ||= findMiddleware(middleware[method], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
499
+ }
500
+ Object.keys(middleware).forEach((m) => {
501
+ if (method === METHOD_NAME_ALL || method === m) {
502
+ Object.keys(middleware[m]).forEach((p) => {
503
+ re.test(p) && middleware[m][p].push([handler, paramCount]);
504
+ });
505
+ }
506
+ });
507
+ Object.keys(routes).forEach((m) => {
508
+ if (method === METHOD_NAME_ALL || method === m) {
509
+ Object.keys(routes[m]).forEach(
510
+ (p) => re.test(p) && routes[m][p].push([handler, paramCount])
511
+ );
512
+ }
513
+ });
514
+ return;
515
+ }
516
+ const paths = checkOptionalParameter(path) || [path];
517
+ for (let i = 0, len = paths.length; i < len; i++) {
518
+ const path2 = paths[i];
519
+ Object.keys(routes).forEach((m) => {
520
+ if (method === METHOD_NAME_ALL || method === m) {
521
+ routes[m][path2] ||= [
522
+ ...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || []
523
+ ];
524
+ routes[m][path2].push([handler, paramCount - len + i + 1]);
525
+ }
526
+ });
527
+ }
528
+ }
529
+ match(method, path) {
530
+ clearWildcardRegExpCache();
531
+ const matchers = this.#buildAllMatchers();
532
+ this.match = (method2, path2) => {
533
+ const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
534
+ const staticMatch = matcher[2][path2];
535
+ if (staticMatch) {
536
+ return staticMatch;
537
+ }
538
+ const match = path2.match(matcher[0]);
539
+ if (!match) {
540
+ return [[], emptyParam];
541
+ }
542
+ const index = match.indexOf("", 1);
543
+ return [matcher[1][index], match];
544
+ };
545
+ return this.match(method, path);
546
+ }
547
+ #buildAllMatchers() {
548
+ const matchers = /* @__PURE__ */ Object.create(null);
549
+ Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => {
550
+ matchers[method] ||= this.#buildMatcher(method);
551
+ });
552
+ this.#middleware = this.#routes = void 0;
553
+ return matchers;
554
+ }
555
+ #buildMatcher(method) {
556
+ const routes = [];
557
+ let hasOwnRoute = method === METHOD_NAME_ALL;
558
+ [this.#middleware, this.#routes].forEach((r) => {
559
+ const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : [];
560
+ if (ownRoute.length !== 0) {
561
+ hasOwnRoute ||= true;
562
+ routes.push(...ownRoute);
563
+ } else if (method !== METHOD_NAME_ALL) {
564
+ routes.push(
565
+ ...Object.keys(r[METHOD_NAME_ALL]).map((path) => [path, r[METHOD_NAME_ALL][path]])
566
+ );
567
+ }
568
+ });
569
+ if (!hasOwnRoute) {
570
+ return null;
571
+ } else {
572
+ return buildMatcherFromPreprocessedRoutes(routes);
573
+ }
574
+ }
575
+ };
576
+
577
+ // src/fetch/server-handler.ts
578
+ function createOpenAPIServerHandler() {
579
+ return createOpenAPIHandler(() => new RegExpRouter());
580
+ }
581
+
582
+ // ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/linear-router/router.js
583
+ var emptyParams = /* @__PURE__ */ Object.create(null);
584
+ var splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g;
585
+ var splitByStarRe = /\*/;
586
+ var LinearRouter = class {
587
+ name = "LinearRouter";
588
+ #routes = [];
589
+ add(method, path, handler) {
590
+ for (let i = 0, paths = checkOptionalParameter(path) || [path], len = paths.length; i < len; i++) {
591
+ this.#routes.push([method, paths[i], handler]);
592
+ }
593
+ }
594
+ match(method, path) {
595
+ const handlers = [];
596
+ ROUTES_LOOP:
597
+ for (let i = 0, len = this.#routes.length; i < len; i++) {
598
+ const [routeMethod, routePath, handler] = this.#routes[i];
599
+ if (routeMethod === method || routeMethod === METHOD_NAME_ALL) {
600
+ if (routePath === "*" || routePath === "/*") {
601
+ handlers.push([handler, emptyParams]);
602
+ continue;
603
+ }
604
+ const hasStar = routePath.indexOf("*") !== -1;
605
+ const hasLabel = routePath.indexOf(":") !== -1;
606
+ if (!hasStar && !hasLabel) {
607
+ if (routePath === path || routePath + "/" === path) {
608
+ handlers.push([handler, emptyParams]);
609
+ }
610
+ } else if (hasStar && !hasLabel) {
611
+ const endsWithStar = routePath.charCodeAt(routePath.length - 1) === 42;
612
+ const parts = (endsWithStar ? routePath.slice(0, -2) : routePath).split(splitByStarRe);
613
+ const lastIndex = parts.length - 1;
614
+ for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) {
615
+ const part = parts[j];
616
+ const index = path.indexOf(part, pos);
617
+ if (index !== pos) {
618
+ continue ROUTES_LOOP;
619
+ }
620
+ pos += part.length;
621
+ if (j === lastIndex) {
622
+ if (!endsWithStar && pos !== path.length && !(pos === path.length - 1 && path.charCodeAt(pos) === 47)) {
623
+ continue ROUTES_LOOP;
624
+ }
625
+ } else {
626
+ const index2 = path.indexOf("/", pos);
627
+ if (index2 === -1) {
628
+ continue ROUTES_LOOP;
629
+ }
630
+ pos = index2;
631
+ }
632
+ }
633
+ handlers.push([handler, emptyParams]);
634
+ } else if (hasLabel && !hasStar) {
635
+ const params = /* @__PURE__ */ Object.create(null);
636
+ const parts = routePath.match(splitPathRe);
637
+ const lastIndex = parts.length - 1;
638
+ for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) {
639
+ if (pos === -1 || pos >= path.length) {
640
+ continue ROUTES_LOOP;
641
+ }
642
+ const part = parts[j];
643
+ if (part.charCodeAt(1) === 58) {
644
+ let name = part.slice(2);
645
+ let value2;
646
+ if (name.charCodeAt(name.length - 1) === 125) {
647
+ const openBracePos = name.indexOf("{");
648
+ const pattern = name.slice(openBracePos + 1, -1);
649
+ const restPath = path.slice(pos + 1);
650
+ const match = new RegExp(pattern, "d").exec(restPath);
651
+ if (!match || match.indices[0][0] !== 0 || match.indices[0][1] === 0) {
652
+ continue ROUTES_LOOP;
653
+ }
654
+ name = name.slice(0, openBracePos);
655
+ value2 = restPath.slice(...match.indices[0]);
656
+ pos += match.indices[0][1] + 1;
657
+ } else {
658
+ let endValuePos = path.indexOf("/", pos + 1);
659
+ if (endValuePos === -1) {
660
+ if (pos + 1 === path.length) {
661
+ continue ROUTES_LOOP;
662
+ }
663
+ endValuePos = path.length;
664
+ }
665
+ value2 = path.slice(pos + 1, endValuePos);
666
+ pos = endValuePos;
667
+ }
668
+ params[name] ||= value2;
669
+ } else {
670
+ const index = path.indexOf(part, pos);
671
+ if (index !== pos) {
672
+ continue ROUTES_LOOP;
673
+ }
674
+ pos += part.length;
675
+ }
676
+ if (j === lastIndex) {
677
+ if (pos !== path.length && !(pos === path.length - 1 && path.charCodeAt(pos) === 47)) {
678
+ continue ROUTES_LOOP;
679
+ }
680
+ }
681
+ }
682
+ handlers.push([handler, params]);
683
+ } else if (hasLabel && hasStar) {
684
+ throw new UnsupportedPathError();
685
+ }
686
+ }
687
+ }
688
+ return [handlers];
689
+ }
690
+ };
691
+
692
+ // src/fetch/serverless-handler.ts
693
+ function createOpenAPIServerlessHandler() {
694
+ return createOpenAPIHandler(() => new LinearRouter());
695
+ }
696
+ export {
697
+ createOpenAPIHandler,
698
+ createOpenAPIServerHandler,
699
+ createOpenAPIServerlessHandler,
700
+ createResolveRouter,
701
+ openAPIPathToRouterPath
702
+ };
703
+ //# sourceMappingURL=fetch.js.map
package/dist/index.js CHANGED
@@ -1,6 +1,10 @@
1
+ import {
2
+ eachContractProcedureLeaf
3
+ } from "./chunk-KZIT2WCV.js";
4
+
1
5
  // src/generator.ts
2
- import { eachContractRouterLeaf } from "@orpc/contract";
3
- import { toContractRouter } from "@orpc/server";
6
+ import { isContractProcedure } from "@orpc/contract";
7
+ import { LAZY_LOADER_SYMBOL } from "@orpc/server";
4
8
  import { findDeepMatches, isPlainObject, omit } from "@orpc/shared";
5
9
  import { preSerialize } from "@orpc/transformer";
6
10
  import {
@@ -4210,7 +4214,7 @@ function extractJSONSchema(schema, check, matches = []) {
4210
4214
  }
4211
4215
 
4212
4216
  // src/generator.ts
4213
- function generateOpenAPI(opts, options) {
4217
+ async function generateOpenAPI(opts, options) {
4214
4218
  const throwOnMissingTagDefinition = options?.throwOnMissingTagDefinition ?? false;
4215
4219
  const ignoreUndefinedPathProcedures = options?.ignoreUndefinedPathProcedures ?? false;
4216
4220
  const builder = new OpenApiBuilder({
@@ -4218,197 +4222,212 @@ function generateOpenAPI(opts, options) {
4218
4222
  openapi: "3.1.0"
4219
4223
  });
4220
4224
  const rootTags = opts.tags?.map((tag) => tag.name) ?? [];
4221
- const router = toContractRouter(opts.router);
4222
- eachContractRouterLeaf(router, (procedure, path_) => {
4223
- const internal = procedure.zz$cp;
4224
- if (ignoreUndefinedPathProcedures && internal.path === void 0) {
4225
- return;
4226
- }
4227
- const path = internal.path ?? `/${path_.map(encodeURIComponent).join("/")}`;
4228
- const method = internal.method ?? "POST";
4229
- let inputSchema = internal.InputSchema ? zodToJsonSchema(internal.InputSchema, { mode: "input" }) : {};
4230
- const outputSchema = internal.OutputSchema ? zodToJsonSchema(internal.OutputSchema, { mode: "output" }) : {};
4231
- const params = (() => {
4232
- const names = path.match(/\{([^}]+)\}/g);
4233
- if (!names || !names.length) {
4234
- return void 0;
4225
+ const pending = [{
4226
+ path: [],
4227
+ router: opts.router
4228
+ }];
4229
+ for (const item of pending) {
4230
+ const lazies = eachContractProcedureLeaf(item, ({ contract, path }) => {
4231
+ if (!isContractProcedure(contract)) {
4232
+ return;
4235
4233
  }
4236
- if (typeof inputSchema !== "object" || inputSchema.type !== "object") {
4237
- throw new Error(
4238
- `When path has parameters, input schema must be an object [${path_.join(".")}]`
4239
- );
4234
+ const internal = contract.zz$cp;
4235
+ if (ignoreUndefinedPathProcedures && internal.path === void 0) {
4236
+ return;
4240
4237
  }
4241
- return names.map((raw) => raw.slice(1, -1)).map((name) => {
4242
- let schema = inputSchema.properties?.[name];
4243
- const required = inputSchema.required?.includes(name);
4244
- if (schema === void 0) {
4245
- throw new Error(
4246
- `Parameter ${name} is missing in input schema [${path_.join(".")}]`
4247
- );
4238
+ const httpPath = internal.path ?? `/${path.map(encodeURIComponent).join("/")}`;
4239
+ const method = internal.method ?? "POST";
4240
+ let inputSchema = internal.InputSchema ? zodToJsonSchema(internal.InputSchema, { mode: "input" }) : {};
4241
+ const outputSchema = internal.OutputSchema ? zodToJsonSchema(internal.OutputSchema, { mode: "output" }) : {};
4242
+ const params = (() => {
4243
+ const names = httpPath.match(/\{([^}]+)\}/g);
4244
+ if (!names || !names.length) {
4245
+ return void 0;
4248
4246
  }
4249
- if (!required) {
4247
+ if (typeof inputSchema !== "object" || inputSchema.type !== "object") {
4250
4248
  throw new Error(
4251
- `Parameter ${name} must be required in input schema [${path_.join(".")}]`
4249
+ `When path has parameters, input schema must be an object [${path.join(".")}]`
4252
4250
  );
4253
4251
  }
4254
- const examples = inputSchema.examples?.filter((example) => {
4255
- return isPlainObject(example) && name in example;
4256
- }).map((example) => {
4257
- return example[name];
4258
- });
4259
- schema = {
4260
- examples: examples?.length ? examples : void 0,
4261
- ...schema === true ? {} : schema === false ? UNSUPPORTED_JSON_SCHEMA : schema
4262
- };
4263
- inputSchema = {
4264
- ...inputSchema,
4265
- properties: inputSchema.properties ? Object.entries(inputSchema.properties).reduce(
4266
- (acc, [key, value]) => {
4267
- if (key !== name) {
4268
- acc[key] = value;
4269
- }
4270
- return acc;
4271
- },
4272
- {}
4273
- ) : void 0,
4274
- required: inputSchema.required?.filter((v) => v !== name),
4275
- examples: inputSchema.examples?.map((example) => {
4276
- if (!isPlainObject(example))
4277
- return example;
4278
- return Object.entries(example).reduce(
4279
- (acc, [key, value]) => {
4280
- if (key !== name) {
4281
- acc[key] = value;
4282
- }
4283
- return acc;
4284
- },
4285
- {}
4252
+ return names.map((raw) => raw.slice(1, -1)).map((name) => {
4253
+ let schema = inputSchema.properties?.[name];
4254
+ const required = inputSchema.required?.includes(name);
4255
+ if (schema === void 0) {
4256
+ throw new Error(
4257
+ `Parameter ${name} is missing in input schema [${path.join(".")}]`
4286
4258
  );
4287
- })
4288
- };
4289
- return {
4290
- name,
4291
- in: "path",
4292
- required: true,
4293
- schema,
4294
- example: internal.inputExample?.[name]
4295
- };
4296
- });
4297
- })();
4298
- const query = (() => {
4299
- if (method !== "GET" || Object.keys(inputSchema).length === 0) {
4300
- return void 0;
4301
- }
4302
- if (typeof inputSchema !== "object" || inputSchema.type !== "object") {
4303
- throw new Error(
4304
- `When method is GET, input schema must be an object [${path_.join(".")}]`
4305
- );
4306
- }
4307
- return Object.entries(inputSchema.properties ?? {}).map(
4308
- ([name, schema]) => {
4259
+ }
4260
+ if (!required) {
4261
+ throw new Error(
4262
+ `Parameter ${name} must be required in input schema [${path.join(".")}]`
4263
+ );
4264
+ }
4309
4265
  const examples = inputSchema.examples?.filter((example) => {
4310
4266
  return isPlainObject(example) && name in example;
4311
4267
  }).map((example) => {
4312
4268
  return example[name];
4313
4269
  });
4314
- const schema_ = {
4270
+ schema = {
4315
4271
  examples: examples?.length ? examples : void 0,
4316
4272
  ...schema === true ? {} : schema === false ? UNSUPPORTED_JSON_SCHEMA : schema
4317
4273
  };
4274
+ inputSchema = {
4275
+ ...inputSchema,
4276
+ properties: inputSchema.properties ? Object.entries(inputSchema.properties).reduce(
4277
+ (acc, [key, value]) => {
4278
+ if (key !== name) {
4279
+ acc[key] = value;
4280
+ }
4281
+ return acc;
4282
+ },
4283
+ {}
4284
+ ) : void 0,
4285
+ required: inputSchema.required?.filter((v) => v !== name),
4286
+ examples: inputSchema.examples?.map((example) => {
4287
+ if (!isPlainObject(example))
4288
+ return example;
4289
+ return Object.entries(example).reduce(
4290
+ (acc, [key, value]) => {
4291
+ if (key !== name) {
4292
+ acc[key] = value;
4293
+ }
4294
+ return acc;
4295
+ },
4296
+ {}
4297
+ );
4298
+ })
4299
+ };
4318
4300
  return {
4319
4301
  name,
4320
- in: "query",
4321
- style: "deepObject",
4322
- required: inputSchema?.required?.includes(name) ?? false,
4323
- schema: schema_,
4302
+ in: "path",
4303
+ required: true,
4304
+ schema,
4324
4305
  example: internal.inputExample?.[name]
4325
4306
  };
4307
+ });
4308
+ })();
4309
+ const query = (() => {
4310
+ if (method !== "GET" || Object.keys(inputSchema).length === 0) {
4311
+ return void 0;
4326
4312
  }
4327
- );
4328
- })();
4329
- const parameters = [...params ?? [], ...query ?? []];
4330
- const requestBody = (() => {
4331
- if (method === "GET") {
4332
- return void 0;
4333
- }
4334
- const { schema, matches } = extractJSONSchema(inputSchema, isFileSchema);
4335
- const files = matches;
4336
- const isStillHasFileSchema = findDeepMatches(isFileSchema, schema).values.length > 0;
4337
- if (files.length) {
4338
- parameters.push({
4339
- name: "content-disposition",
4340
- in: "header",
4341
- required: schema === void 0,
4342
- schema: {
4343
- type: "string",
4344
- pattern: "filename",
4345
- example: 'filename="file.png"',
4346
- description: "To define the file name. Required when the request body is a file."
4313
+ if (typeof inputSchema !== "object" || inputSchema.type !== "object") {
4314
+ throw new Error(
4315
+ `When method is GET, input schema must be an object [${path.join(".")}]`
4316
+ );
4317
+ }
4318
+ return Object.entries(inputSchema.properties ?? {}).map(
4319
+ ([name, schema]) => {
4320
+ const examples = inputSchema.examples?.filter((example) => {
4321
+ return isPlainObject(example) && name in example;
4322
+ }).map((example) => {
4323
+ return example[name];
4324
+ });
4325
+ const schema_ = {
4326
+ examples: examples?.length ? examples : void 0,
4327
+ ...schema === true ? {} : schema === false ? UNSUPPORTED_JSON_SCHEMA : schema
4328
+ };
4329
+ return {
4330
+ name,
4331
+ in: "query",
4332
+ style: "deepObject",
4333
+ required: inputSchema?.required?.includes(name) ?? false,
4334
+ schema: schema_,
4335
+ example: internal.inputExample?.[name]
4336
+ };
4347
4337
  }
4348
- });
4349
- }
4350
- const content = {};
4351
- for (const file of files) {
4352
- content[file.contentMediaType] = {
4353
- schema: file
4354
- };
4355
- }
4356
- if (schema !== void 0) {
4357
- content[isStillHasFileSchema ? "multipart/form-data" : "application/json"] = {
4358
- schema,
4359
- example: internal.inputExample
4360
- };
4361
- }
4362
- return {
4363
- required: Boolean(internal.InputSchema?.isOptional()),
4364
- content
4365
- };
4366
- })();
4367
- const successResponse = (() => {
4368
- const { schema, matches } = extractJSONSchema(outputSchema, isFileSchema);
4369
- const files = matches;
4370
- const isStillHasFileSchema = findDeepMatches(isFileSchema, schema).values.length > 0;
4371
- const content = {};
4372
- for (const file of files) {
4373
- content[file.contentMediaType] = {
4374
- schema: file
4338
+ );
4339
+ })();
4340
+ const parameters = [...params ?? [], ...query ?? []];
4341
+ const requestBody = (() => {
4342
+ if (method === "GET") {
4343
+ return void 0;
4344
+ }
4345
+ const { schema, matches } = extractJSONSchema(inputSchema, isFileSchema);
4346
+ const files = matches;
4347
+ const isStillHasFileSchema = findDeepMatches(isFileSchema, schema).values.length > 0;
4348
+ if (files.length) {
4349
+ parameters.push({
4350
+ name: "content-disposition",
4351
+ in: "header",
4352
+ required: schema === void 0,
4353
+ schema: {
4354
+ type: "string",
4355
+ pattern: "filename",
4356
+ example: 'filename="file.png"',
4357
+ description: "To define the file name. Required when the request body is a file."
4358
+ }
4359
+ });
4360
+ }
4361
+ const content = {};
4362
+ for (const file of files) {
4363
+ content[file.contentMediaType] = {
4364
+ schema: file
4365
+ };
4366
+ }
4367
+ if (schema !== void 0) {
4368
+ content[isStillHasFileSchema ? "multipart/form-data" : "application/json"] = {
4369
+ schema,
4370
+ example: internal.inputExample
4371
+ };
4372
+ }
4373
+ return {
4374
+ required: Boolean(internal.InputSchema?.isOptional()),
4375
+ content
4375
4376
  };
4376
- }
4377
- if (schema !== void 0) {
4378
- content[isStillHasFileSchema ? "multipart/form-data" : "application/json"] = {
4379
- schema,
4380
- example: internal.outputExample
4377
+ })();
4378
+ const successResponse = (() => {
4379
+ const { schema, matches } = extractJSONSchema(outputSchema, isFileSchema);
4380
+ const files = matches;
4381
+ const isStillHasFileSchema = findDeepMatches(isFileSchema, schema).values.length > 0;
4382
+ const content = {};
4383
+ for (const file of files) {
4384
+ content[file.contentMediaType] = {
4385
+ schema: file
4386
+ };
4387
+ }
4388
+ if (schema !== void 0) {
4389
+ content[isStillHasFileSchema ? "multipart/form-data" : "application/json"] = {
4390
+ schema,
4391
+ example: internal.outputExample
4392
+ };
4393
+ }
4394
+ return {
4395
+ description: "OK",
4396
+ content
4381
4397
  };
4398
+ })();
4399
+ if (throwOnMissingTagDefinition && internal.tags) {
4400
+ const missingTag = internal.tags.find((tag) => !rootTags.includes(tag));
4401
+ if (missingTag !== void 0) {
4402
+ throw new Error(
4403
+ `Tag "${missingTag}" is missing definition. Please define it in OpenAPI root tags object. [${path.join(".")}]`
4404
+ );
4405
+ }
4382
4406
  }
4383
- return {
4384
- description: "OK",
4385
- content
4407
+ const operation = {
4408
+ summary: internal.summary,
4409
+ description: internal.description,
4410
+ deprecated: internal.deprecated,
4411
+ tags: internal.tags,
4412
+ operationId: path.join("."),
4413
+ parameters: parameters.length ? parameters : void 0,
4414
+ requestBody,
4415
+ responses: {
4416
+ 200: successResponse
4417
+ }
4386
4418
  };
4387
- })();
4388
- if (throwOnMissingTagDefinition && internal.tags) {
4389
- const missingTag = internal.tags.find((tag) => !rootTags.includes(tag));
4390
- if (missingTag !== void 0) {
4391
- throw new Error(
4392
- `Tag "${missingTag}" is missing definition. Please define it in OpenAPI root tags object. [${path_.join(".")}]`
4393
- );
4394
- }
4395
- }
4396
- const operation = {
4397
- summary: internal.summary,
4398
- description: internal.description,
4399
- deprecated: internal.deprecated,
4400
- tags: internal.tags,
4401
- operationId: path_.join("."),
4402
- parameters: parameters.length ? parameters : void 0,
4403
- requestBody,
4404
- responses: {
4405
- 200: successResponse
4406
- }
4407
- };
4408
- builder.addPath(path, {
4409
- [method.toLocaleLowerCase()]: operation
4419
+ builder.addPath(httpPath, {
4420
+ [method.toLocaleLowerCase()]: operation
4421
+ });
4410
4422
  });
4411
- });
4423
+ for (const lazy of lazies) {
4424
+ const router = (await lazy.lazy[LAZY_LOADER_SYMBOL]()).default;
4425
+ pending.push({
4426
+ path: lazy.path,
4427
+ router
4428
+ });
4429
+ }
4430
+ }
4412
4431
  return preSerialize(builder.getSpec());
4413
4432
  }
4414
4433
  function isFileSchema(schema) {
@@ -4419,3 +4438,4 @@ function isFileSchema(schema) {
4419
4438
  export {
4420
4439
  generateOpenAPI
4421
4440
  };
4441
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,15 @@
1
+ import type { HTTPPath } from '@orpc/contract';
2
+ import type { ANY_LAZY_PROCEDURE, ANY_PROCEDURE, Router } from '@orpc/server';
3
+ import type { FetchHandler } from '@orpc/server/fetch';
4
+ import type { Router as HonoRouter } from 'hono/router';
5
+ export type ResolveRouter = (router: Router<any>, method: string, pathname: string) => Promise<{
6
+ path: string[];
7
+ procedure: ANY_PROCEDURE | ANY_LAZY_PROCEDURE;
8
+ params: Record<string, string>;
9
+ } | undefined>;
10
+ type Routing = HonoRouter<string[]>;
11
+ export declare function createOpenAPIHandler(createHonoRouter: () => Routing): FetchHandler;
12
+ export declare function createResolveRouter(createHonoRouter: () => Routing): ResolveRouter;
13
+ export declare function openAPIPathToRouterPath(path: HTTPPath): string;
14
+ export {};
15
+ //# sourceMappingURL=base-handler.d.ts.map
@@ -0,0 +1,4 @@
1
+ export * from './base-handler';
2
+ export * from './server-handler';
3
+ export * from './serverless-handler';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ import type { FetchHandler } from '@orpc/server/fetch';
2
+ export declare function createOpenAPIServerHandler(): FetchHandler;
3
+ //# sourceMappingURL=server-handler.d.ts.map
@@ -0,0 +1,3 @@
1
+ import type { FetchHandler } from '@orpc/server/fetch';
2
+ export declare function createOpenAPIServerlessHandler(): FetchHandler;
3
+ //# sourceMappingURL=serverless-handler.d.ts.map
@@ -20,4 +20,5 @@ export interface GenerateOpenAPIOptions {
20
20
  }
21
21
  export declare function generateOpenAPI(opts: {
22
22
  router: ContractRouter | Router<any>;
23
- } & Omit<OpenAPIObject, 'openapi'>, options?: GenerateOpenAPIOptions): OpenAPIObject;
23
+ } & Omit<OpenAPIObject, 'openapi'>, options?: GenerateOpenAPIOptions): Promise<OpenAPIObject>;
24
+ //# sourceMappingURL=generator.d.ts.map
@@ -1,2 +1,3 @@
1
1
  /** unnoq */
2
2
  export * from './generator';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,16 @@
1
+ import type { ContractProcedure, ContractRouter, WELL_CONTRACT_PROCEDURE } from '@orpc/contract';
2
+ import type { ANY_LAZY_PROCEDURE, ANY_PROCEDURE, Lazy, Router } from '@orpc/server';
3
+ export interface EachLeafOptions {
4
+ router: ANY_PROCEDURE | Router<any> | ContractRouter | ContractProcedure<any, any>;
5
+ path: string[];
6
+ }
7
+ export interface EachLeafCallbackOptions {
8
+ contract: WELL_CONTRACT_PROCEDURE;
9
+ path: string[];
10
+ }
11
+ export interface EachContractLeafResultItem {
12
+ lazy: ANY_LAZY_PROCEDURE | Lazy<Router<any>>;
13
+ path: string[];
14
+ }
15
+ export declare function eachContractProcedureLeaf(options: EachLeafOptions, callback: (options: EachLeafCallbackOptions) => void, result?: EachContractLeafResultItem[], isCurrentRouterContract?: boolean): EachContractLeafResultItem[];
16
+ //# sourceMappingURL=utils.d.ts.map
@@ -40,3 +40,4 @@ export declare function extractJSONSchema(schema: JSONSchema, check: (schema: JS
40
40
  schema: JSONSchema | undefined;
41
41
  matches: JSONSchema[];
42
42
  };
43
+ //# sourceMappingURL=zod-to-json-schema.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/openapi",
3
3
  "type": "module",
4
- "version": "0.11.0",
4
+ "version": "0.13.0",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -19,30 +19,37 @@
19
19
  "import": "./dist/index.js",
20
20
  "default": "./dist/index.js"
21
21
  },
22
+ "./fetch": {
23
+ "types": "./dist/src/fetch/index.d.ts",
24
+ "import": "./dist/fetch.js",
25
+ "default": "./dist/fetch.js"
26
+ },
22
27
  "./🔒/*": {
23
28
  "types": "./dist/src/*.d.ts"
24
29
  }
25
30
  },
26
31
  "files": [
27
- "!dist/*.tsbuildinfo",
32
+ "!**/*.map",
33
+ "!**/*.tsbuildinfo",
28
34
  "dist"
29
35
  ],
30
36
  "dependencies": {
31
37
  "escape-string-regexp": "^5.0.0",
32
38
  "json-schema-typed": "^8.0.1",
33
39
  "openapi3-ts": "^4.4.0",
34
- "@orpc/contract": "0.11.0",
35
- "@orpc/server": "0.11.0",
36
- "@orpc/shared": "0.11.0",
37
- "@orpc/transformer": "0.11.0",
38
- "@orpc/zod": "0.11.0"
40
+ "@orpc/contract": "0.13.0",
41
+ "@orpc/shared": "0.13.0",
42
+ "@orpc/server": "0.13.0",
43
+ "@orpc/transformer": "0.13.0",
44
+ "@orpc/zod": "0.13.0"
39
45
  },
40
46
  "devDependencies": {
41
47
  "@readme/openapi-parser": "^2.6.0",
48
+ "hono": "^4.6.12",
42
49
  "zod": "^3.23.8"
43
50
  },
44
51
  "scripts": {
45
- "build": "tsup --clean --entry.index=src/index.ts --format=esm --onSuccess='tsc -b --noCheck'",
52
+ "build": "tsup --clean --sourcemap --entry.index=src/index.ts --entry.fetch=src/fetch/index.ts --format=esm --onSuccess='tsc -b --noCheck'",
46
53
  "build:watch": "pnpm run build --watch",
47
54
  "type:check": "tsc -b"
48
55
  }