@rcmade/hono-docs 1.0.29 → 1.0.31
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 +32 -27
- package/dist/cli/index.js +5 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +60 -0
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- **
|
|
9
|
+
- **CLI** (`@rcmade/hono-docs generate`) to:
|
|
10
10
|
- Extract your route `AppType` definitions via **ts-morph**
|
|
11
|
-
- Emit `.
|
|
11
|
+
- Emit `.json` OpenAPI” files per API prefix under `output/*.json`
|
|
12
12
|
- Generate a merged `openapi.json` spec at your configured output path
|
|
13
13
|
- Full TypeScript support (TS & JS config files, inference via `defineConfig`)
|
|
14
14
|
|
|
@@ -61,7 +61,7 @@ yarn add -D @rcmade/hono-docs
|
|
|
61
61
|
openApi: {
|
|
62
62
|
openapi: "3.0.0",
|
|
63
63
|
info: { title: "My API", version: "1.0.0" },
|
|
64
|
-
servers: [{ url: "http://localhost:3000" }],
|
|
64
|
+
servers: [{ url: "http://localhost:3000/api" }],
|
|
65
65
|
},
|
|
66
66
|
outputs: {
|
|
67
67
|
openApiJson: "./openapi/openapi.json",
|
|
@@ -288,21 +288,26 @@ Visiting `/api/docs` shows the UI; `/api/docs/open-api` serves the JSON.
|
|
|
288
288
|
|
|
289
289
|
All options live in your `defineConfig({ ... })` object:
|
|
290
290
|
|
|
291
|
-
| Field
|
|
292
|
-
|
|
|
293
|
-
| `tsConfigPath`
|
|
294
|
-
| `openApi`
|
|
295
|
-
| `
|
|
296
|
-
| `
|
|
297
|
-
| `
|
|
298
|
-
| `outputs`
|
|
299
|
-
| `
|
|
300
|
-
| `apis`
|
|
301
|
-
|
|
|
302
|
-
|
|
|
303
|
-
|
|
|
304
|
-
|
|
|
305
|
-
| `
|
|
291
|
+
| Field | Type | Required | Description |
|
|
292
|
+
| ---------------------- | ------------------------------------------------- | -------- | ---------------------------------------------------------------------------- |
|
|
293
|
+
| `tsConfigPath` | `string` | Yes | Path to your project’s `tsconfig.json` |
|
|
294
|
+
| `openApi` | `OpenAPIConfig` | Yes | Static OpenAPI fields excluding `paths`, `components`, and `tags` |
|
|
295
|
+
| └ `openapi` | `string` | Yes | OpenAPI version (e.g., `"3.0.0"`) |
|
|
296
|
+
| └ `info` | `{ title: string; version: string }` | Yes | API title and version metadata |
|
|
297
|
+
| └ `servers` | `Array<{ url: string }>` | Yes | Array of server objects describing base URLs for the API |
|
|
298
|
+
| `outputs` | `{ openApiJson: string }` | Yes | File output paths |
|
|
299
|
+
| └ `openApiJson` | `string` | Yes | Path to output the generated `openapi.json` file |
|
|
300
|
+
| `apis` | `ApiGroup[]` | Yes | Array of route groups to include in the documentation |
|
|
301
|
+
| └ `name` | `string` | Yes | Human-readable name for the route group |
|
|
302
|
+
| └ `apiPrefix` | `string` | Yes | URL path prefix for all routes in this group (e.g., `/auth`) |
|
|
303
|
+
| └ `appTypePath` | `string` | Yes | File path to the module exporting `AppType = typeof routesInstance` |
|
|
304
|
+
| └ `api` | `Array<Api>` | No | Optional list of endpoint definitions; if omitted, all in `AppType` are used |
|
|
305
|
+
| └ `api` | `string` | Yes | Endpoint path (without prefix), e.g., `/user/{id}` |
|
|
306
|
+
| └ `method` | `"get" \| "post" \| "put" \| "patch" \| "delete"` | Yes | HTTP method for the endpoint |
|
|
307
|
+
| └ `summary` | `string` | No | Short summary for OpenAPI documentation |
|
|
308
|
+
| └ `description` | `string` | No | Longer description for the endpoint |
|
|
309
|
+
| └ `tag` | `string[]` | No | Tags used to categorize the endpoint |
|
|
310
|
+
| `preDefineTypeContent` | `string` | No | Optional content injected at the top of each generated `.d.ts` snapshot |
|
|
306
311
|
|
|
307
312
|
---
|
|
308
313
|
|
|
@@ -343,16 +348,16 @@ Check out [`examples/basic-app/`](https://github.com/rcmade/hono-docs/tree/main/
|
|
|
343
348
|
|
|
344
349
|
1. Clone & install dependencies:
|
|
345
350
|
|
|
346
|
-
git clone [https://github.com/rcmade/hono-docs.git](https://github.com/rcmade/hono-docs.git)
|
|
347
|
-
cd hono-docs
|
|
348
|
-
pnpm install
|
|
351
|
+
git clone [https://github.com/rcmade/hono-docs.git](https://github.com/rcmade/hono-docs.git)
|
|
352
|
+
cd hono-docs
|
|
353
|
+
pnpm install
|
|
349
354
|
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
```
|
|
355
|
+
```bash
|
|
356
|
+
1. Implement or modify code under `src/`.
|
|
357
|
+
2. Build and watch: pnpm build --watch
|
|
358
|
+
```
|
|
354
359
|
|
|
355
|
-
|
|
360
|
+
2. Test locally via `npm link` or `file:` install in a demo project.
|
|
356
361
|
|
|
357
362
|
---
|
|
358
363
|
|
|
@@ -367,4 +372,4 @@ pnpm install
|
|
|
367
372
|
|
|
368
373
|
## License
|
|
369
374
|
|
|
370
|
-
[MIT](
|
|
375
|
+
[MIT](https://github.com/Rcmade/hono-docs/blob/main/LICENSE)
|
package/dist/cli/index.js
CHANGED
|
@@ -34,6 +34,7 @@ function unwrapModule(module) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// src/config/loadConfig.ts
|
|
37
|
+
import { pathToFileURL } from "url";
|
|
37
38
|
async function loadConfig(configFile) {
|
|
38
39
|
const fullPath = resolve2(process.cwd(), configFile);
|
|
39
40
|
if (!existsSync(fullPath)) {
|
|
@@ -41,7 +42,10 @@ async function loadConfig(configFile) {
|
|
|
41
42
|
}
|
|
42
43
|
let configModule;
|
|
43
44
|
try {
|
|
44
|
-
configModule = await tsImport(
|
|
45
|
+
configModule = await tsImport(
|
|
46
|
+
pathToFileURL(fullPath).href,
|
|
47
|
+
import.meta.url
|
|
48
|
+
);
|
|
45
49
|
} catch (err) {
|
|
46
50
|
throw new Error(
|
|
47
51
|
`[hono-docs] Failed to load config: ${err.message ?? String(err)}`
|
|
@@ -335,7 +339,6 @@ async function generateOpenApi({
|
|
|
335
339
|
|
|
336
340
|
// src/core/runGenerate.ts
|
|
337
341
|
async function runGenerate(configPath) {
|
|
338
|
-
console.log({ configPath });
|
|
339
342
|
const config = await loadConfig(configPath);
|
|
340
343
|
const rootPath = process.cwd();
|
|
341
344
|
console.log("Initializing ts-morph with tsConfig:", config.tsConfigPath);
|
|
@@ -434,7 +437,6 @@ yargs(hideBin(process.argv)).scriptName("hono-docs").command(
|
|
|
434
437
|
}),
|
|
435
438
|
async (argv) => {
|
|
436
439
|
try {
|
|
437
|
-
console.log(argv.config, "----------------");
|
|
438
440
|
await runGenerate(argv.config);
|
|
439
441
|
} catch (e) {
|
|
440
442
|
console.error("\u274C", e);
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/core/runGenerate.ts","../../src/config/loadConfig.ts","../../src/utils/libDir.ts","../../src/core/generateTypes.ts","../../src/utils/format.ts","../../src/core/generateOpenApi.ts","../../src/utils/buildSchema.ts","../../src/utils/parameters.ts","../../src/utils/requestBody.ts"],"sourcesContent":["#!/usr/bin/env node\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { runGenerate } from \"../core\";\n\nyargs(hideBin(process.argv))\n .scriptName(\"hono-docs\")\n .command(\n \"generate\",\n \"Generate OpenAPI JSON\",\n (y) =>\n y.option(\"config\", {\n alias: \"c\",\n type: \"string\",\n describe: \"Path to config file\",\n demandOption: true,\n default: \"./hono-docs.ts\",\n }),\n async (argv) => {\n try {\n console.log(argv.config, \"----------------\");\n await runGenerate(argv.config);\n } catch (e) {\n console.error(\"❌\", e);\n process.exit(1);\n }\n }\n )\n .demandCommand(1)\n .help()\n .parse();\n","import fs from \"node:fs\";\nimport path, { resolve } from \"node:path\";\nimport { Project } from \"ts-morph\";\nimport { loadConfig } from \"../config/loadConfig\";\nimport { generateTypes } from \"./generateTypes\";\nimport { generateOpenApi } from \"./generateOpenApi\";\nimport { Api } from \"../types\";\nimport { cleanDefaultResponse, sanitizeApiPrefix } from \"../utils/format\";\nimport { getLibDir } from \"../utils/libDir\";\n\nexport async function runGenerate(configPath: string) {\n console.log({ configPath });\n const config = await loadConfig(configPath);\n\n const rootPath = process.cwd();\n console.log(\"Initializing ts-morph with tsConfig:\", config.tsConfigPath);\n const project = new Project({\n tsConfigFilePath: resolve(rootPath, config.tsConfigPath),\n });\n\n // const isDevMode =\n // __dirname.includes(\"/src/\") || __dirname.includes(\"\\\\src\\\\\");\n\n // const libDir = isDevMode\n // ? path.resolve(__dirname, \"../../\")\n // : // : path.dirname(require.resolve(\"@rcmade/hono-docs/package.json\"));\n // path.dirname(fileURLToPath(import.meta.url));\n const libDir = getLibDir();\n console.log(\"Library root directory:\", libDir);\n\n const apis = config.apis;\n\n const snapshotOutputRoot = path.resolve(libDir, \"output/types\");\n const openAPiOutputRoot = path.resolve(libDir, \"output/openapi\");\n\n const commonParams = {\n config,\n libDir,\n project,\n rootPath,\n };\n for (const apiGroup of apis) {\n const sanitizedName = sanitizeApiPrefix(apiGroup.apiPrefix);\n\n const snapshotPath = await generateTypes({\n ...commonParams,\n apiGroup: apiGroup,\n fileName: sanitizedName,\n outputRoot: snapshotOutputRoot,\n });\n\n await generateOpenApi({\n snapshotPath,\n ...commonParams,\n fileName: sanitizedName,\n outputRoot: openAPiOutputRoot,\n });\n }\n\n const merged = {\n ...config.openApi,\n tags: [] as { name: string }[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n paths: {} as Record<string, any>,\n };\n\n for (const apiGroup of apis) {\n const name = sanitizeApiPrefix(apiGroup.apiPrefix);\n const openApiFile = path.join(openAPiOutputRoot, `${name}.json`);\n\n if (!fs.existsSync(openApiFile)) {\n console.warn(`⚠️ Missing OpenAPI file: ${openApiFile}`);\n continue;\n }\n\n const json = JSON.parse(fs.readFileSync(openApiFile, \"utf-8\"));\n merged.tags.push({ name: apiGroup.name });\n\n const customApiMap = new Map<string, Api>();\n\n if (apiGroup?.api) {\n for (const customApi of apiGroup.api) {\n const fullPath =\n path.posix\n .join(apiGroup.apiPrefix, customApi.api)\n .replace(/\\/+$/, \"\") || \"/\";\n customApiMap.set(\n `${customApi.method.toLowerCase()} ${fullPath}`,\n customApi\n );\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [pathKey, operations] of Object.entries<any>(json.paths)) {\n const prefixedPath =\n path.posix.join(apiGroup.apiPrefix, pathKey).replace(/\\/+$/, \"\") || \"/\";\n if (!merged.paths[prefixedPath]) merged.paths[prefixedPath] = {};\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [method, operation] of Object.entries<any>(operations)) {\n const opKey = `${method.toLowerCase()} ${prefixedPath}`;\n const customApi = customApiMap.get(opKey);\n\n // Override or enrich metadata if defined\n if (customApi) {\n operation.summary = customApi.summary || operation.summary;\n operation.description =\n customApi.description || operation.description;\n operation.tags =\n customApi.tag && customApi.tag.length > 0\n ? customApi.tag\n : [apiGroup.name];\n } else {\n operation.tags = operation.tags || [];\n if (!operation.tags.includes(apiGroup.name)) {\n operation.tags.push(apiGroup.name);\n }\n }\n\n cleanDefaultResponse(operation, prefixedPath, method);\n merged.paths[prefixedPath][method] = operation;\n }\n }\n }\n\n const outputPath = path.join(rootPath, config.outputs.openApiJson);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n\n fs.writeFileSync(outputPath, `${JSON.stringify(merged, null, 2)}\\n`);\n\n console.log(`✅ Final merged OpenAPI spec written to: ${outputPath}`);\n}\n","// src/cli/loadConfig.ts\nimport { resolve } from \"path\";\nimport { existsSync } from \"fs\";\n// <-- import tsImport from tsx:\nimport { tsImport } from \"tsx/esm/api\";\nimport type { HonoDocsConfig } from \"../types\";\nimport { unwrapModule } from \"../utils/libDir\";\n\nexport async function loadConfig(configFile: string): Promise<HonoDocsConfig> {\n // 1. Resolve absolute path\n const fullPath = resolve(process.cwd(), configFile);\n if (!existsSync(fullPath)) {\n throw new Error(`[hono-docs] Config file not found: ${fullPath}`);\n }\n\n // 2. Dynamically load the config via tsx's tsImport()\n let configModule: unknown;\n try {\n // tsImport(filePath, importMetaUrl) returns the loaded module\n configModule = await tsImport(fullPath, import.meta.url);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n throw new Error(\n `[hono-docs] Failed to load config: ${err.message ?? String(err)}`\n );\n }\n\n const config = unwrapModule(configModule);\n\n if (!config || typeof config !== \"object\") {\n throw new Error(\n `[hono-docs] Invalid config file. Expected an object, got: ${typeof config}`\n );\n }\n\n // console.log({ config });\n return config as HonoDocsConfig;\n}\n","// src/utils/libDir.ts\n\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Returns the root folder of the library, whether running in\n * development (src/) or installed (dist/).\n */\nexport function getLibDir(): string {\n // In CJS (__dirname is injected)\n if (typeof __dirname !== \"undefined\") {\n // When running from dist/core or dist/cli\n return resolve(__dirname, \"../../\");\n }\n // In ESM (import.meta.url)\n const __filename = fileURLToPath(import.meta.url);\n const __dirnameEsm = dirname(__filename);\n return resolve(__dirnameEsm, \"../../\");\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function unwrapModule(module: any): unknown {\n let result = module;\n while (result?.default) {\n result = result.default;\n }\n return result;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { ApiGroup, GenerateParams } from \"../types\";\nimport { normalizeImportPaths } from \"../utils/format\";\n\nexport async function generateTypes({\n config,\n project,\n rootPath,\n apiGroup,\n fileName,\n outputRoot,\n}: GenerateParams & { apiGroup: ApiGroup }) {\n fs.mkdirSync(outputRoot, { recursive: true });\n\n const outputPath = path.join(outputRoot, `${fileName}.d.ts`);\n const absInput = path.resolve(rootPath, apiGroup.appTypePath);\n\n const sourceFile = project.addSourceFileAtPath(absInput);\n const typeAliases = sourceFile.getTypeAliases();\n const interfaces = sourceFile.getInterfaces();\n\n let result = `// AUTO-GENERATED from ${apiGroup.appTypePath}\\n\\n`;\n\n typeAliases.forEach((alias) => {\n const raw = alias.getType().getText(alias);\n const clean = normalizeImportPaths(raw);\n result += `export type ${alias.getName()} = ${clean};\\n\\n`;\n });\n\n interfaces.forEach((intf) => {\n result += intf.getText() + \"\\n\\n\";\n });\n\n const preContent = config.preDefineTypeContent || \"\";\n\n fs.writeFileSync(outputPath, `${preContent}\\n${result}`, \"utf-8\");\n console.log(`✅ Wrote: ${outputPath}`);\n return { appTypePath: outputPath, name: fileName };\n}\n","export function sanitizeApiPrefix(prefix: string): string {\n return prefix\n .replace(/^\\//, \"\")\n .split(/[^a-z0-9]+/i)\n .filter(Boolean)\n .map((seg, i) =>\n i === 0\n ? seg.toLowerCase()\n : seg[0].toUpperCase() + seg.slice(1).toLowerCase()\n )\n .join(\"\");\n}\n\nexport function unwrapUnion(\n type: import(\"ts-morph\").Type\n): import(\"ts-morph\").Type[] {\n return type.isUnion() ? type.getUnionTypes() : [type];\n}\n\nexport function normalizeImportPaths(typeText: string): string {\n return typeText.replace(/from [\"'].*node_modules\\/(.*)[\"']/g, `from \"$1\"`);\n}\n\nexport function cleanDefaultResponse(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n operation: any,\n pathKey: string,\n method: string\n) {\n const defaultResponse = operation.responses?.default;\n if (!defaultResponse) return;\n\n const desc = defaultResponse.description ?? \"\";\n\n if (desc.includes(\"import(\")) {\n const content = defaultResponse.content;\n\n if (content && Object.keys(content).length > 0) {\n defaultResponse.description = \"Default fallback response\";\n console.log(\n `ℹ️ Cleaned 'default' description in ${method.toUpperCase()} ${pathKey}`\n );\n } else {\n delete operation.responses.default;\n console.log(\n `🗑️ Removed empty 'default' in ${method.toUpperCase()} ${pathKey}`\n );\n }\n }\n}\n\n\nexport function groupBy<T>(\n arr: T[],\n fn: (x: T) => string\n): Record<string, T[]> {\n return arr.reduce((acc, x) => {\n (acc[fn(x)] ||= []).push(x);\n return acc;\n }, {} as Record<string, T[]>);\n}\n","// src/core/generateOpenApi.ts\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n SyntaxKind,\n TypeLiteralNode,\n ImportTypeNode,\n TypeReferenceNode,\n TypeNode,\n ts,\n} from \"ts-morph\";\nimport type {\n AppTypeSnapshotPath,\n GenerateParams,\n OpenApiPath,\n} from \"../types\";\nimport { genParameters } from \"../utils/parameters\";\nimport { genRequestBody } from \"../utils/requestBody\";\nimport { buildSchema } from \"../utils/buildSchema\";\nimport { groupBy, unwrapUnion } from \"../utils/format\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype OpenAPI = Record<string, any>;\n\nexport async function generateOpenApi({\n config,\n snapshotPath,\n fileName,\n project,\n rootPath,\n outputRoot,\n}: // {\n// config: HonoDocsConfig;\n// snapshotPath: AppTypeSnapshotPath;\n// }\nGenerateParams & {\n snapshotPath: AppTypeSnapshotPath;\n}): Promise<OpenApiPath> {\n const sf = project.addSourceFileAtPath(\n path.resolve(rootPath, snapshotPath.appTypePath)\n );\n const aliasDecl = sf.getTypeAliasOrThrow(\"AppType\");\n\n const topTypeNode = aliasDecl.getTypeNode();\n\n let typeArgs: readonly TypeNode<ts.TypeNode>[];\n\n if (topTypeNode?.isKind(SyntaxKind.TypeReference)) {\n typeArgs = (topTypeNode as TypeReferenceNode).getTypeArguments();\n } else if (topTypeNode?.isKind(SyntaxKind.ImportType)) {\n typeArgs = (topTypeNode as ImportTypeNode).getTypeArguments();\n } else {\n throw new Error(\"AppType must be an ImportType or a TypeReference\");\n }\n\n if (typeArgs.length < 2) {\n throw new Error(\"Expected two type arguments on HonoBase\");\n }\n\n const routesNode = typeArgs[1];\n\n // Gather all TypeLiteralNodes (handle intersections)\n const literals: TypeLiteralNode[] = [];\n if (routesNode.isKind(SyntaxKind.IntersectionType)) {\n for (const tn of routesNode\n .asKind(SyntaxKind.IntersectionType)!\n .getTypeNodes()) {\n if (tn.isKind(SyntaxKind.TypeLiteral))\n literals.push(tn as TypeLiteralNode);\n }\n } else if (routesNode.isKind(SyntaxKind.TypeLiteral)) {\n literals.push(routesNode as TypeLiteralNode);\n } else {\n throw new Error(\"Routes type is not a literal or intersection of literals\");\n }\n\n const paths: OpenAPI = {};\n\n for (const lit of literals) {\n for (const member of lit.getMembers()) {\n if (!member.isKind(SyntaxKind.PropertySignature)) continue;\n const routeProp = member.asKindOrThrow(SyntaxKind.PropertySignature);\n // Extract route string and normalize to OpenAPI path syntax\n const raw = routeProp.getNameNode().getText().replace(/\"/g, \"\");\n const route = raw.replace(/:([^/]+)/g, \"{$1}\");\n if (!paths[route]) paths[route] = {};\n\n // === NEW: get the RHS TypeLiteralNode properly ===\n const tn = routeProp.getTypeNode();\n if (!tn || !tn.isKind(SyntaxKind.TypeLiteral)) continue;\n const rhs = tn as TypeLiteralNode;\n\n for (const m of rhs.getMembers()) {\n if (!m.isKind(SyntaxKind.PropertySignature)) continue;\n const methodProp = m.asKindOrThrow(SyntaxKind.PropertySignature);\n const name = methodProp.getNameNode().getText(); // e.g. \"$get\"\n const http = name.slice(1).toLowerCase(); // \"get\", \"post\", etc.\n const variants = unwrapUnion(methodProp.getType());\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const op: any = {\n summary: `Auto-generated ${http.toUpperCase()} ${route}`,\n };\n\n // parameters\n const params = genParameters(variants[0]);\n if (params.length) op.parameters = params;\n\n // requestBody\n const rb = genRequestBody(variants[0]);\n if (rb) op.requestBody = rb;\n\n // responses\n op.responses = {};\n const byStatus = groupBy(variants, (v) => {\n const s = v\n .getProperty(\"status\")!\n .getValueDeclarationOrThrow()\n .getType()\n .getText();\n return /^\\d+$/.test(s) ? s : \"default\";\n });\n for (const [code, vs] of Object.entries(byStatus)) {\n const schemas = vs.map((v) =>\n buildSchema(\n v.getProperty(\"output\")!.getValueDeclarationOrThrow().getType()\n )\n );\n const schema = schemas.length > 1 ? { oneOf: schemas } : schemas[0];\n op.responses[code] = {\n description:\n code === \"default\"\n ? `Generic status from ${vs[0]\n .getProperty(\"status\")!\n .getValueDeclarationOrThrow()\n .getType()\n .getText()}`\n : `Status ${code}`,\n content: { \"application/json\": { schema } },\n };\n }\n\n paths[route][http] = op;\n }\n }\n }\n\n const spec = {\n ...config.openApi,\n paths,\n };\n\n // write to disk\n const outputPath = path.join(outputRoot, `${fileName}.json`);\n\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, JSON.stringify(spec, null, 2), \"utf-8\");\n console.log(`✅ OpenAPI written to ${outputPath}`);\n return { openApiPath: outputPath };\n}\n","import { SyntaxKind } from \"ts-morph\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function buildSchema(type: import(\"ts-morph\").Type): any {\n if (type.isUnion()) {\n const members = type.getUnionTypes();\n const lits = members.filter((u) => u.isStringLiteral());\n const onlyNull = members.every(\n (u) => u.isStringLiteral() || u.isNull() || u.isUndefined()\n );\n if (lits.length && onlyNull) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const schema: any = {\n type: \"string\",\n enum: lits.map((u) => u.getLiteralValue()),\n };\n if (members.some((u) => u.isNull() || u.isUndefined()))\n schema.nullable = true;\n return schema;\n }\n const nonNull = members.filter((u) => !u.isNull() && !u.isUndefined());\n return { oneOf: nonNull.map(buildSchema) };\n }\n if (type.isString()) return { type: \"string\" };\n if (type.isNumber()) return { type: \"number\" };\n if (type.isBoolean()) return { type: \"boolean\" };\n if (type.isArray()) {\n return {\n type: \"array\",\n items: buildSchema(type.getArrayElementTypeOrThrow()),\n };\n }\n\n const decls = type.getSymbol()?.getDeclarations() || [];\n const isLit = decls.some(\n (d) =>\n d.getKind() === SyntaxKind.TypeLiteral ||\n d.getKind() === SyntaxKind.InterfaceDeclaration\n );\n if (!isLit) return {};\n\n const props = type\n .getProperties()\n .filter(\n (p) => p.getValueDeclaration()?.getKind() === SyntaxKind.PropertySignature\n );\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const propsMap: Record<string, any> = {};\n const req: string[] = [];\n for (const p of props) {\n const decl = p.getValueDeclarationOrThrow();\n propsMap[p.getName()] = buildSchema(decl.getType());\n if (!p.isOptional()) req.push(p.getName());\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const res: any = { type: \"object\", properties: propsMap };\n if (req.length) res.required = req;\n return res;\n}\n","import { buildSchema } from \"./buildSchema\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function genParameters(type: import(\"ts-morph\").Type): any[] {\n const input = type\n .getProperty(\"input\")\n ?.getValueDeclarationOrThrow()\n .getType();\n if (!input) return [];\n const sources = [\"query\", \"param\", \"header\", \"cookie\"];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const params: any[] = [];\n for (const src of sources) {\n const p = input.getProperty(src);\n if (!p) continue;\n const srcType = p.getValueDeclarationOrThrow().getType();\n for (const f of srcType.getProperties()) {\n const ft = f.getValueDeclarationOrThrow().getType();\n params.push({\n name: f.getName(),\n in: src === \"param\" ? \"path\" : src,\n required: !f.isOptional(),\n schema: buildSchema(ft),\n });\n }\n }\n return params;\n}\n","import { buildSchema } from \"./buildSchema\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function genRequestBody(type: import(\"ts-morph\").Type): any | null {\n const inp = type.getProperty(\"input\")?.getValueDeclarationOrThrow().getType();\n if (!inp) return null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const content: Record<string, any> = {};\n const j = inp.getProperty(\"json\");\n if (j) {\n content[\"application/json\"] = {\n schema: buildSchema(j.getValueDeclarationOrThrow().getType()),\n };\n }\n const f = inp.getProperty(\"form\");\n if (f) {\n content[\"multipart/form-data\"] = {\n schema: buildSchema(f.getValueDeclarationOrThrow().getType()),\n };\n }\n return Object.keys(content).length ? { required: true, content } : null;\n}\n"],"mappings":"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","names":["fs","path","resolve","resolve","resolve","fs","path","SyntaxKind","_a","path","SyntaxKind","fs","resolve","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/core/runGenerate.ts","../../src/config/loadConfig.ts","../../src/utils/libDir.ts","../../src/core/generateTypes.ts","../../src/utils/format.ts","../../src/core/generateOpenApi.ts","../../src/utils/buildSchema.ts","../../src/utils/parameters.ts","../../src/utils/requestBody.ts"],"sourcesContent":["#!/usr/bin/env node\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { runGenerate } from \"../core\";\n\nyargs(hideBin(process.argv))\n .scriptName(\"hono-docs\")\n .command(\n \"generate\",\n \"Generate OpenAPI JSON\",\n (y) =>\n y.option(\"config\", {\n alias: \"c\",\n type: \"string\",\n describe: \"Path to config file\",\n demandOption: true,\n default: \"./hono-docs.ts\",\n }),\n async (argv) => {\n try {\n await runGenerate(argv.config);\n } catch (e) {\n console.error(\"❌\", e);\n process.exit(1);\n }\n }\n )\n .demandCommand(1)\n .help()\n .parse();\n","import fs from \"node:fs\";\nimport path, { resolve } from \"node:path\";\nimport { Project } from \"ts-morph\";\nimport { loadConfig } from \"../config/loadConfig\";\nimport { generateTypes } from \"./generateTypes\";\nimport { generateOpenApi } from \"./generateOpenApi\";\nimport { Api } from \"../types\";\nimport { cleanDefaultResponse, sanitizeApiPrefix } from \"../utils/format\";\nimport { getLibDir } from \"../utils/libDir\";\n\nexport async function runGenerate(configPath: string) {\n const config = await loadConfig(configPath);\n const rootPath = process.cwd();\n console.log(\"Initializing ts-morph with tsConfig:\", config.tsConfigPath);\n const project = new Project({\n tsConfigFilePath: resolve(rootPath, config.tsConfigPath),\n });\n\n // const isDevMode =\n // __dirname.includes(\"/src/\") || __dirname.includes(\"\\\\src\\\\\");\n\n // const libDir = isDevMode\n // ? path.resolve(__dirname, \"../../\")\n // : // : path.dirname(require.resolve(\"@rcmade/hono-docs/package.json\"));\n // path.dirname(fileURLToPath(import.meta.url));\n const libDir = getLibDir();\n console.log(\"Library root directory:\", libDir);\n\n const apis = config.apis;\n\n const snapshotOutputRoot = path.resolve(libDir, \"output/types\");\n const openAPiOutputRoot = path.resolve(libDir, \"output/openapi\");\n\n const commonParams = {\n config,\n libDir,\n project,\n rootPath,\n };\n for (const apiGroup of apis) {\n const sanitizedName = sanitizeApiPrefix(apiGroup.apiPrefix);\n\n const snapshotPath = await generateTypes({\n ...commonParams,\n apiGroup: apiGroup,\n fileName: sanitizedName,\n outputRoot: snapshotOutputRoot,\n });\n\n await generateOpenApi({\n snapshotPath,\n ...commonParams,\n fileName: sanitizedName,\n outputRoot: openAPiOutputRoot,\n });\n }\n\n const merged = {\n ...config.openApi,\n tags: [] as { name: string }[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n paths: {} as Record<string, any>,\n };\n\n for (const apiGroup of apis) {\n const name = sanitizeApiPrefix(apiGroup.apiPrefix);\n const openApiFile = path.join(openAPiOutputRoot, `${name}.json`);\n\n if (!fs.existsSync(openApiFile)) {\n console.warn(`⚠️ Missing OpenAPI file: ${openApiFile}`);\n continue;\n }\n\n const json = JSON.parse(fs.readFileSync(openApiFile, \"utf-8\"));\n merged.tags.push({ name: apiGroup.name });\n\n const customApiMap = new Map<string, Api>();\n\n if (apiGroup?.api) {\n for (const customApi of apiGroup.api) {\n const fullPath =\n path.posix\n .join(apiGroup.apiPrefix, customApi.api)\n .replace(/\\/+$/, \"\") || \"/\";\n customApiMap.set(\n `${customApi.method.toLowerCase()} ${fullPath}`,\n customApi\n );\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [pathKey, operations] of Object.entries<any>(json.paths)) {\n const prefixedPath =\n path.posix.join(apiGroup.apiPrefix, pathKey).replace(/\\/+$/, \"\") || \"/\";\n if (!merged.paths[prefixedPath]) merged.paths[prefixedPath] = {};\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [method, operation] of Object.entries<any>(operations)) {\n const opKey = `${method.toLowerCase()} ${prefixedPath}`;\n const customApi = customApiMap.get(opKey);\n\n // Override or enrich metadata if defined\n if (customApi) {\n operation.summary = customApi.summary || operation.summary;\n operation.description =\n customApi.description || operation.description;\n operation.tags =\n customApi.tag && customApi.tag.length > 0\n ? customApi.tag\n : [apiGroup.name];\n } else {\n operation.tags = operation.tags || [];\n if (!operation.tags.includes(apiGroup.name)) {\n operation.tags.push(apiGroup.name);\n }\n }\n\n cleanDefaultResponse(operation, prefixedPath, method);\n merged.paths[prefixedPath][method] = operation;\n }\n }\n }\n\n const outputPath = path.join(rootPath, config.outputs.openApiJson);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n\n fs.writeFileSync(outputPath, `${JSON.stringify(merged, null, 2)}\\n`);\n\n console.log(`✅ Final merged OpenAPI spec written to: ${outputPath}`);\n}\n","import { resolve } from \"path\";\nimport { existsSync } from \"fs\";\nimport { tsImport } from \"tsx/esm/api\";\nimport type { HonoDocsConfig } from \"../types\";\nimport { unwrapModule } from \"../utils/libDir\";\nimport { pathToFileURL } from \"url\";\n\nexport async function loadConfig(configFile: string): Promise<HonoDocsConfig> {\n // 1. Resolve absolute path\n const fullPath = resolve(process.cwd(), configFile);\n if (!existsSync(fullPath)) {\n throw new Error(`[hono-docs] Config file not found: ${fullPath}`);\n }\n\n // 2. Dynamically load the config via tsx's tsImport()\n let configModule: unknown;\n try {\n configModule = await tsImport(\n pathToFileURL(fullPath).href,\n import.meta.url\n );\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n throw new Error(\n `[hono-docs] Failed to load config: ${err.message ?? String(err)}`\n );\n }\n\n const config = unwrapModule(configModule);\n\n if (!config || typeof config !== \"object\") {\n throw new Error(\n `[hono-docs] Invalid config file. Expected an object, got: ${typeof config}`\n );\n }\n\n // console.log({ config });\n return config as HonoDocsConfig;\n}\n","// src/utils/libDir.ts\n\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Returns the root folder of the library, whether running in\n * development (src/) or installed (dist/).\n */\nexport function getLibDir(): string {\n // In CJS (__dirname is injected)\n if (typeof __dirname !== \"undefined\") {\n // When running from dist/core or dist/cli\n return resolve(__dirname, \"../../\");\n }\n // In ESM (import.meta.url)\n const __filename = fileURLToPath(import.meta.url);\n const __dirnameEsm = dirname(__filename);\n return resolve(__dirnameEsm, \"../../\");\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function unwrapModule(module: any): unknown {\n let result = module;\n while (result?.default) {\n result = result.default;\n }\n return result;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { ApiGroup, GenerateParams } from \"../types\";\nimport { normalizeImportPaths } from \"../utils/format\";\n\nexport async function generateTypes({\n config,\n project,\n rootPath,\n apiGroup,\n fileName,\n outputRoot,\n}: GenerateParams & { apiGroup: ApiGroup }) {\n fs.mkdirSync(outputRoot, { recursive: true });\n\n const outputPath = path.join(outputRoot, `${fileName}.d.ts`);\n const absInput = path.resolve(rootPath, apiGroup.appTypePath);\n\n const sourceFile = project.addSourceFileAtPath(absInput);\n const typeAliases = sourceFile.getTypeAliases();\n const interfaces = sourceFile.getInterfaces();\n\n let result = `// AUTO-GENERATED from ${apiGroup.appTypePath}\\n\\n`;\n\n typeAliases.forEach((alias) => {\n const raw = alias.getType().getText(alias);\n const clean = normalizeImportPaths(raw);\n result += `export type ${alias.getName()} = ${clean};\\n\\n`;\n });\n\n interfaces.forEach((intf) => {\n result += intf.getText() + \"\\n\\n\";\n });\n\n const preContent = config.preDefineTypeContent || \"\";\n\n fs.writeFileSync(outputPath, `${preContent}\\n${result}`, \"utf-8\");\n console.log(`✅ Wrote: ${outputPath}`);\n return { appTypePath: outputPath, name: fileName };\n}\n","export function sanitizeApiPrefix(prefix: string): string {\n return prefix\n .replace(/^\\//, \"\")\n .split(/[^a-z0-9]+/i)\n .filter(Boolean)\n .map((seg, i) =>\n i === 0\n ? seg.toLowerCase()\n : seg[0].toUpperCase() + seg.slice(1).toLowerCase()\n )\n .join(\"\");\n}\n\nexport function unwrapUnion(\n type: import(\"ts-morph\").Type\n): import(\"ts-morph\").Type[] {\n return type.isUnion() ? type.getUnionTypes() : [type];\n}\n\nexport function normalizeImportPaths(typeText: string): string {\n return typeText.replace(/from [\"'].*node_modules\\/(.*)[\"']/g, `from \"$1\"`);\n}\n\nexport function cleanDefaultResponse(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n operation: any,\n pathKey: string,\n method: string\n) {\n const defaultResponse = operation.responses?.default;\n if (!defaultResponse) return;\n\n const desc = defaultResponse.description ?? \"\";\n\n if (desc.includes(\"import(\")) {\n const content = defaultResponse.content;\n\n if (content && Object.keys(content).length > 0) {\n defaultResponse.description = \"Default fallback response\";\n console.log(\n `ℹ️ Cleaned 'default' description in ${method.toUpperCase()} ${pathKey}`\n );\n } else {\n delete operation.responses.default;\n console.log(\n `🗑️ Removed empty 'default' in ${method.toUpperCase()} ${pathKey}`\n );\n }\n }\n}\n\n\nexport function groupBy<T>(\n arr: T[],\n fn: (x: T) => string\n): Record<string, T[]> {\n return arr.reduce((acc, x) => {\n (acc[fn(x)] ||= []).push(x);\n return acc;\n }, {} as Record<string, T[]>);\n}\n","// src/core/generateOpenApi.ts\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n SyntaxKind,\n TypeLiteralNode,\n ImportTypeNode,\n TypeReferenceNode,\n TypeNode,\n ts,\n} from \"ts-morph\";\nimport type {\n AppTypeSnapshotPath,\n GenerateParams,\n OpenApiPath,\n} from \"../types\";\nimport { genParameters } from \"../utils/parameters\";\nimport { genRequestBody } from \"../utils/requestBody\";\nimport { buildSchema } from \"../utils/buildSchema\";\nimport { groupBy, unwrapUnion } from \"../utils/format\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype OpenAPI = Record<string, any>;\n\nexport async function generateOpenApi({\n config,\n snapshotPath,\n fileName,\n project,\n rootPath,\n outputRoot,\n}: // {\n// config: HonoDocsConfig;\n// snapshotPath: AppTypeSnapshotPath;\n// }\nGenerateParams & {\n snapshotPath: AppTypeSnapshotPath;\n}): Promise<OpenApiPath> {\n const sf = project.addSourceFileAtPath(\n path.resolve(rootPath, snapshotPath.appTypePath)\n );\n const aliasDecl = sf.getTypeAliasOrThrow(\"AppType\");\n\n const topTypeNode = aliasDecl.getTypeNode();\n\n let typeArgs: readonly TypeNode<ts.TypeNode>[];\n\n if (topTypeNode?.isKind(SyntaxKind.TypeReference)) {\n typeArgs = (topTypeNode as TypeReferenceNode).getTypeArguments();\n } else if (topTypeNode?.isKind(SyntaxKind.ImportType)) {\n typeArgs = (topTypeNode as ImportTypeNode).getTypeArguments();\n } else {\n throw new Error(\"AppType must be an ImportType or a TypeReference\");\n }\n\n if (typeArgs.length < 2) {\n throw new Error(\"Expected two type arguments on HonoBase\");\n }\n\n const routesNode = typeArgs[1];\n\n // Gather all TypeLiteralNodes (handle intersections)\n const literals: TypeLiteralNode[] = [];\n if (routesNode.isKind(SyntaxKind.IntersectionType)) {\n for (const tn of routesNode\n .asKind(SyntaxKind.IntersectionType)!\n .getTypeNodes()) {\n if (tn.isKind(SyntaxKind.TypeLiteral))\n literals.push(tn as TypeLiteralNode);\n }\n } else if (routesNode.isKind(SyntaxKind.TypeLiteral)) {\n literals.push(routesNode as TypeLiteralNode);\n } else {\n throw new Error(\"Routes type is not a literal or intersection of literals\");\n }\n\n const paths: OpenAPI = {};\n\n for (const lit of literals) {\n for (const member of lit.getMembers()) {\n if (!member.isKind(SyntaxKind.PropertySignature)) continue;\n const routeProp = member.asKindOrThrow(SyntaxKind.PropertySignature);\n // Extract route string and normalize to OpenAPI path syntax\n const raw = routeProp.getNameNode().getText().replace(/\"/g, \"\");\n const route = raw.replace(/:([^/]+)/g, \"{$1}\");\n if (!paths[route]) paths[route] = {};\n\n // === NEW: get the RHS TypeLiteralNode properly ===\n const tn = routeProp.getTypeNode();\n if (!tn || !tn.isKind(SyntaxKind.TypeLiteral)) continue;\n const rhs = tn as TypeLiteralNode;\n\n for (const m of rhs.getMembers()) {\n if (!m.isKind(SyntaxKind.PropertySignature)) continue;\n const methodProp = m.asKindOrThrow(SyntaxKind.PropertySignature);\n const name = methodProp.getNameNode().getText(); // e.g. \"$get\"\n const http = name.slice(1).toLowerCase(); // \"get\", \"post\", etc.\n const variants = unwrapUnion(methodProp.getType());\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const op: any = {\n summary: `Auto-generated ${http.toUpperCase()} ${route}`,\n };\n\n // parameters\n const params = genParameters(variants[0]);\n if (params.length) op.parameters = params;\n\n // requestBody\n const rb = genRequestBody(variants[0]);\n if (rb) op.requestBody = rb;\n\n // responses\n op.responses = {};\n const byStatus = groupBy(variants, (v) => {\n const s = v\n .getProperty(\"status\")!\n .getValueDeclarationOrThrow()\n .getType()\n .getText();\n return /^\\d+$/.test(s) ? s : \"default\";\n });\n for (const [code, vs] of Object.entries(byStatus)) {\n const schemas = vs.map((v) =>\n buildSchema(\n v.getProperty(\"output\")!.getValueDeclarationOrThrow().getType()\n )\n );\n const schema = schemas.length > 1 ? { oneOf: schemas } : schemas[0];\n op.responses[code] = {\n description:\n code === \"default\"\n ? `Generic status from ${vs[0]\n .getProperty(\"status\")!\n .getValueDeclarationOrThrow()\n .getType()\n .getText()}`\n : `Status ${code}`,\n content: { \"application/json\": { schema } },\n };\n }\n\n paths[route][http] = op;\n }\n }\n }\n\n const spec = {\n ...config.openApi,\n paths,\n };\n\n // write to disk\n const outputPath = path.join(outputRoot, `${fileName}.json`);\n\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, JSON.stringify(spec, null, 2), \"utf-8\");\n console.log(`✅ OpenAPI written to ${outputPath}`);\n return { openApiPath: outputPath };\n}\n","import { SyntaxKind } from \"ts-morph\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function buildSchema(type: import(\"ts-morph\").Type): any {\n if (type.isUnion()) {\n const members = type.getUnionTypes();\n const lits = members.filter((u) => u.isStringLiteral());\n const onlyNull = members.every(\n (u) => u.isStringLiteral() || u.isNull() || u.isUndefined()\n );\n if (lits.length && onlyNull) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const schema: any = {\n type: \"string\",\n enum: lits.map((u) => u.getLiteralValue()),\n };\n if (members.some((u) => u.isNull() || u.isUndefined()))\n schema.nullable = true;\n return schema;\n }\n const nonNull = members.filter((u) => !u.isNull() && !u.isUndefined());\n return { oneOf: nonNull.map(buildSchema) };\n }\n if (type.isString()) return { type: \"string\" };\n if (type.isNumber()) return { type: \"number\" };\n if (type.isBoolean()) return { type: \"boolean\" };\n if (type.isArray()) {\n return {\n type: \"array\",\n items: buildSchema(type.getArrayElementTypeOrThrow()),\n };\n }\n\n const decls = type.getSymbol()?.getDeclarations() || [];\n const isLit = decls.some(\n (d) =>\n d.getKind() === SyntaxKind.TypeLiteral ||\n d.getKind() === SyntaxKind.InterfaceDeclaration\n );\n if (!isLit) return {};\n\n const props = type\n .getProperties()\n .filter(\n (p) => p.getValueDeclaration()?.getKind() === SyntaxKind.PropertySignature\n );\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const propsMap: Record<string, any> = {};\n const req: string[] = [];\n for (const p of props) {\n const decl = p.getValueDeclarationOrThrow();\n propsMap[p.getName()] = buildSchema(decl.getType());\n if (!p.isOptional()) req.push(p.getName());\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const res: any = { type: \"object\", properties: propsMap };\n if (req.length) res.required = req;\n return res;\n}\n","import { buildSchema } from \"./buildSchema\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function genParameters(type: import(\"ts-morph\").Type): any[] {\n const input = type\n .getProperty(\"input\")\n ?.getValueDeclarationOrThrow()\n .getType();\n if (!input) return [];\n const sources = [\"query\", \"param\", \"header\", \"cookie\"];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const params: any[] = [];\n for (const src of sources) {\n const p = input.getProperty(src);\n if (!p) continue;\n const srcType = p.getValueDeclarationOrThrow().getType();\n for (const f of srcType.getProperties()) {\n const ft = f.getValueDeclarationOrThrow().getType();\n params.push({\n name: f.getName(),\n in: src === \"param\" ? \"path\" : src,\n required: !f.isOptional(),\n schema: buildSchema(ft),\n });\n }\n }\n return params;\n}\n","import { buildSchema } from \"./buildSchema\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function genRequestBody(type: import(\"ts-morph\").Type): any | null {\n const inp = type.getProperty(\"input\")?.getValueDeclarationOrThrow().getType();\n if (!inp) return null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const content: Record<string, any> = {};\n const j = inp.getProperty(\"json\");\n if (j) {\n content[\"application/json\"] = {\n schema: buildSchema(j.getValueDeclarationOrThrow().getType()),\n };\n }\n const f = inp.getProperty(\"form\");\n if (f) {\n content[\"multipart/form-data\"] = {\n schema: buildSchema(f.getValueDeclarationOrThrow().getType()),\n };\n }\n return Object.keys(content).length ? { required: true, content } : null;\n}\n"],"mappings":"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","names":["fs","path","resolve","resolve","resolve","fs","path","SyntaxKind","_a","path","SyntaxKind","fs","resolve","path","fs"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,26 +1,86 @@
|
|
|
1
1
|
import { OpenAPIV3 } from 'openapi-types';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* The base OpenAPI configuration, excluding dynamically generated fields.
|
|
5
|
+
*
|
|
6
|
+
* This config maps directly to the OpenAPI 3.0 `Document` type,
|
|
7
|
+
* excluding `paths`, `components`, and `tags` which are generated.
|
|
8
|
+
*/
|
|
3
9
|
type OpenAPIConfig = Omit<OpenAPIV3.Document, "paths" | "components" | "tags">;
|
|
10
|
+
/**
|
|
11
|
+
* Describes a single HTTP API endpoint under a route.
|
|
12
|
+
*/
|
|
4
13
|
type Api = {
|
|
14
|
+
/**
|
|
15
|
+
* The path of the API (excluding any prefix), e.g., `/devices/d/{deviceId}`.
|
|
16
|
+
*/
|
|
5
17
|
api: string;
|
|
18
|
+
/**
|
|
19
|
+
* Optional summary displayed in generated docs.
|
|
20
|
+
*/
|
|
6
21
|
summary?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Detailed description of the endpoint for OpenAPI docs.
|
|
24
|
+
*/
|
|
7
25
|
description?: string;
|
|
26
|
+
/**
|
|
27
|
+
* OpenAPI tags used to group this endpoint in the docs.
|
|
28
|
+
*/
|
|
8
29
|
tag?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* HTTP method supported by this endpoint.
|
|
32
|
+
*/
|
|
9
33
|
method: "get" | "post" | "put" | "patch" | "delete";
|
|
10
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Represents a group of related API routes, each with a shared prefix and appType.
|
|
37
|
+
*/
|
|
11
38
|
type ApiGroup = {
|
|
39
|
+
/**
|
|
40
|
+
* URL prefix applied to all `api` paths within this group (e.g., `/auth`).
|
|
41
|
+
*/
|
|
12
42
|
apiPrefix: string;
|
|
43
|
+
/**
|
|
44
|
+
* File path to the module exporting `AppType = typeof routeInstance`.
|
|
45
|
+
*/
|
|
13
46
|
appTypePath: string;
|
|
47
|
+
/**
|
|
48
|
+
* Human-readable name for the group, shown in logs and docs.
|
|
49
|
+
*/
|
|
14
50
|
name: string;
|
|
51
|
+
/**
|
|
52
|
+
* Optional list of specific routes to include; if omitted, all from AppType are used.
|
|
53
|
+
*/
|
|
15
54
|
api?: Api[];
|
|
16
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Top-level configuration object for hono-docs.
|
|
58
|
+
*/
|
|
17
59
|
type HonoDocsConfig = {
|
|
60
|
+
/**
|
|
61
|
+
* Path to your `tsconfig.json`.
|
|
62
|
+
*/
|
|
18
63
|
tsConfigPath: string;
|
|
64
|
+
/**
|
|
65
|
+
* Static parts of the OpenAPI document (title, version, servers, etc.).
|
|
66
|
+
*/
|
|
19
67
|
openApi: OpenAPIConfig;
|
|
68
|
+
/**
|
|
69
|
+
* Output configuration for generated files.
|
|
70
|
+
*/
|
|
20
71
|
outputs: {
|
|
72
|
+
/**
|
|
73
|
+
* File path where the generated `openapi.json` should be saved.
|
|
74
|
+
*/
|
|
21
75
|
openApiJson: string;
|
|
22
76
|
};
|
|
77
|
+
/**
|
|
78
|
+
* List of API groups (routes) to generate docs for.
|
|
79
|
+
*/
|
|
23
80
|
apis: ApiGroup[];
|
|
81
|
+
/**
|
|
82
|
+
* Optional raw string content to inject at the top of each generated `.d.ts` snapshot.
|
|
83
|
+
*/
|
|
24
84
|
preDefineTypeContent?: string;
|
|
25
85
|
};
|
|
26
86
|
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ function unwrapModule(module) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// src/config/loadConfig.ts
|
|
36
|
+
import { pathToFileURL } from "url";
|
|
36
37
|
async function loadConfig(configFile) {
|
|
37
38
|
const fullPath = resolve2(process.cwd(), configFile);
|
|
38
39
|
if (!existsSync(fullPath)) {
|
|
@@ -40,7 +41,10 @@ async function loadConfig(configFile) {
|
|
|
40
41
|
}
|
|
41
42
|
let configModule;
|
|
42
43
|
try {
|
|
43
|
-
configModule = await tsImport(
|
|
44
|
+
configModule = await tsImport(
|
|
45
|
+
pathToFileURL(fullPath).href,
|
|
46
|
+
import.meta.url
|
|
47
|
+
);
|
|
44
48
|
} catch (err) {
|
|
45
49
|
throw new Error(
|
|
46
50
|
`[hono-docs] Failed to load config: ${err.message ?? String(err)}`
|
|
@@ -334,7 +338,6 @@ async function generateOpenApi({
|
|
|
334
338
|
|
|
335
339
|
// src/core/runGenerate.ts
|
|
336
340
|
async function runGenerate(configPath) {
|
|
337
|
-
console.log({ configPath });
|
|
338
341
|
const config = await loadConfig(configPath);
|
|
339
342
|
const rootPath = process.cwd();
|
|
340
343
|
console.log("Initializing ts-morph with tsConfig:", config.tsConfigPath);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/index.ts","../src/core/runGenerate.ts","../src/config/loadConfig.ts","../src/utils/libDir.ts","../src/core/generateTypes.ts","../src/utils/format.ts","../src/core/generateOpenApi.ts","../src/utils/buildSchema.ts","../src/utils/parameters.ts","../src/utils/requestBody.ts"],"sourcesContent":["// src/config/index.ts\nimport type { HonoDocsConfig } from \"../types\";\n\n/**\n * A no‑op helper to get TS inference and IDE support when\n * writing `export default defineConfig({...})` in userland.\n */\nexport function defineConfig(config: HonoDocsConfig): HonoDocsConfig {\n return config;\n}\n","import fs from \"node:fs\";\nimport path, { resolve } from \"node:path\";\nimport { Project } from \"ts-morph\";\nimport { loadConfig } from \"../config/loadConfig\";\nimport { generateTypes } from \"./generateTypes\";\nimport { generateOpenApi } from \"./generateOpenApi\";\nimport { Api } from \"../types\";\nimport { cleanDefaultResponse, sanitizeApiPrefix } from \"../utils/format\";\nimport { getLibDir } from \"../utils/libDir\";\n\nexport async function runGenerate(configPath: string) {\n console.log({ configPath });\n const config = await loadConfig(configPath);\n\n const rootPath = process.cwd();\n console.log(\"Initializing ts-morph with tsConfig:\", config.tsConfigPath);\n const project = new Project({\n tsConfigFilePath: resolve(rootPath, config.tsConfigPath),\n });\n\n // const isDevMode =\n // __dirname.includes(\"/src/\") || __dirname.includes(\"\\\\src\\\\\");\n\n // const libDir = isDevMode\n // ? path.resolve(__dirname, \"../../\")\n // : // : path.dirname(require.resolve(\"@rcmade/hono-docs/package.json\"));\n // path.dirname(fileURLToPath(import.meta.url));\n const libDir = getLibDir();\n console.log(\"Library root directory:\", libDir);\n\n const apis = config.apis;\n\n const snapshotOutputRoot = path.resolve(libDir, \"output/types\");\n const openAPiOutputRoot = path.resolve(libDir, \"output/openapi\");\n\n const commonParams = {\n config,\n libDir,\n project,\n rootPath,\n };\n for (const apiGroup of apis) {\n const sanitizedName = sanitizeApiPrefix(apiGroup.apiPrefix);\n\n const snapshotPath = await generateTypes({\n ...commonParams,\n apiGroup: apiGroup,\n fileName: sanitizedName,\n outputRoot: snapshotOutputRoot,\n });\n\n await generateOpenApi({\n snapshotPath,\n ...commonParams,\n fileName: sanitizedName,\n outputRoot: openAPiOutputRoot,\n });\n }\n\n const merged = {\n ...config.openApi,\n tags: [] as { name: string }[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n paths: {} as Record<string, any>,\n };\n\n for (const apiGroup of apis) {\n const name = sanitizeApiPrefix(apiGroup.apiPrefix);\n const openApiFile = path.join(openAPiOutputRoot, `${name}.json`);\n\n if (!fs.existsSync(openApiFile)) {\n console.warn(`⚠️ Missing OpenAPI file: ${openApiFile}`);\n continue;\n }\n\n const json = JSON.parse(fs.readFileSync(openApiFile, \"utf-8\"));\n merged.tags.push({ name: apiGroup.name });\n\n const customApiMap = new Map<string, Api>();\n\n if (apiGroup?.api) {\n for (const customApi of apiGroup.api) {\n const fullPath =\n path.posix\n .join(apiGroup.apiPrefix, customApi.api)\n .replace(/\\/+$/, \"\") || \"/\";\n customApiMap.set(\n `${customApi.method.toLowerCase()} ${fullPath}`,\n customApi\n );\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [pathKey, operations] of Object.entries<any>(json.paths)) {\n const prefixedPath =\n path.posix.join(apiGroup.apiPrefix, pathKey).replace(/\\/+$/, \"\") || \"/\";\n if (!merged.paths[prefixedPath]) merged.paths[prefixedPath] = {};\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [method, operation] of Object.entries<any>(operations)) {\n const opKey = `${method.toLowerCase()} ${prefixedPath}`;\n const customApi = customApiMap.get(opKey);\n\n // Override or enrich metadata if defined\n if (customApi) {\n operation.summary = customApi.summary || operation.summary;\n operation.description =\n customApi.description || operation.description;\n operation.tags =\n customApi.tag && customApi.tag.length > 0\n ? customApi.tag\n : [apiGroup.name];\n } else {\n operation.tags = operation.tags || [];\n if (!operation.tags.includes(apiGroup.name)) {\n operation.tags.push(apiGroup.name);\n }\n }\n\n cleanDefaultResponse(operation, prefixedPath, method);\n merged.paths[prefixedPath][method] = operation;\n }\n }\n }\n\n const outputPath = path.join(rootPath, config.outputs.openApiJson);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n\n fs.writeFileSync(outputPath, `${JSON.stringify(merged, null, 2)}\\n`);\n\n console.log(`✅ Final merged OpenAPI spec written to: ${outputPath}`);\n}\n","// src/cli/loadConfig.ts\nimport { resolve } from \"path\";\nimport { existsSync } from \"fs\";\n// <-- import tsImport from tsx:\nimport { tsImport } from \"tsx/esm/api\";\nimport type { HonoDocsConfig } from \"../types\";\nimport { unwrapModule } from \"../utils/libDir\";\n\nexport async function loadConfig(configFile: string): Promise<HonoDocsConfig> {\n // 1. Resolve absolute path\n const fullPath = resolve(process.cwd(), configFile);\n if (!existsSync(fullPath)) {\n throw new Error(`[hono-docs] Config file not found: ${fullPath}`);\n }\n\n // 2. Dynamically load the config via tsx's tsImport()\n let configModule: unknown;\n try {\n // tsImport(filePath, importMetaUrl) returns the loaded module\n configModule = await tsImport(fullPath, import.meta.url);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n throw new Error(\n `[hono-docs] Failed to load config: ${err.message ?? String(err)}`\n );\n }\n\n const config = unwrapModule(configModule);\n\n if (!config || typeof config !== \"object\") {\n throw new Error(\n `[hono-docs] Invalid config file. Expected an object, got: ${typeof config}`\n );\n }\n\n // console.log({ config });\n return config as HonoDocsConfig;\n}\n","// src/utils/libDir.ts\n\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Returns the root folder of the library, whether running in\n * development (src/) or installed (dist/).\n */\nexport function getLibDir(): string {\n // In CJS (__dirname is injected)\n if (typeof __dirname !== \"undefined\") {\n // When running from dist/core or dist/cli\n return resolve(__dirname, \"../../\");\n }\n // In ESM (import.meta.url)\n const __filename = fileURLToPath(import.meta.url);\n const __dirnameEsm = dirname(__filename);\n return resolve(__dirnameEsm, \"../../\");\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function unwrapModule(module: any): unknown {\n let result = module;\n while (result?.default) {\n result = result.default;\n }\n return result;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { ApiGroup, GenerateParams } from \"../types\";\nimport { normalizeImportPaths } from \"../utils/format\";\n\nexport async function generateTypes({\n config,\n project,\n rootPath,\n apiGroup,\n fileName,\n outputRoot,\n}: GenerateParams & { apiGroup: ApiGroup }) {\n fs.mkdirSync(outputRoot, { recursive: true });\n\n const outputPath = path.join(outputRoot, `${fileName}.d.ts`);\n const absInput = path.resolve(rootPath, apiGroup.appTypePath);\n\n const sourceFile = project.addSourceFileAtPath(absInput);\n const typeAliases = sourceFile.getTypeAliases();\n const interfaces = sourceFile.getInterfaces();\n\n let result = `// AUTO-GENERATED from ${apiGroup.appTypePath}\\n\\n`;\n\n typeAliases.forEach((alias) => {\n const raw = alias.getType().getText(alias);\n const clean = normalizeImportPaths(raw);\n result += `export type ${alias.getName()} = ${clean};\\n\\n`;\n });\n\n interfaces.forEach((intf) => {\n result += intf.getText() + \"\\n\\n\";\n });\n\n const preContent = config.preDefineTypeContent || \"\";\n\n fs.writeFileSync(outputPath, `${preContent}\\n${result}`, \"utf-8\");\n console.log(`✅ Wrote: ${outputPath}`);\n return { appTypePath: outputPath, name: fileName };\n}\n","export function sanitizeApiPrefix(prefix: string): string {\n return prefix\n .replace(/^\\//, \"\")\n .split(/[^a-z0-9]+/i)\n .filter(Boolean)\n .map((seg, i) =>\n i === 0\n ? seg.toLowerCase()\n : seg[0].toUpperCase() + seg.slice(1).toLowerCase()\n )\n .join(\"\");\n}\n\nexport function unwrapUnion(\n type: import(\"ts-morph\").Type\n): import(\"ts-morph\").Type[] {\n return type.isUnion() ? type.getUnionTypes() : [type];\n}\n\nexport function normalizeImportPaths(typeText: string): string {\n return typeText.replace(/from [\"'].*node_modules\\/(.*)[\"']/g, `from \"$1\"`);\n}\n\nexport function cleanDefaultResponse(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n operation: any,\n pathKey: string,\n method: string\n) {\n const defaultResponse = operation.responses?.default;\n if (!defaultResponse) return;\n\n const desc = defaultResponse.description ?? \"\";\n\n if (desc.includes(\"import(\")) {\n const content = defaultResponse.content;\n\n if (content && Object.keys(content).length > 0) {\n defaultResponse.description = \"Default fallback response\";\n console.log(\n `ℹ️ Cleaned 'default' description in ${method.toUpperCase()} ${pathKey}`\n );\n } else {\n delete operation.responses.default;\n console.log(\n `🗑️ Removed empty 'default' in ${method.toUpperCase()} ${pathKey}`\n );\n }\n }\n}\n\n\nexport function groupBy<T>(\n arr: T[],\n fn: (x: T) => string\n): Record<string, T[]> {\n return arr.reduce((acc, x) => {\n (acc[fn(x)] ||= []).push(x);\n return acc;\n }, {} as Record<string, T[]>);\n}\n","// src/core/generateOpenApi.ts\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n SyntaxKind,\n TypeLiteralNode,\n ImportTypeNode,\n TypeReferenceNode,\n TypeNode,\n ts,\n} from \"ts-morph\";\nimport type {\n AppTypeSnapshotPath,\n GenerateParams,\n OpenApiPath,\n} from \"../types\";\nimport { genParameters } from \"../utils/parameters\";\nimport { genRequestBody } from \"../utils/requestBody\";\nimport { buildSchema } from \"../utils/buildSchema\";\nimport { groupBy, unwrapUnion } from \"../utils/format\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype OpenAPI = Record<string, any>;\n\nexport async function generateOpenApi({\n config,\n snapshotPath,\n fileName,\n project,\n rootPath,\n outputRoot,\n}: // {\n// config: HonoDocsConfig;\n// snapshotPath: AppTypeSnapshotPath;\n// }\nGenerateParams & {\n snapshotPath: AppTypeSnapshotPath;\n}): Promise<OpenApiPath> {\n const sf = project.addSourceFileAtPath(\n path.resolve(rootPath, snapshotPath.appTypePath)\n );\n const aliasDecl = sf.getTypeAliasOrThrow(\"AppType\");\n\n const topTypeNode = aliasDecl.getTypeNode();\n\n let typeArgs: readonly TypeNode<ts.TypeNode>[];\n\n if (topTypeNode?.isKind(SyntaxKind.TypeReference)) {\n typeArgs = (topTypeNode as TypeReferenceNode).getTypeArguments();\n } else if (topTypeNode?.isKind(SyntaxKind.ImportType)) {\n typeArgs = (topTypeNode as ImportTypeNode).getTypeArguments();\n } else {\n throw new Error(\"AppType must be an ImportType or a TypeReference\");\n }\n\n if (typeArgs.length < 2) {\n throw new Error(\"Expected two type arguments on HonoBase\");\n }\n\n const routesNode = typeArgs[1];\n\n // Gather all TypeLiteralNodes (handle intersections)\n const literals: TypeLiteralNode[] = [];\n if (routesNode.isKind(SyntaxKind.IntersectionType)) {\n for (const tn of routesNode\n .asKind(SyntaxKind.IntersectionType)!\n .getTypeNodes()) {\n if (tn.isKind(SyntaxKind.TypeLiteral))\n literals.push(tn as TypeLiteralNode);\n }\n } else if (routesNode.isKind(SyntaxKind.TypeLiteral)) {\n literals.push(routesNode as TypeLiteralNode);\n } else {\n throw new Error(\"Routes type is not a literal or intersection of literals\");\n }\n\n const paths: OpenAPI = {};\n\n for (const lit of literals) {\n for (const member of lit.getMembers()) {\n if (!member.isKind(SyntaxKind.PropertySignature)) continue;\n const routeProp = member.asKindOrThrow(SyntaxKind.PropertySignature);\n // Extract route string and normalize to OpenAPI path syntax\n const raw = routeProp.getNameNode().getText().replace(/\"/g, \"\");\n const route = raw.replace(/:([^/]+)/g, \"{$1}\");\n if (!paths[route]) paths[route] = {};\n\n // === NEW: get the RHS TypeLiteralNode properly ===\n const tn = routeProp.getTypeNode();\n if (!tn || !tn.isKind(SyntaxKind.TypeLiteral)) continue;\n const rhs = tn as TypeLiteralNode;\n\n for (const m of rhs.getMembers()) {\n if (!m.isKind(SyntaxKind.PropertySignature)) continue;\n const methodProp = m.asKindOrThrow(SyntaxKind.PropertySignature);\n const name = methodProp.getNameNode().getText(); // e.g. \"$get\"\n const http = name.slice(1).toLowerCase(); // \"get\", \"post\", etc.\n const variants = unwrapUnion(methodProp.getType());\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const op: any = {\n summary: `Auto-generated ${http.toUpperCase()} ${route}`,\n };\n\n // parameters\n const params = genParameters(variants[0]);\n if (params.length) op.parameters = params;\n\n // requestBody\n const rb = genRequestBody(variants[0]);\n if (rb) op.requestBody = rb;\n\n // responses\n op.responses = {};\n const byStatus = groupBy(variants, (v) => {\n const s = v\n .getProperty(\"status\")!\n .getValueDeclarationOrThrow()\n .getType()\n .getText();\n return /^\\d+$/.test(s) ? s : \"default\";\n });\n for (const [code, vs] of Object.entries(byStatus)) {\n const schemas = vs.map((v) =>\n buildSchema(\n v.getProperty(\"output\")!.getValueDeclarationOrThrow().getType()\n )\n );\n const schema = schemas.length > 1 ? { oneOf: schemas } : schemas[0];\n op.responses[code] = {\n description:\n code === \"default\"\n ? `Generic status from ${vs[0]\n .getProperty(\"status\")!\n .getValueDeclarationOrThrow()\n .getType()\n .getText()}`\n : `Status ${code}`,\n content: { \"application/json\": { schema } },\n };\n }\n\n paths[route][http] = op;\n }\n }\n }\n\n const spec = {\n ...config.openApi,\n paths,\n };\n\n // write to disk\n const outputPath = path.join(outputRoot, `${fileName}.json`);\n\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, JSON.stringify(spec, null, 2), \"utf-8\");\n console.log(`✅ OpenAPI written to ${outputPath}`);\n return { openApiPath: outputPath };\n}\n","import { SyntaxKind } from \"ts-morph\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function buildSchema(type: import(\"ts-morph\").Type): any {\n if (type.isUnion()) {\n const members = type.getUnionTypes();\n const lits = members.filter((u) => u.isStringLiteral());\n const onlyNull = members.every(\n (u) => u.isStringLiteral() || u.isNull() || u.isUndefined()\n );\n if (lits.length && onlyNull) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const schema: any = {\n type: \"string\",\n enum: lits.map((u) => u.getLiteralValue()),\n };\n if (members.some((u) => u.isNull() || u.isUndefined()))\n schema.nullable = true;\n return schema;\n }\n const nonNull = members.filter((u) => !u.isNull() && !u.isUndefined());\n return { oneOf: nonNull.map(buildSchema) };\n }\n if (type.isString()) return { type: \"string\" };\n if (type.isNumber()) return { type: \"number\" };\n if (type.isBoolean()) return { type: \"boolean\" };\n if (type.isArray()) {\n return {\n type: \"array\",\n items: buildSchema(type.getArrayElementTypeOrThrow()),\n };\n }\n\n const decls = type.getSymbol()?.getDeclarations() || [];\n const isLit = decls.some(\n (d) =>\n d.getKind() === SyntaxKind.TypeLiteral ||\n d.getKind() === SyntaxKind.InterfaceDeclaration\n );\n if (!isLit) return {};\n\n const props = type\n .getProperties()\n .filter(\n (p) => p.getValueDeclaration()?.getKind() === SyntaxKind.PropertySignature\n );\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const propsMap: Record<string, any> = {};\n const req: string[] = [];\n for (const p of props) {\n const decl = p.getValueDeclarationOrThrow();\n propsMap[p.getName()] = buildSchema(decl.getType());\n if (!p.isOptional()) req.push(p.getName());\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const res: any = { type: \"object\", properties: propsMap };\n if (req.length) res.required = req;\n return res;\n}\n","import { buildSchema } from \"./buildSchema\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function genParameters(type: import(\"ts-morph\").Type): any[] {\n const input = type\n .getProperty(\"input\")\n ?.getValueDeclarationOrThrow()\n .getType();\n if (!input) return [];\n const sources = [\"query\", \"param\", \"header\", \"cookie\"];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const params: any[] = [];\n for (const src of sources) {\n const p = input.getProperty(src);\n if (!p) continue;\n const srcType = p.getValueDeclarationOrThrow().getType();\n for (const f of srcType.getProperties()) {\n const ft = f.getValueDeclarationOrThrow().getType();\n params.push({\n name: f.getName(),\n in: src === \"param\" ? \"path\" : src,\n required: !f.isOptional(),\n schema: buildSchema(ft),\n });\n }\n }\n return params;\n}\n","import { buildSchema } from \"./buildSchema\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function genRequestBody(type: import(\"ts-morph\").Type): any | null {\n const inp = type.getProperty(\"input\")?.getValueDeclarationOrThrow().getType();\n if (!inp) return null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const content: Record<string, any> = {};\n const j = inp.getProperty(\"json\");\n if (j) {\n content[\"application/json\"] = {\n schema: buildSchema(j.getValueDeclarationOrThrow().getType()),\n };\n }\n const f = inp.getProperty(\"form\");\n if (f) {\n content[\"multipart/form-data\"] = {\n schema: buildSchema(f.getValueDeclarationOrThrow().getType()),\n };\n }\n return Object.keys(content).length ? { required: true, content } : null;\n}\n"],"mappings":"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","names":["fs","path","resolve","resolve","resolve","fs","path","SyntaxKind","_a","path","SyntaxKind","fs","resolve","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/config/index.ts","../src/core/runGenerate.ts","../src/config/loadConfig.ts","../src/utils/libDir.ts","../src/core/generateTypes.ts","../src/utils/format.ts","../src/core/generateOpenApi.ts","../src/utils/buildSchema.ts","../src/utils/parameters.ts","../src/utils/requestBody.ts"],"sourcesContent":["// src/config/index.ts\nimport type { HonoDocsConfig } from \"../types\";\n\n/**\n * A no‑op helper to get TS inference and IDE support when\n * writing `export default defineConfig({...})` in userland.\n */\nexport function defineConfig(config: HonoDocsConfig): HonoDocsConfig {\n return config;\n}\n","import fs from \"node:fs\";\nimport path, { resolve } from \"node:path\";\nimport { Project } from \"ts-morph\";\nimport { loadConfig } from \"../config/loadConfig\";\nimport { generateTypes } from \"./generateTypes\";\nimport { generateOpenApi } from \"./generateOpenApi\";\nimport { Api } from \"../types\";\nimport { cleanDefaultResponse, sanitizeApiPrefix } from \"../utils/format\";\nimport { getLibDir } from \"../utils/libDir\";\n\nexport async function runGenerate(configPath: string) {\n const config = await loadConfig(configPath);\n const rootPath = process.cwd();\n console.log(\"Initializing ts-morph with tsConfig:\", config.tsConfigPath);\n const project = new Project({\n tsConfigFilePath: resolve(rootPath, config.tsConfigPath),\n });\n\n // const isDevMode =\n // __dirname.includes(\"/src/\") || __dirname.includes(\"\\\\src\\\\\");\n\n // const libDir = isDevMode\n // ? path.resolve(__dirname, \"../../\")\n // : // : path.dirname(require.resolve(\"@rcmade/hono-docs/package.json\"));\n // path.dirname(fileURLToPath(import.meta.url));\n const libDir = getLibDir();\n console.log(\"Library root directory:\", libDir);\n\n const apis = config.apis;\n\n const snapshotOutputRoot = path.resolve(libDir, \"output/types\");\n const openAPiOutputRoot = path.resolve(libDir, \"output/openapi\");\n\n const commonParams = {\n config,\n libDir,\n project,\n rootPath,\n };\n for (const apiGroup of apis) {\n const sanitizedName = sanitizeApiPrefix(apiGroup.apiPrefix);\n\n const snapshotPath = await generateTypes({\n ...commonParams,\n apiGroup: apiGroup,\n fileName: sanitizedName,\n outputRoot: snapshotOutputRoot,\n });\n\n await generateOpenApi({\n snapshotPath,\n ...commonParams,\n fileName: sanitizedName,\n outputRoot: openAPiOutputRoot,\n });\n }\n\n const merged = {\n ...config.openApi,\n tags: [] as { name: string }[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n paths: {} as Record<string, any>,\n };\n\n for (const apiGroup of apis) {\n const name = sanitizeApiPrefix(apiGroup.apiPrefix);\n const openApiFile = path.join(openAPiOutputRoot, `${name}.json`);\n\n if (!fs.existsSync(openApiFile)) {\n console.warn(`⚠️ Missing OpenAPI file: ${openApiFile}`);\n continue;\n }\n\n const json = JSON.parse(fs.readFileSync(openApiFile, \"utf-8\"));\n merged.tags.push({ name: apiGroup.name });\n\n const customApiMap = new Map<string, Api>();\n\n if (apiGroup?.api) {\n for (const customApi of apiGroup.api) {\n const fullPath =\n path.posix\n .join(apiGroup.apiPrefix, customApi.api)\n .replace(/\\/+$/, \"\") || \"/\";\n customApiMap.set(\n `${customApi.method.toLowerCase()} ${fullPath}`,\n customApi\n );\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [pathKey, operations] of Object.entries<any>(json.paths)) {\n const prefixedPath =\n path.posix.join(apiGroup.apiPrefix, pathKey).replace(/\\/+$/, \"\") || \"/\";\n if (!merged.paths[prefixedPath]) merged.paths[prefixedPath] = {};\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [method, operation] of Object.entries<any>(operations)) {\n const opKey = `${method.toLowerCase()} ${prefixedPath}`;\n const customApi = customApiMap.get(opKey);\n\n // Override or enrich metadata if defined\n if (customApi) {\n operation.summary = customApi.summary || operation.summary;\n operation.description =\n customApi.description || operation.description;\n operation.tags =\n customApi.tag && customApi.tag.length > 0\n ? customApi.tag\n : [apiGroup.name];\n } else {\n operation.tags = operation.tags || [];\n if (!operation.tags.includes(apiGroup.name)) {\n operation.tags.push(apiGroup.name);\n }\n }\n\n cleanDefaultResponse(operation, prefixedPath, method);\n merged.paths[prefixedPath][method] = operation;\n }\n }\n }\n\n const outputPath = path.join(rootPath, config.outputs.openApiJson);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n\n fs.writeFileSync(outputPath, `${JSON.stringify(merged, null, 2)}\\n`);\n\n console.log(`✅ Final merged OpenAPI spec written to: ${outputPath}`);\n}\n","import { resolve } from \"path\";\nimport { existsSync } from \"fs\";\nimport { tsImport } from \"tsx/esm/api\";\nimport type { HonoDocsConfig } from \"../types\";\nimport { unwrapModule } from \"../utils/libDir\";\nimport { pathToFileURL } from \"url\";\n\nexport async function loadConfig(configFile: string): Promise<HonoDocsConfig> {\n // 1. Resolve absolute path\n const fullPath = resolve(process.cwd(), configFile);\n if (!existsSync(fullPath)) {\n throw new Error(`[hono-docs] Config file not found: ${fullPath}`);\n }\n\n // 2. Dynamically load the config via tsx's tsImport()\n let configModule: unknown;\n try {\n configModule = await tsImport(\n pathToFileURL(fullPath).href,\n import.meta.url\n );\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n throw new Error(\n `[hono-docs] Failed to load config: ${err.message ?? String(err)}`\n );\n }\n\n const config = unwrapModule(configModule);\n\n if (!config || typeof config !== \"object\") {\n throw new Error(\n `[hono-docs] Invalid config file. Expected an object, got: ${typeof config}`\n );\n }\n\n // console.log({ config });\n return config as HonoDocsConfig;\n}\n","// src/utils/libDir.ts\n\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Returns the root folder of the library, whether running in\n * development (src/) or installed (dist/).\n */\nexport function getLibDir(): string {\n // In CJS (__dirname is injected)\n if (typeof __dirname !== \"undefined\") {\n // When running from dist/core or dist/cli\n return resolve(__dirname, \"../../\");\n }\n // In ESM (import.meta.url)\n const __filename = fileURLToPath(import.meta.url);\n const __dirnameEsm = dirname(__filename);\n return resolve(__dirnameEsm, \"../../\");\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function unwrapModule(module: any): unknown {\n let result = module;\n while (result?.default) {\n result = result.default;\n }\n return result;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { ApiGroup, GenerateParams } from \"../types\";\nimport { normalizeImportPaths } from \"../utils/format\";\n\nexport async function generateTypes({\n config,\n project,\n rootPath,\n apiGroup,\n fileName,\n outputRoot,\n}: GenerateParams & { apiGroup: ApiGroup }) {\n fs.mkdirSync(outputRoot, { recursive: true });\n\n const outputPath = path.join(outputRoot, `${fileName}.d.ts`);\n const absInput = path.resolve(rootPath, apiGroup.appTypePath);\n\n const sourceFile = project.addSourceFileAtPath(absInput);\n const typeAliases = sourceFile.getTypeAliases();\n const interfaces = sourceFile.getInterfaces();\n\n let result = `// AUTO-GENERATED from ${apiGroup.appTypePath}\\n\\n`;\n\n typeAliases.forEach((alias) => {\n const raw = alias.getType().getText(alias);\n const clean = normalizeImportPaths(raw);\n result += `export type ${alias.getName()} = ${clean};\\n\\n`;\n });\n\n interfaces.forEach((intf) => {\n result += intf.getText() + \"\\n\\n\";\n });\n\n const preContent = config.preDefineTypeContent || \"\";\n\n fs.writeFileSync(outputPath, `${preContent}\\n${result}`, \"utf-8\");\n console.log(`✅ Wrote: ${outputPath}`);\n return { appTypePath: outputPath, name: fileName };\n}\n","export function sanitizeApiPrefix(prefix: string): string {\n return prefix\n .replace(/^\\//, \"\")\n .split(/[^a-z0-9]+/i)\n .filter(Boolean)\n .map((seg, i) =>\n i === 0\n ? seg.toLowerCase()\n : seg[0].toUpperCase() + seg.slice(1).toLowerCase()\n )\n .join(\"\");\n}\n\nexport function unwrapUnion(\n type: import(\"ts-morph\").Type\n): import(\"ts-morph\").Type[] {\n return type.isUnion() ? type.getUnionTypes() : [type];\n}\n\nexport function normalizeImportPaths(typeText: string): string {\n return typeText.replace(/from [\"'].*node_modules\\/(.*)[\"']/g, `from \"$1\"`);\n}\n\nexport function cleanDefaultResponse(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n operation: any,\n pathKey: string,\n method: string\n) {\n const defaultResponse = operation.responses?.default;\n if (!defaultResponse) return;\n\n const desc = defaultResponse.description ?? \"\";\n\n if (desc.includes(\"import(\")) {\n const content = defaultResponse.content;\n\n if (content && Object.keys(content).length > 0) {\n defaultResponse.description = \"Default fallback response\";\n console.log(\n `ℹ️ Cleaned 'default' description in ${method.toUpperCase()} ${pathKey}`\n );\n } else {\n delete operation.responses.default;\n console.log(\n `🗑️ Removed empty 'default' in ${method.toUpperCase()} ${pathKey}`\n );\n }\n }\n}\n\n\nexport function groupBy<T>(\n arr: T[],\n fn: (x: T) => string\n): Record<string, T[]> {\n return arr.reduce((acc, x) => {\n (acc[fn(x)] ||= []).push(x);\n return acc;\n }, {} as Record<string, T[]>);\n}\n","// src/core/generateOpenApi.ts\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n SyntaxKind,\n TypeLiteralNode,\n ImportTypeNode,\n TypeReferenceNode,\n TypeNode,\n ts,\n} from \"ts-morph\";\nimport type {\n AppTypeSnapshotPath,\n GenerateParams,\n OpenApiPath,\n} from \"../types\";\nimport { genParameters } from \"../utils/parameters\";\nimport { genRequestBody } from \"../utils/requestBody\";\nimport { buildSchema } from \"../utils/buildSchema\";\nimport { groupBy, unwrapUnion } from \"../utils/format\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype OpenAPI = Record<string, any>;\n\nexport async function generateOpenApi({\n config,\n snapshotPath,\n fileName,\n project,\n rootPath,\n outputRoot,\n}: // {\n// config: HonoDocsConfig;\n// snapshotPath: AppTypeSnapshotPath;\n// }\nGenerateParams & {\n snapshotPath: AppTypeSnapshotPath;\n}): Promise<OpenApiPath> {\n const sf = project.addSourceFileAtPath(\n path.resolve(rootPath, snapshotPath.appTypePath)\n );\n const aliasDecl = sf.getTypeAliasOrThrow(\"AppType\");\n\n const topTypeNode = aliasDecl.getTypeNode();\n\n let typeArgs: readonly TypeNode<ts.TypeNode>[];\n\n if (topTypeNode?.isKind(SyntaxKind.TypeReference)) {\n typeArgs = (topTypeNode as TypeReferenceNode).getTypeArguments();\n } else if (topTypeNode?.isKind(SyntaxKind.ImportType)) {\n typeArgs = (topTypeNode as ImportTypeNode).getTypeArguments();\n } else {\n throw new Error(\"AppType must be an ImportType or a TypeReference\");\n }\n\n if (typeArgs.length < 2) {\n throw new Error(\"Expected two type arguments on HonoBase\");\n }\n\n const routesNode = typeArgs[1];\n\n // Gather all TypeLiteralNodes (handle intersections)\n const literals: TypeLiteralNode[] = [];\n if (routesNode.isKind(SyntaxKind.IntersectionType)) {\n for (const tn of routesNode\n .asKind(SyntaxKind.IntersectionType)!\n .getTypeNodes()) {\n if (tn.isKind(SyntaxKind.TypeLiteral))\n literals.push(tn as TypeLiteralNode);\n }\n } else if (routesNode.isKind(SyntaxKind.TypeLiteral)) {\n literals.push(routesNode as TypeLiteralNode);\n } else {\n throw new Error(\"Routes type is not a literal or intersection of literals\");\n }\n\n const paths: OpenAPI = {};\n\n for (const lit of literals) {\n for (const member of lit.getMembers()) {\n if (!member.isKind(SyntaxKind.PropertySignature)) continue;\n const routeProp = member.asKindOrThrow(SyntaxKind.PropertySignature);\n // Extract route string and normalize to OpenAPI path syntax\n const raw = routeProp.getNameNode().getText().replace(/\"/g, \"\");\n const route = raw.replace(/:([^/]+)/g, \"{$1}\");\n if (!paths[route]) paths[route] = {};\n\n // === NEW: get the RHS TypeLiteralNode properly ===\n const tn = routeProp.getTypeNode();\n if (!tn || !tn.isKind(SyntaxKind.TypeLiteral)) continue;\n const rhs = tn as TypeLiteralNode;\n\n for (const m of rhs.getMembers()) {\n if (!m.isKind(SyntaxKind.PropertySignature)) continue;\n const methodProp = m.asKindOrThrow(SyntaxKind.PropertySignature);\n const name = methodProp.getNameNode().getText(); // e.g. \"$get\"\n const http = name.slice(1).toLowerCase(); // \"get\", \"post\", etc.\n const variants = unwrapUnion(methodProp.getType());\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const op: any = {\n summary: `Auto-generated ${http.toUpperCase()} ${route}`,\n };\n\n // parameters\n const params = genParameters(variants[0]);\n if (params.length) op.parameters = params;\n\n // requestBody\n const rb = genRequestBody(variants[0]);\n if (rb) op.requestBody = rb;\n\n // responses\n op.responses = {};\n const byStatus = groupBy(variants, (v) => {\n const s = v\n .getProperty(\"status\")!\n .getValueDeclarationOrThrow()\n .getType()\n .getText();\n return /^\\d+$/.test(s) ? s : \"default\";\n });\n for (const [code, vs] of Object.entries(byStatus)) {\n const schemas = vs.map((v) =>\n buildSchema(\n v.getProperty(\"output\")!.getValueDeclarationOrThrow().getType()\n )\n );\n const schema = schemas.length > 1 ? { oneOf: schemas } : schemas[0];\n op.responses[code] = {\n description:\n code === \"default\"\n ? `Generic status from ${vs[0]\n .getProperty(\"status\")!\n .getValueDeclarationOrThrow()\n .getType()\n .getText()}`\n : `Status ${code}`,\n content: { \"application/json\": { schema } },\n };\n }\n\n paths[route][http] = op;\n }\n }\n }\n\n const spec = {\n ...config.openApi,\n paths,\n };\n\n // write to disk\n const outputPath = path.join(outputRoot, `${fileName}.json`);\n\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, JSON.stringify(spec, null, 2), \"utf-8\");\n console.log(`✅ OpenAPI written to ${outputPath}`);\n return { openApiPath: outputPath };\n}\n","import { SyntaxKind } from \"ts-morph\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function buildSchema(type: import(\"ts-morph\").Type): any {\n if (type.isUnion()) {\n const members = type.getUnionTypes();\n const lits = members.filter((u) => u.isStringLiteral());\n const onlyNull = members.every(\n (u) => u.isStringLiteral() || u.isNull() || u.isUndefined()\n );\n if (lits.length && onlyNull) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const schema: any = {\n type: \"string\",\n enum: lits.map((u) => u.getLiteralValue()),\n };\n if (members.some((u) => u.isNull() || u.isUndefined()))\n schema.nullable = true;\n return schema;\n }\n const nonNull = members.filter((u) => !u.isNull() && !u.isUndefined());\n return { oneOf: nonNull.map(buildSchema) };\n }\n if (type.isString()) return { type: \"string\" };\n if (type.isNumber()) return { type: \"number\" };\n if (type.isBoolean()) return { type: \"boolean\" };\n if (type.isArray()) {\n return {\n type: \"array\",\n items: buildSchema(type.getArrayElementTypeOrThrow()),\n };\n }\n\n const decls = type.getSymbol()?.getDeclarations() || [];\n const isLit = decls.some(\n (d) =>\n d.getKind() === SyntaxKind.TypeLiteral ||\n d.getKind() === SyntaxKind.InterfaceDeclaration\n );\n if (!isLit) return {};\n\n const props = type\n .getProperties()\n .filter(\n (p) => p.getValueDeclaration()?.getKind() === SyntaxKind.PropertySignature\n );\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const propsMap: Record<string, any> = {};\n const req: string[] = [];\n for (const p of props) {\n const decl = p.getValueDeclarationOrThrow();\n propsMap[p.getName()] = buildSchema(decl.getType());\n if (!p.isOptional()) req.push(p.getName());\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const res: any = { type: \"object\", properties: propsMap };\n if (req.length) res.required = req;\n return res;\n}\n","import { buildSchema } from \"./buildSchema\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function genParameters(type: import(\"ts-morph\").Type): any[] {\n const input = type\n .getProperty(\"input\")\n ?.getValueDeclarationOrThrow()\n .getType();\n if (!input) return [];\n const sources = [\"query\", \"param\", \"header\", \"cookie\"];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const params: any[] = [];\n for (const src of sources) {\n const p = input.getProperty(src);\n if (!p) continue;\n const srcType = p.getValueDeclarationOrThrow().getType();\n for (const f of srcType.getProperties()) {\n const ft = f.getValueDeclarationOrThrow().getType();\n params.push({\n name: f.getName(),\n in: src === \"param\" ? \"path\" : src,\n required: !f.isOptional(),\n schema: buildSchema(ft),\n });\n }\n }\n return params;\n}\n","import { buildSchema } from \"./buildSchema\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function genRequestBody(type: import(\"ts-morph\").Type): any | null {\n const inp = type.getProperty(\"input\")?.getValueDeclarationOrThrow().getType();\n if (!inp) return null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const content: Record<string, any> = {};\n const j = inp.getProperty(\"json\");\n if (j) {\n content[\"application/json\"] = {\n schema: buildSchema(j.getValueDeclarationOrThrow().getType()),\n };\n }\n const f = inp.getProperty(\"form\");\n if (f) {\n content[\"multipart/form-data\"] = {\n schema: buildSchema(f.getValueDeclarationOrThrow().getType()),\n };\n }\n return Object.keys(content).length ? { required: true, content } : null;\n}\n"],"mappings":"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","names":["fs","path","resolve","resolve","resolve","fs","path","SyntaxKind","_a","path","SyntaxKind","fs","resolve","path","fs"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rcmade/hono-docs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.31",
|
|
4
4
|
"description": "Auto-generate OpenAPI 3.0 spec from Hono route types",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"cli",
|
|
20
20
|
"generator"
|
|
21
21
|
],
|
|
22
|
+
"license": "MIT",
|
|
22
23
|
"main": "dist/index.js",
|
|
23
24
|
"types": "dist/index.d.ts",
|
|
24
25
|
"bin": {
|