hono-takibi 0.9.70 → 0.9.72
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/README.md +111 -53
- package/dist/cli/index.d.ts +0 -36
- package/dist/cli/index.js +317 -3
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +62 -1
- package/dist/core/components/examples.js +42 -6
- package/dist/core/components/headers.js +2 -2
- package/dist/core/components/parameters.js +2 -2
- package/dist/core/components/requestBodies.js +2 -2
- package/dist/core/components/responses.js +2 -2
- package/dist/core/components/schemas.js +2 -2
- package/dist/core/route/index.js +237 -2
- package/dist/core/rpc/index.js +1159 -227
- package/dist/core/takibi/index.d.ts +1 -1
- package/dist/core/takibi/index.js +501 -2
- package/dist/core/type/index.d.ts +0 -28
- package/dist/core/type/index.js +546 -119
- package/dist/format/index.js +18 -0
- package/dist/fsp/index.js +87 -0
- package/dist/generator/zod-openapi-hono/app/index.js +116 -0
- package/dist/generator/zod-openapi-hono/openapi/components/callbacks.js +61 -0
- package/dist/generator/zod-openapi-hono/openapi/components/examples.d.ts +137 -0
- package/dist/generator/zod-openapi-hono/openapi/components/examples.js +405 -2
- package/dist/generator/zod-openapi-hono/openapi/components/headers.js +46 -0
- package/dist/generator/zod-openapi-hono/openapi/components/index.js +100 -0
- package/dist/generator/zod-openapi-hono/openapi/components/links.js +34 -0
- package/dist/generator/zod-openapi-hono/openapi/components/parameters.js +53 -0
- package/dist/generator/zod-openapi-hono/openapi/components/request-bodies.js +49 -0
- package/dist/generator/zod-openapi-hono/openapi/components/responses.js +43 -0
- package/dist/generator/zod-openapi-hono/openapi/components/schemas.js +72 -0
- package/dist/generator/zod-openapi-hono/openapi/components/securitySchemes.js +36 -0
- package/dist/generator/zod-openapi-hono/openapi/index.js +460 -0
- package/dist/generator/zod-openapi-hono/openapi/routes/create-route.js +36 -0
- package/dist/generator/zod-openapi-hono/openapi/routes/index.js +44 -0
- package/dist/generator/zod-to-openapi/index.js +781 -26
- package/dist/generator/zod-to-openapi/z/enum.js +27 -0
- package/dist/generator/zod-to-openapi/z/index.js +27 -0
- package/dist/generator/zod-to-openapi/z/integer.js +139 -0
- package/dist/generator/zod-to-openapi/z/number.js +45 -0
- package/dist/generator/zod-to-openapi/z/object.d.ts +6 -0
- package/dist/generator/zod-to-openapi/z/object.js +101 -55
- package/dist/generator/zod-to-openapi/z/string.js +38 -0
- package/dist/helper/ast.d.ts +15 -31
- package/dist/helper/ast.js +314 -7
- package/dist/helper/barell.js +32 -0
- package/dist/helper/code.js +36 -1
- package/dist/helper/core.js +18 -0
- package/dist/helper/exports.d.ts +22 -0
- package/dist/helper/exports.js +104 -3
- package/dist/helper/handler.js +2 -2
- package/dist/helper/index.d.ts +0 -1
- package/dist/helper/index.js +14 -0
- package/dist/helper/openapi.d.ts +40 -3
- package/dist/helper/openapi.js +901 -9
- package/dist/helper/schema.d.ts +4 -4
- package/dist/helper/schema.js +210 -1
- package/dist/helper/type.js +232 -0
- package/dist/helper/wrap.js +279 -1
- package/dist/index.js +2178 -10
- package/dist/openapi/index.d.ts +83 -4
- package/dist/openapi/index.js +253 -0
- package/dist/utils/index.d.ts +1 -78
- package/dist/utils/index.js +265 -100
- package/dist/vite-plugin/index.js +155 -0
- package/package.json +1 -5
package/README.md
CHANGED
|
@@ -91,66 +91,142 @@ export const getRoute = createRoute({
|
|
|
91
91
|
|
|
92
92
|
### Options
|
|
93
93
|
|
|
94
|
-
basic
|
|
95
|
-
|
|
96
94
|
```bash
|
|
97
95
|
Options:
|
|
98
|
-
--export-
|
|
99
|
-
--export-
|
|
100
|
-
--
|
|
101
|
-
--
|
|
102
|
-
--
|
|
96
|
+
--export-schemas-types export schemas types
|
|
97
|
+
--export-schemas export schemas
|
|
98
|
+
--export-parameters-types export parameters types
|
|
99
|
+
--export-parameters export parameters
|
|
100
|
+
--export-security-schemes export securitySchemes
|
|
101
|
+
--export-request-bodies export requestBodies
|
|
102
|
+
--export-responses export responses
|
|
103
|
+
--export-headers-types export headers types
|
|
104
|
+
--export-headers export headers
|
|
105
|
+
--export-examples export examples
|
|
106
|
+
--export-links export links
|
|
107
|
+
--export-callbacks export callbacks
|
|
108
|
+
--template generate app file and handler stubs
|
|
109
|
+
--test generate empty *.test.ts files
|
|
110
|
+
--base-path <path> api prefix (default: /)
|
|
111
|
+
-h, --help display help for command
|
|
103
112
|
```
|
|
104
113
|
|
|
105
|
-
template
|
|
106
|
-
|
|
107
|
-
> **⚠️** When using the `--template` option, you must specify a valid directory path. Ensure the directory exists before executing the
|
|
108
|
-
|
|
109
114
|
### Example
|
|
110
115
|
|
|
111
116
|
```bash
|
|
112
|
-
npx hono-takibi path/to/input.{yaml,json,tsp} -o path/to/output.ts --export-
|
|
117
|
+
npx hono-takibi path/to/input.{yaml,json,tsp} -o path/to/output.ts --export-schemas --export-schemas-types --template --base-path '/api/v1'
|
|
113
118
|
```
|
|
114
119
|
|
|
115
120
|
## Configuration File (`hono-takibi.config.ts`)
|
|
116
121
|
|
|
117
122
|
Config used by both the CLI and the Vite plugin.
|
|
118
123
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
* Put **`hono-takibi.config.ts`** at repo root.
|
|
122
|
-
* Default‑export with `defineConfig(...)`.
|
|
123
|
-
* `input`: **`openapi.yaml`** (recommended), or `*.json` / `*.tsp`.
|
|
124
|
-
|
|
125
|
-
> **About `split`**
|
|
126
|
-
>
|
|
127
|
-
> * `split: true` → `output` is a **directory**; many files + `index.ts`.
|
|
128
|
-
> * `split` **omitted** or `false` → `output` is a **single `*.ts` file** (one file only).
|
|
124
|
+
### Config Reference
|
|
129
125
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
## Single‑file
|
|
133
|
-
|
|
134
|
-
One file. Set top‑level `output` (don’t define `schema`/`route`).
|
|
126
|
+
All available options are shown below. In practice, use only the options you need.
|
|
135
127
|
|
|
136
128
|
```ts
|
|
129
|
+
// hono-takibi.config.ts
|
|
137
130
|
import { defineConfig } from 'hono-takibi/config'
|
|
138
131
|
|
|
139
132
|
export default defineConfig({
|
|
140
133
|
input: 'openapi.yaml',
|
|
141
134
|
'zod-openapi': {
|
|
142
135
|
output: './src/index.ts',
|
|
143
|
-
|
|
144
|
-
|
|
136
|
+
exportSchemas: true,
|
|
137
|
+
exportSchemasTypes: true,
|
|
138
|
+
exportParameters: true,
|
|
139
|
+
exportParametersTypes: true,
|
|
140
|
+
exportSecuritySchemes: true,
|
|
141
|
+
exportRequestBodies: true,
|
|
142
|
+
exportResponses: true,
|
|
143
|
+
exportHeaders: true,
|
|
144
|
+
exportHeadersTypes: true,
|
|
145
|
+
exportExamples: true,
|
|
146
|
+
exportLinks: true,
|
|
147
|
+
exportCallbacks: true,
|
|
148
|
+
routes: {
|
|
149
|
+
output: './src/routes',
|
|
150
|
+
split: true,
|
|
151
|
+
},
|
|
152
|
+
components: {
|
|
153
|
+
schemas: {
|
|
154
|
+
output: './src/schemas',
|
|
155
|
+
exportTypes: true,
|
|
156
|
+
split: true,
|
|
157
|
+
import: '../schemas',
|
|
158
|
+
},
|
|
159
|
+
parameters: {
|
|
160
|
+
output: './src/parameters',
|
|
161
|
+
exportTypes: true,
|
|
162
|
+
split: true,
|
|
163
|
+
import: '../parameters',
|
|
164
|
+
},
|
|
165
|
+
securitySchemes: {
|
|
166
|
+
output: './src/securitySchemes',
|
|
167
|
+
split: true,
|
|
168
|
+
import: '../securitySchemes',
|
|
169
|
+
},
|
|
170
|
+
requestBodies: {
|
|
171
|
+
output: './src/requestBodies',
|
|
172
|
+
split: true,
|
|
173
|
+
import: '../requestBodies',
|
|
174
|
+
},
|
|
175
|
+
responses: {
|
|
176
|
+
output: './src/responses',
|
|
177
|
+
split: true,
|
|
178
|
+
import: '../responses',
|
|
179
|
+
},
|
|
180
|
+
headers: {
|
|
181
|
+
output: './src/headers',
|
|
182
|
+
exportTypes: true,
|
|
183
|
+
split: true,
|
|
184
|
+
import: '../headers',
|
|
185
|
+
},
|
|
186
|
+
examples: {
|
|
187
|
+
output: './src/examples',
|
|
188
|
+
split: true,
|
|
189
|
+
import: '../examples',
|
|
190
|
+
},
|
|
191
|
+
links: {
|
|
192
|
+
output: './src/links',
|
|
193
|
+
split: true,
|
|
194
|
+
import: '../links',
|
|
195
|
+
},
|
|
196
|
+
callbacks: {
|
|
197
|
+
output: './src/callbacks',
|
|
198
|
+
split: true,
|
|
199
|
+
import: '../callbacks',
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
type: {
|
|
204
|
+
output: './src/types.ts',
|
|
205
|
+
},
|
|
206
|
+
rpc: {
|
|
207
|
+
output: './src/rpc',
|
|
208
|
+
import: '../client',
|
|
209
|
+
split: true,
|
|
145
210
|
},
|
|
146
211
|
})
|
|
147
212
|
```
|
|
148
213
|
|
|
214
|
+
## Essentials
|
|
215
|
+
|
|
216
|
+
* Put **`hono-takibi.config.ts`** at repo root.
|
|
217
|
+
* Default‑export with `defineConfig(...)`.
|
|
218
|
+
* `input`: **`openapi.yaml`** (recommended), or `*.json` / `*.tsp`.
|
|
219
|
+
|
|
220
|
+
> **About `split`**
|
|
221
|
+
>
|
|
222
|
+
> * `split: true` → `output` is a **directory**; many files + `index.ts`.
|
|
223
|
+
> * `split` **omitted** or `false` → `output` is a **single `*.ts` file** (one file only).
|
|
224
|
+
|
|
149
225
|
---
|
|
150
226
|
|
|
151
|
-
##
|
|
227
|
+
## Single‑file
|
|
152
228
|
|
|
153
|
-
|
|
229
|
+
One file. Set top‑level `output` (don't define `components`/`routes`).
|
|
154
230
|
|
|
155
231
|
```ts
|
|
156
232
|
import { defineConfig } from 'hono-takibi/config'
|
|
@@ -158,13 +234,9 @@ import { defineConfig } from 'hono-takibi/config'
|
|
|
158
234
|
export default defineConfig({
|
|
159
235
|
input: 'openapi.yaml',
|
|
160
236
|
'zod-openapi': {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// split OFF example (one file each):
|
|
166
|
-
// schema: { output: './src/schemas/index.ts' },
|
|
167
|
-
// route: { output: './src/routes/index.ts', import: '../schemas' },
|
|
237
|
+
output: './src/index.ts',
|
|
238
|
+
exportSchemas: true,
|
|
239
|
+
exportSchemasTypes: true,
|
|
168
240
|
},
|
|
169
241
|
})
|
|
170
242
|
```
|
|
@@ -178,30 +250,16 @@ Works with either pattern.
|
|
|
178
250
|
* `split: true` → `output` is a **directory**; many files + `index.ts`.
|
|
179
251
|
* `split` **omitted** or `false` → `output` is **one `*.ts` file**.
|
|
180
252
|
|
|
181
|
-
**Example (split: true)**
|
|
182
|
-
|
|
183
253
|
```ts
|
|
184
254
|
import { defineConfig } from 'hono-takibi/config'
|
|
185
255
|
|
|
186
256
|
export default defineConfig({
|
|
187
257
|
input: 'openapi.yaml',
|
|
188
|
-
'zod-openapi': { output: './src/index.ts',
|
|
258
|
+
'zod-openapi': { output: './src/index.ts', exportSchemas: true, exportSchemasTypes: true },
|
|
189
259
|
rpc: { output: './src/rpc', import: '../client', split: true },
|
|
190
260
|
})
|
|
191
261
|
```
|
|
192
262
|
|
|
193
|
-
**Example (single file; split omitted/false)**
|
|
194
|
-
|
|
195
|
-
```ts
|
|
196
|
-
import { defineConfig } from 'hono-takibi/config'
|
|
197
|
-
|
|
198
|
-
export default defineConfig({
|
|
199
|
-
input: 'openapi.yaml',
|
|
200
|
-
'zod-openapi': { output: './src/index.ts', exportSchema: true, exportType: true },
|
|
201
|
-
rpc: { output: './src/rpc/index.ts', import: '../client' },
|
|
202
|
-
})
|
|
203
|
-
```
|
|
204
|
-
|
|
205
263
|
---
|
|
206
264
|
|
|
207
265
|
## Vite Plugin (`honoTakibiVite`)
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Main CLI entry point for hono-takibi.
|
|
3
|
-
*
|
|
4
|
-
* Processes command-line arguments or config file to generate TypeScript
|
|
5
|
-
* code from OpenAPI specifications. Supports both CLI mode and config file mode.
|
|
6
|
-
*
|
|
7
|
-
* ```mermaid
|
|
8
|
-
* flowchart TD
|
|
9
|
-
* A["Start"] --> B{"Args: --help/-h?"}
|
|
10
|
-
* B -->|Yes| C["Return help text"]
|
|
11
|
-
* B -->|No| D{"Config file exists?"}
|
|
12
|
-
* D -->|No| E["CLI Mode"]
|
|
13
|
-
* D -->|Yes| F["Config Mode"]
|
|
14
|
-
* E --> G["parseCli(args)"]
|
|
15
|
-
* G --> H["parseOpenAPI(input)"]
|
|
16
|
-
* H --> I["takibi(openAPI, ...)"]
|
|
17
|
-
* F --> J["config()"]
|
|
18
|
-
* J --> K["parseOpenAPI(config.input)"]
|
|
19
|
-
* K --> L["Generate all components"]
|
|
20
|
-
* L --> M["Return results"]
|
|
21
|
-
* I --> M
|
|
22
|
-
* ```
|
|
23
|
-
*
|
|
24
|
-
* @returns Promise resolving to success with output message or error
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```ts
|
|
28
|
-
* // CLI usage
|
|
29
|
-
* const result = await honoTakibi()
|
|
30
|
-
* if (result.ok) {
|
|
31
|
-
* console.log(result.value) // "Generated code written to routes.ts"
|
|
32
|
-
* } else {
|
|
33
|
-
* console.error(result.error)
|
|
34
|
-
* }
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
1
|
export declare function honoTakibi(): Promise<{
|
|
38
2
|
readonly ok: true;
|
|
39
3
|
readonly value: string;
|
package/dist/cli/index.js
CHANGED
|
@@ -21,10 +21,9 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { existsSync } from 'node:fs';
|
|
23
23
|
import { resolve } from 'node:path';
|
|
24
|
-
import {
|
|
24
|
+
import { readConfig } from '../config/index.js';
|
|
25
25
|
import { callbacks, examples, headers, links, parameters, requestBodies, responses, route, rpc, schemas, securitySchemes, takibi, type, } from '../core/index.js';
|
|
26
26
|
import { parseOpenAPI } from '../openapi/index.js';
|
|
27
|
-
import { parseCli } from '../utils/index.js';
|
|
28
27
|
const HELP_TEXT = `Usage: hono-takibi <input.{yaml,json,tsp}> -o <routes.ts> [options]
|
|
29
28
|
|
|
30
29
|
Options:
|
|
@@ -80,6 +79,71 @@ Options:
|
|
|
80
79
|
* }
|
|
81
80
|
* ```
|
|
82
81
|
*/
|
|
82
|
+
/**
|
|
83
|
+
* Parse raw CLI arguments into structured options.
|
|
84
|
+
*
|
|
85
|
+
* - Validates `<input>` ends with `.yaml`/`.json`/`.tsp`
|
|
86
|
+
* - Requires `-o <output.ts>`
|
|
87
|
+
* - Extracts boolean flags for component exports and templates/tests
|
|
88
|
+
* - Extracts optional `--base-path <path>`
|
|
89
|
+
*
|
|
90
|
+
* ```mermaid
|
|
91
|
+
* flowchart TD
|
|
92
|
+
* A["parseCli(args)"] --> B["Extract input & output (-o)"]
|
|
93
|
+
* B --> C{"input endsWith .yaml/.json/.tsp AND output endsWith .ts?"}
|
|
94
|
+
* C -->|No| D["return { ok:false, error:'Usage: hono-takibi ...' }"]
|
|
95
|
+
* C -->|Yes| E["Read flags (--export-schemas-types, --export-schemas, ..., --template, --test)"]
|
|
96
|
+
* E --> F["Read optional --base-path value"]
|
|
97
|
+
* F --> G["return { ok:true, value:{ input, output, flags... } }"]
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* @param args - Raw CLI arguments (e.g., `process.argv.slice(2)`).
|
|
101
|
+
* @returns `{ ok:true, value }` on success; `{ ok:false, error }` on invalid usage.
|
|
102
|
+
*/
|
|
103
|
+
function parseCli(args) {
|
|
104
|
+
const input = args[0];
|
|
105
|
+
const oIdx = args.indexOf('-o');
|
|
106
|
+
const output = oIdx !== -1 ? args[oIdx + 1] : undefined;
|
|
107
|
+
/** yaml or json or tsp */
|
|
108
|
+
const isYamlOrJsonOrTsp = (i) => i.endsWith('.yaml') || i.endsWith('.json') || i.endsWith('.tsp');
|
|
109
|
+
const isTs = (o) => o.endsWith('.ts');
|
|
110
|
+
const getFlagValue = (args, flag) => {
|
|
111
|
+
const idx = args.indexOf(flag);
|
|
112
|
+
if (idx !== -1 && args[idx + 1] && !args[idx + 1].startsWith('-'))
|
|
113
|
+
return args[idx + 1];
|
|
114
|
+
return undefined;
|
|
115
|
+
};
|
|
116
|
+
if (!(input && output && isYamlOrJsonOrTsp(input) && isTs(output))) {
|
|
117
|
+
return {
|
|
118
|
+
ok: false,
|
|
119
|
+
error: HELP_TEXT,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
ok: true,
|
|
124
|
+
value: {
|
|
125
|
+
input,
|
|
126
|
+
output,
|
|
127
|
+
template: args.includes('--template'),
|
|
128
|
+
test: args.includes('--test'),
|
|
129
|
+
basePath: getFlagValue(args, '--base-path') ?? '/', // default: /
|
|
130
|
+
componentsOptions: {
|
|
131
|
+
exportSchemas: args.includes('--export-schemas') ?? false,
|
|
132
|
+
exportSchemasTypes: args.includes('--export-schemas-types') ?? false,
|
|
133
|
+
exportParameters: args.includes('--export-parameters') ?? false,
|
|
134
|
+
exportParametersTypes: args.includes('--export-parameters-types') ?? false,
|
|
135
|
+
exportSecuritySchemes: args.includes('--export-security-schemes') ?? false,
|
|
136
|
+
exportRequestBodies: args.includes('--export-request-bodies') ?? false,
|
|
137
|
+
exportResponses: args.includes('--export-responses') ?? false,
|
|
138
|
+
exportHeaders: args.includes('--export-headers') ?? false,
|
|
139
|
+
exportHeadersTypes: args.includes('--export-headers-types') ?? false,
|
|
140
|
+
exportExamples: args.includes('--export-examples') ?? false,
|
|
141
|
+
exportLinks: args.includes('--export-links') ?? false,
|
|
142
|
+
exportCallbacks: args.includes('--export-callbacks') ?? false,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
83
147
|
export async function honoTakibi() {
|
|
84
148
|
const args = process.argv.slice(2);
|
|
85
149
|
if (args.length === 1 && (args[0] === '--help' || args[0] === '-h')) {
|
|
@@ -101,7 +165,7 @@ export async function honoTakibi() {
|
|
|
101
165
|
return { ok: false, error: takibiResult.error };
|
|
102
166
|
return { ok: true, value: takibiResult.value };
|
|
103
167
|
}
|
|
104
|
-
const loadConfigResult = await
|
|
168
|
+
const loadConfigResult = await readConfig();
|
|
105
169
|
if (!loadConfigResult.ok)
|
|
106
170
|
return { ok: false, error: loadConfigResult.error };
|
|
107
171
|
const config = loadConfigResult.value;
|
|
@@ -204,3 +268,253 @@ export async function honoTakibi() {
|
|
|
204
268
|
].filter((v) => v !== undefined);
|
|
205
269
|
return { ok: true, value: results.join('\n') };
|
|
206
270
|
}
|
|
271
|
+
// Test run
|
|
272
|
+
// pnpm vitest run ./packages/hono-takibi/src/cli/index.ts
|
|
273
|
+
if (import.meta.vitest) {
|
|
274
|
+
const { describe, it, expect, beforeAll, afterAll } = import.meta.vitest;
|
|
275
|
+
const fs = await import('node:fs');
|
|
276
|
+
const openapi = {
|
|
277
|
+
openapi: '3.1.0',
|
|
278
|
+
info: {
|
|
279
|
+
title: 'HonoTakibi',
|
|
280
|
+
version: 'v1',
|
|
281
|
+
},
|
|
282
|
+
tags: [{ name: 'Hono' }, { name: 'HonoX' }, { name: 'ZodOpenAPIHono' }],
|
|
283
|
+
paths: {
|
|
284
|
+
'/hono': {
|
|
285
|
+
get: {
|
|
286
|
+
tags: ['Hono'],
|
|
287
|
+
summary: 'Hono',
|
|
288
|
+
description: 'Hono',
|
|
289
|
+
responses: {
|
|
290
|
+
'200': {
|
|
291
|
+
description: 'OK',
|
|
292
|
+
content: {
|
|
293
|
+
'application/json': {
|
|
294
|
+
schema: {
|
|
295
|
+
type: 'object',
|
|
296
|
+
properties: {
|
|
297
|
+
message: {
|
|
298
|
+
type: 'string',
|
|
299
|
+
example: 'Hono',
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
required: ['message'],
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
'/hono-x': {
|
|
311
|
+
get: {
|
|
312
|
+
tags: ['HonoX'],
|
|
313
|
+
summary: 'HonoX',
|
|
314
|
+
description: 'HonoX',
|
|
315
|
+
responses: {
|
|
316
|
+
'200': {
|
|
317
|
+
description: 'OK',
|
|
318
|
+
content: {
|
|
319
|
+
'application/json': {
|
|
320
|
+
schema: {
|
|
321
|
+
type: 'object',
|
|
322
|
+
properties: {
|
|
323
|
+
message: {
|
|
324
|
+
type: 'string',
|
|
325
|
+
example: 'HonoX',
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
required: ['message'],
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
'/zod-openapi-hono': {
|
|
337
|
+
get: {
|
|
338
|
+
tags: ['ZodOpenAPIHono'],
|
|
339
|
+
summary: 'ZodOpenAPIHono',
|
|
340
|
+
description: 'ZodOpenAPIHono',
|
|
341
|
+
responses: {
|
|
342
|
+
'200': {
|
|
343
|
+
description: 'OK',
|
|
344
|
+
content: {
|
|
345
|
+
'application/json': {
|
|
346
|
+
schema: {
|
|
347
|
+
type: 'object',
|
|
348
|
+
properties: {
|
|
349
|
+
message: {
|
|
350
|
+
type: 'string',
|
|
351
|
+
example: 'ZodOpenAPIHono',
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
required: ['message'],
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
};
|
|
364
|
+
describe('honoTakibi', () => {
|
|
365
|
+
beforeAll(() => {
|
|
366
|
+
process.argv = [
|
|
367
|
+
'*/*/bin/node',
|
|
368
|
+
'*/dist/index.js',
|
|
369
|
+
'openapi.json',
|
|
370
|
+
'-o',
|
|
371
|
+
'zod-openapi-hono.ts',
|
|
372
|
+
];
|
|
373
|
+
fs.writeFileSync('openapi.json', JSON.stringify(openapi));
|
|
374
|
+
});
|
|
375
|
+
afterAll(() => {
|
|
376
|
+
fs.rmSync('openapi.json', { force: true });
|
|
377
|
+
fs.rmSync('zod-openapi-hono.ts', { force: true });
|
|
378
|
+
});
|
|
379
|
+
it('honoTakibi generated', async () => {
|
|
380
|
+
const result = await honoTakibi();
|
|
381
|
+
expect(result).toEqual({
|
|
382
|
+
ok: true,
|
|
383
|
+
value: 'Generated code written to zod-openapi-hono.ts',
|
|
384
|
+
});
|
|
385
|
+
const generatedCode = fs.readFileSync('zod-openapi-hono.ts', 'utf-8');
|
|
386
|
+
const expectedCode = `import { createRoute, z } from '@hono/zod-openapi'
|
|
387
|
+
|
|
388
|
+
export const getHonoRoute = createRoute({
|
|
389
|
+
method: 'get',
|
|
390
|
+
path: '/hono',
|
|
391
|
+
tags: ['Hono'],
|
|
392
|
+
summary: 'Hono',
|
|
393
|
+
description: 'Hono',
|
|
394
|
+
responses: {
|
|
395
|
+
200: {
|
|
396
|
+
description: 'OK',
|
|
397
|
+
content: {
|
|
398
|
+
'application/json': {
|
|
399
|
+
schema: z
|
|
400
|
+
.object({ message: z.string().openapi({ example: 'Hono' }) })
|
|
401
|
+
.openapi({ required: ['message'] }),
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
export const getHonoXRoute = createRoute({
|
|
409
|
+
method: 'get',
|
|
410
|
+
path: '/hono-x',
|
|
411
|
+
tags: ['HonoX'],
|
|
412
|
+
summary: 'HonoX',
|
|
413
|
+
description: 'HonoX',
|
|
414
|
+
responses: {
|
|
415
|
+
200: {
|
|
416
|
+
description: 'OK',
|
|
417
|
+
content: {
|
|
418
|
+
'application/json': {
|
|
419
|
+
schema: z
|
|
420
|
+
.object({ message: z.string().openapi({ example: 'HonoX' }) })
|
|
421
|
+
.openapi({ required: ['message'] }),
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
export const getZodOpenapiHonoRoute = createRoute({
|
|
429
|
+
method: 'get',
|
|
430
|
+
path: '/zod-openapi-hono',
|
|
431
|
+
tags: ['ZodOpenAPIHono'],
|
|
432
|
+
summary: 'ZodOpenAPIHono',
|
|
433
|
+
description: 'ZodOpenAPIHono',
|
|
434
|
+
responses: {
|
|
435
|
+
200: {
|
|
436
|
+
description: 'OK',
|
|
437
|
+
content: {
|
|
438
|
+
'application/json': {
|
|
439
|
+
schema: z
|
|
440
|
+
.object({ message: z.string().openapi({ example: 'ZodOpenAPIHono' }) })
|
|
441
|
+
.openapi({ required: ['message'] }),
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
})
|
|
447
|
+
`;
|
|
448
|
+
expect(generatedCode).toBe(expectedCode);
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
describe('honoTakibi --help', () => {
|
|
452
|
+
beforeAll(() => {
|
|
453
|
+
process.argv = ['*/*/bin/node', '*/dist/index.js', '--help'];
|
|
454
|
+
});
|
|
455
|
+
it('honoTakibi help requested --help', async () => {
|
|
456
|
+
const result = await honoTakibi();
|
|
457
|
+
expect(result).toStrictEqual({
|
|
458
|
+
ok: true,
|
|
459
|
+
value: `Usage: hono-takibi <input.{yaml,json,tsp}> -o <routes.ts> [options]
|
|
460
|
+
|
|
461
|
+
Options:
|
|
462
|
+
--export-schemas-types export schemas types
|
|
463
|
+
--export-schemas export schemas
|
|
464
|
+
--export-parameters-types export parameters types
|
|
465
|
+
--export-parameters export parameters
|
|
466
|
+
--export-security-schemes export securitySchemes
|
|
467
|
+
--export-request-bodies export requestBodies
|
|
468
|
+
--export-responses export responses
|
|
469
|
+
--export-headers-types export headers types
|
|
470
|
+
--export-headers export headers
|
|
471
|
+
--export-examples export examples
|
|
472
|
+
--export-links export links
|
|
473
|
+
--export-callbacks export callbacks
|
|
474
|
+
--template generate app file and handler stubs
|
|
475
|
+
--test generate empty *.test.ts files
|
|
476
|
+
--base-path <path> api prefix (default: /)
|
|
477
|
+
-h, --help display help for command`,
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
describe('honoTakibi -h', () => {
|
|
482
|
+
beforeAll(() => {
|
|
483
|
+
process.argv = ['*/*/bin/node', '*/dist/index.js', '-h'];
|
|
484
|
+
});
|
|
485
|
+
it('honoTakibi help requested -h', async () => {
|
|
486
|
+
const result = await honoTakibi();
|
|
487
|
+
expect(result).toStrictEqual({
|
|
488
|
+
ok: true,
|
|
489
|
+
value: `Usage: hono-takibi <input.{yaml,json,tsp}> -o <routes.ts> [options]
|
|
490
|
+
|
|
491
|
+
Options:
|
|
492
|
+
--export-schemas-types export schemas types
|
|
493
|
+
--export-schemas export schemas
|
|
494
|
+
--export-parameters-types export parameters types
|
|
495
|
+
--export-parameters export parameters
|
|
496
|
+
--export-security-schemes export securitySchemes
|
|
497
|
+
--export-request-bodies export requestBodies
|
|
498
|
+
--export-responses export responses
|
|
499
|
+
--export-headers-types export headers types
|
|
500
|
+
--export-headers export headers
|
|
501
|
+
--export-examples export examples
|
|
502
|
+
--export-links export links
|
|
503
|
+
--export-callbacks export callbacks
|
|
504
|
+
--template generate app file and handler stubs
|
|
505
|
+
--test generate empty *.test.ts files
|
|
506
|
+
--base-path <path> api prefix (default: /)
|
|
507
|
+
-h, --help display help for command`,
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
describe('honoTakibi missing output', () => {
|
|
511
|
+
beforeAll(() => {
|
|
512
|
+
process.argv = ['node', 'dist/index.js', 'openapi.yaml'];
|
|
513
|
+
});
|
|
514
|
+
it('should fail if output is not specified', async () => {
|
|
515
|
+
const result = await honoTakibi();
|
|
516
|
+
expect(result.ok).toBe(false);
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
}
|
package/dist/config/index.d.ts
CHANGED
|
@@ -85,7 +85,7 @@ export declare function parseConfig(config: Config): {
|
|
|
85
85
|
readonly ok: false;
|
|
86
86
|
readonly error: string;
|
|
87
87
|
};
|
|
88
|
-
export declare function
|
|
88
|
+
export declare function readConfig(): Promise<{
|
|
89
89
|
readonly ok: true;
|
|
90
90
|
readonly value: Config;
|
|
91
91
|
} | {
|
package/dist/config/index.js
CHANGED
|
@@ -225,7 +225,7 @@ export function parseConfig(config) {
|
|
|
225
225
|
}
|
|
226
226
|
return { ok: true, value: config };
|
|
227
227
|
}
|
|
228
|
-
export async function
|
|
228
|
+
export async function readConfig() {
|
|
229
229
|
const abs = resolve(process.cwd(), 'hono-takibi.config.ts');
|
|
230
230
|
if (!existsSync(abs))
|
|
231
231
|
return { ok: false, error: `Config not found: ${abs}` };
|
|
@@ -252,3 +252,64 @@ export async function loadConfig() {
|
|
|
252
252
|
export function defineConfig(config) {
|
|
253
253
|
return config;
|
|
254
254
|
}
|
|
255
|
+
// Test run
|
|
256
|
+
// pnpm vitest run ./packages/hono-takibi/src/config/index.ts
|
|
257
|
+
if (import.meta.vitest) {
|
|
258
|
+
const { describe, it, expect, beforeEach, afterEach, vi } = import.meta.vitest;
|
|
259
|
+
const fs = await import('node:fs');
|
|
260
|
+
const os = await import('node:os');
|
|
261
|
+
const path = await import('node:path');
|
|
262
|
+
describe('loadConfig()', () => {
|
|
263
|
+
const origCwd = process.cwd();
|
|
264
|
+
beforeEach(() => {
|
|
265
|
+
vi.resetModules();
|
|
266
|
+
const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'hono-takibi-config-ts-'));
|
|
267
|
+
process.chdir(tmpdir);
|
|
268
|
+
});
|
|
269
|
+
afterEach(() => {
|
|
270
|
+
const cwd = process.cwd();
|
|
271
|
+
process.chdir(origCwd);
|
|
272
|
+
fs.rmSync(cwd, { recursive: true, force: true });
|
|
273
|
+
});
|
|
274
|
+
it('passes: legacy top-level output mode', async () => {
|
|
275
|
+
const p = path.join(process.cwd(), 'hono-takibi.config.ts');
|
|
276
|
+
const c = `
|
|
277
|
+
export default {
|
|
278
|
+
input: 'openapi.yaml',
|
|
279
|
+
'zod-openapi': {
|
|
280
|
+
output: 'routes/index.ts',
|
|
281
|
+
exportSchemasTypes: true,
|
|
282
|
+
exportSchemas: true
|
|
283
|
+
},
|
|
284
|
+
rpc: {
|
|
285
|
+
output: 'rpc/index.ts',
|
|
286
|
+
import: '../client'
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
`;
|
|
290
|
+
fs.writeFileSync(p, c, 'utf-8');
|
|
291
|
+
await expect(readConfig()).resolves.toStrictEqual({
|
|
292
|
+
ok: true,
|
|
293
|
+
value: {
|
|
294
|
+
input: 'openapi.yaml',
|
|
295
|
+
'zod-openapi': {
|
|
296
|
+
output: 'routes/index.ts',
|
|
297
|
+
exportSchemasTypes: true,
|
|
298
|
+
exportSchemas: true,
|
|
299
|
+
},
|
|
300
|
+
rpc: {
|
|
301
|
+
output: 'rpc/index.ts',
|
|
302
|
+
import: '../client',
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
it('fails: config file missing', async () => {
|
|
308
|
+
const result = await readConfig();
|
|
309
|
+
expect(result.ok).toBe(false);
|
|
310
|
+
if (!result.ok) {
|
|
311
|
+
expect(result.error).toMatch(/Config not found:/);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
}
|