@rcmade/hono-docs 1.0.5 → 1.0.25

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,73 +1,32 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- var __create = Object.create;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
- // If the importer is in node compatibility mode or this is not an ESM
19
- // file that has been converted to a CommonJS file using a Babel-
20
- // compatible transform (i.e. "__esModule" has not been set), then set
21
- // "default" to the CommonJS "module.exports" for node compatibility.
22
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
- mod
24
- ));
25
2
 
26
3
  // src/cli/index.ts
27
- var import_yargs = __toESM(require("yargs"));
28
- var import_helpers = require("yargs/helpers");
4
+ import yargs from "yargs";
5
+ import { hideBin } from "yargs/helpers";
29
6
 
30
7
  // src/core/runGenerate.ts
31
- var import_node_fs3 = __toESM(require("fs"));
32
- var import_node_path4 = __toESM(require("path"));
33
- var import_ts_morph3 = require("ts-morph");
8
+ import fs3 from "fs";
9
+ import path3, { resolve as resolve3 } from "path";
10
+ import { Project } from "ts-morph";
34
11
 
35
12
  // src/config/loadConfig.ts
36
- var import_path = require("path");
37
- var import_fs = require("fs");
38
- var import_url = require("url");
39
- var import_node = require("esbuild-register/dist/node");
13
+ import { resolve } from "path";
14
+ import { existsSync } from "fs";
15
+ import { tsImport } from "tsx/esm/api";
40
16
  async function loadConfig(configFile) {
41
- const fullPath = (0, import_path.resolve)(process.cwd(), configFile);
42
- if (!(0, import_fs.existsSync)(fullPath)) {
17
+ const fullPath = resolve(process.cwd(), configFile);
18
+ if (!existsSync(fullPath)) {
43
19
  throw new Error(`[hono-docs] Config file not found: ${fullPath}`);
44
20
  }
45
- const ext = (0, import_path.extname)(fullPath);
46
- let unregister = () => {
47
- };
48
- if (ext === ".ts" || ext === ".tsx" || ext === ".mts") {
49
- const reg = (0, import_node.register)({
50
- target: "es2020",
51
- jsx: "automatic"
52
- });
53
- unregister = reg.unregister;
54
- }
55
21
  let configModule;
56
22
  try {
57
- if (ext === ".mjs" || ext === ".mts") {
58
- configModule = await import((0, import_url.pathToFileURL)(fullPath).href);
59
- } else {
60
- configModule = require(fullPath);
61
- }
23
+ configModule = await tsImport(fullPath, import.meta.url);
62
24
  } catch (err) {
63
- unregister();
64
25
  throw new Error(
65
- `[hono-docs] Failed to load config: ${err instanceof Error ? err.message : String(err)}`
26
+ `[hono-docs] Failed to load config: ${err.message ?? String(err)}`
66
27
  );
67
- } finally {
68
- unregister();
69
28
  }
70
- const config = configModule && typeof configModule === "object" && "default" in configModule ? (
29
+ const config = typeof configModule === "object" && configModule !== null && "default" in configModule ? (
71
30
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
31
  configModule.default
73
32
  ) : configModule;
@@ -80,8 +39,8 @@ async function loadConfig(configFile) {
80
39
  }
81
40
 
82
41
  // src/core/generateTypes.ts
83
- var import_node_fs = __toESM(require("fs"));
84
- var import_node_path = __toESM(require("path"));
42
+ import fs from "fs";
43
+ import path from "path";
85
44
 
86
45
  // src/utils/format.ts
87
46
  function sanitizeApiPrefix(prefix) {
@@ -131,9 +90,9 @@ async function generateTypes({
131
90
  fileName,
132
91
  outputRoot
133
92
  }) {
134
- import_node_fs.default.mkdirSync(outputRoot, { recursive: true });
135
- const outputPath = import_node_path.default.join(outputRoot, `${fileName}.d.ts`);
136
- const absInput = import_node_path.default.resolve(rootPath, apiGroup.appTypePath);
93
+ fs.mkdirSync(outputRoot, { recursive: true });
94
+ const outputPath = path.join(outputRoot, `${fileName}.d.ts`);
95
+ const absInput = path.resolve(rootPath, apiGroup.appTypePath);
137
96
  const sourceFile = project.addSourceFileAtPath(absInput);
138
97
  const typeAliases = sourceFile.getTypeAliases();
139
98
  const interfaces = sourceFile.getInterfaces();
@@ -151,19 +110,21 @@ async function generateTypes({
151
110
  result += intf.getText() + "\n\n";
152
111
  });
153
112
  const preContent = config.preDefineTypeContent || "";
154
- import_node_fs.default.writeFileSync(outputPath, `${preContent}
113
+ fs.writeFileSync(outputPath, `${preContent}
155
114
  ${result}`, "utf-8");
156
115
  console.log(`\u2705 Wrote: ${outputPath}`);
157
116
  return { appTypePath: outputPath, name: fileName };
158
117
  }
159
118
 
160
119
  // src/core/generateOpenApi.ts
161
- var import_node_fs2 = __toESM(require("fs"));
162
- var import_node_path2 = __toESM(require("path"));
163
- var import_ts_morph2 = require("ts-morph");
120
+ import fs2 from "fs";
121
+ import path2 from "path";
122
+ import {
123
+ SyntaxKind as SyntaxKind2
124
+ } from "ts-morph";
164
125
 
165
126
  // src/utils/buildSchema.ts
166
- var import_ts_morph = require("ts-morph");
127
+ import { SyntaxKind } from "ts-morph";
167
128
  function buildSchema(type) {
168
129
  var _a;
169
130
  if (type.isUnion()) {
@@ -195,13 +156,13 @@ function buildSchema(type) {
195
156
  }
196
157
  const decls = ((_a = type.getSymbol()) == null ? void 0 : _a.getDeclarations()) || [];
197
158
  const isLit = decls.some(
198
- (d) => d.getKind() === import_ts_morph.SyntaxKind.TypeLiteral || d.getKind() === import_ts_morph.SyntaxKind.InterfaceDeclaration
159
+ (d) => d.getKind() === SyntaxKind.TypeLiteral || d.getKind() === SyntaxKind.InterfaceDeclaration
199
160
  );
200
161
  if (!isLit) return {};
201
162
  const props = type.getProperties().filter(
202
163
  (p) => {
203
164
  var _a2;
204
- return ((_a2 = p.getValueDeclaration()) == null ? void 0 : _a2.getKind()) === import_ts_morph.SyntaxKind.PropertySignature;
165
+ return ((_a2 = p.getValueDeclaration()) == null ? void 0 : _a2.getKind()) === SyntaxKind.PropertySignature;
205
166
  }
206
167
  );
207
168
  const propsMap = {};
@@ -271,14 +232,14 @@ async function generateOpenApi({
271
232
  outputRoot
272
233
  }) {
273
234
  const sf = project.addSourceFileAtPath(
274
- import_node_path2.default.resolve(rootPath, snapshotPath.appTypePath)
235
+ path2.resolve(rootPath, snapshotPath.appTypePath)
275
236
  );
276
237
  const aliasDecl = sf.getTypeAliasOrThrow("AppType");
277
238
  const topTypeNode = aliasDecl.getTypeNode();
278
239
  let typeArgs;
279
- if (topTypeNode == null ? void 0 : topTypeNode.isKind(import_ts_morph2.SyntaxKind.TypeReference)) {
240
+ if (topTypeNode == null ? void 0 : topTypeNode.isKind(SyntaxKind2.TypeReference)) {
280
241
  typeArgs = topTypeNode.getTypeArguments();
281
- } else if (topTypeNode == null ? void 0 : topTypeNode.isKind(import_ts_morph2.SyntaxKind.ImportType)) {
242
+ } else if (topTypeNode == null ? void 0 : topTypeNode.isKind(SyntaxKind2.ImportType)) {
282
243
  typeArgs = topTypeNode.getTypeArguments();
283
244
  } else {
284
245
  throw new Error("AppType must be an ImportType or a TypeReference");
@@ -288,12 +249,12 @@ async function generateOpenApi({
288
249
  }
289
250
  const routesNode = typeArgs[1];
290
251
  const literals = [];
291
- if (routesNode.isKind(import_ts_morph2.SyntaxKind.IntersectionType)) {
292
- for (const tn of routesNode.asKind(import_ts_morph2.SyntaxKind.IntersectionType).getTypeNodes()) {
293
- if (tn.isKind(import_ts_morph2.SyntaxKind.TypeLiteral))
252
+ if (routesNode.isKind(SyntaxKind2.IntersectionType)) {
253
+ for (const tn of routesNode.asKind(SyntaxKind2.IntersectionType).getTypeNodes()) {
254
+ if (tn.isKind(SyntaxKind2.TypeLiteral))
294
255
  literals.push(tn);
295
256
  }
296
- } else if (routesNode.isKind(import_ts_morph2.SyntaxKind.TypeLiteral)) {
257
+ } else if (routesNode.isKind(SyntaxKind2.TypeLiteral)) {
297
258
  literals.push(routesNode);
298
259
  } else {
299
260
  throw new Error("Routes type is not a literal or intersection of literals");
@@ -301,17 +262,17 @@ async function generateOpenApi({
301
262
  const paths = {};
302
263
  for (const lit of literals) {
303
264
  for (const member of lit.getMembers()) {
304
- if (!member.isKind(import_ts_morph2.SyntaxKind.PropertySignature)) continue;
305
- const routeProp = member.asKindOrThrow(import_ts_morph2.SyntaxKind.PropertySignature);
265
+ if (!member.isKind(SyntaxKind2.PropertySignature)) continue;
266
+ const routeProp = member.asKindOrThrow(SyntaxKind2.PropertySignature);
306
267
  const raw = routeProp.getNameNode().getText().replace(/"/g, "");
307
268
  const route = raw.replace(/:([^/]+)/g, "{$1}");
308
269
  if (!paths[route]) paths[route] = {};
309
270
  const tn = routeProp.getTypeNode();
310
- if (!tn || !tn.isKind(import_ts_morph2.SyntaxKind.TypeLiteral)) continue;
271
+ if (!tn || !tn.isKind(SyntaxKind2.TypeLiteral)) continue;
311
272
  const rhs = tn;
312
273
  for (const m of rhs.getMembers()) {
313
- if (!m.isKind(import_ts_morph2.SyntaxKind.PropertySignature)) continue;
314
- const methodProp = m.asKindOrThrow(import_ts_morph2.SyntaxKind.PropertySignature);
274
+ if (!m.isKind(SyntaxKind2.PropertySignature)) continue;
275
+ const methodProp = m.asKindOrThrow(SyntaxKind2.PropertySignature);
315
276
  const name = methodProp.getNameNode().getText();
316
277
  const http = name.slice(1).toLowerCase();
317
278
  const variants = unwrapUnion(methodProp.getType());
@@ -347,24 +308,23 @@ async function generateOpenApi({
347
308
  ...config.openApi,
348
309
  paths
349
310
  };
350
- const outputPath = import_node_path2.default.join(outputRoot, `${fileName}.json`);
351
- import_node_fs2.default.mkdirSync(import_node_path2.default.dirname(outputPath), { recursive: true });
352
- import_node_fs2.default.writeFileSync(outputPath, JSON.stringify(spec, null, 2), "utf-8");
311
+ const outputPath = path2.join(outputRoot, `${fileName}.json`);
312
+ fs2.mkdirSync(path2.dirname(outputPath), { recursive: true });
313
+ fs2.writeFileSync(outputPath, JSON.stringify(spec, null, 2), "utf-8");
353
314
  console.log(`\u2705 OpenAPI written to ${outputPath}`);
354
315
  return { openApiPath: outputPath };
355
316
  }
356
317
 
357
318
  // src/utils/libDir.ts
358
- var import_node_path3 = require("path");
359
- var import_node_url = require("url");
360
- var import_meta = {};
319
+ import { dirname, resolve as resolve2 } from "path";
320
+ import { fileURLToPath } from "url";
361
321
  function getLibDir() {
362
322
  if (typeof __dirname !== "undefined") {
363
- return (0, import_node_path3.resolve)(__dirname, "../../");
323
+ return resolve2(__dirname, "../../");
364
324
  }
365
- const __filename = (0, import_node_url.fileURLToPath)(import_meta.url);
366
- const __dirnameEsm = (0, import_node_path3.dirname)(__filename);
367
- return (0, import_node_path3.resolve)(__dirnameEsm, "../../");
325
+ const __filename = fileURLToPath(import.meta.url);
326
+ const __dirnameEsm = dirname(__filename);
327
+ return resolve2(__dirnameEsm, "../../");
368
328
  }
369
329
 
370
330
  // src/core/runGenerate.ts
@@ -372,14 +332,14 @@ async function runGenerate(configPath) {
372
332
  const config = await loadConfig(configPath);
373
333
  const rootPath = process.cwd();
374
334
  console.log("Initializing ts-morph with tsConfig:", config.tsConfigPath);
375
- const project = new import_ts_morph3.Project({
376
- tsConfigFilePath: (0, import_node_path4.resolve)(rootPath, config.tsConfigPath)
335
+ const project = new Project({
336
+ tsConfigFilePath: resolve3(rootPath, config.tsConfigPath)
377
337
  });
378
338
  const libDir = getLibDir();
379
339
  console.log("Library root directory:", libDir);
380
340
  const apis = config.apis;
381
- const snapshotOutputRoot = import_node_path4.default.resolve(libDir, "output/types");
382
- const openAPiOutputRoot = import_node_path4.default.resolve(libDir, "output/openapi");
341
+ const snapshotOutputRoot = path3.resolve(libDir, "output/types");
342
+ const openAPiOutputRoot = path3.resolve(libDir, "output/openapi");
383
343
  const commonParams = {
384
344
  config,
385
345
  libDir,
@@ -409,17 +369,17 @@ async function runGenerate(configPath) {
409
369
  };
410
370
  for (const apiGroup of apis) {
411
371
  const name = sanitizeApiPrefix(apiGroup.apiPrefix);
412
- const openApiFile = import_node_path4.default.join(openAPiOutputRoot, `${name}.json`);
413
- if (!import_node_fs3.default.existsSync(openApiFile)) {
372
+ const openApiFile = path3.join(openAPiOutputRoot, `${name}.json`);
373
+ if (!fs3.existsSync(openApiFile)) {
414
374
  console.warn(`\u26A0\uFE0F Missing OpenAPI file: ${openApiFile}`);
415
375
  continue;
416
376
  }
417
- const json = JSON.parse(import_node_fs3.default.readFileSync(openApiFile, "utf-8"));
377
+ const json = JSON.parse(fs3.readFileSync(openApiFile, "utf-8"));
418
378
  merged.tags.push({ name: apiGroup.name });
419
379
  const customApiMap = /* @__PURE__ */ new Map();
420
380
  if (apiGroup == null ? void 0 : apiGroup.api) {
421
381
  for (const customApi of apiGroup.api) {
422
- const fullPath = import_node_path4.default.posix.join(apiGroup.apiPrefix, customApi.api).replace(/\/+$/, "") || "/";
382
+ const fullPath = path3.posix.join(apiGroup.apiPrefix, customApi.api).replace(/\/+$/, "") || "/";
423
383
  customApiMap.set(
424
384
  `${customApi.method.toLowerCase()} ${fullPath}`,
425
385
  customApi
@@ -427,7 +387,7 @@ async function runGenerate(configPath) {
427
387
  }
428
388
  }
429
389
  for (const [pathKey, operations] of Object.entries(json.paths)) {
430
- const prefixedPath = import_node_path4.default.posix.join(apiGroup.apiPrefix, pathKey).replace(/\/+$/, "") || "/";
390
+ const prefixedPath = path3.posix.join(apiGroup.apiPrefix, pathKey).replace(/\/+$/, "") || "/";
431
391
  if (!merged.paths[prefixedPath]) merged.paths[prefixedPath] = {};
432
392
  for (const [method, operation] of Object.entries(operations)) {
433
393
  const opKey = `${method.toLowerCase()} ${prefixedPath}`;
@@ -447,15 +407,15 @@ async function runGenerate(configPath) {
447
407
  }
448
408
  }
449
409
  }
450
- const outputPath = import_node_path4.default.join(rootPath, config.outputs.openApiJson);
451
- import_node_fs3.default.mkdirSync(import_node_path4.default.dirname(outputPath), { recursive: true });
452
- import_node_fs3.default.writeFileSync(outputPath, `${JSON.stringify(merged, null, 2)}
410
+ const outputPath = path3.join(rootPath, config.outputs.openApiJson);
411
+ fs3.mkdirSync(path3.dirname(outputPath), { recursive: true });
412
+ fs3.writeFileSync(outputPath, `${JSON.stringify(merged, null, 2)}
453
413
  `);
454
414
  console.log(`\u2705 Final merged OpenAPI spec written to: ${outputPath}`);
455
415
  }
456
416
 
457
417
  // src/cli/index.ts
458
- (0, import_yargs.default)((0, import_helpers.hideBin)(process.argv)).scriptName("hono-docs").command(
418
+ yargs(hideBin(process.argv)).scriptName("hono-docs").command(
459
419
  "generate",
460
420
  "Generate OpenAPI JSON",
461
421
  (y) => y.option("config", {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts","../../src/core/runGenerate.ts","../../src/config/loadConfig.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","../../src/utils/libDir.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\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, extname } from \"path\";\nimport { existsSync } from \"fs\";\nimport { pathToFileURL } from \"url\";\nimport { register } from \"esbuild-register/dist/node\";\nimport type { HonoDocsConfig } from \"../types\";\n\nexport async function loadConfig(configFile: string): Promise<HonoDocsConfig> {\n // 1. Resolve absolute path\n const fullPath = resolve(process.cwd(), configFile);\n\n if (!existsSync(fullPath)) {\n throw new Error(`[hono-docs] Config file not found: ${fullPath}`);\n }\n\n // 2. Detect file extension\n const ext = extname(fullPath);\n let unregister = () => {};\n\n // 3. Register TS transpiler if needed\n if (ext === \".ts\" || ext === \".tsx\" || ext === \".mts\") {\n const reg = register({\n target: \"es2020\",\n jsx: \"automatic\",\n });\n unregister = reg.unregister;\n }\n\n // 4. Dynamically load the config\n let configModule: unknown;\n\n try {\n if (ext === \".mjs\" || ext === \".mts\") {\n // ESM config\n configModule = await import(pathToFileURL(fullPath).href);\n } else {\n // Use require with esbuild-register hook for .ts/.js\n configModule = require(fullPath);\n }\n } catch (err) {\n unregister();\n throw new Error(\n `[hono-docs] Failed to load config: ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n } finally {\n unregister();\n }\n\n // 5. Handle default or named export\n const config =\n configModule &&\n typeof configModule === \"object\" &&\n \"default\" in configModule\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (configModule as any).default\n : 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 return config as HonoDocsConfig;\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","// 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"],"mappings":"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","names":["import_node_fs","import_node_path","import_ts_morph","fs","path","import_node_fs","import_node_path","import_ts_morph","_a","path","fs","import_node_path","path","fs","yargs"]}
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/core/runGenerate.ts","../../src/config/loadConfig.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","../../src/utils/libDir.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\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\";\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 // 3. Unwrap default export if present\n const config =\n typeof configModule === \"object\" &&\n configModule !== null &&\n \"default\" in configModule\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (configModule as any).default\n : 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 return config as HonoDocsConfig;\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","// 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"],"mappings":"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","names":["fs","path","resolve","fs","path","SyntaxKind","_a","path","SyntaxKind","fs","resolve","resolve","path","fs"]}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,35 @@
1
- export { defineConfig, runGenerate } from './core/index.js';
2
- import 'openapi-types';
1
+ import { OpenAPIV3 } from 'openapi-types';
2
+
3
+ type OpenAPIConfig = Omit<OpenAPIV3.Document, "paths" | "components" | "tags">;
4
+ type Api = {
5
+ api: string;
6
+ summary?: string;
7
+ description?: string;
8
+ tag?: string[];
9
+ method: "get" | "post" | "put" | "patch" | "delete";
10
+ };
11
+ type ApiGroup = {
12
+ apiPrefix: string;
13
+ appTypePath: string;
14
+ name: string;
15
+ api?: Api[];
16
+ };
17
+ type HonoDocsConfig = {
18
+ tsConfigPath: string;
19
+ openApi: OpenAPIConfig;
20
+ outputs: {
21
+ openApiJson: string;
22
+ };
23
+ apis: ApiGroup[];
24
+ preDefineTypeContent?: string;
25
+ };
26
+
27
+ /**
28
+ * A no‑op helper to get TS inference and IDE support when
29
+ * writing `export default defineConfig({...})` in userland.
30
+ */
31
+ declare function defineConfig(config: HonoDocsConfig): HonoDocsConfig;
32
+
33
+ declare function runGenerate(configPath: string): Promise<void>;
34
+
35
+ export { defineConfig, runGenerate };