@orpc/openapi 0.12.0 → 0.14.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.
- package/dist/chunk-KZIT2WCV.js +49 -0
- package/dist/fetch.js +70 -32
- package/dist/index.js +188 -168
- package/dist/src/fetch/base-handler.d.ts +6 -5
- package/dist/src/fetch/index.d.ts +1 -0
- package/dist/src/fetch/server-handler.d.ts +1 -0
- package/dist/src/fetch/serverless-handler.d.ts +1 -0
- package/dist/src/generator.d.ts +2 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/utils.d.ts +16 -0
- package/dist/src/zod-to-json-schema.d.ts +1 -0
- package/package.json +9 -8
|
@@ -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
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
eachContractProcedureLeaf
|
|
3
|
+
} from "./chunk-KZIT2WCV.js";
|
|
4
|
+
|
|
1
5
|
// src/fetch/base-handler.ts
|
|
2
6
|
import { ORPC_HEADER, standardizeHTTPPath } from "@orpc/contract";
|
|
3
|
-
import { createProcedureCaller, isProcedure, ORPCError } from "@orpc/server";
|
|
4
|
-
import { isPlainObject, mapValues, trim, value } from "@orpc/shared";
|
|
7
|
+
import { createProcedureCaller, isLazy, isProcedure, LAZY_LOADER_SYMBOL, LAZY_ROUTER_PREFIX_SYMBOL, ORPCError } from "@orpc/server";
|
|
8
|
+
import { executeWithHooks, isPlainObject, mapValues, trim, value } from "@orpc/shared";
|
|
5
9
|
import { OpenAPIDeserializer, OpenAPISerializer, zodCoerce } from "@orpc/transformer";
|
|
6
10
|
function createOpenAPIHandler(createHonoRouter) {
|
|
7
11
|
const resolveRouter = createResolveRouter(createHonoRouter);
|
|
@@ -17,12 +21,18 @@ function createOpenAPIHandler(createHonoRouter) {
|
|
|
17
21
|
const pathname = `/${trim(url.pathname.replace(options.prefix ?? "", ""), "/")}`;
|
|
18
22
|
const customMethod = options.request.method === "POST" ? url.searchParams.get("method")?.toUpperCase() : void 0;
|
|
19
23
|
const method = customMethod || options.request.method;
|
|
20
|
-
const match = resolveRouter(options.router, method, pathname);
|
|
24
|
+
const match = await resolveRouter(options.router, method, pathname);
|
|
21
25
|
if (!match) {
|
|
22
26
|
throw new ORPCError({ code: "NOT_FOUND", message: "Not found" });
|
|
23
27
|
}
|
|
24
|
-
const procedure = match.procedure;
|
|
28
|
+
const procedure = isLazy(match.procedure) ? (await match.procedure[LAZY_LOADER_SYMBOL]()).default : match.procedure;
|
|
25
29
|
const path = match.path;
|
|
30
|
+
if (!isProcedure(procedure)) {
|
|
31
|
+
throw new ORPCError({
|
|
32
|
+
code: "NOT_FOUND",
|
|
33
|
+
message: "Not found"
|
|
34
|
+
});
|
|
35
|
+
}
|
|
26
36
|
const params = procedure.zz$p.contract.zz$cp.InputSchema ? zodCoerce(
|
|
27
37
|
procedure.zz$p.contract.zz$cp.InputSchema,
|
|
28
38
|
match.params,
|
|
@@ -43,10 +53,13 @@ function createOpenAPIHandler(createHonoRouter) {
|
|
|
43
53
|
});
|
|
44
54
|
};
|
|
45
55
|
try {
|
|
46
|
-
return await
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
return await executeWithHooks({
|
|
57
|
+
context,
|
|
58
|
+
hooks: options,
|
|
59
|
+
execute: handler,
|
|
60
|
+
input: options.request,
|
|
61
|
+
meta: void 0
|
|
62
|
+
});
|
|
50
63
|
} catch (e) {
|
|
51
64
|
const error = toORPCError(e);
|
|
52
65
|
try {
|
|
@@ -69,27 +82,44 @@ function createOpenAPIHandler(createHonoRouter) {
|
|
|
69
82
|
};
|
|
70
83
|
}
|
|
71
84
|
var routingCache = /* @__PURE__ */ new Map();
|
|
85
|
+
var pendingCache = /* @__PURE__ */ new Map();
|
|
72
86
|
function createResolveRouter(createHonoRouter) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
routingCache.
|
|
87
|
+
const addRoutes = (routing, pending, options) => {
|
|
88
|
+
const lazies = eachContractProcedureLeaf(options, ({ path, contract }) => {
|
|
89
|
+
const method = contract.zz$cp.method ?? "POST";
|
|
90
|
+
const httpPath = contract.zz$cp.path ? openAPIPathToRouterPath(contract.zz$cp.path) : `/${path.map(encodeURIComponent).join("/")}`;
|
|
91
|
+
routing.add(method, httpPath, path);
|
|
92
|
+
});
|
|
93
|
+
pending.ref.push(...lazies);
|
|
94
|
+
};
|
|
95
|
+
return async (router, method, pathname) => {
|
|
96
|
+
const pending = (() => {
|
|
97
|
+
let pending2 = pendingCache.get(router);
|
|
98
|
+
if (!pending2) {
|
|
99
|
+
pending2 = { ref: [] };
|
|
100
|
+
pendingCache.set(router, pending2);
|
|
101
|
+
}
|
|
102
|
+
return pending2;
|
|
103
|
+
})();
|
|
104
|
+
const routing = (() => {
|
|
105
|
+
let routing2 = routingCache.get(router);
|
|
106
|
+
if (!routing2) {
|
|
107
|
+
routing2 = createHonoRouter();
|
|
108
|
+
routingCache.set(router, routing2);
|
|
109
|
+
addRoutes(routing2, pending, { router, path: [] });
|
|
110
|
+
}
|
|
111
|
+
return routing2;
|
|
112
|
+
})();
|
|
113
|
+
const newPending = [];
|
|
114
|
+
for (const item of pending.ref) {
|
|
115
|
+
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("/")}`)) {
|
|
116
|
+
newPending.push(item);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const router2 = (await item.lazy[LAZY_LOADER_SYMBOL]()).default;
|
|
120
|
+
addRoutes(routing, pending, { path: item.path, router: router2 });
|
|
92
121
|
}
|
|
122
|
+
pending.ref = newPending;
|
|
93
123
|
const [matches, params_] = routing.match(method, pathname);
|
|
94
124
|
const [match] = matches.sort((a, b) => {
|
|
95
125
|
return Object.keys(a[1]).length - Object.keys(b[1]).length;
|
|
@@ -97,18 +127,25 @@ function createResolveRouter(createHonoRouter) {
|
|
|
97
127
|
if (!match) {
|
|
98
128
|
return void 0;
|
|
99
129
|
}
|
|
100
|
-
const path = match[0]
|
|
101
|
-
const procedure = match[0][1];
|
|
130
|
+
const path = match[0];
|
|
102
131
|
const params = params_ ? mapValues(
|
|
103
132
|
match[1],
|
|
104
133
|
(v) => params_[v]
|
|
105
134
|
) : match[1];
|
|
106
|
-
|
|
135
|
+
let current = router;
|
|
136
|
+
for (const segment of path) {
|
|
137
|
+
if (typeof current !== "object" && typeof current !== "function" || !current) {
|
|
138
|
+
current = void 0;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
current = current[segment];
|
|
142
|
+
}
|
|
143
|
+
return isProcedure(current) || isLazy(current) ? {
|
|
107
144
|
path,
|
|
108
|
-
procedure,
|
|
145
|
+
procedure: current,
|
|
109
146
|
params: { ...params }
|
|
110
147
|
// params from hono not a normal object, so we need spread here
|
|
111
|
-
};
|
|
148
|
+
} : void 0;
|
|
112
149
|
};
|
|
113
150
|
}
|
|
114
151
|
function mergeParamsAndInput(coercedParams, input) {
|
|
@@ -666,3 +703,4 @@ export {
|
|
|
666
703
|
createResolveRouter,
|
|
667
704
|
openAPIPathToRouterPath
|
|
668
705
|
};
|
|
706
|
+
//# 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 {
|
|
3
|
-
import {
|
|
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
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
}
|
|
4227
|
-
|
|
4228
|
-
|
|
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
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
);
|
|
4234
|
+
const internal = contract.zz$cp;
|
|
4235
|
+
if (ignoreUndefinedPathProcedures && internal.path === void 0) {
|
|
4236
|
+
return;
|
|
4240
4237
|
}
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
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 (
|
|
4247
|
+
if (typeof inputSchema !== "object" || inputSchema.type !== "object") {
|
|
4250
4248
|
throw new Error(
|
|
4251
|
-
`
|
|
4249
|
+
`When path has parameters, input schema must be an object [${path.join(".")}]`
|
|
4252
4250
|
);
|
|
4253
4251
|
}
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
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
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
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
|
-
|
|
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: "
|
|
4321
|
-
|
|
4322
|
-
|
|
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
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
return
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
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
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
}
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
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
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
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
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
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
|
-
|
|
4389
|
-
|
|
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
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import type { HTTPPath } from '@orpc/contract';
|
|
2
|
+
import type { ANY_LAZY_PROCEDURE, ANY_PROCEDURE, Router } from '@orpc/server';
|
|
2
3
|
import type { FetchHandler } from '@orpc/server/fetch';
|
|
3
4
|
import type { Router as HonoRouter } from 'hono/router';
|
|
4
|
-
|
|
5
|
-
export type ResolveRouter = (router: Router<any>, method: string, pathname: string) => {
|
|
5
|
+
export type ResolveRouter = (router: Router<any>, method: string, pathname: string) => Promise<{
|
|
6
6
|
path: string[];
|
|
7
|
-
procedure:
|
|
7
|
+
procedure: ANY_PROCEDURE | ANY_LAZY_PROCEDURE;
|
|
8
8
|
params: Record<string, string>;
|
|
9
|
-
} | undefined
|
|
10
|
-
type Routing = HonoRouter<
|
|
9
|
+
} | undefined>;
|
|
10
|
+
type Routing = HonoRouter<string[]>;
|
|
11
11
|
export declare function createOpenAPIHandler(createHonoRouter: () => Routing): FetchHandler;
|
|
12
12
|
export declare function createResolveRouter(createHonoRouter: () => Routing): ResolveRouter;
|
|
13
13
|
export declare function openAPIPathToRouterPath(path: HTTPPath): string;
|
|
14
14
|
export {};
|
|
15
|
+
//# sourceMappingURL=base-handler.d.ts.map
|
package/dist/src/generator.d.ts
CHANGED
|
@@ -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
|
package/dist/src/index.d.ts
CHANGED
|
@@ -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
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orpc/openapi",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.14.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://orpc.unnoq.com",
|
|
7
7
|
"repository": {
|
|
@@ -29,18 +29,19 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
|
-
"
|
|
32
|
+
"!**/*.map",
|
|
33
|
+
"!**/*.tsbuildinfo",
|
|
33
34
|
"dist"
|
|
34
35
|
],
|
|
35
36
|
"dependencies": {
|
|
36
37
|
"escape-string-regexp": "^5.0.0",
|
|
37
38
|
"json-schema-typed": "^8.0.1",
|
|
38
39
|
"openapi3-ts": "^4.4.0",
|
|
39
|
-
"@orpc/contract": "0.
|
|
40
|
-
"@orpc/
|
|
41
|
-
"@orpc/
|
|
42
|
-
"@orpc/
|
|
43
|
-
"@orpc/zod": "0.
|
|
40
|
+
"@orpc/contract": "0.14.0",
|
|
41
|
+
"@orpc/server": "0.14.0",
|
|
42
|
+
"@orpc/shared": "0.14.0",
|
|
43
|
+
"@orpc/transformer": "0.14.0",
|
|
44
|
+
"@orpc/zod": "0.14.0"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"@readme/openapi-parser": "^2.6.0",
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
"zod": "^3.23.8"
|
|
49
50
|
},
|
|
50
51
|
"scripts": {
|
|
51
|
-
"build": "tsup --clean --entry.index=src/index.ts --entry.fetch=src/fetch/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'",
|
|
52
53
|
"build:watch": "pnpm run build --watch",
|
|
53
54
|
"type:check": "tsc -b"
|
|
54
55
|
}
|