hono-takibi 0.9.1 → 0.9.2

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 CHANGED
@@ -1,8 +1,10 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { resolve } from 'node:path';
3
3
  import { config } from '../config/index.js';
4
- import { rpc } from '../core/rpc.js';
4
+ import core from '../core/core.js';
5
5
  import { takibi } from '../core/takibi.js';
6
+ import rpc from '../generator/rpc/index.js';
7
+ // import { honoRpcWithSWR } from '../generator/swr/index.js'
6
8
  import { parseCli } from '../utils/index.js';
7
9
  const HELP_TEXT = `Usage: hono-takibi <input.{yaml,json,tsp}> -o <routes.ts> [options]
8
10
 
@@ -86,10 +88,24 @@ export async function honoTakibi() {
86
88
  if (takibiResult && !takibiResult.ok) {
87
89
  return { ok: false, error: takibiResult.error };
88
90
  }
89
- const rpcResult = c.rpc ? await rpc(c.rpc.input, c.rpc.output, c.rpc.import) : undefined;
91
+ const rpcResult = c.rpc
92
+ ? await core(c.rpc.input, c.rpc.output, c.rpc.import, 'Generated RPC code written to', rpc)
93
+ : undefined;
90
94
  if (rpcResult && !rpcResult.ok) {
91
95
  return { ok: false, error: rpcResult.error };
92
96
  }
97
+ // const swrResult = c.swr
98
+ // ? await core(
99
+ // c.swr.input,
100
+ // c.swr.output,
101
+ // c.swr.import,
102
+ // 'Generated SWR code written to',
103
+ // honoRpcWithSWR,
104
+ // )
105
+ // : undefined
106
+ // if (swrResult && !swrResult.ok) {
107
+ // return { ok: false, error: swrResult.error }
108
+ // }
93
109
  const results = [takibiResult?.value, rpcResult?.value].filter((v) => Boolean(v));
94
110
  return {
95
111
  ok: true,
@@ -10,6 +10,11 @@ type Config = {
10
10
  output: `${string}.ts`;
11
11
  import: string;
12
12
  };
13
+ swr?: {
14
+ input: `${string}.yaml` | `${string}.json` | `${string}.tsp`;
15
+ output: `${string}.ts`;
16
+ import: string;
17
+ };
13
18
  };
14
19
  export declare function config(): Promise<{
15
20
  ok: true;
@@ -18,5 +23,5 @@ export declare function config(): Promise<{
18
23
  ok: false;
19
24
  error: string;
20
25
  }>;
21
- export declare function defineConfig(config: Config): Config;
26
+ export default function defineConfig(config: Config): Config;
22
27
  export {};
@@ -18,6 +18,6 @@ export async function config() {
18
18
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
19
19
  }
20
20
  }
21
- export function defineConfig(config) {
21
+ export default function defineConfig(config) {
22
22
  return config;
23
23
  }
@@ -0,0 +1,8 @@
1
+ import { type OpenAPI } from '../openapi/index.js';
2
+ export default function core(input: `${string}.yaml` | `${string}.json` | `${string}.tsp`, output: `${string}.ts`, importCode: string, value: string, fn: (openapi: OpenAPI, importCode: string) => string): Promise<{
3
+ ok: true;
4
+ value: string;
5
+ } | {
6
+ ok: false;
7
+ error: string;
8
+ }>;
@@ -1,15 +1,14 @@
1
1
  import path from 'node:path';
2
2
  import { fmt } from '../format/index.js';
3
3
  import { mkdir, writeFile } from '../fsp/index.js';
4
- import { honoRpc } from '../generator/rpc/index.js';
5
4
  import { parseOpenAPI } from '../openapi/index.js';
6
- export async function rpc(input, output, importCode) {
5
+ export default async function core(input, output, importCode, value, fn) {
7
6
  const openAPIResult = await parseOpenAPI(input);
8
7
  if (!openAPIResult.ok) {
9
8
  return { ok: false, error: openAPIResult.error };
10
9
  }
11
10
  const openAPI = openAPIResult.value;
12
- const honoRpcResult = await fmt(honoRpc(openAPI, importCode));
11
+ const honoRpcResult = await fmt(fn(openAPI, importCode));
13
12
  if (!honoRpcResult.ok) {
14
13
  return { ok: false, error: honoRpcResult.error };
15
14
  }
@@ -23,6 +22,6 @@ export async function rpc(input, output, importCode) {
23
22
  }
24
23
  return {
25
24
  ok: true,
26
- value: `Generated RPC code written to ${output}`,
25
+ value: `${value} ${output}`,
27
26
  };
28
27
  }
@@ -111,7 +111,7 @@ async function zodOpenapiHonoHandler(openapi, output, test) {
111
111
  const handlers = [];
112
112
  for (const [path, pathItem] of Object.entries(paths)) {
113
113
  for (const [method] of Object.entries(pathItem)) {
114
- const routeHandlerContent = `export const ${methodPath(method, path)}RouteHandler:RouteHandler<typeof ${methodPath(method, path)}>=async(c)=>{}`;
114
+ const routeHandlerContent = `export const ${methodPath(method, path)}RouteHandler:RouteHandler<typeof ${methodPath(method, path)}Route>=async(c)=>{}`;
115
115
  const rawSegment = path.replace(/^\/+/, '').split('/')[0] ?? '';
116
116
  const pathName = (rawSegment === '' ? 'index' : rawSegment)
117
117
  .replace(/\{([^}]+)\}/g, '$1')
@@ -1,2 +1,2 @@
1
1
  import type { OpenAPI } from '../../openapi/index.js';
2
- export declare function honoRpc(openapi: OpenAPI, importCode: string): string;
2
+ export default function rpc(openapi: OpenAPI, importCode: string): string;
@@ -14,8 +14,6 @@ const isOpenAPIPaths = (v) => {
14
14
  /** Treat any object as Schema (we rely on downstream field checks) */
15
15
  const isSchema = (v) => isRecord(v);
16
16
  /* ─────────────────────────────── Formatters ─────────────────────────────── */
17
- /** Uppercase the first character */
18
- const upperHead = (s) => (s ? s.charAt(0).toUpperCase() + s.slice(1) : s);
19
17
  /** JS identifier check */
20
18
  const isValidIdent = (s) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(s);
21
19
  /** Escape single quotes and backslashes for single-quoted strings */
@@ -288,7 +286,7 @@ const generateOperationCode = (path, method, item, deps) => {
288
286
  '}');
289
287
  };
290
288
  /* ─────────────────────────────── Entry ─────────────────────────────── */
291
- export function honoRpc(openapi, importCode) {
289
+ export default function rpc(openapi, importCode) {
292
290
  const client = 'client';
293
291
  const out = [];
294
292
  // import header (kept as-is, then a blank line if present)
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -12,42 +12,75 @@ import { zodToOpenAPI } from '../../../../zod-to-openapi/index.js';
12
12
  * - Deduplicates content types if all share the same schema.
13
13
  * - Escapes all descriptions safely for inline code.
14
14
  */
15
+ // export function response(responses: Responses): string {
16
+ // // 1. get response codes (200, 404, etc.)
17
+ // const responseCodes = Object.keys(responses)
18
+ // // 2. processing for each response code
19
+ // const responseEntries = responseCodes.map((code) => {
20
+ // const response = responses[code]
21
+ // // 2.1 no content (description only response)
22
+ // if (!response.content)
23
+ // return `${code}:{description:'${escapeStringLiteral(response.description ?? '')}',},`
24
+ // // check duplication
25
+ // const contentTypes = Object.keys(response.content)
26
+ // const isUniqueSchema = isUniqueContentSchema(contentTypes, response.content)
27
+ // // all duplication same schema
28
+ // if (isUniqueSchema) {
29
+ // const contentParts: string[] = []
30
+ // for (const contentType of contentTypes) {
31
+ // const content = response.content[contentType]
32
+ // const z = zodToOpenAPI(content.schema)
33
+ // const examples = content.examples
34
+ // const exampleString =
35
+ // examples && Object.keys(examples).length > 0
36
+ // ? `,examples:{${Object.entries(examples)
37
+ // .map(([key, example]) => {
38
+ // const parts = []
39
+ // if (example.summary) parts.push(`summary:${JSON.stringify(example.summary)}`)
40
+ // if (example.value !== undefined)
41
+ // parts.push(`value:${JSON.stringify(example.value)}`)
42
+ // return `${JSON.stringify(key)}:{${parts.join(',')}}`
43
+ // })
44
+ // .join(',')}}`
45
+ // : ''
46
+ // contentParts.push(`'${contentType}':{schema:${z}${exampleString}}`)
47
+ // }
48
+ // return `${code}:{description:'${escapeStringLiteral(response.description ?? '')}',content:{${contentParts.join(',')}}},`
49
+ // }
50
+ // })
51
+ // // 3.combine all response definitions
52
+ // return responseEntries.join('')
53
+ // }
15
54
  export function response(responses) {
16
55
  // 1. get response codes (200, 404, etc.)
17
- const responseCodes = Object.keys(responses);
18
- // 2. processing for each response code
19
- const responseEntries = responseCodes.map((code) => {
20
- const response = responses[code];
21
- // 2.1 no content (description only response)
22
- if (!response.content)
23
- return `${code}:{description:'${escapeStringLiteral(response.description ?? '')}',},`;
24
- // check duplication
25
- const contentTypes = Object.keys(response.content);
26
- const isUniqueSchema = isUniqueContentSchema(contentTypes, response.content);
27
- // all duplication same schema
28
- if (isUniqueSchema) {
29
- const contentParts = [];
30
- for (const contentType of contentTypes) {
31
- const content = response.content[contentType];
32
- const z = zodToOpenAPI(content.schema);
33
- const examples = content.examples;
34
- const exampleString = examples && Object.keys(examples).length > 0
35
- ? `,examples:{${Object.entries(examples)
36
- .map(([key, example]) => {
37
- const parts = [];
38
- if (example.summary)
39
- parts.push(`summary:${JSON.stringify(example.summary)}`);
40
- if (example.value !== undefined)
41
- parts.push(`value:${JSON.stringify(example.value)}`);
42
- return `${JSON.stringify(key)}:{${parts.join(',')}}`;
43
- })
44
- .join(',')}}`
45
- : '';
46
- contentParts.push(`'${contentType}':{schema:${z}${exampleString}}`);
47
- }
48
- return `${code}:{description:'${escapeStringLiteral(response.description ?? '')}',content:{${contentParts.join(',')}}},`;
56
+ const responseEntries = Object.keys(responses).map((code) => {
57
+ const res = responses[code];
58
+ const content = res.content;
59
+ if (!content) {
60
+ return `${code}:{description:'${escapeStringLiteral(res.description ?? '')}',},`;
49
61
  }
62
+ const contentTypes = Object.keys(content);
63
+ const isUnique = isUniqueContentSchema(contentTypes, content);
64
+ const sharedZ = isUnique ? zodToOpenAPI(content[contentTypes[0]].schema) : undefined;
65
+ const contentParts = contentTypes.map((ct) => {
66
+ const media = content[ct];
67
+ const z = sharedZ ?? zodToOpenAPI(media.schema);
68
+ const examples = media.examples;
69
+ const exampleString = examples && Object.keys(examples).length > 0
70
+ ? `,examples:{${Object.entries(examples)
71
+ .map(([k, v]) => {
72
+ const parts = [];
73
+ if (v.summary)
74
+ parts.push(`summary:${JSON.stringify(v.summary)}`);
75
+ if (v.value !== undefined)
76
+ parts.push(`value:${JSON.stringify(v.value)}`);
77
+ return `${JSON.stringify(k)}:{${parts.join(',')}}`;
78
+ })
79
+ .join(',')}}`
80
+ : '';
81
+ return `'${ct}':{schema:${z}${exampleString}}`;
82
+ });
83
+ return `${code}:{description:'${escapeStringLiteral(res.description ?? '')}',content:{${contentParts.join(',')}}},`;
50
84
  });
51
- // 3.combine all response definitions
52
85
  return responseEntries.join('');
53
86
  }
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.01",
4
+ "version": "0.9.2",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -33,16 +33,20 @@
33
33
  "import": "./dist/vite-plugin/index.js"
34
34
  },
35
35
  "./config": {
36
- "types": "./dist/generator/config/index.d.ts",
37
- "import": "./dist/generator/config/index.js"
36
+ "types": "./dist/config/index.d.ts",
37
+ "import": "./dist/config/index.js"
38
38
  },
39
39
  "./zod-openapi-hono": {
40
40
  "types": "./dist/generator/zod-openapi-hono/openapi/index.d.ts",
41
41
  "import": "./dist/generator/zod-openapi-hono/openapi/index.js"
42
42
  },
43
- "./rpc-beta": {
44
- "types": "./dist/core/rpc.d.ts",
45
- "import": "./dist/core/rpc.js"
43
+ "./core": {
44
+ "types": "./dist/core/core.d.ts",
45
+ "import": "./dist/core/core.js"
46
+ },
47
+ "./rpc": {
48
+ "types": "./dist/generator/rpc/index.d.ts",
49
+ "import": "./dist/generator/rpc/index.js"
46
50
  }
47
51
  },
48
52
  "dependencies": {
@@ -1,7 +0,0 @@
1
- export declare function rpc(input: `${string}.yaml` | `${string}.json` | `${string}.tsp`, output: `${string}.ts`, importCode: string): Promise<{
2
- ok: true;
3
- value: string;
4
- } | {
5
- ok: false;
6
- error: string;
7
- }>;