hono-takibi 0.9.22 → 0.9.24
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/cli/index.d.ts +4 -4
- package/dist/cli/index.js +21 -5
- package/dist/config/index.d.ts +23 -19
- package/dist/config/index.js +133 -6
- package/dist/core/core.d.ts +5 -5
- package/dist/core/core.js +5 -5
- package/dist/core/route.d.ts +7 -0
- package/dist/core/route.js +96 -0
- package/dist/core/schema.d.ts +7 -0
- package/dist/core/schema.js +103 -0
- package/dist/core/takibi.d.ts +4 -4
- package/dist/core/takibi.js +3 -11
- package/dist/format/index.d.ts +4 -6
- package/dist/fsp/index.d.ts +11 -11
- package/dist/generator/rpc/index.d.ts +1 -1
- package/dist/generator/rpc/index.js +26 -79
- package/dist/generator/zod-openapi-hono/openapi/index.d.ts +1 -1
- package/dist/generator/zod-openapi-hono/openapi/index.js +1 -1
- package/dist/generator/zod-openapi-hono/openapi/route/params/params-object.d.ts +1 -1
- package/dist/generator/zod-openapi-hono/openapi/route/params/request-parameter.d.ts +1 -1
- package/dist/helper/get-route-maps.d.ts +1 -1
- package/dist/helper/get-route-maps.js +1 -8
- package/dist/helper/properties-schema.d.ts +1 -1
- package/dist/openapi/index.d.ts +4 -4
- package/dist/typespec/index.d.ts +4 -4
- package/dist/utils/index.d.ts +57 -50
- package/dist/utils/index.js +16 -0
- package/dist/vite-plugin/index.js +1 -1
- package/package.json +1 -1
package/dist/cli/index.d.ts
CHANGED
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
* - `{ ok: false, error: string }` on validation or generation errors
|
|
32
32
|
*/
|
|
33
33
|
export declare function honoTakibi(): Promise<{
|
|
34
|
-
ok: true;
|
|
35
|
-
value: string;
|
|
34
|
+
readonly ok: true;
|
|
35
|
+
readonly value: string;
|
|
36
36
|
} | {
|
|
37
|
-
ok: false;
|
|
38
|
-
error: string;
|
|
37
|
+
readonly ok: false;
|
|
38
|
+
readonly error: string;
|
|
39
39
|
}>;
|
package/dist/cli/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { config } from '../config/index.js';
|
|
4
|
-
import core from '../core/core.js';
|
|
4
|
+
import { core } from '../core/core.js';
|
|
5
|
+
import { route } from '../core/route.js';
|
|
6
|
+
import { schema } from '../core/schema.js';
|
|
5
7
|
import { takibi } from '../core/takibi.js';
|
|
6
|
-
import rpc from '../generator/rpc/index.js';
|
|
8
|
+
import { rpc } from '../generator/rpc/index.js';
|
|
7
9
|
// import { honoRpcWithSWR } from '../generator/swr/index.js'
|
|
8
10
|
import { parseCli } from '../utils/index.js';
|
|
9
11
|
const HELP_TEXT = `Usage: hono-takibi <input.{yaml,json,tsp}> -o <routes.ts> [options]
|
|
@@ -81,15 +83,29 @@ export async function honoTakibi() {
|
|
|
81
83
|
return { ok: false, error: configResult.error };
|
|
82
84
|
}
|
|
83
85
|
const c = configResult.value;
|
|
84
|
-
const takibiResult = c['
|
|
85
|
-
? await takibi(c
|
|
86
|
+
const takibiResult = c['zod-openapi']
|
|
87
|
+
? await takibi(c.input, c['zod-openapi']?.output, c['zod-openapi']?.exportSchema ?? false, c['zod-openapi']?.exportType ?? false, false, // template
|
|
86
88
|
false)
|
|
87
89
|
: undefined;
|
|
88
90
|
if (takibiResult && !takibiResult.ok) {
|
|
89
91
|
return { ok: false, error: takibiResult.error };
|
|
90
92
|
}
|
|
93
|
+
// schema
|
|
94
|
+
const schemaResult = c['zod-openapi']?.schema
|
|
95
|
+
? await schema(c.input, c['zod-openapi'].schema.output, c['zod-openapi'].schema.exportType ?? false, c['zod-openapi']?.schema.split ?? false)
|
|
96
|
+
: undefined;
|
|
97
|
+
if (schemaResult && !schemaResult.ok) {
|
|
98
|
+
return { ok: false, error: schemaResult.error };
|
|
99
|
+
}
|
|
100
|
+
// route
|
|
101
|
+
const routeResult = c['zod-openapi']?.route
|
|
102
|
+
? await route(c.input, c['zod-openapi'].route.output, c['zod-openapi'].route.import, c['zod-openapi'].route.split ?? false)
|
|
103
|
+
: undefined;
|
|
104
|
+
if (routeResult && !routeResult.ok) {
|
|
105
|
+
return { ok: false, error: routeResult.error };
|
|
106
|
+
}
|
|
91
107
|
const rpcResult = c.rpc
|
|
92
|
-
? await core(c.
|
|
108
|
+
? await core(c.input, c.rpc.output, c.rpc.import, 'Generated RPC code written to', rpc)
|
|
93
109
|
: undefined;
|
|
94
110
|
if (rpcResult && !rpcResult.ok) {
|
|
95
111
|
return { ok: false, error: rpcResult.error };
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
type Config = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
output: `${string}.ts`;
|
|
5
|
-
exportType?: boolean;
|
|
6
|
-
exportSchema?: boolean;
|
|
2
|
+
readonly input: `${string}.yaml` | `${string}.json` | `${string}.tsp`;
|
|
3
|
+
readonly 'zod-openapi'?: {
|
|
4
|
+
readonly output: `${string}.ts`;
|
|
5
|
+
readonly exportType?: boolean;
|
|
6
|
+
readonly exportSchema?: boolean;
|
|
7
|
+
readonly schema?: {
|
|
8
|
+
readonly output: string | `${string}.ts`;
|
|
9
|
+
readonly exportType?: boolean;
|
|
10
|
+
readonly split?: boolean;
|
|
11
|
+
};
|
|
12
|
+
readonly route?: {
|
|
13
|
+
readonly output: string | `${string}.ts`;
|
|
14
|
+
readonly import: string;
|
|
15
|
+
readonly split?: boolean;
|
|
16
|
+
};
|
|
7
17
|
};
|
|
8
|
-
rpc?: {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import: string;
|
|
12
|
-
};
|
|
13
|
-
swr?: {
|
|
14
|
-
input: `${string}.yaml` | `${string}.json` | `${string}.tsp`;
|
|
15
|
-
output: `${string}.ts`;
|
|
16
|
-
import: string;
|
|
18
|
+
readonly rpc?: {
|
|
19
|
+
readonly output: `${string}.ts`;
|
|
20
|
+
readonly import: string;
|
|
17
21
|
};
|
|
18
22
|
};
|
|
19
23
|
export declare function config(): Promise<{
|
|
20
|
-
ok: true;
|
|
21
|
-
value: Config;
|
|
24
|
+
readonly ok: true;
|
|
25
|
+
readonly value: Config;
|
|
22
26
|
} | {
|
|
23
|
-
ok: false;
|
|
24
|
-
error: string;
|
|
27
|
+
readonly ok: false;
|
|
28
|
+
readonly error: string;
|
|
25
29
|
}>;
|
|
26
|
-
export
|
|
30
|
+
export declare function defineConfig(c: Config): Config;
|
|
27
31
|
export {};
|
package/dist/config/index.js
CHANGED
|
@@ -1,23 +1,150 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
1
2
|
import { resolve } from 'node:path';
|
|
2
3
|
import { pathToFileURL } from 'node:url';
|
|
3
4
|
import { register } from 'tsx/esm/api';
|
|
5
|
+
const isYamlOrJsonOrTsp = (i) => typeof i === 'string' && (i.endsWith('.yaml') || i.endsWith('.json') || i.endsWith('.tsp'));
|
|
6
|
+
const isTs = (o) => typeof o === 'string' && o.endsWith('.ts');
|
|
4
7
|
export async function config() {
|
|
5
8
|
const abs = resolve(process.cwd(), 'hono-takibi.config.ts');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// }
|
|
9
|
-
register();
|
|
9
|
+
if (!existsSync(abs))
|
|
10
|
+
return { ok: false, error: `Config not found: ${abs}` };
|
|
10
11
|
try {
|
|
12
|
+
register();
|
|
11
13
|
const mod = await import(pathToFileURL(abs).href);
|
|
12
14
|
if (!('default' in mod)) {
|
|
13
15
|
return { ok: false, error: 'Config must export default object' };
|
|
14
16
|
}
|
|
17
|
+
if (mod.default) {
|
|
18
|
+
// input
|
|
19
|
+
if (!isYamlOrJsonOrTsp(mod.default.input)) {
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
error: `Invalid input format for zod-openapi: ${String(mod.default.input)}`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// zod-openapi
|
|
26
|
+
const zo = mod.default['zod-openapi'];
|
|
27
|
+
if (zo) {
|
|
28
|
+
// boolean flags
|
|
29
|
+
if (zo.exportSchema !== undefined && typeof zo.exportSchema !== 'boolean') {
|
|
30
|
+
return {
|
|
31
|
+
ok: false,
|
|
32
|
+
error: `Invalid exportSchema format for zod-openapi: ${String(zo.exportSchema)}`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (zo.exportType !== undefined && typeof zo.exportType !== 'boolean') {
|
|
36
|
+
return {
|
|
37
|
+
ok: false,
|
|
38
|
+
error: `Invalid exportType format for zod-openapi: ${String(zo.exportType)}`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const hasSchema = zo.schema !== undefined;
|
|
42
|
+
const hasRoute = zo.route !== undefined;
|
|
43
|
+
if (hasSchema || hasRoute) {
|
|
44
|
+
if (Object.hasOwn(zo, 'output')) {
|
|
45
|
+
return {
|
|
46
|
+
ok: false,
|
|
47
|
+
error: "Invalid config: When using 'zod-openapi.schema' or 'zod-openapi.route', do NOT set 'zod-openapi.output'.",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
if (!isTs(zo.output)) {
|
|
53
|
+
return {
|
|
54
|
+
ok: false,
|
|
55
|
+
error: `Invalid output format for zod-openapi: ${String(zo.output)}`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (hasSchema) {
|
|
60
|
+
const s = zo.schema;
|
|
61
|
+
if (!s)
|
|
62
|
+
return { ok: false, error: 'Invalid config: zod-openapi.schema is undefined' };
|
|
63
|
+
if (s.split !== undefined && typeof s.split !== 'boolean') {
|
|
64
|
+
return {
|
|
65
|
+
ok: false,
|
|
66
|
+
error: `Invalid schema split format for zod-openapi: ${String(s.split)}`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (typeof s.output !== 'string') {
|
|
70
|
+
return { ok: false, error: `Invalid schema output path: ${String(s.output)}` };
|
|
71
|
+
}
|
|
72
|
+
if (s.split === true) {
|
|
73
|
+
if (isTs(s.output)) {
|
|
74
|
+
return {
|
|
75
|
+
ok: false,
|
|
76
|
+
error: `Invalid schema output path for split mode (must be a directory, not .ts): ${s.output}`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
if (!isTs(s.output)) {
|
|
82
|
+
return {
|
|
83
|
+
ok: false,
|
|
84
|
+
error: `Invalid schema output path for non-split mode (must be .ts file): ${s.output}`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (s.exportType !== undefined && typeof s.exportType !== 'boolean') {
|
|
89
|
+
return {
|
|
90
|
+
ok: false,
|
|
91
|
+
error: `Invalid schema exportType format for zod-openapi: ${String(s.exportType)}`,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (hasRoute) {
|
|
96
|
+
const r = zo.route;
|
|
97
|
+
if (!r)
|
|
98
|
+
return { ok: false, error: 'Invalid config: zod-openapi.route is undefined' };
|
|
99
|
+
if (typeof r.import !== 'string') {
|
|
100
|
+
return {
|
|
101
|
+
ok: false,
|
|
102
|
+
error: `Invalid route import format for zod-openapi: ${String(r.import)}`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (r.split !== undefined && typeof r.split !== 'boolean') {
|
|
106
|
+
return {
|
|
107
|
+
ok: false,
|
|
108
|
+
error: `Invalid route split format for zod-openapi: ${String(r.split)}`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (typeof r.output !== 'string') {
|
|
112
|
+
return { ok: false, error: `Invalid route output path: ${String(r.output)}` };
|
|
113
|
+
}
|
|
114
|
+
if (r.split === true) {
|
|
115
|
+
if (isTs(r.output)) {
|
|
116
|
+
return {
|
|
117
|
+
ok: false,
|
|
118
|
+
error: `Invalid route output path for split mode (must be a directory, not .ts): ${r.output}`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
if (!isTs(r.output)) {
|
|
124
|
+
return {
|
|
125
|
+
ok: false,
|
|
126
|
+
error: `Invalid route output path for non-split mode (must be .ts file): ${r.output}`,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const rpc = mod.default.rpc;
|
|
133
|
+
if (rpc) {
|
|
134
|
+
if (!isTs(rpc.output)) {
|
|
135
|
+
return { ok: false, error: `Invalid output format for rpc: ${String(rpc.output)}` };
|
|
136
|
+
}
|
|
137
|
+
if (typeof rpc.import !== 'string') {
|
|
138
|
+
return { ok: false, error: `Invalid import format for rpc: ${String(rpc.import)}` };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
15
142
|
return { ok: true, value: mod.default };
|
|
16
143
|
}
|
|
17
144
|
catch (e) {
|
|
18
145
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
19
146
|
}
|
|
20
147
|
}
|
|
21
|
-
export
|
|
22
|
-
return
|
|
148
|
+
export function defineConfig(c) {
|
|
149
|
+
return c;
|
|
23
150
|
}
|
package/dist/core/core.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type OpenAPI } from '../openapi/index.js';
|
|
2
|
-
export
|
|
3
|
-
ok: true;
|
|
4
|
-
value: string;
|
|
2
|
+
export declare function core(input: `${string}.yaml` | `${string}.json` | `${string}.tsp`, output: `${string}.ts`, importCode: string, value: string, fn: (openapi: OpenAPI, importCode: string) => string): Promise<{
|
|
3
|
+
readonly ok: true;
|
|
4
|
+
readonly value: string;
|
|
5
5
|
} | {
|
|
6
|
-
ok: false;
|
|
7
|
-
error: string;
|
|
6
|
+
readonly ok: false;
|
|
7
|
+
readonly error: string;
|
|
8
8
|
}>;
|
package/dist/core/core.js
CHANGED
|
@@ -2,21 +2,21 @@ import path from 'node:path';
|
|
|
2
2
|
import { fmt } from '../format/index.js';
|
|
3
3
|
import { mkdir, writeFile } from '../fsp/index.js';
|
|
4
4
|
import { parseOpenAPI } from '../openapi/index.js';
|
|
5
|
-
export
|
|
5
|
+
export async function core(input, output, importCode, value, fn) {
|
|
6
6
|
const openAPIResult = await parseOpenAPI(input);
|
|
7
7
|
if (!openAPIResult.ok) {
|
|
8
8
|
return { ok: false, error: openAPIResult.error };
|
|
9
9
|
}
|
|
10
10
|
const openAPI = openAPIResult.value;
|
|
11
|
-
const
|
|
12
|
-
if (!
|
|
13
|
-
return { ok: false, error:
|
|
11
|
+
const fnResult = await fmt(fn(openAPI, importCode));
|
|
12
|
+
if (!fnResult.ok) {
|
|
13
|
+
return { ok: false, error: fnResult.error };
|
|
14
14
|
}
|
|
15
15
|
const mkdirResult = await mkdir(path.dirname(output));
|
|
16
16
|
if (!mkdirResult.ok) {
|
|
17
17
|
return { ok: false, error: mkdirResult.error };
|
|
18
18
|
}
|
|
19
|
-
const writeResult = await writeFile(output,
|
|
19
|
+
const writeResult = await writeFile(output, fnResult.value);
|
|
20
20
|
if (!writeResult.ok) {
|
|
21
21
|
return { ok: false, error: writeResult.error };
|
|
22
22
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function route(input: `${string}.yaml` | `${string}.json` | `${string}.tsp`, output: string | `${string}.ts`, importPath: string, split?: boolean): Promise<{
|
|
2
|
+
readonly ok: true;
|
|
3
|
+
readonly value: string;
|
|
4
|
+
} | {
|
|
5
|
+
readonly ok: false;
|
|
6
|
+
readonly error: string;
|
|
7
|
+
}>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fmt } from '../format/index.js';
|
|
3
|
+
import { mkdir, writeFile } from '../fsp/index.js';
|
|
4
|
+
import { routeCode } from '../generator/zod-openapi-hono/openapi/route/index.js';
|
|
5
|
+
import { parseOpenAPI } from '../openapi/index.js';
|
|
6
|
+
const findSchemaTokens = (code) => Array.from(new Set(Array.from(code.matchAll(/\b([A-Za-z_$][A-Za-z0-9_$]*Schema)\b/g))
|
|
7
|
+
.map((m) => m[1] ?? '')
|
|
8
|
+
.filter(Boolean)));
|
|
9
|
+
const extractRouteBlocks = (src) => {
|
|
10
|
+
const re = /export\s+const\s+([A-Za-z_$][A-Za-z0-9_$]*)Route\s*=/g;
|
|
11
|
+
const hits = [];
|
|
12
|
+
for (const m of src.matchAll(re)) {
|
|
13
|
+
const name = (m[1] ?? '').trim();
|
|
14
|
+
const start = m.index ?? 0;
|
|
15
|
+
if (name)
|
|
16
|
+
hits.push({ name, start });
|
|
17
|
+
}
|
|
18
|
+
return hits.map((h, i) => {
|
|
19
|
+
const start = h.start;
|
|
20
|
+
const end = i + 1 < hits.length ? (hits[i + 1]?.start ?? src.length) : src.length;
|
|
21
|
+
return { name: h.name, block: src.slice(start, end).trim() };
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
const lowerFirst = (s) => (s ? s.charAt(0).toLowerCase() + s.slice(1) : s);
|
|
25
|
+
export async function route(input, output, importPath, split) {
|
|
26
|
+
const openAPIResult = await parseOpenAPI(input);
|
|
27
|
+
if (!openAPIResult.ok) {
|
|
28
|
+
return { ok: false, error: openAPIResult.error };
|
|
29
|
+
}
|
|
30
|
+
const openAPI = openAPIResult.value;
|
|
31
|
+
const routesSrc = routeCode(openAPI.paths);
|
|
32
|
+
if (!split) {
|
|
33
|
+
const includeZ = routesSrc.includes('z.');
|
|
34
|
+
const schemaTokens = findSchemaTokens(routesSrc);
|
|
35
|
+
const importHono = `import { createRoute${includeZ ? ', z' : ''} } from '@hono/zod-openapi'`;
|
|
36
|
+
const importSchemas = schemaTokens.length > 0 ? `import { ${schemaTokens.join(',')} } from '${importPath}'` : '';
|
|
37
|
+
const finalSrc = [importHono, importSchemas, '\n', routesSrc].filter(Boolean).join('\n');
|
|
38
|
+
const fmtCode = await fmt(finalSrc);
|
|
39
|
+
if (!fmtCode.ok)
|
|
40
|
+
return { ok: false, error: fmtCode.error };
|
|
41
|
+
const mk = await mkdir(path.dirname(output));
|
|
42
|
+
if (!mk.ok)
|
|
43
|
+
return { ok: false, error: mk.error };
|
|
44
|
+
const wr = await writeFile(output, fmtCode.value);
|
|
45
|
+
return wr.ok
|
|
46
|
+
? { ok: true, value: `Generated route code written to ${output}` }
|
|
47
|
+
: { ok: false, error: wr.error };
|
|
48
|
+
}
|
|
49
|
+
const outDir = output.replace(/\.ts$/, '');
|
|
50
|
+
const blocks = extractRouteBlocks(routesSrc);
|
|
51
|
+
if (blocks.length === 0) {
|
|
52
|
+
const includeZ = routesSrc.includes('z.');
|
|
53
|
+
const schemaTokens = findSchemaTokens(routesSrc);
|
|
54
|
+
const importHono = `import { createRoute${includeZ ? ', z' : ''} } from '@hono/zod-openapi'`;
|
|
55
|
+
const importSchemas = schemaTokens.length > 0 ? `import { ${schemaTokens.join(',')} } from '${importPath}'` : '';
|
|
56
|
+
const finalSrc = [importHono, importSchemas, '\n', routesSrc].filter(Boolean).join('\n');
|
|
57
|
+
const fmtCode = await fmt(finalSrc);
|
|
58
|
+
if (!fmtCode.ok)
|
|
59
|
+
return { ok: false, error: fmtCode.error };
|
|
60
|
+
const mk = await mkdir(path.dirname(output));
|
|
61
|
+
if (!mk.ok)
|
|
62
|
+
return { ok: false, error: mk.error };
|
|
63
|
+
const wr = await writeFile(output, fmtCode.value);
|
|
64
|
+
return wr.ok
|
|
65
|
+
? { ok: true, value: `Generated route code written to ${output}` }
|
|
66
|
+
: { ok: false, error: wr.error };
|
|
67
|
+
}
|
|
68
|
+
for (const { name, block } of blocks) {
|
|
69
|
+
const includeZ = block.includes('z.');
|
|
70
|
+
const schemaTokens = findSchemaTokens(block);
|
|
71
|
+
const importHono = `import { createRoute${includeZ ? ', z' : ''} } from '@hono/zod-openapi'`;
|
|
72
|
+
const importSchemas = schemaTokens.length > 0 ? `import { ${schemaTokens.join(',')} } from '${importPath}'` : '';
|
|
73
|
+
const fileSrc = [importHono, importSchemas, '\n', block, ''].filter(Boolean).join('\n');
|
|
74
|
+
const fmtCode = await fmt(fileSrc);
|
|
75
|
+
if (!fmtCode.ok)
|
|
76
|
+
return { ok: false, error: fmtCode.error };
|
|
77
|
+
const filePath = `${outDir}/${lowerFirst(name)}.ts`;
|
|
78
|
+
const mk = await mkdir(path.dirname(filePath));
|
|
79
|
+
if (!mk.ok)
|
|
80
|
+
return { ok: false, error: mk.error };
|
|
81
|
+
const wr = await writeFile(filePath, fmtCode.value);
|
|
82
|
+
if (!wr.ok)
|
|
83
|
+
return { ok: false, error: wr.error };
|
|
84
|
+
}
|
|
85
|
+
const indexBody = `${blocks.map(({ name }) => `export * from './${lowerFirst(name)}'`).join('\n')}\n`;
|
|
86
|
+
const indexFmt = await fmt(indexBody);
|
|
87
|
+
if (!indexFmt.ok)
|
|
88
|
+
return { ok: false, error: indexFmt.error };
|
|
89
|
+
const mkIndex = await mkdir(path.dirname(`${outDir}/index.ts`));
|
|
90
|
+
if (!mkIndex.ok)
|
|
91
|
+
return { ok: false, error: mkIndex.error };
|
|
92
|
+
const wrIndex = await writeFile(`${outDir}/index.ts`, indexFmt.value);
|
|
93
|
+
if (!wrIndex.ok)
|
|
94
|
+
return { ok: false, error: wrIndex.error };
|
|
95
|
+
return { ok: true, value: `Generated route code written to ${outDir}/*.ts (index.ts included)` };
|
|
96
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function schema(input: `${string}.yaml` | `${string}.json` | `${string}.tsp`, output: string | `${string}.ts`, exportType: boolean, split?: boolean): Promise<{
|
|
2
|
+
readonly ok: true;
|
|
3
|
+
readonly value: string;
|
|
4
|
+
} | {
|
|
5
|
+
readonly ok: false;
|
|
6
|
+
readonly error: string;
|
|
7
|
+
}>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fmt } from '../format/index.js';
|
|
3
|
+
import { mkdir, writeFile } from '../fsp/index.js';
|
|
4
|
+
import { zodToOpenAPI } from '../generator/zod-to-openapi/index.js';
|
|
5
|
+
import { resolveSchemasDependencies } from '../helper/resolve-schemas-dependencies.js';
|
|
6
|
+
import { zodToOpenAPISchema } from '../helper/zod-to-openapi-schema.js';
|
|
7
|
+
import { parseOpenAPI } from '../openapi/index.js';
|
|
8
|
+
const lowerFirst = (s) => (s ? (s[0]?.toLowerCase() ?? '') + s.slice(1) : s);
|
|
9
|
+
const findSchemaRefs = (code, selfName) => {
|
|
10
|
+
const re = /\b([A-Za-z_$][A-Za-z0-9_$]*)Schema\b/g;
|
|
11
|
+
const out = new Set();
|
|
12
|
+
for (const m of code.matchAll(re)) {
|
|
13
|
+
const base = m[1] ?? '';
|
|
14
|
+
if (base !== selfName && base)
|
|
15
|
+
out.add(base);
|
|
16
|
+
}
|
|
17
|
+
return Array.from(out);
|
|
18
|
+
};
|
|
19
|
+
export async function schema(input, output, exportType, split) {
|
|
20
|
+
const openAPIResult = await parseOpenAPI(input);
|
|
21
|
+
if (!openAPIResult.ok) {
|
|
22
|
+
return { ok: false, error: openAPIResult.error };
|
|
23
|
+
}
|
|
24
|
+
const openAPI = openAPIResult.value;
|
|
25
|
+
const { schemas } = openAPI.components ? openAPI.components : {};
|
|
26
|
+
if (!schemas) {
|
|
27
|
+
return { ok: false, error: 'No schemas found' };
|
|
28
|
+
}
|
|
29
|
+
const orderedSchemas = resolveSchemasDependencies(schemas);
|
|
30
|
+
if (orderedSchemas.length === 0) {
|
|
31
|
+
return { ok: true, value: 'No schemas found' };
|
|
32
|
+
}
|
|
33
|
+
// split
|
|
34
|
+
if (split) {
|
|
35
|
+
const outDir = output.replace(/\.ts$/, '');
|
|
36
|
+
for (const schemaName of orderedSchemas) {
|
|
37
|
+
const schema = schemas[schemaName];
|
|
38
|
+
const z = zodToOpenAPI(schema);
|
|
39
|
+
const zs = zodToOpenAPISchema(schemaName, z, true, exportType);
|
|
40
|
+
const importZ = `import { z } from '@hono/zod-openapi'`;
|
|
41
|
+
const deps = findSchemaRefs(zs, schemaName).filter((d) => d in schemas);
|
|
42
|
+
const depImports = deps.length > 0
|
|
43
|
+
? deps.map((d) => `import { ${d}Schema } from './${lowerFirst(d)}'`).join('\n')
|
|
44
|
+
: '';
|
|
45
|
+
const fileCode = [importZ, depImports, '\n', zs].filter(Boolean).join('\n');
|
|
46
|
+
const fmtCode = await fmt(fileCode);
|
|
47
|
+
if (!fmtCode.ok) {
|
|
48
|
+
return { ok: false, error: fmtCode.error };
|
|
49
|
+
}
|
|
50
|
+
const filePath = `${outDir}/${lowerFirst(schemaName)}.ts`;
|
|
51
|
+
const mkdirResult = await mkdir(path.dirname(filePath));
|
|
52
|
+
if (!mkdirResult.ok) {
|
|
53
|
+
return { ok: false, error: mkdirResult.error };
|
|
54
|
+
}
|
|
55
|
+
const writeResult = await writeFile(filePath, fmtCode.value);
|
|
56
|
+
if (!writeResult.ok) {
|
|
57
|
+
return { ok: false, error: writeResult.error };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// index.ts
|
|
61
|
+
const indexBody = `${orderedSchemas
|
|
62
|
+
.map((n) => `export * from './${lowerFirst(n)}'`)
|
|
63
|
+
.join('\n')}\n`;
|
|
64
|
+
const indexFmt = await fmt(indexBody);
|
|
65
|
+
if (!indexFmt.ok) {
|
|
66
|
+
return { ok: false, error: indexFmt.error };
|
|
67
|
+
}
|
|
68
|
+
const mkIndex = await mkdir(path.dirname(`${outDir}/index.ts`));
|
|
69
|
+
if (!mkIndex.ok) {
|
|
70
|
+
return { ok: false, error: mkIndex.error };
|
|
71
|
+
}
|
|
72
|
+
const wrIndex = await writeFile(`${outDir}/index.ts`, indexFmt.value);
|
|
73
|
+
if (!wrIndex.ok) {
|
|
74
|
+
return { ok: false, error: wrIndex.error };
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
ok: true,
|
|
78
|
+
value: `Generated schema code written to ${outDir}/*.ts (index.ts included)`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const schemaDefinitions = orderedSchemas
|
|
82
|
+
.map((schemaName) => {
|
|
83
|
+
const schema = schemas[schemaName];
|
|
84
|
+
const z = zodToOpenAPI(schema);
|
|
85
|
+
return zodToOpenAPISchema(schemaName, z, true, exportType);
|
|
86
|
+
})
|
|
87
|
+
.join('\n\n');
|
|
88
|
+
const importCode = `import { z } from '@hono/zod-openapi'`;
|
|
89
|
+
const schemaDefinitionsCode = `${importCode}\n\n${schemaDefinitions}`;
|
|
90
|
+
const fmtCode = await fmt(schemaDefinitionsCode);
|
|
91
|
+
if (!fmtCode.ok) {
|
|
92
|
+
return { ok: false, error: fmtCode.error };
|
|
93
|
+
}
|
|
94
|
+
const mkdirResult = await mkdir(path.dirname(output));
|
|
95
|
+
if (!mkdirResult.ok) {
|
|
96
|
+
return { ok: false, error: mkdirResult.error };
|
|
97
|
+
}
|
|
98
|
+
const writeResult = await writeFile(output, fmtCode.value);
|
|
99
|
+
if (!writeResult.ok) {
|
|
100
|
+
return { ok: false, error: writeResult.error };
|
|
101
|
+
}
|
|
102
|
+
return { ok: true, value: `Generated schema code written to ${output}` };
|
|
103
|
+
}
|
package/dist/core/takibi.d.ts
CHANGED
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
* @returns A `Result` containing a success message or an error string.
|
|
47
47
|
*/
|
|
48
48
|
export declare function takibi(input: `${string}.yaml` | `${string}.json` | `${string}.tsp`, output: `${string}.ts`, exportSchema: boolean, exportType: boolean, template: boolean, test: boolean, basePath?: string): Promise<{
|
|
49
|
-
ok: true;
|
|
50
|
-
value: string;
|
|
49
|
+
readonly ok: true;
|
|
50
|
+
readonly value: string;
|
|
51
51
|
} | {
|
|
52
|
-
ok: false;
|
|
53
|
-
error: string;
|
|
52
|
+
readonly ok: false;
|
|
53
|
+
readonly error: string;
|
|
54
54
|
}>;
|
package/dist/core/takibi.js
CHANGED
|
@@ -2,9 +2,9 @@ import path from 'node:path';
|
|
|
2
2
|
import { fmt } from '../format/index.js';
|
|
3
3
|
import { mkdir, readdir, writeFile } from '../fsp/index.js';
|
|
4
4
|
import { app } from '../generator/zod-openapi-hono/app/index.js';
|
|
5
|
-
import zodOpenAPIHono from '../generator/zod-openapi-hono/openapi/index.js';
|
|
5
|
+
import { zodOpenAPIHono } from '../generator/zod-openapi-hono/openapi/index.js';
|
|
6
6
|
import { parseOpenAPI } from '../openapi/index.js';
|
|
7
|
-
import { groupHandlersByFileName, methodPath } from '../utils/index.js';
|
|
7
|
+
import { groupHandlersByFileName, isHttpMethod, methodPath } from '../utils/index.js';
|
|
8
8
|
/**
|
|
9
9
|
* Generates TypeScript code from an OpenAPI spec and optional templates.
|
|
10
10
|
*
|
|
@@ -81,8 +81,7 @@ export async function takibi(input, output, exportSchema, exportType, template,
|
|
|
81
81
|
if (!readdirResult.ok) {
|
|
82
82
|
return { ok: false, error: readdirResult.error };
|
|
83
83
|
}
|
|
84
|
-
const
|
|
85
|
-
const target = path.join(dir, files.includes('index.ts') ? 'main.ts' : 'index.ts');
|
|
84
|
+
const target = path.join(dir, readdirResult.value.includes('index.ts') ? 'main.ts' : 'index.ts');
|
|
86
85
|
const writeResult = await writeFile(target, appResult.value);
|
|
87
86
|
if (!writeResult.ok) {
|
|
88
87
|
return { ok: false, error: writeResult.error };
|
|
@@ -109,13 +108,6 @@ export async function takibi(input, output, exportSchema, exportType, template,
|
|
|
109
108
|
async function zodOpenapiHonoHandler(openapi, output, test) {
|
|
110
109
|
const paths = openapi.paths;
|
|
111
110
|
const handlers = [];
|
|
112
|
-
const isHttpMethod = (v) => {
|
|
113
|
-
for (const m of ['get', 'put', 'post', 'delete', 'patch', 'options', 'head', 'trace']) {
|
|
114
|
-
if (m === v)
|
|
115
|
-
return true;
|
|
116
|
-
}
|
|
117
|
-
return false;
|
|
118
|
-
};
|
|
119
111
|
for (const [path, pathItem] of Object.entries(paths)) {
|
|
120
112
|
for (const [method] of Object.entries(pathItem)) {
|
|
121
113
|
if (!isHttpMethod(method))
|
package/dist/format/index.d.ts
CHANGED
|
@@ -5,11 +5,9 @@
|
|
|
5
5
|
* @returns A `Result` containing the formatted code or an error message.
|
|
6
6
|
*/
|
|
7
7
|
export declare function fmt(code: string): Promise<{
|
|
8
|
-
ok: true;
|
|
9
|
-
value: string;
|
|
10
|
-
error?: undefined;
|
|
8
|
+
readonly ok: true;
|
|
9
|
+
readonly value: string;
|
|
11
10
|
} | {
|
|
12
|
-
ok: false;
|
|
13
|
-
error: string;
|
|
14
|
-
value?: undefined;
|
|
11
|
+
readonly ok: false;
|
|
12
|
+
readonly error: string;
|
|
15
13
|
}>;
|
package/dist/fsp/index.d.ts
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* @returns A `Result` that is `ok` on success, otherwise an error message.
|
|
6
6
|
*/
|
|
7
7
|
export declare function mkdir(dir: string): Promise<{
|
|
8
|
-
ok: false;
|
|
9
|
-
error: string;
|
|
8
|
+
readonly ok: false;
|
|
9
|
+
readonly error: string;
|
|
10
10
|
} | {
|
|
11
|
-
ok: true;
|
|
12
|
-
value: undefined;
|
|
11
|
+
readonly ok: true;
|
|
12
|
+
readonly value: undefined;
|
|
13
13
|
}>;
|
|
14
14
|
/**
|
|
15
15
|
* Reads the contents of a directory.
|
|
@@ -18,11 +18,11 @@ export declare function mkdir(dir: string): Promise<{
|
|
|
18
18
|
* @returns A `Result` with the file list on success, otherwise an error message.
|
|
19
19
|
*/
|
|
20
20
|
export declare function readdir(dir: string): Promise<{
|
|
21
|
-
ok: false;
|
|
21
|
+
readonly ok: false;
|
|
22
22
|
error: string;
|
|
23
23
|
} | {
|
|
24
|
-
ok: true;
|
|
25
|
-
value: string[];
|
|
24
|
+
readonly ok: true;
|
|
25
|
+
readonly value: string[];
|
|
26
26
|
}>;
|
|
27
27
|
/**
|
|
28
28
|
* Writes UTF-8 text to a file, creating it if necessary.
|
|
@@ -32,9 +32,9 @@ export declare function readdir(dir: string): Promise<{
|
|
|
32
32
|
* @returns A `Result` that is `ok` on success, otherwise an error message.
|
|
33
33
|
*/
|
|
34
34
|
export declare function writeFile(path: string, data: string): Promise<{
|
|
35
|
-
ok: true;
|
|
36
|
-
value: undefined;
|
|
35
|
+
readonly ok: true;
|
|
36
|
+
readonly value: undefined;
|
|
37
37
|
} | {
|
|
38
|
-
ok: false;
|
|
39
|
-
error: string;
|
|
38
|
+
readonly ok: false;
|
|
39
|
+
readonly error: string;
|
|
40
40
|
}>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { OpenAPI } from '../../openapi/index.js';
|
|
2
|
-
export
|
|
2
|
+
export declare function rpc(openapi: OpenAPI, importPath: string): string;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { methodPath } from '../../utils/index.js';
|
|
2
2
|
/* ─────────────────────────────── Guards ─────────────────────────────── */
|
|
3
|
-
/** Narrow to generic object records */
|
|
4
3
|
const isRecord = (v) => typeof v === 'object' && v !== null;
|
|
5
|
-
/** Narrow to OpenAPI paths object (shallow structural check) */
|
|
6
4
|
const isOpenAPIPaths = (v) => {
|
|
7
5
|
if (!isRecord(v))
|
|
8
6
|
return false;
|
|
@@ -11,20 +9,11 @@ const isOpenAPIPaths = (v) => {
|
|
|
11
9
|
return false;
|
|
12
10
|
return true;
|
|
13
11
|
};
|
|
14
|
-
/** Treat any object as Schema (we rely on downstream field checks) */
|
|
15
12
|
const isSchema = (v) => isRecord(v);
|
|
16
13
|
/* ─────────────────────────────── Formatters ─────────────────────────────── */
|
|
17
|
-
/** JS identifier check */
|
|
18
14
|
const isValidIdent = (s) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(s);
|
|
19
|
-
/** Escape single quotes and backslashes for single-quoted strings */
|
|
20
15
|
const esc = (s) => s.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
21
|
-
/**
|
|
22
|
-
* Convert an OpenAPI path to a client access chain.
|
|
23
|
-
* examples:
|
|
24
|
-
* '/' -> ".index"
|
|
25
|
-
* '/hono-x' -> "['hono-x']"
|
|
26
|
-
* '/posts/hono/{id}' -> ".posts.hono[':id']"
|
|
27
|
-
*/
|
|
16
|
+
/** '/'->'.index' | '/hono-x'->"['hono-x']" | '/posts/hono/{id}'->".posts.hono[':id']" */
|
|
28
17
|
const formatPath = (path) => {
|
|
29
18
|
const segs = (path === '/' ? ['index'] : path.replace(/^\/+/, '').split('/')).filter(Boolean);
|
|
30
19
|
return segs
|
|
@@ -35,7 +24,6 @@ const formatPath = (path) => {
|
|
|
35
24
|
: `['${esc(seg)}']`)
|
|
36
25
|
.join('');
|
|
37
26
|
};
|
|
38
|
-
/** 'type' to normalized list for uniform checks */
|
|
39
27
|
const isJSONTypeName = (s) => typeof s === 'string' &&
|
|
40
28
|
(s === 'object' ||
|
|
41
29
|
s === 'array' ||
|
|
@@ -51,7 +39,6 @@ const toTypeArray = (t) => {
|
|
|
51
39
|
return t.filter(isJSONTypeName);
|
|
52
40
|
return [];
|
|
53
41
|
};
|
|
54
|
-
/** Build literal union from enum values (kept compact) */
|
|
55
42
|
const literalFromEnum = (vals) => {
|
|
56
43
|
const toLit = (v) => typeof v === 'string'
|
|
57
44
|
? `'${v.replace(/'/g, "\\'")}'`
|
|
@@ -62,7 +49,6 @@ const literalFromEnum = (vals) => {
|
|
|
62
49
|
: 'unknown';
|
|
63
50
|
return vals.map(toLit).join('|');
|
|
64
51
|
};
|
|
65
|
-
/** Create a $ref resolver for #/components/schemas/... */
|
|
66
52
|
const createResolveRef = (schemas) => (ref) => {
|
|
67
53
|
if (!ref)
|
|
68
54
|
return undefined;
|
|
@@ -72,60 +58,52 @@ const createResolveRef = (schemas) => (ref) => {
|
|
|
72
58
|
const target = schemas[m[1]];
|
|
73
59
|
return isSchema(target) ? target : undefined;
|
|
74
60
|
};
|
|
75
|
-
/**
|
|
61
|
+
/** TS type printer (handles $ref / enums / combinators / additionalProperties / nullable) */
|
|
76
62
|
const createTsTypeFromSchema = (resolveRef) => {
|
|
77
63
|
const tt = (schema, seen = new Set()) => {
|
|
78
64
|
if (!schema)
|
|
79
65
|
return 'unknown';
|
|
80
|
-
// $ref resolution
|
|
81
66
|
if (schema.$ref) {
|
|
82
67
|
const tgt = resolveRef(schema.$ref);
|
|
83
68
|
return tt(tgt, seen);
|
|
84
69
|
}
|
|
85
|
-
// recursion guard
|
|
86
70
|
if (seen.has(schema))
|
|
87
71
|
return 'unknown';
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
// combinators
|
|
72
|
+
const next = new Set(seen);
|
|
73
|
+
next.add(schema);
|
|
91
74
|
if (Array.isArray(schema.oneOf) && schema.oneOf.length)
|
|
92
|
-
return schema.oneOf.map((s) => tt(s,
|
|
75
|
+
return schema.oneOf.map((s) => tt(s, next)).join('|') || 'unknown';
|
|
93
76
|
if (Array.isArray(schema.anyOf) && schema.anyOf.length)
|
|
94
|
-
return schema.anyOf.map((s) => tt(s,
|
|
77
|
+
return schema.anyOf.map((s) => tt(s, next)).join('|') || 'unknown';
|
|
95
78
|
if (Array.isArray(schema.allOf) && schema.allOf.length)
|
|
96
|
-
return schema.allOf.map((s) => tt(s,
|
|
97
|
-
// enum
|
|
79
|
+
return schema.allOf.map((s) => tt(s, next)).join('&') || 'unknown';
|
|
98
80
|
if (Array.isArray(schema.enum) && schema.enum.length) {
|
|
99
81
|
const base = literalFromEnum(schema.enum);
|
|
100
82
|
return schema.nullable ? `${base}|null` : base;
|
|
101
83
|
}
|
|
102
84
|
const types = toTypeArray(schema.type);
|
|
103
|
-
// array
|
|
85
|
+
// array (parentheses when inner contains union/intersection)
|
|
104
86
|
if (types.includes('array')) {
|
|
105
|
-
const
|
|
106
|
-
const
|
|
87
|
+
const item = isSchema(schema.items) ? schema.items : undefined;
|
|
88
|
+
const inner = tt(item, next);
|
|
89
|
+
const needParens = /[|&]/.test(inner) && !/^\(.*\)$/.test(inner);
|
|
90
|
+
const core = `${needParens ? `(${inner})` : inner}[]`;
|
|
107
91
|
return schema.nullable ? `${core}|null` : core;
|
|
108
92
|
}
|
|
109
|
-
// object
|
|
110
93
|
if (types.includes('object')) {
|
|
111
94
|
const req = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
112
95
|
const props = schema.properties ?? {};
|
|
113
96
|
const fields = Object.entries(props).map(([k, v]) => {
|
|
114
97
|
const opt = req.has(k) ? '' : '?';
|
|
115
98
|
const child = isSchema(v) ? v : undefined;
|
|
116
|
-
return `${k}${opt}:${tt(child,
|
|
99
|
+
return `${k}${opt}:${tt(child, next)}`;
|
|
117
100
|
});
|
|
118
101
|
const ap = schema.additionalProperties;
|
|
119
|
-
const addl = ap === true
|
|
120
|
-
? '[key:string]:unknown'
|
|
121
|
-
: isSchema(ap)
|
|
122
|
-
? `[key:string]:${tt(ap, nextSeen)}`
|
|
123
|
-
: '';
|
|
102
|
+
const addl = ap === true ? '[key:string]:unknown' : isSchema(ap) ? `[key:string]:${tt(ap, next)}` : '';
|
|
124
103
|
const members = [...fields, addl].filter(Boolean).join(',');
|
|
125
104
|
const core = `{${members}}`;
|
|
126
105
|
return schema.nullable ? `${core}|null` : core;
|
|
127
106
|
}
|
|
128
|
-
// primitives
|
|
129
107
|
if (types.length === 0)
|
|
130
108
|
return schema.nullable ? 'unknown|null' : 'unknown';
|
|
131
109
|
const prim = types
|
|
@@ -144,13 +122,11 @@ const isParameterObject = (v) => {
|
|
|
144
122
|
const pos = v.in;
|
|
145
123
|
return pos === 'path' || pos === 'query' || pos === 'header' || pos === 'cookie';
|
|
146
124
|
};
|
|
147
|
-
/** Extract components/parameters name from a ref-like value */
|
|
148
125
|
const refParamName = (refLike) => {
|
|
149
126
|
const ref = typeof refLike === 'string' ? refLike : isRefObject(refLike) ? refLike.$ref : undefined;
|
|
150
127
|
const m = ref?.match(/^#\/components\/parameters\/(.+)$/);
|
|
151
128
|
return m ? m[1] : undefined;
|
|
152
129
|
};
|
|
153
|
-
/** Build a resolver that returns normalized ParameterLike (resolving $ref) */
|
|
154
130
|
const createResolveParameter = (componentsParameters) => (p) => {
|
|
155
131
|
if (isParameterObject(p))
|
|
156
132
|
return p;
|
|
@@ -158,7 +134,6 @@ const createResolveParameter = (componentsParameters) => (p) => {
|
|
|
158
134
|
const cand = name ? componentsParameters[name] : undefined;
|
|
159
135
|
return isParameterObject(cand) ? cand : undefined;
|
|
160
136
|
};
|
|
161
|
-
/** Convert raw parameters array into ParameterLike[] */
|
|
162
137
|
const createToParameterLikes = (resolveParam) => (arr) => Array.isArray(arr)
|
|
163
138
|
? arr.reduce((acc, x) => {
|
|
164
139
|
const r = resolveParam(x);
|
|
@@ -178,7 +153,7 @@ const HTTP_METHODS = [
|
|
|
178
153
|
'patch',
|
|
179
154
|
'trace',
|
|
180
155
|
];
|
|
181
|
-
|
|
156
|
+
const hasSchemaProp = (v) => isRecord(v) && 'schema' in v;
|
|
182
157
|
const pickBodySchema = (op) => {
|
|
183
158
|
const rb = op.requestBody;
|
|
184
159
|
if (!isRecord(rb))
|
|
@@ -196,14 +171,12 @@ const pickBodySchema = (op) => {
|
|
|
196
171
|
];
|
|
197
172
|
for (const k of order) {
|
|
198
173
|
const media = isRecord(content[k]) ? content[k] : undefined;
|
|
199
|
-
if (
|
|
174
|
+
if (hasSchemaProp(media) && isSchema(media.schema))
|
|
200
175
|
return media.schema;
|
|
201
|
-
}
|
|
202
176
|
}
|
|
203
177
|
return undefined;
|
|
204
178
|
};
|
|
205
179
|
/* ─────────────────────────────── Args builders ─────────────────────────────── */
|
|
206
|
-
/** Build TS type for params arg (compact formatting) */
|
|
207
180
|
const createBuildParamsType = (tsTypeFromSchema) => (pathParams, queryParams) => {
|
|
208
181
|
const parts = [];
|
|
209
182
|
if (pathParams.length) {
|
|
@@ -216,28 +189,14 @@ const createBuildParamsType = (tsTypeFromSchema) => (pathParams, queryParams) =>
|
|
|
216
189
|
}
|
|
217
190
|
return parts.length ? `{${parts.join(',')}}` : '';
|
|
218
191
|
};
|
|
219
|
-
/** Build function argument signature */
|
|
220
192
|
const buildArgSignature = (paramsType, bodyType) => paramsType && bodyType
|
|
221
|
-
? `params:${paramsType},
|
|
193
|
+
? `params:${paramsType},body:${bodyType}`
|
|
222
194
|
: paramsType
|
|
223
195
|
? `params:${paramsType}`
|
|
224
196
|
: bodyType
|
|
225
197
|
? `body:${bodyType}`
|
|
226
198
|
: '';
|
|
227
|
-
/**
|
|
228
|
-
const buildQueryPiece = (p) => {
|
|
229
|
-
const types = toTypeArray(p.schema?.type);
|
|
230
|
-
const isArr = types.includes('array');
|
|
231
|
-
const itemsInt = isArr && isSchema(p.schema?.items) && toTypeArray(p.schema?.items?.type).includes('integer');
|
|
232
|
-
const isInt = types.includes('integer');
|
|
233
|
-
const rhs = itemsInt
|
|
234
|
-
? `(params.query.${p.name}??[]).map((v:unknown)=>String(v))`
|
|
235
|
-
: isInt
|
|
236
|
-
? `String(params.query.${p.name})`
|
|
237
|
-
: `params.query.${p.name}`;
|
|
238
|
-
return `${p.name}:${rhs}`;
|
|
239
|
-
};
|
|
240
|
-
/** Build client call argument object (compact formatting) */
|
|
199
|
+
/** pass query as-is (keep numbers/arrays) */
|
|
241
200
|
const buildClientArgs = (pathParams, queryParams, hasBody) => {
|
|
242
201
|
const pieces = [];
|
|
243
202
|
if (pathParams.length) {
|
|
@@ -245,7 +204,7 @@ const buildClientArgs = (pathParams, queryParams, hasBody) => {
|
|
|
245
204
|
pieces.push(`param:{${inner}}`);
|
|
246
205
|
}
|
|
247
206
|
if (queryParams.length) {
|
|
248
|
-
const inner = queryParams.map(
|
|
207
|
+
const inner = queryParams.map((p) => `${p.name}:params.query.${p.name}`).join(',');
|
|
249
208
|
pieces.push(`query:{${inner}}`);
|
|
250
209
|
}
|
|
251
210
|
if (hasBody)
|
|
@@ -276,36 +235,25 @@ const generateOperationCode = (path, method, item, deps) => {
|
|
|
276
235
|
: `${deps.client}${clientAccess}.$${method}()`;
|
|
277
236
|
const summary = typeof op.summary === 'string' ? op.summary : '';
|
|
278
237
|
const description = typeof op.description === 'string' ? op.description : '';
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
` * ${method.toUpperCase()} ${path}\n` +
|
|
283
|
-
' */\n' +
|
|
284
|
-
`export async function ${funcName}(${argSig}) {\n` +
|
|
285
|
-
` return await ${call}\n` +
|
|
286
|
-
'}');
|
|
238
|
+
const summaryBlock = summary ? ` * ${summary}\n *\n` : '';
|
|
239
|
+
const descriptionBlock = description ? ` * ${description}\n *\n` : '';
|
|
240
|
+
return `/**\n${summaryBlock}${descriptionBlock} * ${method.toUpperCase()} ${path}\n */\nexport async function ${funcName}(${argSig}){return await ${call}}`;
|
|
287
241
|
};
|
|
288
242
|
/* ─────────────────────────────── Entry ─────────────────────────────── */
|
|
289
|
-
export
|
|
243
|
+
export function rpc(openapi, importPath) {
|
|
290
244
|
const client = 'client';
|
|
291
245
|
const out = [];
|
|
292
|
-
|
|
293
|
-
const header =
|
|
294
|
-
const s = (importCode ?? '').trim();
|
|
295
|
-
return s.length ? `${s}\n\n` : '';
|
|
296
|
-
})();
|
|
297
|
-
// paths guard
|
|
246
|
+
const s = `import { client } from '${importPath}'`;
|
|
247
|
+
const header = s.length ? `${s}\n\n` : '';
|
|
298
248
|
const pathsMaybe = openapi.paths;
|
|
299
249
|
if (!isOpenAPIPaths(pathsMaybe))
|
|
300
250
|
return header;
|
|
301
|
-
// schema & parameter resolvers
|
|
302
251
|
const schemas = openapi.components?.schemas ?? {};
|
|
303
252
|
const resolveRef = createResolveRef(schemas);
|
|
304
253
|
const tsTypeFromSchema = createTsTypeFromSchema(resolveRef);
|
|
305
254
|
const componentsParameters = openapi.components?.parameters ?? {};
|
|
306
255
|
const resolveParameter = createResolveParameter(componentsParameters);
|
|
307
256
|
const toParameterLikes = createToParameterLikes(resolveParameter);
|
|
308
|
-
// iterate path items & operations
|
|
309
257
|
for (const path in pathsMaybe) {
|
|
310
258
|
const rawItem = pathsMaybe[path];
|
|
311
259
|
if (!isRecord(rawItem))
|
|
@@ -331,6 +279,5 @@ export default function rpc(openapi, importCode) {
|
|
|
331
279
|
out.push(code);
|
|
332
280
|
}
|
|
333
281
|
}
|
|
334
|
-
|
|
335
|
-
return header + out.join('\n\n') + (out.length ? '\n' : '');
|
|
282
|
+
return `${header}${out.join('\n\n')}${out.length ? '\n' : ''}`;
|
|
336
283
|
}
|
|
@@ -7,4 +7,4 @@ import type { OpenAPI } from '../../../openapi/index.js';
|
|
|
7
7
|
* @param exportType - Whether to export inferred TypeScript types
|
|
8
8
|
* @returns The generated TypeScript code string
|
|
9
9
|
*/
|
|
10
|
-
export
|
|
10
|
+
export declare function zodOpenAPIHono(openapi: OpenAPI, exportSchema: boolean, exportType: boolean): string;
|
|
@@ -8,7 +8,7 @@ import { routeCode } from './route/index.js';
|
|
|
8
8
|
* @param exportType - Whether to export inferred TypeScript types
|
|
9
9
|
* @returns The generated TypeScript code string
|
|
10
10
|
*/
|
|
11
|
-
export
|
|
11
|
+
export function zodOpenAPIHono(openapi, exportSchema, exportType) {
|
|
12
12
|
const components = openapi.components
|
|
13
13
|
? componentsCode(openapi.components, exportSchema, exportType)
|
|
14
14
|
: '';
|
|
@@ -12,6 +12,6 @@ import type { Parameters } from '../../../../../openapi/index.js';
|
|
|
12
12
|
* - Uses `zodToOpenAPI` for schema conversion and `zodToOpenAPISchema` for output generation.
|
|
13
13
|
* - Supports conditional `export` statements for both schemas and types.
|
|
14
14
|
*/
|
|
15
|
-
export declare function paramsObject(parameters: Parameters[]): {
|
|
15
|
+
export declare function paramsObject(parameters: readonly Parameters[]): {
|
|
16
16
|
[section: string]: Record<string, string>;
|
|
17
17
|
};
|
|
@@ -11,4 +11,4 @@ import type { Parameters, RequestBody } from '../../../../../openapi/index.js';
|
|
|
11
11
|
* - Deduplicates schemas if multiple content types share the same body schema.
|
|
12
12
|
* - Uses `params` instead of `path` for Hono compatibility.
|
|
13
13
|
*/
|
|
14
|
-
export declare function requestParameter(parameters: Parameters[] | undefined, body: RequestBody | undefined): string;
|
|
14
|
+
export declare function requestParameter(parameters: readonly Parameters[] | undefined, body: RequestBody | undefined): string;
|
|
@@ -5,7 +5,7 @@ import type { OpenAPI } from '../openapi/index.js';
|
|
|
5
5
|
* @param openapi - The OpenAPI specification object.
|
|
6
6
|
* @returns An array of route mappings, each with route name, handler name, and path.
|
|
7
7
|
*/
|
|
8
|
-
export declare function getRouteMaps(openapi: OpenAPI): {
|
|
8
|
+
export declare function getRouteMaps(openapi: OpenAPI): readonly {
|
|
9
9
|
routeName: string;
|
|
10
10
|
handlerName: string;
|
|
11
11
|
path: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { methodPath } from '../utils/index.js';
|
|
1
|
+
import { isHttpMethod, methodPath } from '../utils/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Extracts route mappings from an OpenAPI specification.
|
|
4
4
|
*
|
|
@@ -6,13 +6,6 @@ import { methodPath } from '../utils/index.js';
|
|
|
6
6
|
* @returns An array of route mappings, each with route name, handler name, and path.
|
|
7
7
|
*/
|
|
8
8
|
export function getRouteMaps(openapi) {
|
|
9
|
-
const isHttpMethod = (v) => {
|
|
10
|
-
for (const m of ['get', 'put', 'post', 'delete', 'patch', 'options', 'head', 'trace']) {
|
|
11
|
-
if (m === v)
|
|
12
|
-
return true;
|
|
13
|
-
}
|
|
14
|
-
return false;
|
|
15
|
-
};
|
|
16
9
|
const paths = openapi.paths;
|
|
17
10
|
const routeMappings = Object.entries(paths).flatMap(([path, pathItem]) => {
|
|
18
11
|
return Object.entries(pathItem).flatMap(([method]) => {
|
|
@@ -43,4 +43,4 @@ import type { Schema } from '../openapi/index.js';
|
|
|
43
43
|
* )
|
|
44
44
|
* // → 'z.object({user:userSchema.optional(),tags:z.array(tagSchema).optional()}).partial()'
|
|
45
45
|
*/
|
|
46
|
-
export declare function propertiesSchema(properties: Record<string, Schema>, required: string[]): string;
|
|
46
|
+
export declare function propertiesSchema(properties: Record<string, Schema>, required: readonly string[]): string;
|
package/dist/openapi/index.d.ts
CHANGED
|
@@ -23,11 +23,11 @@ import SwaggerParser from '@apidevtools/swagger-parser';
|
|
|
23
23
|
* in downstream code.
|
|
24
24
|
*/
|
|
25
25
|
export declare function parseOpenAPI(input: string): Promise<{
|
|
26
|
-
ok: true;
|
|
27
|
-
value: OpenAPI;
|
|
26
|
+
readonly ok: true;
|
|
27
|
+
readonly value: OpenAPI;
|
|
28
28
|
} | {
|
|
29
|
-
ok: false;
|
|
30
|
-
error: string;
|
|
29
|
+
readonly ok: false;
|
|
30
|
+
readonly error: string;
|
|
31
31
|
}>;
|
|
32
32
|
/**
|
|
33
33
|
* Base OpenAPI type derived from SwaggerParser
|
package/dist/typespec/index.d.ts
CHANGED
|
@@ -25,9 +25,9 @@ import type { SupportedOpenAPIDocuments } from '@typespec/openapi3';
|
|
|
25
25
|
* @returns `{ ok:true, value }` with an OpenAPI document, or `{ ok:false, error }` on failure.
|
|
26
26
|
*/
|
|
27
27
|
export declare function typeSpecToOpenAPI(input: string): Promise<{
|
|
28
|
-
ok: true;
|
|
29
|
-
value: SupportedOpenAPIDocuments;
|
|
28
|
+
readonly ok: true;
|
|
29
|
+
readonly value: SupportedOpenAPIDocuments;
|
|
30
30
|
} | {
|
|
31
|
-
ok: false;
|
|
32
|
-
error: string;
|
|
31
|
+
readonly ok: false;
|
|
32
|
+
readonly error: string;
|
|
33
33
|
}>;
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
* @returns `{ ok:true, value }` on success; `{ ok:false, error }` on invalid usage.
|
|
21
21
|
*/
|
|
22
22
|
export declare function parseCli(args: readonly string[]): {
|
|
23
|
-
ok: true;
|
|
24
|
-
value: {
|
|
25
|
-
input: `${string}.yaml` | `${string}.json` | `${string}.tsp`;
|
|
26
|
-
output: `${string}.ts`;
|
|
27
|
-
exportType: boolean;
|
|
28
|
-
exportSchema: boolean;
|
|
29
|
-
template: boolean;
|
|
30
|
-
test: boolean;
|
|
31
|
-
basePath?: string;
|
|
23
|
+
readonly ok: true;
|
|
24
|
+
readonly value: {
|
|
25
|
+
readonly input: `${string}.yaml` | `${string}.json` | `${string}.tsp`;
|
|
26
|
+
readonly output: `${string}.ts`;
|
|
27
|
+
readonly exportType: boolean;
|
|
28
|
+
readonly exportSchema: boolean;
|
|
29
|
+
readonly template: boolean;
|
|
30
|
+
readonly test: boolean;
|
|
31
|
+
readonly basePath?: string;
|
|
32
32
|
};
|
|
33
33
|
} | {
|
|
34
|
-
ok: false;
|
|
35
|
-
error: string;
|
|
34
|
+
readonly ok: false;
|
|
35
|
+
readonly error: string;
|
|
36
36
|
};
|
|
37
37
|
/**
|
|
38
38
|
* Normalize a JSON Schema `type` value into an array of type strings.
|
|
@@ -77,8 +77,8 @@ export declare function normalizeTypes(t?: 'string' | 'number' | 'integer' | 'da
|
|
|
77
77
|
* @returns Array of import statements.
|
|
78
78
|
*/
|
|
79
79
|
export declare function importRoutes(importsMap: {
|
|
80
|
-
[importPath: `${string}.ts`]: string[];
|
|
81
|
-
}): string[];
|
|
80
|
+
[importPath: `${string}.ts`]: readonly string[];
|
|
81
|
+
}): readonly string[];
|
|
82
82
|
/**
|
|
83
83
|
* Generates registration code for OpenAPI `securitySchemes`.
|
|
84
84
|
*
|
|
@@ -130,12 +130,12 @@ export declare function registerComponent(securitySchemes: {
|
|
|
130
130
|
* @param output - The output TypeScript file name (e.g., 'user.ts'). Used to determine the import path.
|
|
131
131
|
* @returns A record where each key is an import path (e.g., 'user.ts') and the value is an array of route names imported from that path.
|
|
132
132
|
*/
|
|
133
|
-
export declare function importMap(routeMappings: {
|
|
134
|
-
routeName: string;
|
|
135
|
-
handlerName: string;
|
|
136
|
-
path: string;
|
|
137
|
-
}[]
|
|
138
|
-
[importPath: `${string}.ts`]: string[];
|
|
133
|
+
export declare function importMap(routeMappings: Readonly<{
|
|
134
|
+
readonly routeName: string;
|
|
135
|
+
readonly handlerName: string;
|
|
136
|
+
readonly path: string;
|
|
137
|
+
}[]>, output: `${string}.ts`): {
|
|
138
|
+
[importPath: `${string}.ts`]: readonly string[];
|
|
139
139
|
};
|
|
140
140
|
/**
|
|
141
141
|
* Generates import statements for handler functions.
|
|
@@ -159,8 +159,8 @@ export declare function importMap(routeMappings: {
|
|
|
159
159
|
* @returns An array of import statement strings.
|
|
160
160
|
*/
|
|
161
161
|
export declare function importHandlers(handlerImportsMap: {
|
|
162
|
-
[fileName: string]: string[];
|
|
163
|
-
}, output: `${string}.ts`): string[];
|
|
162
|
+
[fileName: string]: readonly string[];
|
|
163
|
+
}, output: `${string}.ts`): readonly string[];
|
|
164
164
|
/**
|
|
165
165
|
* Groups route handlers by file name.
|
|
166
166
|
*
|
|
@@ -180,15 +180,15 @@ export declare function importHandlers(handlerImportsMap: {
|
|
|
180
180
|
* @returns A deduplicated array of grouped handler definitions per file.
|
|
181
181
|
*/
|
|
182
182
|
export declare function groupHandlersByFileName(handlers: {
|
|
183
|
-
fileName: `${string}.ts`;
|
|
184
|
-
testFileName: `${string}.ts`;
|
|
185
|
-
routeHandlerContents: string[];
|
|
186
|
-
routeNames: string[];
|
|
183
|
+
readonly fileName: `${string}.ts`;
|
|
184
|
+
readonly testFileName: `${string}.ts`;
|
|
185
|
+
readonly routeHandlerContents: readonly string[];
|
|
186
|
+
readonly routeNames: readonly string[];
|
|
187
187
|
}[]): {
|
|
188
|
-
fileName: `${string}.ts`;
|
|
189
|
-
testFileName: `${string}.ts`;
|
|
190
|
-
routeHandlerContents: string[];
|
|
191
|
-
routeNames: string[];
|
|
188
|
+
readonly fileName: `${string}.ts`;
|
|
189
|
+
readonly testFileName: `${string}.ts`;
|
|
190
|
+
readonly routeHandlerContents: readonly string[];
|
|
191
|
+
readonly routeNames: readonly string[];
|
|
192
192
|
}[];
|
|
193
193
|
/**
|
|
194
194
|
* Generates a map of handler file names to handler names.
|
|
@@ -210,12 +210,12 @@ export declare function groupHandlersByFileName(handlers: {
|
|
|
210
210
|
* @param handlerMaps - Array of route mappings including route name, handler name, and path.
|
|
211
211
|
* @returns A map where keys are handler file names and values are arrays of handler names.
|
|
212
212
|
*/
|
|
213
|
-
export declare function getHandlerImports(handlerMaps: {
|
|
214
|
-
routeName: string;
|
|
215
|
-
handlerName: string;
|
|
216
|
-
path: string;
|
|
217
|
-
}[]): {
|
|
218
|
-
[fileName: `${string}.ts`]: string[];
|
|
213
|
+
export declare function getHandlerImports(handlerMaps: Readonly<{
|
|
214
|
+
readonly routeName: string;
|
|
215
|
+
readonly handlerName: string;
|
|
216
|
+
readonly path: string;
|
|
217
|
+
}[]>): {
|
|
218
|
+
[fileName: `${string}.ts`]: readonly string[];
|
|
219
219
|
};
|
|
220
220
|
/**
|
|
221
221
|
* Checks if a value is a non-null object (e.g., a potential `$ref` object).
|
|
@@ -238,9 +238,16 @@ export declare function getHandlerImports(handlerMaps: {
|
|
|
238
238
|
* ```
|
|
239
239
|
*/
|
|
240
240
|
export declare function isRefObject(value: unknown): value is {
|
|
241
|
-
$ref?: string;
|
|
242
|
-
[key: string]: unknown;
|
|
241
|
+
readonly $ref?: string;
|
|
242
|
+
readonly [key: string]: unknown;
|
|
243
243
|
};
|
|
244
|
+
/**
|
|
245
|
+
* Checks if a string is a valid HTTP method.
|
|
246
|
+
*
|
|
247
|
+
* @param method - The HTTP method to check.
|
|
248
|
+
* @returns `true` if the method is a valid HTTP method; otherwise `false`.
|
|
249
|
+
*/
|
|
250
|
+
export declare function isHttpMethod(method: string): method is 'get' | 'put' | 'post' | 'delete' | 'patch' | 'options' | 'head' | 'trace';
|
|
244
251
|
/**
|
|
245
252
|
* Checks if all given content types share the same schema definition.
|
|
246
253
|
*
|
|
@@ -266,10 +273,10 @@ export declare function isRefObject(value: unknown): value is {
|
|
|
266
273
|
* }) // true
|
|
267
274
|
* ```
|
|
268
275
|
*/
|
|
269
|
-
export declare function isUniqueContentSchema(contentTypes: string[], content: {
|
|
276
|
+
export declare function isUniqueContentSchema(contentTypes: readonly string[], content: {
|
|
270
277
|
[key: string]: {
|
|
271
278
|
schema: {
|
|
272
|
-
$ref?: `#/components/schemas/${string}`;
|
|
279
|
+
readonly $ref?: `#/components/schemas/${string}`;
|
|
273
280
|
};
|
|
274
281
|
};
|
|
275
282
|
}): boolean;
|
|
@@ -340,16 +347,16 @@ export declare function methodPath(method: string, path: string): string;
|
|
|
340
347
|
* // => export const getUserRoute = createRoute({method:"get",path:"/user",request:{query:...},responses:{...}})
|
|
341
348
|
*/
|
|
342
349
|
export declare function createRoute(args: {
|
|
343
|
-
routeName: string;
|
|
344
|
-
tags?: string;
|
|
345
|
-
method: string;
|
|
346
|
-
path: string;
|
|
347
|
-
operationId?: string;
|
|
348
|
-
summary?: string;
|
|
349
|
-
description?: string;
|
|
350
|
-
security?: string;
|
|
351
|
-
requestParams: string;
|
|
352
|
-
responses: string;
|
|
350
|
+
readonly routeName: string;
|
|
351
|
+
readonly tags?: string;
|
|
352
|
+
readonly method: string;
|
|
353
|
+
readonly path: string;
|
|
354
|
+
readonly operationId?: string;
|
|
355
|
+
readonly summary?: string;
|
|
356
|
+
readonly description?: string;
|
|
357
|
+
readonly security?: string;
|
|
358
|
+
readonly requestParams: string;
|
|
359
|
+
readonly responses: string;
|
|
353
360
|
}): string;
|
|
354
361
|
/**
|
|
355
362
|
* Generates an array of Zod validator strings from OpenAPI parameter objects.
|
|
@@ -371,7 +378,7 @@ export declare function createRoute(args: {
|
|
|
371
378
|
*/
|
|
372
379
|
export declare function requestParamsArray(parameters: {
|
|
373
380
|
[section: string]: Record<string, string>;
|
|
374
|
-
}): string[];
|
|
381
|
+
}): readonly string[];
|
|
375
382
|
/**
|
|
376
383
|
* Escapes a string for safe use in TypeScript string literals.
|
|
377
384
|
*
|
package/dist/utils/index.js
CHANGED
|
@@ -302,6 +302,22 @@ export function getHandlerImports(handlerMaps) {
|
|
|
302
302
|
export function isRefObject(value) {
|
|
303
303
|
return typeof value === 'object' && value !== null;
|
|
304
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* Checks if a string is a valid HTTP method.
|
|
307
|
+
*
|
|
308
|
+
* @param method - The HTTP method to check.
|
|
309
|
+
* @returns `true` if the method is a valid HTTP method; otherwise `false`.
|
|
310
|
+
*/
|
|
311
|
+
export function isHttpMethod(method) {
|
|
312
|
+
return (method === 'get' ||
|
|
313
|
+
method === 'put' ||
|
|
314
|
+
method === 'post' ||
|
|
315
|
+
method === 'delete' ||
|
|
316
|
+
method === 'patch' ||
|
|
317
|
+
method === 'options' ||
|
|
318
|
+
method === 'head' ||
|
|
319
|
+
method === 'trace');
|
|
320
|
+
}
|
|
305
321
|
/**
|
|
306
322
|
* Checks if all given content types share the same schema definition.
|
|
307
323
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fsp from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { fmt } from '../format/index.js';
|
|
4
|
-
import zodOpenAPIHono from '../generator/zod-openapi-hono/openapi/index.js';
|
|
4
|
+
import { zodOpenAPIHono } from '../generator/zod-openapi-hono/openapi/index.js';
|
|
5
5
|
import { parseOpenAPI } from '../openapi/index.js';
|
|
6
6
|
/**
|
|
7
7
|
* Vite plugin to generate Hono routes from an OpenAPI or TypeSpec file.
|