hono-takibi 0.9.52 → 0.9.60
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/core/route.js +6 -6
- package/dist/core/takibi.js +37 -32
- package/dist/generator/zod-to-openapi/z/enum.js +9 -7
- package/dist/helper/wrap.js +9 -9
- package/dist/typespec/index.js +3 -2
- package/dist/utils/index.d.ts +13 -121
- package/dist/utils/index.js +15 -122
- package/dist/vite-plugin/index.js +27 -30
- package/package.json +15 -16
package/dist/core/route.js
CHANGED
|
@@ -41,9 +41,9 @@ export async function route(input, output, importPath, split) {
|
|
|
41
41
|
if (!mkdirResult.ok)
|
|
42
42
|
return { ok: false, error: mkdirResult.error };
|
|
43
43
|
const writeResult = await writeFile(output, fmtResult.value);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
if (!writeResult.ok)
|
|
45
|
+
return { ok: false, error: writeResult.error };
|
|
46
|
+
return { ok: true, value: `Generated route code written to ${output}` };
|
|
47
47
|
}
|
|
48
48
|
const outDir = output.replace(/\.ts$/, '');
|
|
49
49
|
const blocks = extractRouteBlocks(routesSrc);
|
|
@@ -60,9 +60,9 @@ export async function route(input, output, importPath, split) {
|
|
|
60
60
|
if (!mkdirResult.ok)
|
|
61
61
|
return { ok: false, error: mkdirResult.error };
|
|
62
62
|
const writeResult = await writeFile(output, fmtResult.value);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
if (!writeResult.ok)
|
|
64
|
+
return { ok: false, error: writeResult.error };
|
|
65
|
+
return { ok: true, value: `Generated route code written to ${output}` };
|
|
66
66
|
}
|
|
67
67
|
for (const { name, block } of blocks) {
|
|
68
68
|
const includeZ = block.includes('z.');
|
package/dist/core/takibi.js
CHANGED
|
@@ -53,41 +53,46 @@ import { isHttpMethod, methodPath } from '../utils/index.js';
|
|
|
53
53
|
* @returns A `Result` containing a success message or an error string.
|
|
54
54
|
*/
|
|
55
55
|
export async function takibi(input, output, exportSchema, exportType, template, test, basePath) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return { ok: false, error: writeResult.error };
|
|
69
|
-
/** template */
|
|
70
|
-
if (template && output.includes('/')) {
|
|
71
|
-
const appResult = await fmt(app(openAPI, output, basePath));
|
|
72
|
-
if (!appResult.ok)
|
|
73
|
-
return { ok: false, error: appResult.error };
|
|
74
|
-
const dir = path.dirname(output);
|
|
75
|
-
const readdirResult = await readdir(dir);
|
|
76
|
-
if (!readdirResult.ok)
|
|
77
|
-
return { ok: false, error: readdirResult.error };
|
|
78
|
-
const target = path.join(dir, 'index.ts');
|
|
79
|
-
const writeResult = await writeFile(target, appResult.value);
|
|
56
|
+
try {
|
|
57
|
+
const openAPIResult = await parseOpenAPI(input);
|
|
58
|
+
if (!openAPIResult.ok)
|
|
59
|
+
return { ok: false, error: openAPIResult.error };
|
|
60
|
+
const openAPI = openAPIResult.value;
|
|
61
|
+
const honoResult = await fmt(zodOpenAPIHono(openAPI, exportSchema, exportType));
|
|
62
|
+
if (!honoResult.ok)
|
|
63
|
+
return { ok: false, error: honoResult.error };
|
|
64
|
+
const mkdirResult = await mkdir(path.dirname(output));
|
|
65
|
+
if (!mkdirResult.ok)
|
|
66
|
+
return { ok: false, error: mkdirResult.error };
|
|
67
|
+
const writeResult = await writeFile(output, honoResult.value);
|
|
80
68
|
if (!writeResult.ok)
|
|
81
69
|
return { ok: false, error: writeResult.error };
|
|
82
|
-
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
70
|
+
/** template */
|
|
71
|
+
if (template && output.includes('/')) {
|
|
72
|
+
const appResult = await fmt(app(openAPI, output, basePath));
|
|
73
|
+
if (!appResult.ok)
|
|
74
|
+
return { ok: false, error: appResult.error };
|
|
75
|
+
const dir = path.dirname(output);
|
|
76
|
+
const readdirResult = await readdir(dir);
|
|
77
|
+
if (!readdirResult.ok)
|
|
78
|
+
return { ok: false, error: readdirResult.error };
|
|
79
|
+
const target = path.join(dir, 'index.ts');
|
|
80
|
+
const writeResult = await writeFile(target, appResult.value);
|
|
81
|
+
if (!writeResult.ok)
|
|
82
|
+
return { ok: false, error: writeResult.error };
|
|
83
|
+
const zodOpenapiHonoHandlerResult = await zodOpenapiHonoHandler(openAPI, output, test);
|
|
84
|
+
if (!zodOpenapiHonoHandlerResult.ok)
|
|
85
|
+
return { ok: false, error: zodOpenapiHonoHandlerResult.error };
|
|
86
|
+
return { ok: true, value: 'Generated code and template files written' };
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
ok: true,
|
|
90
|
+
value: `Generated code written to ${output}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
86
95
|
}
|
|
87
|
-
return {
|
|
88
|
-
ok: true,
|
|
89
|
-
value: `Generated code written to ${output}`,
|
|
90
|
-
};
|
|
91
96
|
}
|
|
92
97
|
/**
|
|
93
98
|
* Generates route handler files for a Hono app using Zod and OpenAPI.
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
export function _enum(schema) {
|
|
2
|
-
/*
|
|
2
|
+
/* hasType */
|
|
3
3
|
const hasType = (t) => schema.type === t || (Array.isArray(schema.type) && schema.type.some((x) => x === t));
|
|
4
|
+
/* lit */
|
|
4
5
|
const lit = (v) => v === null ? 'null' : typeof v === 'string' ? `'${v}'` : String(v);
|
|
6
|
+
/* tuple */
|
|
5
7
|
const tuple = (arr) => `z.tuple([${arr.map((i) => `z.literal(${lit(i)})`).join(',')}])`;
|
|
6
|
-
/*
|
|
8
|
+
/* guard */
|
|
7
9
|
if (!schema.enum || schema.enum.length === 0)
|
|
8
10
|
return 'z.any()';
|
|
9
|
-
/*
|
|
11
|
+
/* number / integer enum */
|
|
10
12
|
if (hasType('number') || hasType('integer')) {
|
|
11
13
|
return schema.enum.length > 1
|
|
12
14
|
? `z.union([${schema.enum.map((v) => `z.literal(${v})`).join(',')}])`
|
|
13
15
|
: `z.literal(${schema.enum[0]})`;
|
|
14
16
|
}
|
|
15
|
-
/*
|
|
17
|
+
/* boolean enum */
|
|
16
18
|
if (hasType('boolean')) {
|
|
17
19
|
return schema.enum.length > 1
|
|
18
20
|
? `z.union([${schema.enum.map((v) => `z.literal(${v})`).join(',')}])`
|
|
19
21
|
: `z.literal(${schema.enum[0]})`;
|
|
20
22
|
}
|
|
21
|
-
/*
|
|
23
|
+
/* array enum */
|
|
22
24
|
if (hasType('array')) {
|
|
23
25
|
if (schema.enum.length === 1 && Array.isArray(schema.enum[0])) {
|
|
24
26
|
return tuple(schema.enum[0]);
|
|
@@ -26,13 +28,13 @@ export function _enum(schema) {
|
|
|
26
28
|
const parts = schema.enum.map((v) => (Array.isArray(v) ? tuple(v) : `z.literal(${lit(v)})`));
|
|
27
29
|
return `z.union([${parts.join(',')}])`;
|
|
28
30
|
}
|
|
29
|
-
/*
|
|
31
|
+
/* string enum */
|
|
30
32
|
if (schema.enum.every((v) => typeof v === 'string')) {
|
|
31
33
|
return schema.enum.length > 1
|
|
32
34
|
? `z.enum(${JSON.stringify(schema.enum)})`
|
|
33
35
|
: `z.literal('${schema.enum[0]}')`;
|
|
34
36
|
}
|
|
35
|
-
/*
|
|
37
|
+
/* mixed / null only */
|
|
36
38
|
if (schema.enum.length > 1) {
|
|
37
39
|
const parts = schema.enum.map((v) => `z.literal(${lit(v)})`);
|
|
38
40
|
return `z.union([${parts.join(',')}])`;
|
package/dist/helper/wrap.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export function wrap(zod, schema, paramName, paramIn) {
|
|
2
2
|
const formatLiteral = (v) => {
|
|
3
|
-
|
|
3
|
+
/* boolean true or false */
|
|
4
4
|
if (typeof v === 'boolean') {
|
|
5
5
|
return `${v}`;
|
|
6
6
|
}
|
|
7
|
-
|
|
7
|
+
/* number */
|
|
8
8
|
if (typeof v === 'number') {
|
|
9
9
|
if (schema.format === 'int64') {
|
|
10
10
|
return `${v}n`;
|
|
@@ -14,18 +14,18 @@ export function wrap(zod, schema, paramName, paramIn) {
|
|
|
14
14
|
}
|
|
15
15
|
return `${v}`;
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
/* date */
|
|
18
18
|
if (schema.type === 'date' && typeof v === 'string') {
|
|
19
19
|
return `new Date(${JSON.stringify(v)})`;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
/* string */
|
|
22
22
|
if (typeof v === 'string') {
|
|
23
23
|
return JSON.stringify(v);
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
/* other */
|
|
26
26
|
return JSON.stringify(v);
|
|
27
27
|
};
|
|
28
|
-
|
|
28
|
+
/* why schema.default !== undefined becasue schema.default === 0 // → falsy */
|
|
29
29
|
const s = schema.default !== undefined ? `${zod}.default(${formatLiteral(schema.default)})` : zod;
|
|
30
30
|
const isNullable = schema.nullable === true ||
|
|
31
31
|
(Array.isArray(schema.type) ? schema.type.includes('null') : schema.type === 'null');
|
|
@@ -35,15 +35,15 @@ export function wrap(zod, schema, paramName, paramIn) {
|
|
|
35
35
|
const required = paramIn === 'path' ? true : !!schema.required;
|
|
36
36
|
openapiProps.push(`param:{in:"${paramIn}",name:${JSON.stringify(paramName)},required:${required}}`);
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
/* 'example' if defined */
|
|
39
39
|
if ('example' in schema && schema.example !== undefined) {
|
|
40
40
|
openapiProps.push(`example:${JSON.stringify(schema.example)}`);
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
/* 'examples' if defined */
|
|
43
43
|
if ('examples' in schema && Array.isArray(schema.examples) && schema.examples.length > 0) {
|
|
44
44
|
openapiProps.push(`examples:${JSON.stringify(schema.examples)}`);
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
/* 'description' if defined */
|
|
47
47
|
if ('description' in schema && schema.description !== undefined) {
|
|
48
48
|
openapiProps.push(`description:${JSON.stringify(schema.description)}`);
|
|
49
49
|
}
|
package/dist/typespec/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { compile,
|
|
2
|
+
import { compile, NodeHost } from '@typespec/compiler';
|
|
3
3
|
import { getOpenAPI3 } from '@typespec/openapi3';
|
|
4
4
|
/**
|
|
5
5
|
* Compiles a TypeSpec (`.tsp`) file and returns the generated OpenAPI document.
|
|
@@ -32,7 +32,8 @@ export async function typeSpecToOpenAPI(input) {
|
|
|
32
32
|
noEmit: true,
|
|
33
33
|
});
|
|
34
34
|
if (program.diagnostics.length) {
|
|
35
|
-
logDiagnostics(program.diagnostics, program.host.logSink)
|
|
35
|
+
// logDiagnostics(program.diagnostics, program.host.logSink)
|
|
36
|
+
console.log(JSON.stringify(program.diagnostics, null, 2));
|
|
36
37
|
return {
|
|
37
38
|
ok: false,
|
|
38
39
|
error: 'TypeSpec compile failed',
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -88,19 +88,6 @@ export declare function parseCli(args: readonly string[]): {
|
|
|
88
88
|
/**
|
|
89
89
|
* Normalize a JSON Schema `type` value into an array of type strings.
|
|
90
90
|
*
|
|
91
|
-
* - `undefined` → `[]`
|
|
92
|
-
* - `'string'` → `['string']`
|
|
93
|
-
* - `['string','number']` → unchanged
|
|
94
|
-
*
|
|
95
|
-
* ```mermaid
|
|
96
|
-
* graph TD
|
|
97
|
-
* A1[normalizeTypes] --> B1{is undefined}
|
|
98
|
-
* B1 -->|Yes| C1[return empty array]
|
|
99
|
-
* B1 -->|No| D1{is array}
|
|
100
|
-
* D1 -->|Yes| E1[return t]
|
|
101
|
-
* D1 -->|No| F1[return array with t]
|
|
102
|
-
* ```
|
|
103
|
-
*
|
|
104
91
|
* @param t - JSON Schema `type` as a single value or an array of values.
|
|
105
92
|
* @returns A flat array of type strings.
|
|
106
93
|
*/
|
|
@@ -111,41 +98,20 @@ export declare function normalizeTypes(t?: 'string' | 'number' | 'integer' | 'da
|
|
|
111
98
|
/**
|
|
112
99
|
* Generates registration code for OpenAPI `securitySchemes`.
|
|
113
100
|
*
|
|
114
|
-
* The code calls:
|
|
115
|
-
* ```
|
|
116
|
-
* app.openAPIRegistry.registerComponent('securitySchemes', name, scheme)
|
|
117
|
-
* ```
|
|
118
|
-
* for each entry in the provided record.
|
|
119
|
-
*
|
|
120
|
-
* ```mermaid
|
|
121
|
-
* graph TD
|
|
122
|
-
* A[Start registerComponent] --> B[Iterate over securitySchemes]
|
|
123
|
-
* B --> C[Build registration string for each name + scheme]
|
|
124
|
-
* C --> D[Join all strings with newline]
|
|
125
|
-
* D --> E[Return final code string]
|
|
126
|
-
* ```
|
|
127
|
-
*
|
|
128
101
|
* @param securitySchemes - Record of scheme name to scheme properties.
|
|
129
102
|
* @returns Multiline string of registration statements.
|
|
130
103
|
*/
|
|
131
104
|
export declare function registerComponent(securitySchemes: {
|
|
132
|
-
[key: string]: {
|
|
133
|
-
type?: string;
|
|
134
|
-
name?: string;
|
|
135
|
-
scheme?: string;
|
|
136
|
-
bearerFormat?: string;
|
|
105
|
+
readonly [key: string]: {
|
|
106
|
+
readonly type?: string;
|
|
107
|
+
readonly name?: string;
|
|
108
|
+
readonly scheme?: string;
|
|
109
|
+
readonly bearerFormat?: string;
|
|
137
110
|
};
|
|
138
111
|
}): string;
|
|
139
112
|
/**
|
|
140
113
|
* Checks if a value is a non-null object (e.g., a potential `$ref` object).
|
|
141
114
|
*
|
|
142
|
-
* ```mermaid
|
|
143
|
-
* graph TD
|
|
144
|
-
* A[Start isRefObject] --> B[Check typeof value is object]
|
|
145
|
-
* B --> C[Check value is not null]
|
|
146
|
-
* C --> D[Return true or false]
|
|
147
|
-
* ```
|
|
148
|
-
*
|
|
149
115
|
* @param value - The value to check.
|
|
150
116
|
* @returns `true` if the value is a non-null object.
|
|
151
117
|
*
|
|
@@ -170,16 +136,6 @@ export declare function isHttpMethod(method: string): method is 'get' | 'put' |
|
|
|
170
136
|
/**
|
|
171
137
|
* Checks if all given content types share the same schema definition.
|
|
172
138
|
*
|
|
173
|
-
* ```mermaid
|
|
174
|
-
* graph TD
|
|
175
|
-
* A[Start isUniqueContentSchema] --> B[Create empty set]
|
|
176
|
-
* B --> C[Loop over content types]
|
|
177
|
-
* C --> D[Read schema for type]
|
|
178
|
-
* D --> E[Stringify and add to set]
|
|
179
|
-
* E --> F[After loop check size]
|
|
180
|
-
* F --> G[Return true if size is one]
|
|
181
|
-
* ```
|
|
182
|
-
*
|
|
183
139
|
* @param contentTypes - Array of content type keys (e.g., ['application/json', 'application/xml']).
|
|
184
140
|
* @param content - OpenAPI content object mapping content types to media objects.
|
|
185
141
|
* @returns `true` if all specified content types refer to the same schema; otherwise `false`.
|
|
@@ -193,8 +149,8 @@ export declare function isHttpMethod(method: string): method is 'get' | 'put' |
|
|
|
193
149
|
* ```
|
|
194
150
|
*/
|
|
195
151
|
export declare function isUniqueContentSchema(contentTypes: readonly string[], content: {
|
|
196
|
-
[key: string]: {
|
|
197
|
-
schema: {
|
|
152
|
+
readonly [key: string]: {
|
|
153
|
+
readonly schema: {
|
|
198
154
|
readonly $ref?: `#/components/schemas/${string}`;
|
|
199
155
|
};
|
|
200
156
|
};
|
|
@@ -202,14 +158,6 @@ export declare function isUniqueContentSchema(contentTypes: readonly string[], c
|
|
|
202
158
|
/**
|
|
203
159
|
* Extracts the type name from an OpenAPI `$ref` string.
|
|
204
160
|
*
|
|
205
|
-
* ```mermaid
|
|
206
|
-
* graph TD
|
|
207
|
-
* A["Start refSchema"] --> B["Split $ref by slash"]
|
|
208
|
-
* B --> C["Take last segment"]
|
|
209
|
-
* C --> D["Append Schema suffix"]
|
|
210
|
-
* D --> E["Return result string"]
|
|
211
|
-
* ```
|
|
212
|
-
*
|
|
213
161
|
* @param $ref - A reference path like `#/components/schemas/Address`.
|
|
214
162
|
* @returns The extracted type name with `Schema` suffix.
|
|
215
163
|
*
|
|
@@ -223,16 +171,6 @@ export declare function refSchema($ref: `#/components/schemas/${string}`): strin
|
|
|
223
171
|
/**
|
|
224
172
|
* Generates a PascalCase route name from HTTP method and path.
|
|
225
173
|
*
|
|
226
|
-
* ```mermaid
|
|
227
|
-
* graph TD
|
|
228
|
-
* A[Start routeName] --> B[Replace special chars with space]
|
|
229
|
-
* B --> C[Trim and split by spaces]
|
|
230
|
-
* C --> D[Capitalize each segment]
|
|
231
|
-
* D --> E[Join segments into single string]
|
|
232
|
-
* E --> F[Prefix with method and suffix with Route]
|
|
233
|
-
* F --> G[Return final route name]
|
|
234
|
-
* ```
|
|
235
|
-
*
|
|
236
174
|
* @param method - HTTP method (e.g., 'get', 'post').
|
|
237
175
|
* @param path - URL path (e.g., '/users/{id}/posts').
|
|
238
176
|
* @returns A route name string (e.g., 'getUsersIdPostsRoute').
|
|
@@ -244,14 +182,6 @@ export declare function methodPath(method: string, path: string): string;
|
|
|
244
182
|
/**
|
|
245
183
|
* Generates a Hono route definition as a TypeScript export string.
|
|
246
184
|
*
|
|
247
|
-
* ```mermaid
|
|
248
|
-
* graph TD
|
|
249
|
-
* A[Start createRoute] --> B[Collect properties from args]
|
|
250
|
-
* B --> C[Join properties into one string]
|
|
251
|
-
* C --> D[Build export createRoute template]
|
|
252
|
-
* D --> E[Return final code string]
|
|
253
|
-
* ```
|
|
254
|
-
*
|
|
255
185
|
* @param args - Route metadata and OpenAPI friendly fragments (`method`, `path`, `requestParams`, `responses`, etc.).
|
|
256
186
|
* @returns A string representing an `export const <name> = createRoute({ ... })` statement.
|
|
257
187
|
*
|
|
@@ -279,6 +209,7 @@ export declare function createRoute(args: {
|
|
|
279
209
|
}): string;
|
|
280
210
|
/**
|
|
281
211
|
* Generates an array of Zod validator strings from OpenAPI parameter objects.
|
|
212
|
+
*
|
|
282
213
|
* @param parameters - An object containing `query`, `path`, and `header` parameters.
|
|
283
214
|
* @returns An array of strings like `'query:z.object({...})'` or `'params:z.object({...})'`.
|
|
284
215
|
*/
|
|
@@ -286,18 +217,6 @@ export declare const requestParamsArray: (parameters: Record<string, Record<stri
|
|
|
286
217
|
/**
|
|
287
218
|
* Escapes a string for safe use in TypeScript string literals.
|
|
288
219
|
*
|
|
289
|
-
* ```mermaid
|
|
290
|
-
* graph TD
|
|
291
|
-
* A[Start escapeStringLiteral] --> B[Replace newline and tab with space]
|
|
292
|
-
* B --> C[Remove zero width and BOM characters]
|
|
293
|
-
* C --> D[Replace full width spaces with normal space]
|
|
294
|
-
* D --> E[Collapse multiple spaces into one]
|
|
295
|
-
* E --> F[Escape backslashes]
|
|
296
|
-
* F --> G[Escape single quotes]
|
|
297
|
-
* G --> H[Trim leading and trailing spaces]
|
|
298
|
-
* H --> I[Return escaped string]
|
|
299
|
-
* ```
|
|
300
|
-
*
|
|
301
220
|
* @param text - The input text to escape.
|
|
302
221
|
* @returns The escaped string.
|
|
303
222
|
*/
|
|
@@ -305,14 +224,8 @@ export declare function escapeStringLiteral(text: string): string;
|
|
|
305
224
|
/**
|
|
306
225
|
* Converts a string to a safe TypeScript object key.
|
|
307
226
|
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
* A[Start getToSafeIdentifier] --> B[Check if matches identifier regex]
|
|
311
|
-
* B --> C[If matches, return string as is]
|
|
312
|
-
* B --> D[If not, wrap with JSON stringify]
|
|
313
|
-
* C --> E[Return result]
|
|
314
|
-
* D --> E[Return result]
|
|
315
|
-
* ```
|
|
227
|
+
* @param text - The string to convert to a safe identifier.
|
|
228
|
+
* @returns A safe identifier string.
|
|
316
229
|
*
|
|
317
230
|
* @example
|
|
318
231
|
* ```ts
|
|
@@ -323,19 +236,11 @@ export declare function escapeStringLiteral(text: string): string;
|
|
|
323
236
|
* getToSafeIdentifier('if') // → 'if'
|
|
324
237
|
* ```
|
|
325
238
|
*/
|
|
326
|
-
export declare function getToSafeIdentifier(
|
|
239
|
+
export declare function getToSafeIdentifier(text: string): string;
|
|
327
240
|
/**
|
|
328
|
-
* Converts a string to a safe TypeScript identifier.
|
|
329
|
-
*
|
|
330
|
-
* ```mermaid
|
|
331
|
-
* graph TD
|
|
332
|
-
* A[Start sanitizeIdentifier] --> B[Replace invalid characters with underscore]
|
|
333
|
-
* B --> C[Return sanitized string]
|
|
334
|
-
* ```
|
|
335
|
-
*
|
|
336
241
|
* Replaces any character not matching `[A-Za-z0-9_$]` with `_`.
|
|
337
242
|
*
|
|
338
|
-
* @param
|
|
243
|
+
* @param text - The raw string to sanitize.
|
|
339
244
|
* @returns A valid identifier string.
|
|
340
245
|
*
|
|
341
246
|
* @example
|
|
@@ -347,23 +252,10 @@ export declare function getToSafeIdentifier(str: string): string;
|
|
|
347
252
|
* sanitizeIdentifier('valid_Name') // → 'valid_Name'
|
|
348
253
|
* ```
|
|
349
254
|
*/
|
|
350
|
-
export declare function sanitizeIdentifier(
|
|
255
|
+
export declare function sanitizeIdentifier(text: string): string;
|
|
351
256
|
/**
|
|
352
257
|
* Appends a properly escaped `.regex(/pattern/)` clause.
|
|
353
258
|
*
|
|
354
|
-
* Any unescaped forward-slash within the pattern is escaped so the final
|
|
355
|
-
* string remains a valid JavaScript RegExp literal.
|
|
356
|
-
*
|
|
357
|
-
* ```mermaid
|
|
358
|
-
* graph TD
|
|
359
|
-
* A["Start regex(pattern)"] --> B["Receive raw regex pattern without slashes"]
|
|
360
|
-
* B --> C["Find all '/' not preceded by '\\'"]
|
|
361
|
-
* C --> D["Escape them to '\\/'"]
|
|
362
|
-
* D --> E["Wrap pattern in '/ ... /'"]
|
|
363
|
-
* E --> F["Prefix with '.regex(' and suffix with ')' "]
|
|
364
|
-
* F --> G["Return generated string"]
|
|
365
|
-
* ```
|
|
366
|
-
*
|
|
367
259
|
* @param pattern - A raw regex pattern **without** the surrounding slashes.
|
|
368
260
|
* @returns A string like `'.regex(/^[a-z]+$/)'`.
|
|
369
261
|
*/
|
package/dist/utils/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export function parseConfig(config) {
|
|
|
5
5
|
if (!isYamlOrJsonOrTsp(c.input)) {
|
|
6
6
|
return { ok: false, error: `Invalid input: ${String(c.input)} (must be .yaml | .json | .tsp)` };
|
|
7
7
|
}
|
|
8
|
+
// zod-openapi
|
|
8
9
|
const zo = c['zod-openapi'];
|
|
9
10
|
if (zo !== undefined) {
|
|
10
11
|
// boolean flags
|
|
@@ -20,15 +21,15 @@ export function parseConfig(config) {
|
|
|
20
21
|
error: `Invalid exportType format for zod-openapi: ${String(zo.exportType)}`,
|
|
21
22
|
};
|
|
22
23
|
}
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
if (
|
|
24
|
+
const hs = zo.schema !== undefined;
|
|
25
|
+
const hr = zo.route !== undefined;
|
|
26
|
+
if (hs !== hr) {
|
|
26
27
|
return {
|
|
27
28
|
ok: false,
|
|
28
29
|
error: "Invalid config: 'zod-openapi.schema' and 'zod-openapi.route' must be defined together (both or neither).",
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
|
-
if (
|
|
32
|
+
if (hs || hr) {
|
|
32
33
|
if (Object.hasOwn(zo, 'output')) {
|
|
33
34
|
return {
|
|
34
35
|
ok: false,
|
|
@@ -44,7 +45,7 @@ export function parseConfig(config) {
|
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
|
-
if (
|
|
48
|
+
if (hs) {
|
|
48
49
|
const s = zo.schema;
|
|
49
50
|
if (!s)
|
|
50
51
|
return { ok: false, error: 'Invalid config: zod-openapi.schema is undefined' };
|
|
@@ -80,7 +81,7 @@ export function parseConfig(config) {
|
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
|
-
if (
|
|
84
|
+
if (hr) {
|
|
84
85
|
const r = zo.route;
|
|
85
86
|
if (!r)
|
|
86
87
|
return { ok: false, error: 'Invalid config: zod-openapi.route is undefined' };
|
|
@@ -206,19 +207,6 @@ export function parseCli(args) {
|
|
|
206
207
|
/**
|
|
207
208
|
* Normalize a JSON Schema `type` value into an array of type strings.
|
|
208
209
|
*
|
|
209
|
-
* - `undefined` → `[]`
|
|
210
|
-
* - `'string'` → `['string']`
|
|
211
|
-
* - `['string','number']` → unchanged
|
|
212
|
-
*
|
|
213
|
-
* ```mermaid
|
|
214
|
-
* graph TD
|
|
215
|
-
* A1[normalizeTypes] --> B1{is undefined}
|
|
216
|
-
* B1 -->|Yes| C1[return empty array]
|
|
217
|
-
* B1 -->|No| D1{is array}
|
|
218
|
-
* D1 -->|Yes| E1[return t]
|
|
219
|
-
* D1 -->|No| F1[return array with t]
|
|
220
|
-
* ```
|
|
221
|
-
*
|
|
222
210
|
* @param t - JSON Schema `type` as a single value or an array of values.
|
|
223
211
|
* @returns A flat array of type strings.
|
|
224
212
|
*/
|
|
@@ -228,20 +216,6 @@ export function normalizeTypes(t) {
|
|
|
228
216
|
/**
|
|
229
217
|
* Generates registration code for OpenAPI `securitySchemes`.
|
|
230
218
|
*
|
|
231
|
-
* The code calls:
|
|
232
|
-
* ```
|
|
233
|
-
* app.openAPIRegistry.registerComponent('securitySchemes', name, scheme)
|
|
234
|
-
* ```
|
|
235
|
-
* for each entry in the provided record.
|
|
236
|
-
*
|
|
237
|
-
* ```mermaid
|
|
238
|
-
* graph TD
|
|
239
|
-
* A[Start registerComponent] --> B[Iterate over securitySchemes]
|
|
240
|
-
* B --> C[Build registration string for each name + scheme]
|
|
241
|
-
* C --> D[Join all strings with newline]
|
|
242
|
-
* D --> E[Return final code string]
|
|
243
|
-
* ```
|
|
244
|
-
*
|
|
245
219
|
* @param securitySchemes - Record of scheme name to scheme properties.
|
|
246
220
|
* @returns Multiline string of registration statements.
|
|
247
221
|
*/
|
|
@@ -255,13 +229,6 @@ export function registerComponent(securitySchemes) {
|
|
|
255
229
|
/**
|
|
256
230
|
* Checks if a value is a non-null object (e.g., a potential `$ref` object).
|
|
257
231
|
*
|
|
258
|
-
* ```mermaid
|
|
259
|
-
* graph TD
|
|
260
|
-
* A[Start isRefObject] --> B[Check typeof value is object]
|
|
261
|
-
* B --> C[Check value is not null]
|
|
262
|
-
* C --> D[Return true or false]
|
|
263
|
-
* ```
|
|
264
|
-
*
|
|
265
232
|
* @param value - The value to check.
|
|
266
233
|
* @returns `true` if the value is a non-null object.
|
|
267
234
|
*
|
|
@@ -294,16 +261,6 @@ export function isHttpMethod(method) {
|
|
|
294
261
|
/**
|
|
295
262
|
* Checks if all given content types share the same schema definition.
|
|
296
263
|
*
|
|
297
|
-
* ```mermaid
|
|
298
|
-
* graph TD
|
|
299
|
-
* A[Start isUniqueContentSchema] --> B[Create empty set]
|
|
300
|
-
* B --> C[Loop over content types]
|
|
301
|
-
* C --> D[Read schema for type]
|
|
302
|
-
* D --> E[Stringify and add to set]
|
|
303
|
-
* E --> F[After loop check size]
|
|
304
|
-
* F --> G[Return true if size is one]
|
|
305
|
-
* ```
|
|
306
|
-
*
|
|
307
264
|
* @param contentTypes - Array of content type keys (e.g., ['application/json', 'application/xml']).
|
|
308
265
|
* @param content - OpenAPI content object mapping content types to media objects.
|
|
309
266
|
* @returns `true` if all specified content types refer to the same schema; otherwise `false`.
|
|
@@ -323,14 +280,6 @@ export function isUniqueContentSchema(contentTypes, content) {
|
|
|
323
280
|
/**
|
|
324
281
|
* Extracts the type name from an OpenAPI `$ref` string.
|
|
325
282
|
*
|
|
326
|
-
* ```mermaid
|
|
327
|
-
* graph TD
|
|
328
|
-
* A["Start refSchema"] --> B["Split $ref by slash"]
|
|
329
|
-
* B --> C["Take last segment"]
|
|
330
|
-
* C --> D["Append Schema suffix"]
|
|
331
|
-
* D --> E["Return result string"]
|
|
332
|
-
* ```
|
|
333
|
-
*
|
|
334
283
|
* @param $ref - A reference path like `#/components/schemas/Address`.
|
|
335
284
|
* @returns The extracted type name with `Schema` suffix.
|
|
336
285
|
*
|
|
@@ -351,16 +300,6 @@ export function refSchema($ref) {
|
|
|
351
300
|
/**
|
|
352
301
|
* Generates a PascalCase route name from HTTP method and path.
|
|
353
302
|
*
|
|
354
|
-
* ```mermaid
|
|
355
|
-
* graph TD
|
|
356
|
-
* A[Start routeName] --> B[Replace special chars with space]
|
|
357
|
-
* B --> C[Trim and split by spaces]
|
|
358
|
-
* C --> D[Capitalize each segment]
|
|
359
|
-
* D --> E[Join segments into single string]
|
|
360
|
-
* E --> F[Prefix with method and suffix with Route]
|
|
361
|
-
* F --> G[Return final route name]
|
|
362
|
-
* ```
|
|
363
|
-
*
|
|
364
303
|
* @param method - HTTP method (e.g., 'get', 'post').
|
|
365
304
|
* @param path - URL path (e.g., '/users/{id}/posts').
|
|
366
305
|
* @returns A route name string (e.g., 'getUsersIdPostsRoute').
|
|
@@ -386,14 +325,6 @@ export function methodPath(method, path) {
|
|
|
386
325
|
/**
|
|
387
326
|
* Generates a Hono route definition as a TypeScript export string.
|
|
388
327
|
*
|
|
389
|
-
* ```mermaid
|
|
390
|
-
* graph TD
|
|
391
|
-
* A[Start createRoute] --> B[Collect properties from args]
|
|
392
|
-
* B --> C[Join properties into one string]
|
|
393
|
-
* C --> D[Build export createRoute template]
|
|
394
|
-
* D --> E[Return final code string]
|
|
395
|
-
* ```
|
|
396
|
-
*
|
|
397
328
|
* @param args - Route metadata and OpenAPI friendly fragments (`method`, `path`, `requestParams`, `responses`, etc.).
|
|
398
329
|
* @returns A string representing an `export const <name> = createRoute({ ... })` statement.
|
|
399
330
|
*
|
|
@@ -423,6 +354,7 @@ export function createRoute(args) {
|
|
|
423
354
|
}
|
|
424
355
|
/**
|
|
425
356
|
* Generates an array of Zod validator strings from OpenAPI parameter objects.
|
|
357
|
+
*
|
|
426
358
|
* @param parameters - An object containing `query`, `path`, and `header` parameters.
|
|
427
359
|
* @returns An array of strings like `'query:z.object({...})'` or `'params:z.object({...})'`.
|
|
428
360
|
*/
|
|
@@ -438,18 +370,6 @@ export const requestParamsArray = (parameters) => Object.entries(parameters)
|
|
|
438
370
|
/**
|
|
439
371
|
* Escapes a string for safe use in TypeScript string literals.
|
|
440
372
|
*
|
|
441
|
-
* ```mermaid
|
|
442
|
-
* graph TD
|
|
443
|
-
* A[Start escapeStringLiteral] --> B[Replace newline and tab with space]
|
|
444
|
-
* B --> C[Remove zero width and BOM characters]
|
|
445
|
-
* C --> D[Replace full width spaces with normal space]
|
|
446
|
-
* D --> E[Collapse multiple spaces into one]
|
|
447
|
-
* E --> F[Escape backslashes]
|
|
448
|
-
* F --> G[Escape single quotes]
|
|
449
|
-
* G --> H[Trim leading and trailing spaces]
|
|
450
|
-
* H --> I[Return escaped string]
|
|
451
|
-
* ```
|
|
452
|
-
*
|
|
453
373
|
* @param text - The input text to escape.
|
|
454
374
|
* @returns The escaped string.
|
|
455
375
|
*/
|
|
@@ -466,14 +386,8 @@ export function escapeStringLiteral(text) {
|
|
|
466
386
|
/**
|
|
467
387
|
* Converts a string to a safe TypeScript object key.
|
|
468
388
|
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
* A[Start getToSafeIdentifier] --> B[Check if matches identifier regex]
|
|
472
|
-
* B --> C[If matches, return string as is]
|
|
473
|
-
* B --> D[If not, wrap with JSON stringify]
|
|
474
|
-
* C --> E[Return result]
|
|
475
|
-
* D --> E[Return result]
|
|
476
|
-
* ```
|
|
389
|
+
* @param text - The string to convert to a safe identifier.
|
|
390
|
+
* @returns A safe identifier string.
|
|
477
391
|
*
|
|
478
392
|
* @example
|
|
479
393
|
* ```ts
|
|
@@ -484,21 +398,13 @@ export function escapeStringLiteral(text) {
|
|
|
484
398
|
* getToSafeIdentifier('if') // → 'if'
|
|
485
399
|
* ```
|
|
486
400
|
*/
|
|
487
|
-
export function getToSafeIdentifier(
|
|
488
|
-
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(
|
|
401
|
+
export function getToSafeIdentifier(text) {
|
|
402
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(text) ? text : JSON.stringify(text);
|
|
489
403
|
}
|
|
490
404
|
/**
|
|
491
|
-
* Converts a string to a safe TypeScript identifier.
|
|
492
|
-
*
|
|
493
|
-
* ```mermaid
|
|
494
|
-
* graph TD
|
|
495
|
-
* A[Start sanitizeIdentifier] --> B[Replace invalid characters with underscore]
|
|
496
|
-
* B --> C[Return sanitized string]
|
|
497
|
-
* ```
|
|
498
|
-
*
|
|
499
405
|
* Replaces any character not matching `[A-Za-z0-9_$]` with `_`.
|
|
500
406
|
*
|
|
501
|
-
* @param
|
|
407
|
+
* @param text - The raw string to sanitize.
|
|
502
408
|
* @returns A valid identifier string.
|
|
503
409
|
*
|
|
504
410
|
* @example
|
|
@@ -510,25 +416,12 @@ export function getToSafeIdentifier(str) {
|
|
|
510
416
|
* sanitizeIdentifier('valid_Name') // → 'valid_Name'
|
|
511
417
|
* ```
|
|
512
418
|
*/
|
|
513
|
-
export function sanitizeIdentifier(
|
|
514
|
-
return
|
|
419
|
+
export function sanitizeIdentifier(text) {
|
|
420
|
+
return text.replace(/[^A-Za-z0-9_$]/g, '_');
|
|
515
421
|
}
|
|
516
422
|
/**
|
|
517
423
|
* Appends a properly escaped `.regex(/pattern/)` clause.
|
|
518
424
|
*
|
|
519
|
-
* Any unescaped forward-slash within the pattern is escaped so the final
|
|
520
|
-
* string remains a valid JavaScript RegExp literal.
|
|
521
|
-
*
|
|
522
|
-
* ```mermaid
|
|
523
|
-
* graph TD
|
|
524
|
-
* A["Start regex(pattern)"] --> B["Receive raw regex pattern without slashes"]
|
|
525
|
-
* B --> C["Find all '/' not preceded by '\\'"]
|
|
526
|
-
* C --> D["Escape them to '\\/'"]
|
|
527
|
-
* D --> E["Wrap pattern in '/ ... /'"]
|
|
528
|
-
* E --> F["Prefix with '.regex(' and suffix with ')' "]
|
|
529
|
-
* F --> G["Return generated string"]
|
|
530
|
-
* ```
|
|
531
|
-
*
|
|
532
425
|
* @param pattern - A raw regex pattern **without** the surrounding slashes.
|
|
533
426
|
* @returns A string like `'.regex(/^[a-z]+$/)'`.
|
|
534
427
|
*/
|
|
@@ -75,14 +75,15 @@ const deleteAllTsShallow = async (dir) => listTsShallow(dir).then((files) => Pro
|
|
|
75
75
|
const pruneDir = async (dir, expected) => fsp
|
|
76
76
|
.stat(dir)
|
|
77
77
|
.then((st) => st.isDirectory()
|
|
78
|
-
? fsp.readdir(dir, { withFileTypes: true }).then((ents) => {
|
|
78
|
+
? fsp.readdir(dir, { withFileTypes: true }).then(async (ents) => {
|
|
79
79
|
const targets = ents
|
|
80
80
|
.filter((e) => e.isFile() && e.name.endsWith('.ts') && !expected.has(e.name))
|
|
81
81
|
.map((e) => path.join(dir, e.name));
|
|
82
|
-
|
|
82
|
+
const res = await Promise.all(targets.map((f) => fsp
|
|
83
83
|
.unlink(f)
|
|
84
84
|
.then(() => f)
|
|
85
|
-
.catch(() => null)))
|
|
85
|
+
.catch(() => null)));
|
|
86
|
+
return res.filter((x) => x !== null);
|
|
86
87
|
})
|
|
87
88
|
: [])
|
|
88
89
|
.catch(() => []);
|
|
@@ -151,9 +152,6 @@ const extractRouteBlocks = (src) => {
|
|
|
151
152
|
return { name: h.name, block: src.slice(start, end).trim() };
|
|
152
153
|
});
|
|
153
154
|
};
|
|
154
|
-
/* ──────────────────────────────────────────────────────────────
|
|
155
|
-
* Split-mode filename calculators (no `as` cast)
|
|
156
|
-
* ────────────────────────────────────────────────────────────── */
|
|
157
155
|
const computeRpcSplitFiles = async (input) => {
|
|
158
156
|
const spec = await parseOpenAPI(input);
|
|
159
157
|
if (!spec.ok)
|
|
@@ -194,9 +192,6 @@ const computeSchemaSplitFiles = async (input) => {
|
|
|
194
192
|
acc.add('index.ts');
|
|
195
193
|
return acc;
|
|
196
194
|
};
|
|
197
|
-
/* ──────────────────────────────────────────────────────────────
|
|
198
|
-
* Debounce (no `let`)
|
|
199
|
-
* ────────────────────────────────────────────────────────────── */
|
|
200
195
|
const debounce = (ms, fn) => {
|
|
201
196
|
const bucket = new WeakMap();
|
|
202
197
|
const wrapped = () => {
|
|
@@ -207,36 +202,38 @@ const debounce = (ms, fn) => {
|
|
|
207
202
|
};
|
|
208
203
|
return wrapped;
|
|
209
204
|
};
|
|
210
|
-
/* ──────────────────────────────────────────────────────────────
|
|
211
|
-
* Run generators for a given config(parseConfig 済み前提)
|
|
212
|
-
* ────────────────────────────────────────────────────────────── */
|
|
213
205
|
const runAllWithConf = async (c) => {
|
|
214
206
|
const jobs = [];
|
|
215
207
|
const zo = c['zod-openapi'];
|
|
216
208
|
if (zo) {
|
|
217
209
|
const exportType = zo.exportType === true;
|
|
218
210
|
const exportSchema = zo.exportSchema !== false;
|
|
219
|
-
const
|
|
220
|
-
const
|
|
211
|
+
const hs = !!zo.schema;
|
|
212
|
+
const hr = !!zo.route;
|
|
221
213
|
// top-level zod-openapi (non-split)
|
|
222
|
-
if (!(
|
|
214
|
+
if (!(hs || hr)) {
|
|
223
215
|
const runZo = async () => {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
216
|
+
try {
|
|
217
|
+
const spec = await parseOpenAPI(c.input);
|
|
218
|
+
if (!spec.ok)
|
|
219
|
+
return `✗ zod-openapi: ${spec.error}`;
|
|
220
|
+
const code = await fmt(zodOpenAPIHono(spec.value, exportSchema, exportType));
|
|
221
|
+
if (!code.ok)
|
|
222
|
+
return `✗ zod-openapi fmt: ${code.error}`;
|
|
223
|
+
const outputMaybe = zo.output;
|
|
224
|
+
if (typeof outputMaybe !== 'string') {
|
|
225
|
+
return `✗ zod-openapi: Invalid output format for zod-openapi: ${String(outputMaybe)}`;
|
|
226
|
+
}
|
|
227
|
+
const out = toAbs(outputMaybe);
|
|
228
|
+
const mk = await mkdir(path.dirname(out));
|
|
229
|
+
if (!mk.ok)
|
|
230
|
+
return `✗ zod-openapi mkdir: ${mk.error}`;
|
|
231
|
+
const wr = await writeFile(out, code.value);
|
|
232
|
+
return wr.ok ? `✓ zod-openapi -> ${out}` : `✗ zod-openapi write: ${wr.error}`;
|
|
233
|
+
}
|
|
234
|
+
catch (e) {
|
|
235
|
+
return `✗ zod-openapi: ${e instanceof Error ? e.message : String(e)}`;
|
|
233
236
|
}
|
|
234
|
-
const out = toAbs(outputMaybe);
|
|
235
|
-
const mk = await mkdir(path.dirname(out));
|
|
236
|
-
if (!mk.ok)
|
|
237
|
-
return `✗ zod-openapi mkdir: ${mk.error}`;
|
|
238
|
-
const wr = await writeFile(out, code.value);
|
|
239
|
-
return wr.ok ? `✓ zod-openapi -> ${out}` : `✗ zod-openapi write: ${wr.error}`;
|
|
240
237
|
};
|
|
241
238
|
jobs.push(runZo());
|
|
242
239
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono-takibi",
|
|
3
3
|
"description": "Hono Takibi is a CLI tool that generates Hono routes from OpenAPI specifications.",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.60",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
@@ -46,26 +46,25 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@apidevtools/swagger-parser": "^12.
|
|
50
|
-
"@typespec/compiler": "^1.
|
|
51
|
-
"@typespec/openapi3": "^1.
|
|
49
|
+
"@apidevtools/swagger-parser": "^12.1.0",
|
|
50
|
+
"@typespec/compiler": "^1.5.0",
|
|
51
|
+
"@typespec/openapi3": "^1.5.0",
|
|
52
52
|
"prettier": "^3.6.2",
|
|
53
|
-
"tsx": "^4.20.
|
|
53
|
+
"tsx": "^4.20.6"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@hono/zod-openapi": "1.1.
|
|
57
|
-
"@types/node": "^
|
|
58
|
-
"@typespec/http": "^1.
|
|
59
|
-
"@typespec/rest": "^0.
|
|
60
|
-
"@typespec/versioning": "^0.
|
|
61
|
-
"@vitest/coverage-v8": "^
|
|
62
|
-
"typescript": "^5.
|
|
63
|
-
"vite": "^7.
|
|
64
|
-
"vitest": "^
|
|
65
|
-
"zod": "^4.
|
|
56
|
+
"@hono/zod-openapi": "1.1.4",
|
|
57
|
+
"@types/node": "^24.9.1",
|
|
58
|
+
"@typespec/http": "^1.5.0",
|
|
59
|
+
"@typespec/rest": "^0.75.0",
|
|
60
|
+
"@typespec/versioning": "^0.75.0",
|
|
61
|
+
"@vitest/coverage-v8": "^4.0.3",
|
|
62
|
+
"typescript": "^5.9.3",
|
|
63
|
+
"vite": "^7.1.12",
|
|
64
|
+
"vitest": "^4.0.3",
|
|
65
|
+
"zod": "^4.1.12"
|
|
66
66
|
},
|
|
67
67
|
"scripts": {
|
|
68
|
-
"takibis": "pnpm build && tsx exec.ts",
|
|
69
68
|
"dev": "vite --host",
|
|
70
69
|
"deps": "rm -rf node_modules && pnpm install",
|
|
71
70
|
"build": "rm -rf ./dist/* && tsc",
|