hono-takibi 0.9.73 → 0.9.74
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.js +6 -256
- package/dist/config/index.d.ts +14 -1
- package/dist/config/index.js +150 -114
- package/dist/core/route/index.js +0 -235
- package/dist/core/rpc/index.js +22 -1094
- package/dist/core/takibi/index.js +0 -499
- package/dist/core/type/index.js +0 -145
- package/dist/format/index.d.ts +24 -0
- package/dist/format/index.js +24 -18
- package/dist/fsp/index.d.ts +1 -0
- package/dist/fsp/index.js +4 -87
- package/dist/generator/zod-openapi-hono/app/index.js +0 -116
- package/dist/generator/zod-openapi-hono/openapi/components/callbacks.d.ts +15 -0
- package/dist/generator/zod-openapi-hono/openapi/components/callbacks.js +15 -61
- package/dist/generator/zod-openapi-hono/openapi/components/examples.js +0 -151
- package/dist/generator/zod-openapi-hono/openapi/components/headers.d.ts +17 -0
- package/dist/generator/zod-openapi-hono/openapi/components/headers.js +17 -46
- package/dist/generator/zod-openapi-hono/openapi/components/index.js +0 -100
- package/dist/generator/zod-openapi-hono/openapi/components/links.d.ts +16 -0
- package/dist/generator/zod-openapi-hono/openapi/components/links.js +16 -34
- package/dist/generator/zod-openapi-hono/openapi/components/parameters.js +0 -53
- package/dist/generator/zod-openapi-hono/openapi/components/request-bodies.d.ts +16 -0
- package/dist/generator/zod-openapi-hono/openapi/components/request-bodies.js +16 -49
- package/dist/generator/zod-openapi-hono/openapi/components/responses.d.ts +16 -0
- package/dist/generator/zod-openapi-hono/openapi/components/responses.js +16 -43
- package/dist/generator/zod-openapi-hono/openapi/components/schemas.d.ts +17 -0
- package/dist/generator/zod-openapi-hono/openapi/components/schemas.js +17 -72
- package/dist/generator/zod-openapi-hono/openapi/components/securitySchemes.d.ts +16 -0
- package/dist/generator/zod-openapi-hono/openapi/components/securitySchemes.js +16 -36
- package/dist/generator/zod-openapi-hono/openapi/index.js +0 -460
- package/dist/generator/zod-openapi-hono/openapi/routes/create-route.js +0 -36
- package/dist/generator/zod-openapi-hono/openapi/routes/index.d.ts +3 -0
- package/dist/generator/zod-openapi-hono/openapi/routes/index.js +28 -78
- package/dist/generator/zod-to-openapi/index.js +0 -765
- package/dist/generator/zod-to-openapi/z/enum.d.ts +29 -0
- package/dist/generator/zod-to-openapi/z/enum.js +29 -27
- package/dist/generator/zod-to-openapi/z/index.d.ts +12 -0
- package/dist/generator/zod-to-openapi/z/index.js +12 -27
- package/dist/generator/zod-to-openapi/z/integer.js +0 -139
- package/dist/generator/zod-to-openapi/z/number.js +0 -45
- package/dist/generator/zod-to-openapi/z/object.js +0 -73
- package/dist/generator/zod-to-openapi/z/string.js +0 -38
- package/dist/helper/ast.js +0 -295
- package/dist/helper/barell.d.ts +20 -0
- package/dist/helper/barell.js +20 -32
- package/dist/helper/code.d.ts +17 -0
- package/dist/helper/code.js +17 -33
- package/dist/helper/core.js +0 -18
- package/dist/helper/exports.js +0 -79
- package/dist/helper/index.js +0 -14
- package/dist/helper/openapi.d.ts +18 -0
- package/dist/helper/openapi.js +18 -847
- package/dist/helper/schema.d.ts +114 -0
- package/dist/helper/schema.js +114 -209
- package/dist/helper/type.d.ts +34 -0
- package/dist/helper/type.js +34 -232
- package/dist/helper/wrap.js +0 -241
- package/dist/index.js +10 -2178
- package/dist/openapi/index.js +0 -174
- package/dist/utils/index.d.ts +56 -5
- package/dist/utils/index.js +55 -269
- package/dist/vite-plugin/index.js +311 -427
- package/package.json +10 -10
package/dist/cli/index.js
CHANGED
|
@@ -154,8 +154,8 @@ export async function honoTakibi() {
|
|
|
154
154
|
const cliResult = parseCli(args);
|
|
155
155
|
if (!cliResult.ok)
|
|
156
156
|
return { ok: false, error: cliResult.error };
|
|
157
|
-
const
|
|
158
|
-
const { input, output, template, test, basePath, componentsOptions } =
|
|
157
|
+
const value = cliResult.value;
|
|
158
|
+
const { input, output, template, test, basePath, componentsOptions } = value;
|
|
159
159
|
const openAPIResult = await parseOpenAPI(input);
|
|
160
160
|
if (!openAPIResult.ok)
|
|
161
161
|
return { ok: false, error: openAPIResult.error };
|
|
@@ -165,10 +165,10 @@ export async function honoTakibi() {
|
|
|
165
165
|
return { ok: false, error: takibiResult.error };
|
|
166
166
|
return { ok: true, value: takibiResult.value };
|
|
167
167
|
}
|
|
168
|
-
const
|
|
169
|
-
if (!
|
|
170
|
-
return { ok: false, error:
|
|
171
|
-
const config =
|
|
168
|
+
const readConfigResult = await readConfig();
|
|
169
|
+
if (!readConfigResult.ok)
|
|
170
|
+
return { ok: false, error: readConfigResult.error };
|
|
171
|
+
const config = readConfigResult.value;
|
|
172
172
|
const openAPIResult = await parseOpenAPI(config.input);
|
|
173
173
|
if (!openAPIResult.ok)
|
|
174
174
|
return { ok: false, error: openAPIResult.error };
|
|
@@ -268,253 +268,3 @@ export async function honoTakibi() {
|
|
|
268
268
|
].filter((v) => v !== undefined);
|
|
269
269
|
return { ok: true, value: results.join('\n') };
|
|
270
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
|
@@ -78,6 +78,13 @@ type Config = {
|
|
|
78
78
|
readonly split?: boolean;
|
|
79
79
|
};
|
|
80
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* Validates and parses a hono-takibi configuration object.
|
|
83
|
+
* When split is false and output doesn't end with .ts, normalizes to {output}/index.ts.
|
|
84
|
+
*
|
|
85
|
+
* @param config - The configuration object to validate
|
|
86
|
+
* @returns Result object with validated and normalized config or error message
|
|
87
|
+
*/
|
|
81
88
|
export declare function parseConfig(config: Config): {
|
|
82
89
|
readonly ok: true;
|
|
83
90
|
readonly value: Config;
|
|
@@ -85,6 +92,11 @@ export declare function parseConfig(config: Config): {
|
|
|
85
92
|
readonly ok: false;
|
|
86
93
|
readonly error: string;
|
|
87
94
|
};
|
|
95
|
+
/**
|
|
96
|
+
* Reads and validates the hono-takibi configuration from hono-takibi.config.ts.
|
|
97
|
+
*
|
|
98
|
+
* @returns Result object with validated config or error message
|
|
99
|
+
*/
|
|
88
100
|
export declare function readConfig(): Promise<{
|
|
89
101
|
readonly ok: true;
|
|
90
102
|
readonly value: Config;
|
|
@@ -95,7 +107,8 @@ export declare function readConfig(): Promise<{
|
|
|
95
107
|
/**
|
|
96
108
|
* Helper to define a config with full type completion.
|
|
97
109
|
*
|
|
98
|
-
* @
|
|
110
|
+
* @param config - The configuration object
|
|
111
|
+
* @returns The same configuration object (identity function for type inference)
|
|
99
112
|
*/
|
|
100
113
|
export declare function defineConfig(config: Config): Config;
|
|
101
114
|
export {};
|
package/dist/config/index.js
CHANGED
|
@@ -2,11 +2,17 @@ import { existsSync } from 'node:fs';
|
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
import { register } from 'tsx/esm/api';
|
|
5
|
+
/**
|
|
6
|
+
* Validates and parses a hono-takibi configuration object.
|
|
7
|
+
* When split is false and output doesn't end with .ts, normalizes to {output}/index.ts.
|
|
8
|
+
*
|
|
9
|
+
* @param config - The configuration object to validate
|
|
10
|
+
* @returns Result object with validated and normalized config or error message
|
|
11
|
+
*/
|
|
5
12
|
export function parseConfig(config) {
|
|
6
13
|
const isYamlOrJsonOrTsp = (i) => typeof i === 'string' && (i.endsWith('.yaml') || i.endsWith('.json') || i.endsWith('.tsp'));
|
|
7
|
-
// ts
|
|
8
14
|
const isTs = (o) => typeof o === 'string' && o.endsWith('.ts');
|
|
9
|
-
const
|
|
15
|
+
const validateComponentsValue = (k, v) => {
|
|
10
16
|
if (v === undefined)
|
|
11
17
|
return { ok: false, error: `Invalid config: zod-openapi.components.${k} is undefined` };
|
|
12
18
|
if (k === 'schemas' || k === 'parameters' || k === 'headers') {
|
|
@@ -25,22 +31,12 @@ export function parseConfig(config) {
|
|
|
25
31
|
error: `Invalid split format for components.${k}: ${String(splitValue)}`,
|
|
26
32
|
};
|
|
27
33
|
}
|
|
28
|
-
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
if (!isTs(v.output)) {
|
|
39
|
-
return {
|
|
40
|
-
ok: false,
|
|
41
|
-
error: `Invalid ${k} output path for non-split mode (must be .ts file): ${v.output}`,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
34
|
+
// split: true requires directory (no .ts)
|
|
35
|
+
if (splitValue === true && isTs(v.output)) {
|
|
36
|
+
return {
|
|
37
|
+
ok: false,
|
|
38
|
+
error: `Invalid ${k} output path for split mode (must be a directory, not .ts): ${v.output}`,
|
|
39
|
+
};
|
|
44
40
|
}
|
|
45
41
|
if (v.import !== undefined && typeof v.import !== 'string') {
|
|
46
42
|
return {
|
|
@@ -48,7 +44,7 @@ export function parseConfig(config) {
|
|
|
48
44
|
error: `Invalid import format for components.${k}: ${String(v.import)}`,
|
|
49
45
|
};
|
|
50
46
|
}
|
|
51
|
-
return { ok: true
|
|
47
|
+
return { ok: true };
|
|
52
48
|
};
|
|
53
49
|
if (!isYamlOrJsonOrTsp(config.input)) {
|
|
54
50
|
return {
|
|
@@ -151,21 +147,12 @@ export function parseConfig(config) {
|
|
|
151
147
|
error: `Invalid split format for routes: ${String(config['zod-openapi'].routes.split)}`,
|
|
152
148
|
};
|
|
153
149
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
if (!isTs(config['zod-openapi'].routes.output)) {
|
|
164
|
-
return {
|
|
165
|
-
ok: false,
|
|
166
|
-
error: `Invalid routes output path for non-split mode (must be .ts file): ${config['zod-openapi'].routes.output}`,
|
|
167
|
-
};
|
|
168
|
-
}
|
|
150
|
+
// split: true requires directory (no .ts)
|
|
151
|
+
if (config['zod-openapi'].routes.split === true && isTs(config['zod-openapi'].routes.output)) {
|
|
152
|
+
return {
|
|
153
|
+
ok: false,
|
|
154
|
+
error: `Invalid routes output path for split mode (must be a directory, not .ts): ${config['zod-openapi'].routes.output}`,
|
|
155
|
+
};
|
|
169
156
|
}
|
|
170
157
|
}
|
|
171
158
|
if (config['zod-openapi']?.components !== undefined) {
|
|
@@ -179,7 +166,7 @@ export function parseConfig(config) {
|
|
|
179
166
|
k === 'examples' ||
|
|
180
167
|
k === 'links' ||
|
|
181
168
|
k === 'callbacks') {
|
|
182
|
-
const result =
|
|
169
|
+
const result = validateComponentsValue(k, config['zod-openapi'].components[k]);
|
|
183
170
|
if (!result.ok)
|
|
184
171
|
return { ok: false, error: result.error };
|
|
185
172
|
}
|
|
@@ -205,26 +192,135 @@ export function parseConfig(config) {
|
|
|
205
192
|
if (config.rpc.split !== undefined && typeof config.rpc.split !== 'boolean') {
|
|
206
193
|
return { ok: false, error: `Invalid split format for rpc: ${String(config.rpc.split)}` };
|
|
207
194
|
}
|
|
208
|
-
// split
|
|
209
|
-
if (config.rpc.split === true) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
if (!isTs(config.rpc.output)) {
|
|
219
|
-
return {
|
|
220
|
-
ok: false,
|
|
221
|
-
error: `Invalid output format for rpc (non-split mode must be .ts file): ${String(config.rpc.output)}`,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
195
|
+
// split: true requires directory (no .ts)
|
|
196
|
+
if (config.rpc.split === true && isTs(config.rpc.output)) {
|
|
197
|
+
return {
|
|
198
|
+
ok: false,
|
|
199
|
+
error: `Invalid rpc output path for split mode (must be a directory, not .ts): ${config.rpc.output}`,
|
|
200
|
+
};
|
|
224
201
|
}
|
|
225
202
|
}
|
|
226
|
-
|
|
203
|
+
const result = {
|
|
204
|
+
...config,
|
|
205
|
+
...(config['zod-openapi'] && {
|
|
206
|
+
'zod-openapi': {
|
|
207
|
+
...config['zod-openapi'],
|
|
208
|
+
...(config['zod-openapi'].routes && {
|
|
209
|
+
routes: {
|
|
210
|
+
...config['zod-openapi'].routes,
|
|
211
|
+
output: config['zod-openapi'].routes.split !== true &&
|
|
212
|
+
!isTs(config['zod-openapi'].routes.output)
|
|
213
|
+
? `${config['zod-openapi'].routes.output}/index.ts`
|
|
214
|
+
: config['zod-openapi'].routes.output,
|
|
215
|
+
},
|
|
216
|
+
}),
|
|
217
|
+
...(config['zod-openapi'].components && {
|
|
218
|
+
components: {
|
|
219
|
+
...config['zod-openapi'].components,
|
|
220
|
+
...(config['zod-openapi'].components.schemas && {
|
|
221
|
+
schemas: {
|
|
222
|
+
...config['zod-openapi'].components.schemas,
|
|
223
|
+
output: config['zod-openapi'].components.schemas.split !== true &&
|
|
224
|
+
!isTs(config['zod-openapi'].components.schemas.output)
|
|
225
|
+
? `${config['zod-openapi'].components.schemas.output}/index.ts`
|
|
226
|
+
: config['zod-openapi'].components.schemas.output,
|
|
227
|
+
},
|
|
228
|
+
}),
|
|
229
|
+
...(config['zod-openapi'].components.parameters && {
|
|
230
|
+
parameters: {
|
|
231
|
+
...config['zod-openapi'].components.parameters,
|
|
232
|
+
output: config['zod-openapi'].components.parameters.split !== true &&
|
|
233
|
+
!isTs(config['zod-openapi'].components.parameters.output)
|
|
234
|
+
? `${config['zod-openapi'].components.parameters.output}/index.ts`
|
|
235
|
+
: config['zod-openapi'].components.parameters.output,
|
|
236
|
+
},
|
|
237
|
+
}),
|
|
238
|
+
...(config['zod-openapi'].components.securitySchemes && {
|
|
239
|
+
securitySchemes: {
|
|
240
|
+
...config['zod-openapi'].components.securitySchemes,
|
|
241
|
+
output: config['zod-openapi'].components.securitySchemes.split !== true &&
|
|
242
|
+
!isTs(config['zod-openapi'].components.securitySchemes.output)
|
|
243
|
+
? `${config['zod-openapi'].components.securitySchemes.output}/index.ts`
|
|
244
|
+
: config['zod-openapi'].components.securitySchemes.output,
|
|
245
|
+
},
|
|
246
|
+
}),
|
|
247
|
+
...(config['zod-openapi'].components.requestBodies && {
|
|
248
|
+
requestBodies: {
|
|
249
|
+
...config['zod-openapi'].components.requestBodies,
|
|
250
|
+
output: config['zod-openapi'].components.requestBodies.split !== true &&
|
|
251
|
+
!isTs(config['zod-openapi'].components.requestBodies.output)
|
|
252
|
+
? `${config['zod-openapi'].components.requestBodies.output}/index.ts`
|
|
253
|
+
: config['zod-openapi'].components.requestBodies.output,
|
|
254
|
+
},
|
|
255
|
+
}),
|
|
256
|
+
...(config['zod-openapi'].components.responses && {
|
|
257
|
+
responses: {
|
|
258
|
+
...config['zod-openapi'].components.responses,
|
|
259
|
+
output: config['zod-openapi'].components.responses.split !== true &&
|
|
260
|
+
!isTs(config['zod-openapi'].components.responses.output)
|
|
261
|
+
? `${config['zod-openapi'].components.responses.output}/index.ts`
|
|
262
|
+
: config['zod-openapi'].components.responses.output,
|
|
263
|
+
},
|
|
264
|
+
}),
|
|
265
|
+
...(config['zod-openapi'].components.headers && {
|
|
266
|
+
headers: {
|
|
267
|
+
...config['zod-openapi'].components.headers,
|
|
268
|
+
output: config['zod-openapi'].components.headers.split !== true &&
|
|
269
|
+
!isTs(config['zod-openapi'].components.headers.output)
|
|
270
|
+
? `${config['zod-openapi'].components.headers.output}/index.ts`
|
|
271
|
+
: config['zod-openapi'].components.headers.output,
|
|
272
|
+
},
|
|
273
|
+
}),
|
|
274
|
+
...(config['zod-openapi'].components.examples && {
|
|
275
|
+
examples: {
|
|
276
|
+
...config['zod-openapi'].components.examples,
|
|
277
|
+
output: config['zod-openapi'].components.examples.split !== true &&
|
|
278
|
+
!isTs(config['zod-openapi'].components.examples.output)
|
|
279
|
+
? `${config['zod-openapi'].components.examples.output}/index.ts`
|
|
280
|
+
: config['zod-openapi'].components.examples.output,
|
|
281
|
+
},
|
|
282
|
+
}),
|
|
283
|
+
...(config['zod-openapi'].components.links && {
|
|
284
|
+
links: {
|
|
285
|
+
...config['zod-openapi'].components.links,
|
|
286
|
+
output: config['zod-openapi'].components.links.split !== true &&
|
|
287
|
+
!isTs(config['zod-openapi'].components.links.output)
|
|
288
|
+
? `${config['zod-openapi'].components.links.output}/index.ts`
|
|
289
|
+
: config['zod-openapi'].components.links.output,
|
|
290
|
+
},
|
|
291
|
+
}),
|
|
292
|
+
...(config['zod-openapi'].components.callbacks && {
|
|
293
|
+
callbacks: {
|
|
294
|
+
...config['zod-openapi'].components.callbacks,
|
|
295
|
+
output: config['zod-openapi'].components.callbacks.split !== true &&
|
|
296
|
+
!isTs(config['zod-openapi'].components.callbacks.output)
|
|
297
|
+
? `${config['zod-openapi'].components.callbacks.output}/index.ts`
|
|
298
|
+
: config['zod-openapi'].components.callbacks.output,
|
|
299
|
+
},
|
|
300
|
+
}),
|
|
301
|
+
},
|
|
302
|
+
}),
|
|
303
|
+
},
|
|
304
|
+
}),
|
|
305
|
+
...(config.rpc && {
|
|
306
|
+
rpc: {
|
|
307
|
+
...config.rpc,
|
|
308
|
+
output: config.rpc.split !== true && !isTs(config.rpc.output)
|
|
309
|
+
? `${config.rpc.output}/index.ts`
|
|
310
|
+
: config.rpc.output,
|
|
311
|
+
},
|
|
312
|
+
}),
|
|
313
|
+
};
|
|
314
|
+
return {
|
|
315
|
+
ok: true,
|
|
316
|
+
value: result,
|
|
317
|
+
};
|
|
227
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* Reads and validates the hono-takibi configuration from hono-takibi.config.ts.
|
|
321
|
+
*
|
|
322
|
+
* @returns Result object with validated config or error message
|
|
323
|
+
*/
|
|
228
324
|
export async function readConfig() {
|
|
229
325
|
const abs = resolve(process.cwd(), 'hono-takibi.config.ts');
|
|
230
326
|
if (!existsSync(abs))
|
|
@@ -247,69 +343,9 @@ export async function readConfig() {
|
|
|
247
343
|
/**
|
|
248
344
|
* Helper to define a config with full type completion.
|
|
249
345
|
*
|
|
250
|
-
* @
|
|
346
|
+
* @param config - The configuration object
|
|
347
|
+
* @returns The same configuration object (identity function for type inference)
|
|
251
348
|
*/
|
|
252
349
|
export function defineConfig(config) {
|
|
253
350
|
return config;
|
|
254
351
|
}
|
|
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
|
-
}
|