@orval/hono 8.17.0 → 8.18.0
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/index.d.mts +4 -2
- package/dist/index.mjs +62 -44
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClientBuilder, ClientExtraFilesBuilder, ClientFooterBuilder, ClientGeneratorsBuilder, ClientHeaderBuilder, GeneratorDependency, GeneratorVerbOptions, HonoHandlerStrategy } from "@orval/core";
|
|
1
|
+
import { ClientBuilder, ClientExtraFilesBuilder, ClientFooterBuilder, ClientGeneratorsBuilder, ClientHeaderBuilder, GeneratorDependency, GeneratorVerbOptions, HonoHandlerStrategy, Tsconfig } from "@orval/core";
|
|
2
2
|
|
|
3
3
|
//#region src/index.d.ts
|
|
4
4
|
declare const getHonoDependencies: () => GeneratorDependency[];
|
|
@@ -22,7 +22,8 @@ declare const generateHandlerFile: ({
|
|
|
22
22
|
validatorModule,
|
|
23
23
|
zodModule,
|
|
24
24
|
contextModule,
|
|
25
|
-
strategy
|
|
25
|
+
strategy,
|
|
26
|
+
tsconfig
|
|
26
27
|
}: {
|
|
27
28
|
verbs: GeneratorVerbOptions[];
|
|
28
29
|
path: string;
|
|
@@ -31,6 +32,7 @@ declare const generateHandlerFile: ({
|
|
|
31
32
|
zodModule: string;
|
|
32
33
|
contextModule: string;
|
|
33
34
|
strategy: HonoHandlerStrategy;
|
|
35
|
+
tsconfig?: Tsconfig;
|
|
34
36
|
}) => Promise<string>;
|
|
35
37
|
declare const generateExtraFiles: ClientExtraFilesBuilder;
|
|
36
38
|
declare const builder: () => () => ClientGeneratorsBuilder;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import nodePath from "node:path";
|
|
2
|
-
import { camel, generateMutatorImports, getFileInfo, getOrvalGeneratedTypes, getParamsInPath, isObject, jsDoc, kebab, logWarning, pascal, sanitize, upath } from "@orval/core";
|
|
2
|
+
import { camel, generateMutatorImports, getFileInfo, getImportExtension, getOrvalGeneratedTypes, getParamsInPath, isObject, jsDoc, kebab, logWarning, pascal, sanitize, upath } from "@orval/core";
|
|
3
3
|
import { generateZod } from "@orval/zod";
|
|
4
4
|
import fs from "fs-extra";
|
|
5
5
|
//#region src/handler-merge.ts
|
|
@@ -378,16 +378,26 @@ const HONO_DEPENDENCIES = [{
|
|
|
378
378
|
*
|
|
379
379
|
* Otherwise, treated as a package name and returned directly.
|
|
380
380
|
*
|
|
381
|
-
* @
|
|
382
|
-
*
|
|
381
|
+
* @param tsconfig Optional tsconfig used to derive the runtime import
|
|
382
|
+
* extension. Under `module: 'nodenext'/'node16'` the source extension (e.g.
|
|
383
|
+
* `.ts`) is rewritten to its runtime equivalent (e.g. `.js`); otherwise the
|
|
384
|
+
* extension is dropped to match the rest of orval.
|
|
385
|
+
*
|
|
386
|
+
* @return A module specifier that can be used at _from_ to import _to_.
|
|
383
387
|
*/
|
|
384
|
-
const generateModuleSpecifier = (from, to) => {
|
|
385
|
-
if (to.startsWith(".") || nodePath.isAbsolute(to))
|
|
388
|
+
const generateModuleSpecifier = (from, to, tsconfig) => {
|
|
389
|
+
if (to.startsWith(".") || nodePath.isAbsolute(to)) {
|
|
390
|
+
const resolvedFrom = nodePath.resolve(from);
|
|
391
|
+
const resolvedTo = nodePath.resolve(to);
|
|
392
|
+
const relative = upath.getRelativeImportPath(resolvedFrom, resolvedTo);
|
|
393
|
+
const sourceExt = nodePath.extname(to);
|
|
394
|
+
return `${relative}${sourceExt ? getImportExtension(sourceExt, tsconfig) : ""}`;
|
|
395
|
+
}
|
|
386
396
|
return to;
|
|
387
397
|
};
|
|
388
398
|
const getHonoDependencies = () => HONO_DEPENDENCIES;
|
|
389
399
|
const getHonoHeader = ({ verbOptions, output, tag, clientImplementation }) => {
|
|
390
|
-
const targetInfo = getFileInfo(output.target);
|
|
400
|
+
const targetInfo = getFileInfo(output.target, { extension: output.fileExtension });
|
|
391
401
|
let handlers;
|
|
392
402
|
const importHandlers = Object.values(verbOptions).filter((verbOption) => clientImplementation.includes(`${verbOption.operationName}Handlers`));
|
|
393
403
|
if (output.override.hono.handlers) {
|
|
@@ -497,7 +507,7 @@ const getVerbOptionGroupByTag = (verbOptions) => {
|
|
|
497
507
|
return grouped;
|
|
498
508
|
};
|
|
499
509
|
/** Computes the orval-owned imports a handler file should contain. */
|
|
500
|
-
const buildDesiredImports = ({ verbList, path, validatorModule, zodModule, contextModule, validator }) => {
|
|
510
|
+
const buildDesiredImports = ({ verbList, path, validatorModule, zodModule, contextModule, validator, tsconfig }) => {
|
|
501
511
|
const contextNames = verbList.map((verb) => `${pascal(verb.operationName)}Context`);
|
|
502
512
|
const zodNames = verbList.flatMap((verb) => getDesiredValidators(verb, validator).map((v) => v.schema));
|
|
503
513
|
const hasValidators = zodNames.length > 0;
|
|
@@ -508,20 +518,20 @@ const buildDesiredImports = ({ verbList, path, validatorModule, zodModule, conte
|
|
|
508
518
|
},
|
|
509
519
|
validator: hasValidators && validatorModule != void 0 ? {
|
|
510
520
|
names: ["zValidator"],
|
|
511
|
-
module: generateModuleSpecifier(path, validatorModule)
|
|
521
|
+
module: generateModuleSpecifier(path, validatorModule, tsconfig)
|
|
512
522
|
} : void 0,
|
|
513
523
|
context: {
|
|
514
524
|
names: contextNames,
|
|
515
|
-
module: generateModuleSpecifier(path, contextModule)
|
|
525
|
+
module: generateModuleSpecifier(path, contextModule, tsconfig)
|
|
516
526
|
},
|
|
517
527
|
zod: hasValidators ? {
|
|
518
528
|
names: zodNames,
|
|
519
|
-
module: generateModuleSpecifier(path, zodModule)
|
|
529
|
+
module: generateModuleSpecifier(path, zodModule, tsconfig)
|
|
520
530
|
} : void 0
|
|
521
531
|
};
|
|
522
532
|
};
|
|
523
533
|
/** Generates a complete handler file from scratch (no existing file to merge). */
|
|
524
|
-
const generateFreshHandlerFile = ({ verbList, path, header, validatorModule, zodModule, contextModule, validator, bodyFor }) => {
|
|
534
|
+
const generateFreshHandlerFile = ({ verbList, path, header, validatorModule, zodModule, contextModule, validator, bodyFor, tsconfig }) => {
|
|
525
535
|
const [handlerCode, hasZValidator] = getHonoHandlers(...verbList.map((verbOption) => ({
|
|
526
536
|
handlerName: `${verbOption.operationName}Handlers`,
|
|
527
537
|
contextTypeName: `${pascal(verbOption.operationName)}Context`,
|
|
@@ -530,9 +540,9 @@ const generateFreshHandlerFile = ({ verbList, path, header, validatorModule, zod
|
|
|
530
540
|
bodyOverride: bodyFor?.(verbOption.operationName)
|
|
531
541
|
})));
|
|
532
542
|
const imports = ["import { createFactory } from 'hono/factory';"];
|
|
533
|
-
if (hasZValidator && validatorModule != void 0) imports.push(`import { zValidator } from '${generateModuleSpecifier(path, validatorModule)}';`);
|
|
534
|
-
imports.push(`import { ${verbList.map((verb) => `${pascal(verb.operationName)}Context`).join(",\n")} } from '${generateModuleSpecifier(path, contextModule)}';`);
|
|
535
|
-
if (hasZValidator) imports.push(getZvalidatorImports(verbList, generateModuleSpecifier(path, zodModule), validatorModule === "@hono/zod-validator"));
|
|
543
|
+
if (hasZValidator && validatorModule != void 0) imports.push(`import { zValidator } from '${generateModuleSpecifier(path, validatorModule, tsconfig)}';`);
|
|
544
|
+
imports.push(`import { ${verbList.map((verb) => `${pascal(verb.operationName)}Context`).join(",\n")} } from '${generateModuleSpecifier(path, contextModule, tsconfig)}';`);
|
|
545
|
+
if (hasZValidator) imports.push(getZvalidatorImports(verbList, generateModuleSpecifier(path, zodModule, tsconfig), validatorModule === "@hono/zod-validator"));
|
|
536
546
|
return `${header}${imports.filter((imp) => imp !== "").join("\n")}\n\nconst factory = createFactory();${handlerCode}`;
|
|
537
547
|
};
|
|
538
548
|
/**
|
|
@@ -545,7 +555,7 @@ const generateFreshHandlerFile = ({ verbList, path, header, validatorModule, zod
|
|
|
545
555
|
* - `smart` non-destructively reconciles orval-owned imports + validators and
|
|
546
556
|
* appends handlers for new operations, preserving all user-authored code.
|
|
547
557
|
*/
|
|
548
|
-
const generateHandlerFile = async ({ verbs, path, header, validatorModule, zodModule, contextModule, strategy }) => {
|
|
558
|
+
const generateHandlerFile = async ({ verbs, path, header, validatorModule, zodModule, contextModule, strategy, tsconfig }) => {
|
|
549
559
|
const validator = validatorModule === "@hono/zod-validator" ? "hono" : validatorModule != void 0;
|
|
550
560
|
const verbList = Object.values(verbs);
|
|
551
561
|
if (!fs.existsSync(path)) return generateFreshHandlerFile({
|
|
@@ -555,7 +565,8 @@ const generateHandlerFile = async ({ verbs, path, header, validatorModule, zodMo
|
|
|
555
565
|
validatorModule,
|
|
556
566
|
zodModule,
|
|
557
567
|
contextModule,
|
|
558
|
-
validator
|
|
568
|
+
validator,
|
|
569
|
+
tsconfig
|
|
559
570
|
});
|
|
560
571
|
const source = await fs.readFile(path, "utf8");
|
|
561
572
|
if (strategy === "skip") return source;
|
|
@@ -577,7 +588,8 @@ const generateHandlerFile = async ({ verbs, path, header, validatorModule, zodMo
|
|
|
577
588
|
zodModule,
|
|
578
589
|
contextModule,
|
|
579
590
|
validator,
|
|
580
|
-
bodyFor: (operationName) => bodies.get(`${operationName}Handlers`)
|
|
591
|
+
bodyFor: (operationName) => bodies.get(`${operationName}Handlers`),
|
|
592
|
+
tsconfig
|
|
581
593
|
});
|
|
582
594
|
}
|
|
583
595
|
return reconcileHandlerFile(source, {
|
|
@@ -587,7 +599,8 @@ const generateHandlerFile = async ({ verbs, path, header, validatorModule, zodMo
|
|
|
587
599
|
validatorModule,
|
|
588
600
|
zodModule,
|
|
589
601
|
contextModule,
|
|
590
|
-
validator
|
|
602
|
+
validator,
|
|
603
|
+
tsconfig
|
|
591
604
|
}),
|
|
592
605
|
handlers: verbList.map((verbOption) => ({
|
|
593
606
|
handlerName: `${verbOption.operationName}Handlers`,
|
|
@@ -603,7 +616,7 @@ const generateHandlerFile = async ({ verbs, path, header, validatorModule, zodMo
|
|
|
603
616
|
};
|
|
604
617
|
const generateHandlerFiles = async (verbOptions, output, context, validatorModule) => {
|
|
605
618
|
const header = getHeader(output.override.header, getSpecInfo(context));
|
|
606
|
-
const { extension, dirname, filename } = getFileInfo(output.target);
|
|
619
|
+
const { extension, dirname, filename } = getFileInfo(output.target, { extension: output.fileExtension });
|
|
607
620
|
const strategy = output.override.hono.handlerGenerationStrategy;
|
|
608
621
|
if (output.override.hono.handlers) return Promise.all(Object.values(verbOptions).map(async (verbOption) => {
|
|
609
622
|
const tag = kebab(verbOption.tags[0] ?? "default");
|
|
@@ -611,14 +624,14 @@ const generateHandlerFiles = async (verbOptions, output, context, validatorModul
|
|
|
611
624
|
let zodModule;
|
|
612
625
|
let contextModule;
|
|
613
626
|
if (output.mode === "tags") {
|
|
614
|
-
zodModule = nodePath.join(dirname, `${kebab(tag)}.zod`);
|
|
615
|
-
contextModule = nodePath.join(dirname, `${kebab(tag)}.context`);
|
|
627
|
+
zodModule = nodePath.join(dirname, `${kebab(tag)}.zod${extension}`);
|
|
628
|
+
contextModule = nodePath.join(dirname, `${kebab(tag)}.context${extension}`);
|
|
616
629
|
} else if (output.mode === "tags-split") {
|
|
617
|
-
zodModule = nodePath.join(dirname, tag, tag + ".zod");
|
|
618
|
-
contextModule = nodePath.join(dirname, tag, tag + ".context");
|
|
630
|
+
zodModule = nodePath.join(dirname, tag, tag + ".zod" + extension);
|
|
631
|
+
contextModule = nodePath.join(dirname, tag, tag + ".context" + extension);
|
|
619
632
|
} else {
|
|
620
|
-
zodModule = nodePath.join(dirname, `${filename}.zod`);
|
|
621
|
-
contextModule = nodePath.join(dirname, `${filename}.context`);
|
|
633
|
+
zodModule = nodePath.join(dirname, `${filename}.zod${extension}`);
|
|
634
|
+
contextModule = nodePath.join(dirname, `${filename}.context${extension}`);
|
|
622
635
|
}
|
|
623
636
|
return {
|
|
624
637
|
content: await generateHandlerFile({
|
|
@@ -628,7 +641,8 @@ const generateHandlerFiles = async (verbOptions, output, context, validatorModul
|
|
|
628
641
|
validatorModule,
|
|
629
642
|
zodModule,
|
|
630
643
|
contextModule,
|
|
631
|
-
strategy
|
|
644
|
+
strategy,
|
|
645
|
+
tsconfig: output.tsconfig
|
|
632
646
|
}),
|
|
633
647
|
path
|
|
634
648
|
};
|
|
@@ -643,9 +657,10 @@ const generateHandlerFiles = async (verbOptions, output, context, validatorModul
|
|
|
643
657
|
header,
|
|
644
658
|
verbs,
|
|
645
659
|
validatorModule,
|
|
646
|
-
zodModule: output.mode === "tags" ? nodePath.join(dirname, `${kebab(tag)}.zod`) : nodePath.join(dirname, tag, tag + ".zod"),
|
|
647
|
-
contextModule: output.mode === "tags" ? nodePath.join(dirname, `${kebab(tag)}.context`) : nodePath.join(dirname, tag, tag + ".context"),
|
|
648
|
-
strategy
|
|
660
|
+
zodModule: output.mode === "tags" ? nodePath.join(dirname, `${kebab(tag)}.zod${extension}`) : nodePath.join(dirname, tag, tag + ".zod" + extension),
|
|
661
|
+
contextModule: output.mode === "tags" ? nodePath.join(dirname, `${kebab(tag)}.context${extension}`) : nodePath.join(dirname, tag, tag + ".context" + extension),
|
|
662
|
+
strategy,
|
|
663
|
+
tsconfig: output.tsconfig
|
|
649
664
|
}),
|
|
650
665
|
path: handlerPath
|
|
651
666
|
};
|
|
@@ -658,9 +673,10 @@ const generateHandlerFiles = async (verbOptions, output, context, validatorModul
|
|
|
658
673
|
header,
|
|
659
674
|
verbs: Object.values(verbOptions),
|
|
660
675
|
validatorModule,
|
|
661
|
-
zodModule: nodePath.join(dirname, `${filename}.zod`),
|
|
662
|
-
contextModule: nodePath.join(dirname, `${filename}.context`),
|
|
663
|
-
strategy
|
|
676
|
+
zodModule: nodePath.join(dirname, `${filename}.zod${extension}`),
|
|
677
|
+
contextModule: nodePath.join(dirname, `${filename}.context${extension}`),
|
|
678
|
+
strategy,
|
|
679
|
+
tsconfig: output.tsconfig
|
|
664
680
|
}),
|
|
665
681
|
path: handlerPath
|
|
666
682
|
}];
|
|
@@ -686,7 +702,7 @@ const getSpecInfo = (context) => context.spec.info ?? {
|
|
|
686
702
|
title: "API",
|
|
687
703
|
version: "1.0.0"
|
|
688
704
|
};
|
|
689
|
-
const generateContextFile = ({ path, verbs, schemaModule }) => {
|
|
705
|
+
const generateContextFile = ({ path, verbs, schemaModule, tsconfig }) => {
|
|
690
706
|
let content = `import type { Context, Env } from 'hono';\n\n`;
|
|
691
707
|
const contexts = verbs.map((verb) => getContext(verb));
|
|
692
708
|
const imps = new Set(verbs.flatMap((verb) => {
|
|
@@ -700,13 +716,13 @@ const generateContextFile = ({ path, verbs, schemaModule }) => {
|
|
|
700
716
|
content += getOrvalGeneratedTypes();
|
|
701
717
|
content += "\n";
|
|
702
718
|
}
|
|
703
|
-
if (imps.size > 0) content += `import type {\n${[...imps].toSorted().join(",\n ")}\n} from '${generateModuleSpecifier(path, schemaModule)}';\n\n`;
|
|
719
|
+
if (imps.size > 0) content += `import type {\n${[...imps].toSorted().join(",\n ")}\n} from '${generateModuleSpecifier(path, schemaModule, tsconfig)}';\n\n`;
|
|
704
720
|
content += contexts.join("\n");
|
|
705
721
|
return content;
|
|
706
722
|
};
|
|
707
723
|
const generateContextFiles = (verbOptions, output, context, schemaModule) => {
|
|
708
724
|
const header = getHeader(output.override.header, getSpecInfo(context));
|
|
709
|
-
const { extension, dirname, filename } = getFileInfo(output.target);
|
|
725
|
+
const { extension, dirname, filename } = getFileInfo(output.target, { extension: output.fileExtension });
|
|
710
726
|
if (output.mode === "tags" || output.mode === "tags-split") {
|
|
711
727
|
const groupByTags = getVerbOptionGroupByTag(verbOptions);
|
|
712
728
|
return Object.entries(groupByTags).map(([tag, verbs]) => {
|
|
@@ -715,7 +731,8 @@ const generateContextFiles = (verbOptions, output, context, schemaModule) => {
|
|
|
715
731
|
content: `${header}${generateContextFile({
|
|
716
732
|
verbs,
|
|
717
733
|
path,
|
|
718
|
-
schemaModule
|
|
734
|
+
schemaModule,
|
|
735
|
+
tsconfig: output.tsconfig
|
|
719
736
|
})}`,
|
|
720
737
|
path
|
|
721
738
|
};
|
|
@@ -726,13 +743,14 @@ const generateContextFiles = (verbOptions, output, context, schemaModule) => {
|
|
|
726
743
|
content: `${header}${generateContextFile({
|
|
727
744
|
verbs: Object.values(verbOptions),
|
|
728
745
|
path,
|
|
729
|
-
schemaModule
|
|
746
|
+
schemaModule,
|
|
747
|
+
tsconfig: output.tsconfig
|
|
730
748
|
})}`,
|
|
731
749
|
path
|
|
732
750
|
}];
|
|
733
751
|
};
|
|
734
752
|
const generateZodFiles = async (verbOptions, output, context) => {
|
|
735
|
-
const { extension, dirname, filename } = getFileInfo(output.target);
|
|
753
|
+
const { extension, dirname, filename } = getFileInfo(output.target, { extension: output.fileExtension });
|
|
736
754
|
const header = getHeader(output.override.header, getSpecInfo(context));
|
|
737
755
|
if (output.mode === "tags" || output.mode === "tags-split") {
|
|
738
756
|
const groupByTags = getVerbOptionGroupByTag(verbOptions);
|
|
@@ -779,7 +797,7 @@ const generateZvalidator = (output, context) => {
|
|
|
779
797
|
const header = getHeader(output.override.header, getSpecInfo(context));
|
|
780
798
|
let validatorPath = output.override.hono.validatorOutputPath;
|
|
781
799
|
if (!output.override.hono.validatorOutputPath) {
|
|
782
|
-
const { extension, dirname, filename } = getFileInfo(output.target);
|
|
800
|
+
const { extension, dirname, filename } = getFileInfo(output.target, { extension: output.fileExtension });
|
|
783
801
|
validatorPath = nodePath.join(dirname, `${filename}.validator${extension}`);
|
|
784
802
|
}
|
|
785
803
|
return {
|
|
@@ -788,7 +806,7 @@ const generateZvalidator = (output, context) => {
|
|
|
788
806
|
};
|
|
789
807
|
};
|
|
790
808
|
const generateCompositeRoutes = (verbOptions, output, context) => {
|
|
791
|
-
const targetInfo = getFileInfo(output.target);
|
|
809
|
+
const targetInfo = getFileInfo(output.target, { extension: output.fileExtension });
|
|
792
810
|
const compositeRouteInfo = getFileInfo(output.override.hono.compositeRoute);
|
|
793
811
|
const header = getHeader(output.override.header, getSpecInfo(context));
|
|
794
812
|
const routes = Object.values(verbOptions).map((verbOption) => {
|
|
@@ -799,12 +817,12 @@ const generateCompositeRoutes = (verbOptions, output, context) => {
|
|
|
799
817
|
if (output.override.hono.handlers) {
|
|
800
818
|
const handlerFileInfo = getFileInfo(output.override.hono.handlers);
|
|
801
819
|
ImportHandlersImplementation = importHandlers.map((verbOption) => verbOption.operationName).map((operationName) => {
|
|
802
|
-
return `import { ${`${operationName}Handlers`} } from '${generateModuleSpecifier(compositeRouteInfo.path, nodePath.join(handlerFileInfo.dirname, `./${operationName}`))}';`;
|
|
820
|
+
return `import { ${`${operationName}Handlers`} } from '${generateModuleSpecifier(compositeRouteInfo.path, nodePath.join(handlerFileInfo.dirname, `./${operationName}${targetInfo.extension}`), output.tsconfig)}';`;
|
|
803
821
|
}).join("\n");
|
|
804
822
|
} else {
|
|
805
823
|
const tags = importHandlers.map((verbOption) => kebab(verbOption.tags[0] ?? "default"));
|
|
806
824
|
ImportHandlersImplementation = tags.filter((t, i) => tags.indexOf(t) === i).map((tag) => {
|
|
807
|
-
return `import {\n${importHandlers.filter((verbOption) => verbOption.tags[0] === tag).map((verbOption) => ` ${verbOption.operationName}Handlers`).join(`, \n`)}\n} from '${generateModuleSpecifier(compositeRouteInfo.path, nodePath.join(targetInfo.dirname, tag))}/${tag}.handlers';`;
|
|
825
|
+
return `import {\n${importHandlers.filter((verbOption) => verbOption.tags[0] === tag).map((verbOption) => ` ${verbOption.operationName}Handlers`).join(`, \n`)}\n} from '${generateModuleSpecifier(compositeRouteInfo.path, nodePath.join(targetInfo.dirname, tag), output.tsconfig)}/${tag}.handlers${getImportExtension(targetInfo.extension, output.tsconfig)}';`;
|
|
808
826
|
}).join("\n");
|
|
809
827
|
}
|
|
810
828
|
return [{
|
|
@@ -819,12 +837,12 @@ export default app;
|
|
|
819
837
|
}];
|
|
820
838
|
};
|
|
821
839
|
const generateExtraFiles = async (verbOptions, output, context) => {
|
|
822
|
-
const { path, pathWithoutExtension } = getFileInfo(output.target);
|
|
840
|
+
const { path, pathWithoutExtension, extension } = getFileInfo(output.target, { extension: output.fileExtension });
|
|
823
841
|
const validator = generateZvalidator(output, context);
|
|
824
842
|
let schemaModule;
|
|
825
843
|
if (output.schemas != void 0) schemaModule = getFileInfo(isObject(output.schemas) ? output.schemas.path : output.schemas).dirname;
|
|
826
844
|
else if (output.mode === "single") schemaModule = path;
|
|
827
|
-
else schemaModule = `${pathWithoutExtension}.schemas`;
|
|
845
|
+
else schemaModule = `${pathWithoutExtension}.schemas${extension}`;
|
|
828
846
|
const contexts = generateContextFiles(verbOptions, output, context, schemaModule);
|
|
829
847
|
const compositeRoutes = output.override.hono.compositeRoute ? generateCompositeRoutes(verbOptions, output, context) : [];
|
|
830
848
|
const [handlers, zods] = await Promise.all([generateHandlerFiles(verbOptions, output, context, validator.path), generateZodFiles(verbOptions, output, context)]);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/handler-merge.ts","../src/route.ts","../src/index.ts"],"sourcesContent":["import type * as TS from 'typescript';\n\n/**\n * AST-based reconciliation of an existing hono handler file.\n *\n * The `smart` handler strategy regenerates only the regions orval owns — its own\n * imports (names + module specifier) and the `zValidator(...)` arguments of each\n * handler — while leaving every user-authored construct untouched: custom imports,\n * middleware passed to `factory.createHandlers(...)`, the `async (c) => { ... }`\n * body, and any top-level helpers, constants, types, or comments.\n *\n * We edit the original source text in place using node offsets from the\n * TypeScript compiler API, so formatting and comments of untouched regions are\n * preserved. On any parse failure we return the source unchanged — user code is\n * never destroyed by a parser hiccup.\n */\n\n/**\n * `typescript` is an optional peer dependency, imported lazily. Consumers who do\n * not have it installed — and every non-hono or `skip` code path — never trigger\n * the import; `smart`/`full` fall back to `skip` when it is unavailable. Loading\n * the consumer's own typescript also avoids shipping a second copy of it.\n */\nlet ts!: typeof TS;\nlet typeScriptAvailable: boolean | undefined;\n\nexport const ensureTypeScript = async (): Promise<boolean> => {\n if (typeScriptAvailable === undefined) {\n try {\n const mod = await import('typescript');\n ts = (mod as unknown as { default?: typeof TS }).default ?? mod;\n typeScriptAvailable = true;\n } catch {\n typeScriptAvailable = false;\n }\n }\n return typeScriptAvailable;\n};\n\nexport type ValidatorTarget =\n | 'header'\n | 'param'\n | 'query'\n | 'json'\n | 'form'\n | 'response';\n\nexport interface DesiredValidator {\n target: ValidatorTarget;\n /** PascalCase zod schema identifier, e.g. `VerifyAccountResponse`. */\n schema: string;\n}\n\nexport interface DesiredHandler {\n /** e.g. `verifyAccountHandlers`. */\n handlerName: string;\n /** Validators required by the spec, in canonical order. */\n validators: DesiredValidator[];\n /** Full handler block, used only when the handler is missing and appended. */\n stub: string;\n}\n\nexport interface OrvalImport {\n names: string[];\n /** Module specifier as orval would emit it (relative, extensionless). */\n module: string;\n}\n\nexport interface DesiredImports {\n /** `createFactory` from `hono/factory`. */\n factory: OrvalImport;\n /** `zValidator` from the validator module; omitted when no validators exist. */\n validator?: OrvalImport;\n /** `<Op>Context` identifiers from the context module. */\n context: OrvalImport;\n /** zod schema identifiers from the zod module; omitted when none are needed. */\n zod?: OrvalImport;\n}\n\nconst VALIDATOR_TARGETS = new Set<string>([\n 'header',\n 'param',\n 'query',\n 'json',\n 'form',\n 'response',\n]);\n\ninterface Edit {\n start: number;\n end: number;\n text: string;\n}\n\nconst parse = (source: string): TS.SourceFile | undefined => {\n const sourceFile = ts.createSourceFile(\n 'handler.ts',\n source,\n ts.ScriptTarget.Latest,\n /* setParentNodes */ true,\n ts.ScriptKind.TS,\n );\n const diagnostics = (\n sourceFile as unknown as { parseDiagnostics?: TS.Diagnostic[] }\n ).parseDiagnostics;\n if (diagnostics && diagnostics.length > 0) return undefined;\n return sourceFile;\n};\n\ninterface ParsedHandler {\n name: string;\n call: TS.CallExpression;\n}\n\nconst findHandlers = (sourceFile: TS.SourceFile): ParsedHandler[] => {\n const handlers: ParsedHandler[] = [];\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue;\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name)) continue;\n const name = declaration.name.text;\n if (!name.endsWith('Handlers')) continue;\n const init = declaration.initializer;\n if (\n init &&\n ts.isCallExpression(init) &&\n ts.isPropertyAccessExpression(init.expression) &&\n init.expression.name.text === 'createHandlers'\n ) {\n handlers.push({ name, call: init });\n }\n }\n }\n return handlers;\n};\n\nconst importedNames = (declaration: TS.ImportDeclaration): string[] => {\n const bindings = declaration.importClause?.namedBindings;\n if (!bindings || !ts.isNamedImports(bindings)) return [];\n return bindings.elements.map((element) => element.name.text);\n};\n\nconst moduleText = (declaration: TS.ImportDeclaration): string =>\n ts.isStringLiteral(declaration.moduleSpecifier)\n ? declaration.moduleSpecifier.text\n : '';\n\n/**\n * A \"plain\" named import — no default binding, no namespace (`* as x`), and no\n * aliases (`x as y`). Only plain named imports are safe for orval to rewrite;\n * default / namespace / aliased / mixed imports are user-authored and must be\n * left untouched.\n */\nconst isPlainNamedImport = (declaration: TS.ImportDeclaration): boolean => {\n const clause = declaration.importClause;\n if (!clause || clause.name) return false;\n const bindings = clause.namedBindings;\n if (!bindings || !ts.isNamedImports(bindings)) return false;\n return bindings.elements.every(\n (element) => element.propertyName === undefined,\n );\n};\n\nconst setEquals = (a: string[], b: string[]): boolean =>\n a.length === b.length && a.every((value) => b.includes(value));\n\n// Escape regex metacharacters so an identifier can be interpolated literally.\n// JS identifiers may contain `$`, which would otherwise act as an anchor.\nconst escapeRegExp = (value: string): string =>\n value.replaceAll(/[.*+?^${}()|[\\]\\\\]/g, String.raw`\\$&`);\n\n/**\n * The local binding name an imported symbol is bound to, honouring aliases —\n * e.g. `import { zValidator as zv }` → `'zv'`. Returns undefined when the symbol\n * is not imported. Used so a handler that aliases `zValidator` is detected and\n * its new validators are inserted under the same alias (never an unimported name).\n */\nconst localNameFor = (\n importDeclarations: TS.ImportDeclaration[],\n importedName: string,\n module: string,\n): string | undefined => {\n for (const declaration of importDeclarations) {\n if (moduleText(declaration) !== module) continue;\n const bindings = declaration.importClause?.namedBindings;\n if (!bindings || !ts.isNamedImports(bindings)) continue;\n for (const element of bindings.elements) {\n if ((element.propertyName?.text ?? element.name.text) === importedName) {\n return element.name.text;\n }\n }\n }\n return undefined;\n};\n\nconst renderImport = ({ names, module }: OrvalImport): string =>\n names.length <= 1\n ? `import { ${names.join('')} } from '${module}';`\n : `import {\\n ${names.join(',\\n ')}\\n} from '${module}';`;\n\nconst lineStart = (source: string, position: number): number =>\n source.lastIndexOf('\\n', position - 1) + 1;\n\n/** Whether only whitespace sits between the line start and `position`. */\nconst startsLine = (source: string, position: number): boolean =>\n /^\\s*$/.test(source.slice(lineStart(source, position), position));\n\nexport const reconcileHandlerFile = async (\n source: string,\n desired: { imports: DesiredImports; handlers: DesiredHandler[] },\n): Promise<string> => {\n if (!(await ensureTypeScript())) return source;\n\n const sourceFile = parse(source);\n if (!sourceFile) return source;\n\n const edits: Edit[] = [];\n const importDeclarations = sourceFile.statements.filter(\n (statement): statement is TS.ImportDeclaration =>\n ts.isImportDeclaration(statement),\n );\n const handlers = findHandlers(sourceFile);\n const existingNames = new Set(handlers.map((handler) => handler.name));\n const pendingInsertions: string[] = [];\n\n // Locate an orval-owned import by its module specifier (authoritative).\n const byModule = (module: string): TS.ImportDeclaration | undefined =>\n module\n ? importDeclarations.find(\n (declaration) => moduleText(declaration) === module,\n )\n : undefined;\n\n // Fallback used only when the module specifier has moved: a PLAIN named import\n // whose names are EXACTLY `signature` (case-sensitive). This relocates an\n // orval import without the case-folding hazard of fuzzy name matching, which\n // could otherwise clobber an unrelated user import (e.g. `listPetsResponse`).\n const plainExact = (signature: string[]): TS.ImportDeclaration | undefined =>\n signature.length === 0\n ? undefined\n : importDeclarations.find(\n (declaration) =>\n isPlainNamedImport(declaration) &&\n setEquals(importedNames(declaration), signature),\n );\n\n const removeImportEdit = (declaration: TS.ImportDeclaration) => {\n let end = declaration.getEnd();\n if (source.slice(end, end + 2) === '\\r\\n') end += 2;\n else if (source[end] === '\\n') end += 1;\n edits.push({ start: declaration.getStart(sourceFile), end, text: '' });\n };\n\n // Whether `name` is already bound as a bare identifier by some import (a named\n // import's local name, or a default import). Namespace imports do NOT bind\n // their members bare. Used to avoid duplicate imports when augmenting.\n const isImportedBare = (name: string): boolean =>\n importDeclarations.some((declaration) => {\n const clause = declaration.importClause;\n if (!clause) return false;\n if (clause.name?.text === name) return true;\n return importedNames(declaration).includes(name);\n });\n\n /**\n * Reconcile an orval-owned import to `names`. We only rewrite/remove a PLAIN\n * named import whose names are ALL orval-owned (per `isOrvalName`). A\n * user-authored import (aliased / namespace / default / mixed) is never\n * rewritten; instead, when `augment` is provided, we add any orval name that\n * is genuinely needed as a bare reference but isn't yet importable bare — e.g.\n * a newly appended handler's context, or a newly-inserted validator's schema.\n */\n const reconcileImport = (\n existing: TS.ImportDeclaration | undefined,\n names: string[],\n module: string,\n isOrvalName: (name: string) => boolean,\n augment?: (name: string) => boolean,\n collectRenames?: Map<string, string>,\n ) => {\n if (!existing) {\n // Never insert a name that is already bound bare elsewhere (e.g. a default\n // or namespace import from another module) — that would create a duplicate\n // binding.\n const toInsert = (\n augment ? names.filter((name) => augment(name)) : names\n ).filter((name) => !isImportedBare(name));\n if (toInsert.length > 0) {\n pendingInsertions.push(renderImport({ names: toInsert, module }));\n }\n return;\n }\n\n const isOurs =\n isPlainNamedImport(existing) &&\n importedNames(existing).every((name) => isOrvalName(name));\n if (!isOurs) {\n if (augment) {\n const missing = names.filter(\n (name) => augment(name) && !isImportedBare(name),\n );\n if (missing.length > 0) {\n pendingInsertions.push(renderImport({ names: missing, module }));\n }\n }\n return;\n }\n\n if (names.length === 0) {\n removeImportEdit(existing);\n return;\n }\n\n if (\n setEquals(importedNames(existing), names) &&\n moduleText(existing) === module\n ) {\n return;\n }\n\n // Record the camelCase→PascalCase migrations this rewrite implies, so every\n // OTHER reference to the old binding (validator args, `z.infer<typeof X>` in\n // bodies, etc.) can be renamed too — not just the import itself.\n if (collectRenames) {\n for (const old of importedNames(existing)) {\n const next = names.find(\n (name) => name !== old && name.toLowerCase() === old.toLowerCase(),\n );\n if (next) collectRenames.set(old, next);\n }\n }\n\n edits.push({\n start: existing.getStart(sourceFile),\n end: existing.getEnd(),\n text: renderImport({ names, module }),\n });\n };\n\n // --- validators first, so schema names referenced by reconciled validators\n // (newly inserted, or renamed camelCase → PascalCase) are known to the import\n // step below. The local name `zValidator` is bound to in the DESIRED validator\n // module (honours `import { zValidator as zv } from '<validatorModule>'`); a\n // zValidator imported from a different module is the user's own and ignored,\n // so new validators always route through orval's validator. ---\n const validatorModule = desired.imports.validator?.module ?? '';\n const zValidatorName = validatorModule\n ? (localNameFor(importDeclarations, 'zValidator', validatorModule) ??\n 'zValidator')\n : 'zValidator';\n\n const requiredSchemas = new Set<string>();\n const removedValidatorRanges: [number, number][] = [];\n for (const desiredHandler of desired.handlers) {\n const parsed = handlers.find(\n (handler) => handler.name === desiredHandler.handlerName,\n );\n if (parsed) {\n reconcileValidators(\n sourceFile,\n source,\n parsed.call,\n desiredHandler.validators,\n edits,\n zValidatorName,\n requiredSchemas,\n removedValidatorRanges,\n );\n }\n }\n\n // Schema migrations (old camelCase → new PascalCase) implied by rewriting the\n // zod import; applied file-wide below so every reference is migrated.\n const schemaRenames = new Map<string, string>();\n\n const toAppend = desired.handlers.filter(\n (handler) => !existingNames.has(handler.handlerName),\n );\n\n // --- imports ---\n // Source with import declarations blanked out, so an import's own text (e.g.\n // `import { ListPetsResponse as Resp }`) is never counted as a usage.\n let bodySource = source;\n for (const declaration of importDeclarations) {\n const start = declaration.getStart(sourceFile);\n const end = declaration.getEnd();\n bodySource =\n bodySource.slice(0, start) +\n ' '.repeat(end - start) +\n bodySource.slice(end);\n }\n\n // A name needs a bare import when it is referenced unqualified in the body\n // (not as `Ns.Name`), is a schema a reconciled validator now references\n // (inserted or renamed), or is used by an appended handler stub.\n const referencedBare = (name: string): boolean =>\n new RegExp(String.raw`(?<!\\.)\\b${escapeRegExp(name)}\\b`).test(bodySource);\n const inAppendedStub = (name: string): boolean =>\n toAppend.some((handler) => handler.stub.includes(name));\n const needsBareContext = (name: string): boolean =>\n referencedBare(name) || inAppendedStub(name);\n const needsBareZod = (name: string): boolean =>\n referencedBare(name) || requiredSchemas.has(name) || inAppendedStub(name);\n\n // Context types are orval-owned only where a handler references one bare (a\n // typed `async (c: XContext)`) or an appended stub uses it. Match by EXACT\n // orval name — never `endsWith('Context')`, which would clobber a user import\n // such as `getCommunityFilterContext`.\n const contextNames = desired.imports.context.names.filter((name) =>\n needsBareContext(name),\n );\n const zodLower = new Set(\n (desired.imports.zod?.names ?? []).map((name) => name.toLowerCase()),\n );\n\n const factoryModule = desired.imports.factory.module;\n reconcileImport(\n byModule(factoryModule) ?? plainExact(['createFactory']),\n desired.imports.factory.names,\n factoryModule,\n (name) => name === 'createFactory',\n );\n\n reconcileImport(\n byModule(validatorModule) ?? plainExact(['zValidator']),\n desired.imports.validator ? ['zValidator'] : [],\n validatorModule,\n (name) => name === 'zValidator',\n );\n\n reconcileImport(\n byModule(desired.imports.context.module) ?? plainExact(contextNames),\n contextNames,\n desired.imports.context.module,\n (name) => desired.imports.context.names.includes(name),\n needsBareContext,\n );\n\n const zodModule = desired.imports.zod?.module ?? '';\n const zodNames = desired.imports.zod?.names ?? [];\n reconcileImport(\n byModule(zodModule) ?? plainExact(zodNames),\n zodNames,\n zodModule,\n (name) => zodLower.has(name.toLowerCase()),\n needsBareZod,\n schemaRenames,\n );\n\n // Apply the schema migrations file-wide: rename every remaining reference to a\n // migrated schema (validator args, `z.infer<typeof X>` in bodies, helper code).\n // The import is rewritten above (its decl range is skipped here); ranges of\n // removed validators are skipped too (their args are already deleted).\n if (schemaRenames.size > 0) {\n const inSkippedRange = (pos: number): boolean =>\n importDeclarations.some(\n (declaration) =>\n pos >= declaration.getStart(sourceFile) && pos < declaration.getEnd(),\n ) ||\n removedValidatorRanges.some(([start, end]) => pos >= start && pos < end);\n\n const renameReferences = (node: TS.Node): void => {\n if (ts.isIdentifier(node)) {\n const replacement = schemaRenames.get(node.text);\n if (replacement) {\n const parent = node.parent;\n const isMemberName =\n ts.isPropertyAccessExpression(parent) && parent.name === node;\n const isDeclarationName =\n (ts.isVariableDeclaration(parent) && parent.name === node) ||\n (ts.isParameter(parent) && parent.name === node) ||\n (ts.isBindingElement(parent) && parent.name === node) ||\n (ts.isPropertyAssignment(parent) && parent.name === node) ||\n (ts.isPropertySignature(parent) && parent.name === node);\n const start = node.getStart(sourceFile);\n if (!isMemberName && !isDeclarationName && !inSkippedRange(start)) {\n edits.push({ start, end: node.getEnd(), text: replacement });\n }\n }\n }\n ts.forEachChild(node, renameReferences);\n };\n renameReferences(sourceFile);\n }\n\n if (pendingInsertions.length > 0) {\n const lastImport = importDeclarations.at(-1);\n let insertPos = 0;\n if (lastImport) {\n // Guard the EOF case: when the last import has no trailing newline,\n // indexOf returns -1 and `+ 1` would prepend to the top of the file.\n const newline = source.indexOf('\\n', lastImport.getEnd());\n insertPos = newline === -1 ? source.length : newline + 1;\n }\n edits.push({\n start: insertPos,\n end: insertPos,\n text: pendingInsertions.map((line) => `${line}\\n`).join(''),\n });\n }\n\n if (toAppend.length > 0) {\n edits.push({\n start: source.length,\n end: source.length,\n text: toAppend.map((handler) => handler.stub).join(''),\n });\n }\n\n return applyEdits(source, edits);\n};\n\nconst reconcileValidators = (\n sourceFile: TS.SourceFile,\n source: string,\n call: TS.CallExpression,\n desiredValidators: DesiredValidator[],\n edits: Edit[],\n zValidatorName: string,\n requiredSchemas: Set<string>,\n removedRanges: [number, number][],\n) => {\n const existing: { target: string; arg: TS.CallExpression }[] = [];\n\n for (const arg of call.arguments) {\n if (\n ts.isCallExpression(arg) &&\n ts.isIdentifier(arg.expression) &&\n arg.expression.text === zValidatorName\n ) {\n const target = arg.arguments[0];\n if (\n arg.arguments.length > 0 &&\n ts.isStringLiteralLike(target) &&\n VALIDATOR_TARGETS.has(target.text)\n ) {\n existing.push({ target: target.text, arg });\n }\n }\n }\n\n const desiredByTarget = new Map(\n desiredValidators.map((validator) => [validator.target, validator]),\n );\n const existingByTarget = new Set(existing.map((item) => item.target));\n\n // Remove validators the spec no longer requires. (Schema RENAMES — e.g.\n // camelCase→PascalCase — are handled by the file-wide rename pass driven by the\n // zod-import rewrite, so every reference is migrated, not just the arg here.)\n for (const item of existing) {\n if (!desiredByTarget.has(item.target as ValidatorTarget)) {\n const edit = removeArgumentEdit(sourceFile, source, item.arg);\n edits.push(edit);\n removedRanges.push([edit.start, edit.end]);\n }\n }\n\n const missing = desiredValidators.filter(\n (validator) => !existingByTarget.has(validator.target),\n );\n if (missing.length > 0) {\n const insertPos = validatorInsertPos(sourceFile, source, call);\n const text = missing\n .map((validator) => {\n requiredSchemas.add(validator.schema);\n return ` ${zValidatorName}('${validator.target}', ${validator.schema}),\\n`;\n })\n .join('');\n edits.push({ start: insertPos, end: insertPos, text });\n }\n};\n\n/** Position to insert new validators: the line start of the trailing handler. */\nconst validatorInsertPos = (\n sourceFile: TS.SourceFile,\n source: string,\n call: TS.CallExpression,\n): number => {\n // The handler is the LAST function argument; earlier function args may be\n // inline middleware, so search from the end.\n const handler = call.arguments.findLast(\n (arg) => ts.isArrowFunction(arg) || ts.isFunctionExpression(arg),\n );\n if (handler) {\n // Insert at the handler's line start when it's on its own line; otherwise\n // (single-line `createHandlers(async (c) => {})`) insert right before it so\n // the validator isn't pushed to the start of the statement.\n const start = handler.getStart(sourceFile);\n return startsLine(source, start) ? lineStart(source, start) : start;\n }\n // No trailing handler found — insert just before the closing paren.\n return call.getEnd() - 1;\n};\n\nconst removeArgumentEdit = (\n sourceFile: TS.SourceFile,\n source: string,\n arg: TS.Node,\n): Edit => {\n const argStart = arg.getStart(sourceFile);\n const start = startsLine(source, argStart)\n ? lineStart(source, argStart)\n : argStart;\n\n const commaIdx = source.indexOf(',', arg.getEnd());\n let end = commaIdx === -1 ? arg.getEnd() : commaIdx + 1;\n while (source[end] === ' ' || source[end] === '\\t') end += 1;\n if (source.slice(end, end + 2) === '\\r\\n') end += 2;\n else if (source[end] === '\\n') end += 1;\n\n return { start, end, text: '' };\n};\n\nconst applyEdits = (source: string, edits: Edit[]): string => {\n let result = source;\n for (const edit of edits.toSorted((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);\n }\n return result;\n};\n\n/**\n * Extracts the inner body of each handler's `async (c) => { ... }` block, keyed\n * by handler name. Used by the `full` strategy to splice user bodies back into a\n * freshly-regenerated wrapper. Returns `undefined` when the source can't be\n * parsed (or typescript is unavailable) — distinct from an empty map (parsed, no\n * handlers) — so callers can preserve the file instead of dropping its bodies.\n */\nexport const extractHandlerBodies = async (\n source: string,\n): Promise<Map<string, string> | undefined> => {\n if (!(await ensureTypeScript())) return undefined;\n\n const sourceFile = parse(source);\n if (!sourceFile) return undefined;\n\n const bodies = new Map<string, string>();\n for (const { name, call } of findHandlers(sourceFile)) {\n // The handler is the LAST function argument (earlier ones may be inline\n // middleware), so its body — not a middleware's — is what `full` splices.\n const handler = call.arguments.findLast(\n (arg) => ts.isArrowFunction(arg) || ts.isFunctionExpression(arg),\n );\n if (handler?.body && ts.isBlock(handler.body)) {\n const bodyStart = handler.body.getStart(sourceFile) + 1;\n const bodyEnd = handler.body.getEnd() - 1;\n bodies.set(name, source.slice(bodyStart, bodyEnd));\n }\n }\n\n return bodies;\n};\n","import { sanitize } from '@orval/core';\n\nconst hasParam = (path: string): boolean => /[^{]*{[\\w*_-]*}.*/.test(path);\n\nconst getRoutePath = (path: string): string => {\n const matches = /([^{]*){?([\\w*_-]*)}?(.*)/.exec(path);\n if (!matches?.length) return path; // impossible due to regexp grouping here, but for TS\n\n const prev = matches[1];\n const param = sanitize(matches[2], {\n es5keyword: true,\n underscore: true,\n dash: true,\n dot: true,\n });\n const next = hasParam(matches[3]) ? getRoutePath(matches[3]) : matches[3];\n\n return hasParam(path) ? `${prev}:${param}${next}` : `${prev}${param}${next}`;\n};\n\nexport const getRoute = (route: string) => {\n const splittedRoute = route.split('/');\n\n let acc = '';\n for (const [i, path] of splittedRoute.entries()) {\n if (!path && i === 0) continue;\n\n acc += path.includes('{') ? `/${getRoutePath(path)}` : `/${path}`;\n }\n\n return acc;\n};\n","import nodePath from 'node:path';\n\nimport {\n camel,\n type ClientBuilder,\n type ClientExtraFilesBuilder,\n type ClientFooterBuilder,\n type ClientGeneratorsBuilder,\n type ClientHeaderBuilder,\n type ContextSpec,\n generateMutatorImports,\n type GeneratorDependency,\n type GeneratorImport,\n type GeneratorVerbOptions,\n getFileInfo,\n getOrvalGeneratedTypes,\n getParamsInPath,\n type HonoHandlerStrategy,\n isObject,\n jsDoc,\n kebab,\n logWarning,\n type NormalizedMutator,\n type NormalizedOutputOptions,\n type OpenApiInfoObject,\n pascal,\n sanitize,\n upath,\n} from '@orval/core';\nimport { generateZod } from '@orval/zod';\nimport fs from 'fs-extra';\n\nimport {\n type DesiredImports,\n type DesiredValidator,\n ensureTypeScript,\n extractHandlerBodies,\n reconcileHandlerFile,\n} from './handler-merge';\nimport { getRoute } from './route';\n\n// Warn at most once per run when the optional `typescript` peer is missing and a\n// non-`skip` strategy was requested, so the degraded behavior is never silent.\nlet warnedMissingTypeScript = false;\n\nconst ZVALIDATOR_SOURCE = fs\n .readFileSync(nodePath.join(import.meta.dirname, 'zValidator.ts'))\n .toString('utf8');\n\nconst HONO_DEPENDENCIES: GeneratorDependency[] = [\n {\n exports: [\n {\n name: 'Hono',\n values: true,\n },\n {\n name: 'Context',\n },\n {\n name: 'Env',\n },\n ],\n dependency: 'hono',\n },\n];\n\n/**\n * generateModuleSpecifier generates the specifier that _from_ would use to\n * import _to_. This is syntactical and does not validate the paths.\n *\n * @param from The filesystem path to the importer.\n * @param to If a filesystem path, it and _from_ must be use the same frame of\n * reference, such as process.cwd() or both be absolute. If only one is\n * absolute, the other must be relative to process.cwd().\n *\n * Otherwise, treated as a package name and returned directly.\n *\n * @return A module specifier that can be used at _from_ to import _to_. It is\n * extensionless to conform with the rest of orval.\n */\nconst generateModuleSpecifier = (from: string, to: string) => {\n if (to.startsWith('.') || nodePath.isAbsolute(to)) {\n return upath\n .getRelativeImportPath(nodePath.resolve(from), nodePath.resolve(to), true)\n .replace(/\\.ts$/, '');\n }\n\n // Not a relative or absolute file path. Import as-is.\n return to;\n};\n\nexport const getHonoDependencies = () => HONO_DEPENDENCIES;\n\nexport const getHonoHeader: ClientHeaderBuilder = ({\n verbOptions,\n output,\n tag,\n clientImplementation,\n}) => {\n const targetInfo = getFileInfo(output.target);\n\n let handlers: string;\n\n const importHandlers = Object.values(verbOptions).filter((verbOption) =>\n clientImplementation.includes(`${verbOption.operationName}Handlers`),\n );\n\n if (output.override.hono.handlers) {\n const handlerFileInfo = getFileInfo(output.override.hono.handlers);\n handlers = importHandlers\n .map((verbOption) => {\n // Only `tags-split` puts each tag's client file inside its own\n // sub-directory. `tags` mode flattens them next to `target`, so the\n // import must be resolved from `targetInfo.dirname` directly.\n const isSplitDir = output.mode === 'tags-split';\n const tag = kebab(verbOption.tags[0] ?? 'default');\n\n const handlersPath = upath.relativeSafe(\n nodePath.join(targetInfo.dirname, isSplitDir ? tag : ''),\n nodePath.join(\n handlerFileInfo.dirname,\n `./${verbOption.operationName}`,\n ),\n );\n\n return `import { ${verbOption.operationName}Handlers } from '${handlersPath}';`;\n })\n .join('\\n');\n } else {\n const importHandlerNames = importHandlers\n .map((verbOption) => ` ${verbOption.operationName}Handlers`)\n .join(`, \\n`);\n\n handlers = `import {\\n${importHandlerNames}\\n} from './${tag ?? targetInfo.filename}.handlers';`;\n }\n\n return `${handlers}\\n\\nconst app = new Hono()\\n`;\n};\n\nexport const getHonoFooter: ClientFooterBuilder = () =>\n ';\\n\\nexport default app;\\n';\n\nconst generateHonoRoute = (\n { operationName, verb }: GeneratorVerbOptions,\n pathRoute: string,\n) => {\n const path = getRoute(pathRoute);\n\n return `\\n .${verb.toLowerCase()}('${path}', ...${operationName}Handlers)`;\n};\n\nexport const generateHono: ClientBuilder = (verbOptions, options) => {\n if (options.override.hono.compositeRoute) {\n return {\n implementation: '',\n imports: [],\n };\n }\n\n const routeImplementation = generateHonoRoute(verbOptions, options.pathRoute);\n\n return {\n implementation: `${routeImplementation}\\n`,\n imports: [\n ...verbOptions.params.flatMap((param) => param.imports),\n ...verbOptions.body.imports,\n ...(verbOptions.queryParams\n ? [\n {\n name: verbOptions.queryParams.schema.name,\n },\n ]\n : []),\n ],\n };\n};\n\n/**\n * getHonoHandlers generates TypeScript code for the given verbs and reports\n * whether the code requires zValidator.\n */\nconst DEFAULT_HANDLER_BODY = '\\n\\n ';\n\nconst FORM_CONTENT_TYPES = new Set([\n 'multipart/form-data',\n 'application/x-www-form-urlencoded',\n]);\n\n/**\n * Whether a request body uses a form encoding. Hono validates these with\n * `zValidator('form', …)` against `c.req.parseBody()`, not `'json'`.\n */\nconst isFormBody = (body: GeneratorVerbOptions['body']): boolean =>\n FORM_CONTENT_TYPES.has(body.contentType);\n\n/**\n * getDesiredValidators returns the `zValidator` targets (and their PascalCase zod\n * schema identifiers) required by a verb, in canonical order. This is the single\n * source of truth shared by fresh generation and the `smart` reconcile.\n */\nconst getDesiredValidators = (\n verbOption: GeneratorVerbOptions,\n validator: boolean | 'hono' | NormalizedMutator,\n): DesiredValidator[] => {\n if (!validator) return [];\n\n const pascalOperationName = pascal(verbOption.operationName);\n const validators: DesiredValidator[] = [];\n\n if (verbOption.headers) {\n validators.push({\n target: 'header',\n schema: `${pascalOperationName}Header`,\n });\n }\n if (verbOption.params.length > 0) {\n validators.push({\n target: 'param',\n schema: `${pascalOperationName}Params`,\n });\n }\n if (verbOption.queryParams) {\n validators.push({\n target: 'query',\n schema: `${pascalOperationName}QueryParams`,\n });\n }\n if (verbOption.body.definition) {\n validators.push({\n target: isFormBody(verbOption.body) ? 'form' : 'json',\n schema: `${pascalOperationName}Body`,\n });\n }\n if (\n validator !== 'hono' &&\n verbOption.response.originalSchema?.['200']?.content?.[\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n 'application/json'\n ]\n ) {\n validators.push({\n target: 'response',\n schema: `${pascalOperationName}Response`,\n });\n }\n\n return validators;\n};\n\nconst getHonoHandlers = (\n ...opts: {\n handlerName: string;\n contextTypeName: string;\n verbOption: GeneratorVerbOptions;\n validator: boolean | 'hono' | NormalizedMutator;\n /**\n * Optional async-handler body to splice into the generated wrapper. Used by\n * the `full` strategy to preserve user logic across regeneration.\n */\n bodyOverride?: string;\n }[]\n): [\n /** The combined TypeScript handler code snippets. */\n handlerCode: string,\n /** Whether any of the handler code snippets requires importing zValidator. */\n hasZValidator: boolean,\n] => {\n let code = '';\n let hasZValidator = false;\n\n for (const {\n handlerName,\n contextTypeName,\n verbOption,\n validator,\n bodyOverride,\n } of opts) {\n const currentValidator = getDesiredValidators(verbOption, validator)\n .map((v) => `zValidator('${v.target}', ${v.schema}),\\n`)\n .join('');\n\n const body = bodyOverride ?? DEFAULT_HANDLER_BODY;\n\n code += `\nexport const ${handlerName} = factory.createHandlers(\n${currentValidator}async (c: ${contextTypeName}) => {${body}},\n);`;\n\n hasZValidator ||= currentValidator !== '';\n }\n\n return [code, hasZValidator];\n};\n\nconst getZvalidatorImports = (\n verbOptions: GeneratorVerbOptions[],\n importPath: string,\n isHonoValidator: boolean,\n) => {\n const specifiers = [];\n\n for (const {\n operationName,\n headers,\n params,\n queryParams,\n body,\n response,\n } of verbOptions) {\n const pascalOperationName = pascal(operationName);\n\n if (headers) {\n specifiers.push(`${pascalOperationName}Header`);\n }\n\n if (params.length > 0) {\n specifiers.push(`${pascalOperationName}Params`);\n }\n\n if (queryParams) {\n specifiers.push(`${pascalOperationName}QueryParams`);\n }\n\n if (body.definition) {\n specifiers.push(`${pascalOperationName}Body`);\n }\n\n if (\n !isHonoValidator &&\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n response.originalSchema?.['200']?.content?.['application/json'] !=\n undefined\n ) {\n specifiers.push(`${pascalOperationName}Response`);\n }\n }\n\n return specifiers.length === 0\n ? ''\n : `import {\\n${specifiers.join(',\\n')}\\n} from '${importPath}'`;\n};\n\nconst getVerbOptionGroupByTag = (\n verbOptions: Record<string, GeneratorVerbOptions>,\n) => {\n const grouped: Record<string, GeneratorVerbOptions[]> = {};\n\n for (const value of Object.values(verbOptions)) {\n const tag = value.tags[0];\n // this is not always false\n // TODO look into types\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!grouped[tag]) {\n grouped[tag] = [];\n }\n grouped[tag].push(value);\n }\n\n return grouped;\n};\n\n/** Computes the orval-owned imports a handler file should contain. */\nconst buildDesiredImports = ({\n verbList,\n path,\n validatorModule,\n zodModule,\n contextModule,\n validator,\n}: {\n verbList: GeneratorVerbOptions[];\n path: string;\n validatorModule?: string;\n zodModule: string;\n contextModule: string;\n validator: boolean | 'hono';\n}): DesiredImports => {\n const contextNames = verbList.map(\n (verb) => `${pascal(verb.operationName)}Context`,\n );\n const zodNames = verbList.flatMap((verb) =>\n getDesiredValidators(verb, validator).map((v) => v.schema),\n );\n const hasValidators = zodNames.length > 0;\n\n return {\n factory: { names: ['createFactory'], module: 'hono/factory' },\n validator:\n hasValidators && validatorModule != undefined\n ? {\n names: ['zValidator'],\n module: generateModuleSpecifier(path, validatorModule),\n }\n : undefined,\n context: {\n names: contextNames,\n module: generateModuleSpecifier(path, contextModule),\n },\n zod: hasValidators\n ? { names: zodNames, module: generateModuleSpecifier(path, zodModule) }\n : undefined,\n };\n};\n\n/** Generates a complete handler file from scratch (no existing file to merge). */\nconst generateFreshHandlerFile = ({\n verbList,\n path,\n header,\n validatorModule,\n zodModule,\n contextModule,\n validator,\n bodyFor,\n}: {\n verbList: GeneratorVerbOptions[];\n path: string;\n header: string;\n validatorModule?: string;\n zodModule: string;\n contextModule: string;\n validator: boolean | 'hono';\n bodyFor?: (operationName: string) => string | undefined;\n}): string => {\n const [handlerCode, hasZValidator] = getHonoHandlers(\n ...verbList.map((verbOption) => ({\n handlerName: `${verbOption.operationName}Handlers`,\n contextTypeName: `${pascal(verbOption.operationName)}Context`,\n verbOption,\n validator,\n bodyOverride: bodyFor?.(verbOption.operationName),\n })),\n );\n\n const imports = [\"import { createFactory } from 'hono/factory';\"];\n\n if (hasZValidator && validatorModule != undefined) {\n imports.push(\n `import { zValidator } from '${generateModuleSpecifier(path, validatorModule)}';`,\n );\n }\n\n imports.push(\n `import { ${verbList\n .map((verb) => `${pascal(verb.operationName)}Context`)\n .join(',\\n')} } from '${generateModuleSpecifier(path, contextModule)}';`,\n );\n\n if (hasZValidator) {\n imports.push(\n getZvalidatorImports(\n verbList,\n generateModuleSpecifier(path, zodModule),\n validatorModule === '@hono/zod-validator',\n ),\n );\n }\n\n return `${header}${imports.filter((imp) => imp !== '').join('\\n')}\\n\\nconst factory = createFactory();${handlerCode}`;\n};\n\n/**\n * Generates or updates a handler file according to `strategy`:\n *\n * - a non-existent file is always freshly generated;\n * - `skip` leaves an existing file byte-for-byte unchanged;\n * - `full` rebuilds the preamble + validator chain and splices back user bodies\n * (drops custom imports/middleware/helpers — the thin-handler model);\n * - `smart` non-destructively reconciles orval-owned imports + validators and\n * appends handlers for new operations, preserving all user-authored code.\n */\nexport const generateHandlerFile = async ({\n verbs,\n path,\n header,\n validatorModule,\n zodModule,\n contextModule,\n strategy,\n}: {\n verbs: GeneratorVerbOptions[];\n path: string;\n header: string;\n validatorModule?: string;\n zodModule: string;\n contextModule: string;\n strategy: HonoHandlerStrategy;\n}) => {\n const validator =\n validatorModule === '@hono/zod-validator'\n ? ('hono' as const)\n : validatorModule != undefined;\n\n const verbList = Object.values(verbs);\n\n if (!fs.existsSync(path)) {\n return generateFreshHandlerFile({\n verbList,\n path,\n header,\n validatorModule,\n zodModule,\n contextModule,\n validator,\n });\n }\n\n const source = await fs.readFile(path, 'utf8');\n\n if (strategy === 'skip') {\n return source;\n }\n\n // `smart` and `full` parse the existing file with the TypeScript compiler API.\n // typescript is an optional peer dependency; without it we cannot safely\n // reconcile or splice, so we preserve the existing file untouched and warn.\n if (!(await ensureTypeScript())) {\n if (!warnedMissingTypeScript) {\n warnedMissingTypeScript = true;\n logWarning(\n `hono handlerGenerationStrategy '${strategy}' requires the optional peer dependency \"typescript\", which is not installed. Existing handler files are left unchanged (as with 'skip'). Install typescript to enable handler reconciliation.`,\n );\n }\n return source;\n }\n\n if (strategy === 'full') {\n const bodies = await extractHandlerBodies(source);\n // A parse failure yields `undefined` (not an empty map): preserve the file\n // rather than regenerate with empty bodies and drop the user's logic.\n if (!bodies) {\n return source;\n }\n return generateFreshHandlerFile({\n verbList,\n path,\n header,\n validatorModule,\n zodModule,\n contextModule,\n validator,\n bodyFor: (operationName) => bodies.get(`${operationName}Handlers`),\n });\n }\n\n return reconcileHandlerFile(source, {\n imports: buildDesiredImports({\n verbList,\n path,\n validatorModule,\n zodModule,\n contextModule,\n validator,\n }),\n handlers: verbList.map((verbOption) => ({\n handlerName: `${verbOption.operationName}Handlers`,\n validators: getDesiredValidators(verbOption, validator),\n stub: getHonoHandlers({\n handlerName: `${verbOption.operationName}Handlers`,\n contextTypeName: `${pascal(verbOption.operationName)}Context`,\n verbOption,\n validator,\n })[0],\n })),\n });\n};\n\nconst generateHandlerFiles = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpec,\n validatorModule: string,\n) => {\n const header = getHeader(output.override.header, getSpecInfo(context));\n const { extension, dirname, filename } = getFileInfo(output.target);\n const strategy = output.override.hono.handlerGenerationStrategy;\n\n // This function _does not control_ where the .zod and .context modules land.\n // That determination is made elsewhere and this function must implement the\n // same conventions.\n\n if (output.override.hono.handlers) {\n // One file per operation in the user-provided directory.\n return Promise.all(\n Object.values(verbOptions).map(async (verbOption) => {\n const tag = kebab(verbOption.tags[0] ?? 'default');\n\n const path = nodePath.join(\n output.override.hono.handlers ?? '',\n `./${verbOption.operationName}` + extension,\n );\n\n // Mirror the layout used by generateZodFiles/generateContextFiles so\n // imports resolve to the actual emitted modules.\n let zodModule: string;\n let contextModule: string;\n if (output.mode === 'tags') {\n zodModule = nodePath.join(dirname, `${kebab(tag)}.zod`);\n contextModule = nodePath.join(dirname, `${kebab(tag)}.context`);\n } else if (output.mode === 'tags-split') {\n zodModule = nodePath.join(dirname, tag, tag + '.zod');\n contextModule = nodePath.join(dirname, tag, tag + '.context');\n } else {\n zodModule = nodePath.join(dirname, `${filename}.zod`);\n contextModule = nodePath.join(dirname, `${filename}.context`);\n }\n\n return {\n content: await generateHandlerFile({\n path,\n header,\n verbs: [verbOption],\n validatorModule,\n zodModule,\n contextModule,\n strategy,\n }),\n path,\n };\n }),\n );\n }\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n // One file per operation _tag_ under dirname.\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n return Promise.all(\n Object.entries(groupByTags).map(async ([tag, verbs]) => {\n const handlerPath =\n output.mode === 'tags'\n ? nodePath.join(dirname, `${kebab(tag)}.handlers${extension}`)\n : nodePath.join(dirname, tag, tag + '.handlers' + extension);\n\n return {\n content: await generateHandlerFile({\n path: handlerPath,\n header,\n verbs,\n validatorModule,\n zodModule:\n output.mode === 'tags'\n ? nodePath.join(dirname, `${kebab(tag)}.zod`)\n : nodePath.join(dirname, tag, tag + '.zod'),\n contextModule:\n output.mode === 'tags'\n ? nodePath.join(dirname, `${kebab(tag)}.context`)\n : nodePath.join(dirname, tag, tag + '.context'),\n strategy,\n }),\n path: handlerPath,\n };\n }),\n );\n }\n\n // One file with all operations.\n const handlerPath = nodePath.join(\n dirname,\n `${filename}.handlers${extension}`,\n );\n\n return [\n {\n content: await generateHandlerFile({\n path: handlerPath,\n header,\n verbs: Object.values(verbOptions),\n validatorModule,\n zodModule: nodePath.join(dirname, `${filename}.zod`),\n contextModule: nodePath.join(dirname, `${filename}.context`),\n strategy,\n }),\n path: handlerPath,\n },\n ];\n};\n\nconst getContext = (verbOption: GeneratorVerbOptions) => {\n let paramType = '';\n if (verbOption.params.length > 0) {\n const params = getParamsInPath(verbOption.pathRoute).map((name) => {\n const param = verbOption.params.find(\n (p) => p.name === sanitize(camel(name), { es5keyword: true }),\n );\n const definition = param?.definition.split(':')[1];\n const required = param?.required ?? false;\n return {\n definition: `${name}${required ? '' : '?'}:${definition}`,\n };\n });\n paramType = `param: {\\n ${params\n .map((property) => property.definition)\n .join(',\\n ')},\\n },`;\n }\n\n const queryType = verbOption.queryParams\n ? `query: ${verbOption.queryParams.schema.name},`\n : '';\n const bodyType = verbOption.body.definition\n ? `${isFormBody(verbOption.body) ? 'form' : 'json'}: ${verbOption.body.definition},`\n : '';\n const hasIn = !!paramType || !!queryType || !!bodyType;\n\n return `export type ${pascal(\n verbOption.operationName,\n )}Context<E extends Env = any> = Context<E, '${getRoute(\n verbOption.pathRoute,\n )}'${\n hasIn\n ? `, { in: { ${paramType}${queryType}${bodyType} }, out: { ${paramType}${queryType}${bodyType} } }`\n : ''\n }>`;\n};\n\nconst getHeader = (\n option: false | ((info: OpenApiInfoObject) => string | string[]),\n info: OpenApiInfoObject,\n): string => {\n if (!option) {\n return '';\n }\n\n const header = option(info);\n\n return Array.isArray(header) ? jsDoc({ description: header }) : header;\n};\n\nconst getSpecInfo = (context: ContextSpec): OpenApiInfoObject =>\n context.spec.info ?? {\n title: 'API',\n version: '1.0.0',\n };\n\nconst generateContextFile = ({\n path,\n verbs,\n schemaModule,\n}: {\n path: string;\n verbs: GeneratorVerbOptions[];\n schemaModule: string;\n}) => {\n let content = `import type { Context, Env } from 'hono';\\n\\n`;\n\n const contexts = verbs.map((verb) => getContext(verb));\n\n const imps = new Set(\n verbs\n .flatMap((verb) => {\n const imports: GeneratorImport[] = [];\n if (verb.params.length > 0) {\n imports.push(...verb.params.flatMap((param) => param.imports));\n }\n\n if (verb.queryParams) {\n imports.push({\n name: verb.queryParams.schema.name,\n });\n }\n\n if (verb.body.definition) {\n imports.push(...verb.body.imports);\n }\n\n return imports;\n })\n .map((imp) => imp.name)\n .filter((imp) => contexts.some((context) => context.includes(imp))),\n );\n\n if (contexts.some((context) => context.includes('NonReadonly<'))) {\n content += getOrvalGeneratedTypes();\n content += '\\n';\n }\n\n if (imps.size > 0) {\n content += `import type {\\n${[...imps]\n .toSorted()\n .join(\n ',\\n ',\n )}\\n} from '${generateModuleSpecifier(path, schemaModule)}';\\n\\n`;\n }\n\n content += contexts.join('\\n');\n\n return content;\n};\n\nconst generateContextFiles = (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpec,\n schemaModule: string,\n) => {\n const header = getHeader(output.override.header, getSpecInfo(context));\n const { extension, dirname, filename } = getFileInfo(output.target);\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n return Object.entries(groupByTags).map(([tag, verbs]) => {\n const path =\n output.mode === 'tags'\n ? nodePath.join(dirname, `${kebab(tag)}.context${extension}`)\n : nodePath.join(dirname, tag, tag + '.context' + extension);\n const code = generateContextFile({\n verbs,\n path,\n schemaModule: schemaModule,\n });\n return { content: `${header}${code}`, path };\n });\n }\n\n const path = nodePath.join(dirname, `${filename}.context${extension}`);\n const code = generateContextFile({\n verbs: Object.values(verbOptions),\n path,\n schemaModule: schemaModule,\n });\n\n return [\n {\n content: `${header}${code}`,\n path,\n },\n ];\n};\n\nconst generateZodFiles = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpec,\n) => {\n const { extension, dirname, filename } = getFileInfo(output.target);\n\n const header = getHeader(output.override.header, getSpecInfo(context));\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n const builderContexts = await Promise.all(\n Object.entries(groupByTags).map(async ([tag, verbs]) => {\n const zods = await Promise.all(\n verbs.map(async (verbOption) =>\n generateZod(\n verbOption,\n {\n route: verbOption.route,\n pathRoute: verbOption.pathRoute,\n override: output.override,\n context,\n output: output.target,\n },\n output.client,\n ),\n ),\n );\n\n if (zods.every((z) => z.implementation === '')) {\n return {\n content: '',\n path: '',\n };\n }\n\n const allMutators = new Map(\n zods.flatMap((z) => z.mutators ?? []).map((m) => [m.name, m]),\n )\n .values()\n .toArray();\n\n const mutatorsImports = generateMutatorImports({\n mutators: allMutators,\n oneMore: output.mode === 'tags-split',\n });\n\n let content = `${header}import { z as zod } from 'zod';\\n${mutatorsImports}\\n`;\n\n const zodPath =\n output.mode === 'tags'\n ? nodePath.join(dirname, `${kebab(tag)}.zod${extension}`)\n : nodePath.join(dirname, tag, tag + '.zod' + extension);\n\n content += zods.map((zod) => zod.implementation).join('\\n');\n\n return {\n content,\n path: zodPath,\n };\n }),\n );\n\n return builderContexts.filter((context) => context.content !== '');\n }\n\n const zods = await Promise.all(\n Object.values(verbOptions).map(async (verbOption) =>\n generateZod(\n verbOption,\n {\n route: verbOption.route,\n pathRoute: verbOption.pathRoute,\n override: output.override,\n context,\n output: output.target,\n },\n output.client,\n ),\n ),\n );\n\n const allMutators = new Map(\n zods.flatMap((z) => z.mutators ?? []).map((m) => [m.name, m]),\n )\n .values()\n .toArray();\n\n const mutatorsImports = generateMutatorImports({\n mutators: allMutators,\n });\n\n let content = `${header}import { z as zod } from 'zod';\\n${mutatorsImports}\\n`;\n\n const zodPath = nodePath.join(dirname, `${filename}.zod${extension}`);\n\n content += zods.map((zod) => zod.implementation).join('\\n');\n\n return [\n {\n content,\n path: zodPath,\n },\n ];\n};\n\nconst generateZvalidator = (\n output: NormalizedOutputOptions,\n context: ContextSpec,\n) => {\n const header = getHeader(output.override.header, getSpecInfo(context));\n\n let validatorPath = output.override.hono.validatorOutputPath;\n if (!output.override.hono.validatorOutputPath) {\n const { extension, dirname, filename } = getFileInfo(output.target);\n\n validatorPath = nodePath.join(dirname, `${filename}.validator${extension}`);\n }\n\n return {\n content: `${header}${ZVALIDATOR_SOURCE}`,\n path: validatorPath,\n };\n};\n\nconst generateCompositeRoutes = (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpec,\n) => {\n const targetInfo = getFileInfo(output.target);\n const compositeRouteInfo = getFileInfo(output.override.hono.compositeRoute);\n\n const header = getHeader(output.override.header, getSpecInfo(context));\n\n const routes = Object.values(verbOptions)\n .map((verbOption) => {\n return generateHonoRoute(verbOption, verbOption.pathRoute);\n })\n .join('');\n\n const importHandlers = Object.values(verbOptions);\n\n let ImportHandlersImplementation: string;\n if (output.override.hono.handlers) {\n const handlerFileInfo = getFileInfo(output.override.hono.handlers);\n const operationNames = importHandlers.map(\n (verbOption) => verbOption.operationName,\n );\n\n ImportHandlersImplementation = operationNames\n .map((operationName) => {\n const importHandlerName = `${operationName}Handlers`;\n\n const handlersPath = generateModuleSpecifier(\n compositeRouteInfo.path,\n nodePath.join(handlerFileInfo.dirname, `./${operationName}`),\n );\n\n return `import { ${importHandlerName} } from '${handlersPath}';`;\n })\n .join('\\n');\n } else {\n const tags = importHandlers.map((verbOption) =>\n kebab(verbOption.tags[0] ?? 'default'),\n );\n const uniqueTags = tags.filter((t, i) => tags.indexOf(t) === i);\n\n ImportHandlersImplementation = uniqueTags\n .map((tag) => {\n const importHandlerNames = importHandlers\n .filter((verbOption) => verbOption.tags[0] === tag)\n .map((verbOption) => ` ${verbOption.operationName}Handlers`)\n .join(`, \\n`);\n\n const handlersPath = generateModuleSpecifier(\n compositeRouteInfo.path,\n nodePath.join(targetInfo.dirname, tag),\n );\n\n return `import {\\n${importHandlerNames}\\n} from '${handlersPath}/${tag}.handlers';`;\n })\n .join('\\n');\n }\n\n const honoImport = `import { Hono } from 'hono';`;\n const honoInitialization = `\\nconst app = new Hono()`;\n const honoAppExport = `\\nexport default app;`;\n\n const content = `${header}${honoImport}\n${ImportHandlersImplementation}\n${honoInitialization}${routes};\n${honoAppExport}\n`;\n\n return [\n {\n content,\n path: output.override.hono.compositeRoute || '',\n },\n ];\n};\n\nexport const generateExtraFiles: ClientExtraFilesBuilder = async (\n verbOptions,\n output,\n context,\n) => {\n const { path, pathWithoutExtension } = getFileInfo(output.target);\n const validator = generateZvalidator(output, context);\n let schemaModule: string;\n\n if (output.schemas != undefined) {\n const schemasPath = (\n isObject(output.schemas) ? output.schemas.path : output.schemas\n ) as string;\n const basePath = getFileInfo(schemasPath).dirname;\n schemaModule = basePath;\n } else if (output.mode === 'single') {\n schemaModule = path;\n } else {\n schemaModule = `${pathWithoutExtension}.schemas`;\n }\n\n const contexts = generateContextFiles(\n verbOptions,\n output,\n context,\n schemaModule,\n );\n const compositeRoutes = output.override.hono.compositeRoute\n ? generateCompositeRoutes(verbOptions, output, context)\n : [];\n const [handlers, zods] = await Promise.all([\n generateHandlerFiles(verbOptions, output, context, validator.path),\n generateZodFiles(verbOptions, output, context),\n ]);\n\n return [\n ...handlers,\n ...contexts,\n ...zods,\n ...(output.override.hono.validator &&\n output.override.hono.validator !== 'hono'\n ? [validator]\n : []),\n ...compositeRoutes,\n ];\n};\n\nconst honoClientBuilder: ClientGeneratorsBuilder = {\n client: generateHono,\n dependencies: getHonoDependencies,\n header: getHonoHeader,\n footer: getHonoFooter,\n extraFiles: generateExtraFiles,\n};\n\nexport const builder = () => () => honoClientBuilder;\n\nexport default builder;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/handler-merge.ts","../src/route.ts","../src/index.ts"],"sourcesContent":["import type * as TS from 'typescript';\n\n/**\n * AST-based reconciliation of an existing hono handler file.\n *\n * The `smart` handler strategy regenerates only the regions orval owns — its own\n * imports (names + module specifier) and the `zValidator(...)` arguments of each\n * handler — while leaving every user-authored construct untouched: custom imports,\n * middleware passed to `factory.createHandlers(...)`, the `async (c) => { ... }`\n * body, and any top-level helpers, constants, types, or comments.\n *\n * We edit the original source text in place using node offsets from the\n * TypeScript compiler API, so formatting and comments of untouched regions are\n * preserved. On any parse failure we return the source unchanged — user code is\n * never destroyed by a parser hiccup.\n */\n\n/**\n * `typescript` is an optional peer dependency, imported lazily. Consumers who do\n * not have it installed — and every non-hono or `skip` code path — never trigger\n * the import; `smart`/`full` fall back to `skip` when it is unavailable. Loading\n * the consumer's own typescript also avoids shipping a second copy of it.\n */\nlet ts!: typeof TS;\nlet typeScriptAvailable: boolean | undefined;\n\nexport const ensureTypeScript = async (): Promise<boolean> => {\n if (typeScriptAvailable === undefined) {\n try {\n const mod = await import('typescript');\n ts = (mod as unknown as { default?: typeof TS }).default ?? mod;\n typeScriptAvailable = true;\n } catch {\n typeScriptAvailable = false;\n }\n }\n return typeScriptAvailable;\n};\n\nexport type ValidatorTarget =\n | 'header'\n | 'param'\n | 'query'\n | 'json'\n | 'form'\n | 'response';\n\nexport interface DesiredValidator {\n target: ValidatorTarget;\n /** PascalCase zod schema identifier, e.g. `VerifyAccountResponse`. */\n schema: string;\n}\n\nexport interface DesiredHandler {\n /** e.g. `verifyAccountHandlers`. */\n handlerName: string;\n /** Validators required by the spec, in canonical order. */\n validators: DesiredValidator[];\n /** Full handler block, used only when the handler is missing and appended. */\n stub: string;\n}\n\nexport interface OrvalImport {\n names: string[];\n /** Module specifier as orval would emit it (relative, extensionless). */\n module: string;\n}\n\nexport interface DesiredImports {\n /** `createFactory` from `hono/factory`. */\n factory: OrvalImport;\n /** `zValidator` from the validator module; omitted when no validators exist. */\n validator?: OrvalImport;\n /** `<Op>Context` identifiers from the context module. */\n context: OrvalImport;\n /** zod schema identifiers from the zod module; omitted when none are needed. */\n zod?: OrvalImport;\n}\n\nconst VALIDATOR_TARGETS = new Set<string>([\n 'header',\n 'param',\n 'query',\n 'json',\n 'form',\n 'response',\n]);\n\ninterface Edit {\n start: number;\n end: number;\n text: string;\n}\n\nconst parse = (source: string): TS.SourceFile | undefined => {\n const sourceFile = ts.createSourceFile(\n 'handler.ts',\n source,\n ts.ScriptTarget.Latest,\n /* setParentNodes */ true,\n ts.ScriptKind.TS,\n );\n const diagnostics = (\n sourceFile as unknown as { parseDiagnostics?: TS.Diagnostic[] }\n ).parseDiagnostics;\n if (diagnostics && diagnostics.length > 0) return undefined;\n return sourceFile;\n};\n\ninterface ParsedHandler {\n name: string;\n call: TS.CallExpression;\n}\n\nconst findHandlers = (sourceFile: TS.SourceFile): ParsedHandler[] => {\n const handlers: ParsedHandler[] = [];\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue;\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name)) continue;\n const name = declaration.name.text;\n if (!name.endsWith('Handlers')) continue;\n const init = declaration.initializer;\n if (\n init &&\n ts.isCallExpression(init) &&\n ts.isPropertyAccessExpression(init.expression) &&\n init.expression.name.text === 'createHandlers'\n ) {\n handlers.push({ name, call: init });\n }\n }\n }\n return handlers;\n};\n\nconst importedNames = (declaration: TS.ImportDeclaration): string[] => {\n const bindings = declaration.importClause?.namedBindings;\n if (!bindings || !ts.isNamedImports(bindings)) return [];\n return bindings.elements.map((element) => element.name.text);\n};\n\nconst moduleText = (declaration: TS.ImportDeclaration): string =>\n ts.isStringLiteral(declaration.moduleSpecifier)\n ? declaration.moduleSpecifier.text\n : '';\n\n/**\n * A \"plain\" named import — no default binding, no namespace (`* as x`), and no\n * aliases (`x as y`). Only plain named imports are safe for orval to rewrite;\n * default / namespace / aliased / mixed imports are user-authored and must be\n * left untouched.\n */\nconst isPlainNamedImport = (declaration: TS.ImportDeclaration): boolean => {\n const clause = declaration.importClause;\n if (!clause || clause.name) return false;\n const bindings = clause.namedBindings;\n if (!bindings || !ts.isNamedImports(bindings)) return false;\n return bindings.elements.every(\n (element) => element.propertyName === undefined,\n );\n};\n\nconst setEquals = (a: string[], b: string[]): boolean =>\n a.length === b.length && a.every((value) => b.includes(value));\n\n// Escape regex metacharacters so an identifier can be interpolated literally.\n// JS identifiers may contain `$`, which would otherwise act as an anchor.\nconst escapeRegExp = (value: string): string =>\n value.replaceAll(/[.*+?^${}()|[\\]\\\\]/g, String.raw`\\$&`);\n\n/**\n * The local binding name an imported symbol is bound to, honouring aliases —\n * e.g. `import { zValidator as zv }` → `'zv'`. Returns undefined when the symbol\n * is not imported. Used so a handler that aliases `zValidator` is detected and\n * its new validators are inserted under the same alias (never an unimported name).\n */\nconst localNameFor = (\n importDeclarations: TS.ImportDeclaration[],\n importedName: string,\n module: string,\n): string | undefined => {\n for (const declaration of importDeclarations) {\n if (moduleText(declaration) !== module) continue;\n const bindings = declaration.importClause?.namedBindings;\n if (!bindings || !ts.isNamedImports(bindings)) continue;\n for (const element of bindings.elements) {\n if ((element.propertyName?.text ?? element.name.text) === importedName) {\n return element.name.text;\n }\n }\n }\n return undefined;\n};\n\nconst renderImport = ({ names, module }: OrvalImport): string =>\n names.length <= 1\n ? `import { ${names.join('')} } from '${module}';`\n : `import {\\n ${names.join(',\\n ')}\\n} from '${module}';`;\n\nconst lineStart = (source: string, position: number): number =>\n source.lastIndexOf('\\n', position - 1) + 1;\n\n/** Whether only whitespace sits between the line start and `position`. */\nconst startsLine = (source: string, position: number): boolean =>\n /^\\s*$/.test(source.slice(lineStart(source, position), position));\n\nexport const reconcileHandlerFile = async (\n source: string,\n desired: { imports: DesiredImports; handlers: DesiredHandler[] },\n): Promise<string> => {\n if (!(await ensureTypeScript())) return source;\n\n const sourceFile = parse(source);\n if (!sourceFile) return source;\n\n const edits: Edit[] = [];\n const importDeclarations = sourceFile.statements.filter(\n (statement): statement is TS.ImportDeclaration =>\n ts.isImportDeclaration(statement),\n );\n const handlers = findHandlers(sourceFile);\n const existingNames = new Set(handlers.map((handler) => handler.name));\n const pendingInsertions: string[] = [];\n\n // Locate an orval-owned import by its module specifier (authoritative).\n const byModule = (module: string): TS.ImportDeclaration | undefined =>\n module\n ? importDeclarations.find(\n (declaration) => moduleText(declaration) === module,\n )\n : undefined;\n\n // Fallback used only when the module specifier has moved: a PLAIN named import\n // whose names are EXACTLY `signature` (case-sensitive). This relocates an\n // orval import without the case-folding hazard of fuzzy name matching, which\n // could otherwise clobber an unrelated user import (e.g. `listPetsResponse`).\n const plainExact = (signature: string[]): TS.ImportDeclaration | undefined =>\n signature.length === 0\n ? undefined\n : importDeclarations.find(\n (declaration) =>\n isPlainNamedImport(declaration) &&\n setEquals(importedNames(declaration), signature),\n );\n\n const removeImportEdit = (declaration: TS.ImportDeclaration) => {\n let end = declaration.getEnd();\n if (source.slice(end, end + 2) === '\\r\\n') end += 2;\n else if (source[end] === '\\n') end += 1;\n edits.push({ start: declaration.getStart(sourceFile), end, text: '' });\n };\n\n // Whether `name` is already bound as a bare identifier by some import (a named\n // import's local name, or a default import). Namespace imports do NOT bind\n // their members bare. Used to avoid duplicate imports when augmenting.\n const isImportedBare = (name: string): boolean =>\n importDeclarations.some((declaration) => {\n const clause = declaration.importClause;\n if (!clause) return false;\n if (clause.name?.text === name) return true;\n return importedNames(declaration).includes(name);\n });\n\n /**\n * Reconcile an orval-owned import to `names`. We only rewrite/remove a PLAIN\n * named import whose names are ALL orval-owned (per `isOrvalName`). A\n * user-authored import (aliased / namespace / default / mixed) is never\n * rewritten; instead, when `augment` is provided, we add any orval name that\n * is genuinely needed as a bare reference but isn't yet importable bare — e.g.\n * a newly appended handler's context, or a newly-inserted validator's schema.\n */\n const reconcileImport = (\n existing: TS.ImportDeclaration | undefined,\n names: string[],\n module: string,\n isOrvalName: (name: string) => boolean,\n augment?: (name: string) => boolean,\n collectRenames?: Map<string, string>,\n ) => {\n if (!existing) {\n // Never insert a name that is already bound bare elsewhere (e.g. a default\n // or namespace import from another module) — that would create a duplicate\n // binding.\n const toInsert = (\n augment ? names.filter((name) => augment(name)) : names\n ).filter((name) => !isImportedBare(name));\n if (toInsert.length > 0) {\n pendingInsertions.push(renderImport({ names: toInsert, module }));\n }\n return;\n }\n\n const isOurs =\n isPlainNamedImport(existing) &&\n importedNames(existing).every((name) => isOrvalName(name));\n if (!isOurs) {\n if (augment) {\n const missing = names.filter(\n (name) => augment(name) && !isImportedBare(name),\n );\n if (missing.length > 0) {\n pendingInsertions.push(renderImport({ names: missing, module }));\n }\n }\n return;\n }\n\n if (names.length === 0) {\n removeImportEdit(existing);\n return;\n }\n\n if (\n setEquals(importedNames(existing), names) &&\n moduleText(existing) === module\n ) {\n return;\n }\n\n // Record the camelCase→PascalCase migrations this rewrite implies, so every\n // OTHER reference to the old binding (validator args, `z.infer<typeof X>` in\n // bodies, etc.) can be renamed too — not just the import itself.\n if (collectRenames) {\n for (const old of importedNames(existing)) {\n const next = names.find(\n (name) => name !== old && name.toLowerCase() === old.toLowerCase(),\n );\n if (next) collectRenames.set(old, next);\n }\n }\n\n edits.push({\n start: existing.getStart(sourceFile),\n end: existing.getEnd(),\n text: renderImport({ names, module }),\n });\n };\n\n // --- validators first, so schema names referenced by reconciled validators\n // (newly inserted, or renamed camelCase → PascalCase) are known to the import\n // step below. The local name `zValidator` is bound to in the DESIRED validator\n // module (honours `import { zValidator as zv } from '<validatorModule>'`); a\n // zValidator imported from a different module is the user's own and ignored,\n // so new validators always route through orval's validator. ---\n const validatorModule = desired.imports.validator?.module ?? '';\n const zValidatorName = validatorModule\n ? (localNameFor(importDeclarations, 'zValidator', validatorModule) ??\n 'zValidator')\n : 'zValidator';\n\n const requiredSchemas = new Set<string>();\n const removedValidatorRanges: [number, number][] = [];\n for (const desiredHandler of desired.handlers) {\n const parsed = handlers.find(\n (handler) => handler.name === desiredHandler.handlerName,\n );\n if (parsed) {\n reconcileValidators(\n sourceFile,\n source,\n parsed.call,\n desiredHandler.validators,\n edits,\n zValidatorName,\n requiredSchemas,\n removedValidatorRanges,\n );\n }\n }\n\n // Schema migrations (old camelCase → new PascalCase) implied by rewriting the\n // zod import; applied file-wide below so every reference is migrated.\n const schemaRenames = new Map<string, string>();\n\n const toAppend = desired.handlers.filter(\n (handler) => !existingNames.has(handler.handlerName),\n );\n\n // --- imports ---\n // Source with import declarations blanked out, so an import's own text (e.g.\n // `import { ListPetsResponse as Resp }`) is never counted as a usage.\n let bodySource = source;\n for (const declaration of importDeclarations) {\n const start = declaration.getStart(sourceFile);\n const end = declaration.getEnd();\n bodySource =\n bodySource.slice(0, start) +\n ' '.repeat(end - start) +\n bodySource.slice(end);\n }\n\n // A name needs a bare import when it is referenced unqualified in the body\n // (not as `Ns.Name`), is a schema a reconciled validator now references\n // (inserted or renamed), or is used by an appended handler stub.\n const referencedBare = (name: string): boolean =>\n new RegExp(String.raw`(?<!\\.)\\b${escapeRegExp(name)}\\b`).test(bodySource);\n const inAppendedStub = (name: string): boolean =>\n toAppend.some((handler) => handler.stub.includes(name));\n const needsBareContext = (name: string): boolean =>\n referencedBare(name) || inAppendedStub(name);\n const needsBareZod = (name: string): boolean =>\n referencedBare(name) || requiredSchemas.has(name) || inAppendedStub(name);\n\n // Context types are orval-owned only where a handler references one bare (a\n // typed `async (c: XContext)`) or an appended stub uses it. Match by EXACT\n // orval name — never `endsWith('Context')`, which would clobber a user import\n // such as `getCommunityFilterContext`.\n const contextNames = desired.imports.context.names.filter((name) =>\n needsBareContext(name),\n );\n const zodLower = new Set(\n (desired.imports.zod?.names ?? []).map((name) => name.toLowerCase()),\n );\n\n const factoryModule = desired.imports.factory.module;\n reconcileImport(\n byModule(factoryModule) ?? plainExact(['createFactory']),\n desired.imports.factory.names,\n factoryModule,\n (name) => name === 'createFactory',\n );\n\n reconcileImport(\n byModule(validatorModule) ?? plainExact(['zValidator']),\n desired.imports.validator ? ['zValidator'] : [],\n validatorModule,\n (name) => name === 'zValidator',\n );\n\n reconcileImport(\n byModule(desired.imports.context.module) ?? plainExact(contextNames),\n contextNames,\n desired.imports.context.module,\n (name) => desired.imports.context.names.includes(name),\n needsBareContext,\n );\n\n const zodModule = desired.imports.zod?.module ?? '';\n const zodNames = desired.imports.zod?.names ?? [];\n reconcileImport(\n byModule(zodModule) ?? plainExact(zodNames),\n zodNames,\n zodModule,\n (name) => zodLower.has(name.toLowerCase()),\n needsBareZod,\n schemaRenames,\n );\n\n // Apply the schema migrations file-wide: rename every remaining reference to a\n // migrated schema (validator args, `z.infer<typeof X>` in bodies, helper code).\n // The import is rewritten above (its decl range is skipped here); ranges of\n // removed validators are skipped too (their args are already deleted).\n if (schemaRenames.size > 0) {\n const inSkippedRange = (pos: number): boolean =>\n importDeclarations.some(\n (declaration) =>\n pos >= declaration.getStart(sourceFile) && pos < declaration.getEnd(),\n ) ||\n removedValidatorRanges.some(([start, end]) => pos >= start && pos < end);\n\n const renameReferences = (node: TS.Node): void => {\n if (ts.isIdentifier(node)) {\n const replacement = schemaRenames.get(node.text);\n if (replacement) {\n const parent = node.parent;\n const isMemberName =\n ts.isPropertyAccessExpression(parent) && parent.name === node;\n const isDeclarationName =\n (ts.isVariableDeclaration(parent) && parent.name === node) ||\n (ts.isParameter(parent) && parent.name === node) ||\n (ts.isBindingElement(parent) && parent.name === node) ||\n (ts.isPropertyAssignment(parent) && parent.name === node) ||\n (ts.isPropertySignature(parent) && parent.name === node);\n const start = node.getStart(sourceFile);\n if (!isMemberName && !isDeclarationName && !inSkippedRange(start)) {\n edits.push({ start, end: node.getEnd(), text: replacement });\n }\n }\n }\n ts.forEachChild(node, renameReferences);\n };\n renameReferences(sourceFile);\n }\n\n if (pendingInsertions.length > 0) {\n const lastImport = importDeclarations.at(-1);\n let insertPos = 0;\n if (lastImport) {\n // Guard the EOF case: when the last import has no trailing newline,\n // indexOf returns -1 and `+ 1` would prepend to the top of the file.\n const newline = source.indexOf('\\n', lastImport.getEnd());\n insertPos = newline === -1 ? source.length : newline + 1;\n }\n edits.push({\n start: insertPos,\n end: insertPos,\n text: pendingInsertions.map((line) => `${line}\\n`).join(''),\n });\n }\n\n if (toAppend.length > 0) {\n edits.push({\n start: source.length,\n end: source.length,\n text: toAppend.map((handler) => handler.stub).join(''),\n });\n }\n\n return applyEdits(source, edits);\n};\n\nconst reconcileValidators = (\n sourceFile: TS.SourceFile,\n source: string,\n call: TS.CallExpression,\n desiredValidators: DesiredValidator[],\n edits: Edit[],\n zValidatorName: string,\n requiredSchemas: Set<string>,\n removedRanges: [number, number][],\n) => {\n const existing: { target: string; arg: TS.CallExpression }[] = [];\n\n for (const arg of call.arguments) {\n if (\n ts.isCallExpression(arg) &&\n ts.isIdentifier(arg.expression) &&\n arg.expression.text === zValidatorName\n ) {\n const target = arg.arguments[0];\n if (\n arg.arguments.length > 0 &&\n ts.isStringLiteralLike(target) &&\n VALIDATOR_TARGETS.has(target.text)\n ) {\n existing.push({ target: target.text, arg });\n }\n }\n }\n\n const desiredByTarget = new Map(\n desiredValidators.map((validator) => [validator.target, validator]),\n );\n const existingByTarget = new Set(existing.map((item) => item.target));\n\n // Remove validators the spec no longer requires. (Schema RENAMES — e.g.\n // camelCase→PascalCase — are handled by the file-wide rename pass driven by the\n // zod-import rewrite, so every reference is migrated, not just the arg here.)\n for (const item of existing) {\n if (!desiredByTarget.has(item.target as ValidatorTarget)) {\n const edit = removeArgumentEdit(sourceFile, source, item.arg);\n edits.push(edit);\n removedRanges.push([edit.start, edit.end]);\n }\n }\n\n const missing = desiredValidators.filter(\n (validator) => !existingByTarget.has(validator.target),\n );\n if (missing.length > 0) {\n const insertPos = validatorInsertPos(sourceFile, source, call);\n const text = missing\n .map((validator) => {\n requiredSchemas.add(validator.schema);\n return ` ${zValidatorName}('${validator.target}', ${validator.schema}),\\n`;\n })\n .join('');\n edits.push({ start: insertPos, end: insertPos, text });\n }\n};\n\n/** Position to insert new validators: the line start of the trailing handler. */\nconst validatorInsertPos = (\n sourceFile: TS.SourceFile,\n source: string,\n call: TS.CallExpression,\n): number => {\n // The handler is the LAST function argument; earlier function args may be\n // inline middleware, so search from the end.\n const handler = call.arguments.findLast(\n (arg) => ts.isArrowFunction(arg) || ts.isFunctionExpression(arg),\n );\n if (handler) {\n // Insert at the handler's line start when it's on its own line; otherwise\n // (single-line `createHandlers(async (c) => {})`) insert right before it so\n // the validator isn't pushed to the start of the statement.\n const start = handler.getStart(sourceFile);\n return startsLine(source, start) ? lineStart(source, start) : start;\n }\n // No trailing handler found — insert just before the closing paren.\n return call.getEnd() - 1;\n};\n\nconst removeArgumentEdit = (\n sourceFile: TS.SourceFile,\n source: string,\n arg: TS.Node,\n): Edit => {\n const argStart = arg.getStart(sourceFile);\n const start = startsLine(source, argStart)\n ? lineStart(source, argStart)\n : argStart;\n\n const commaIdx = source.indexOf(',', arg.getEnd());\n let end = commaIdx === -1 ? arg.getEnd() : commaIdx + 1;\n while (source[end] === ' ' || source[end] === '\\t') end += 1;\n if (source.slice(end, end + 2) === '\\r\\n') end += 2;\n else if (source[end] === '\\n') end += 1;\n\n return { start, end, text: '' };\n};\n\nconst applyEdits = (source: string, edits: Edit[]): string => {\n let result = source;\n for (const edit of edits.toSorted((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);\n }\n return result;\n};\n\n/**\n * Extracts the inner body of each handler's `async (c) => { ... }` block, keyed\n * by handler name. Used by the `full` strategy to splice user bodies back into a\n * freshly-regenerated wrapper. Returns `undefined` when the source can't be\n * parsed (or typescript is unavailable) — distinct from an empty map (parsed, no\n * handlers) — so callers can preserve the file instead of dropping its bodies.\n */\nexport const extractHandlerBodies = async (\n source: string,\n): Promise<Map<string, string> | undefined> => {\n if (!(await ensureTypeScript())) return undefined;\n\n const sourceFile = parse(source);\n if (!sourceFile) return undefined;\n\n const bodies = new Map<string, string>();\n for (const { name, call } of findHandlers(sourceFile)) {\n // The handler is the LAST function argument (earlier ones may be inline\n // middleware), so its body — not a middleware's — is what `full` splices.\n const handler = call.arguments.findLast(\n (arg) => ts.isArrowFunction(arg) || ts.isFunctionExpression(arg),\n );\n if (handler?.body && ts.isBlock(handler.body)) {\n const bodyStart = handler.body.getStart(sourceFile) + 1;\n const bodyEnd = handler.body.getEnd() - 1;\n bodies.set(name, source.slice(bodyStart, bodyEnd));\n }\n }\n\n return bodies;\n};\n","import { sanitize } from '@orval/core';\n\nconst hasParam = (path: string): boolean => /[^{]*{[\\w*_-]*}.*/.test(path);\n\nconst getRoutePath = (path: string): string => {\n const matches = /([^{]*){?([\\w*_-]*)}?(.*)/.exec(path);\n if (!matches?.length) return path; // impossible due to regexp grouping here, but for TS\n\n const prev = matches[1];\n const param = sanitize(matches[2], {\n es5keyword: true,\n underscore: true,\n dash: true,\n dot: true,\n });\n const next = hasParam(matches[3]) ? getRoutePath(matches[3]) : matches[3];\n\n return hasParam(path) ? `${prev}:${param}${next}` : `${prev}${param}${next}`;\n};\n\nexport const getRoute = (route: string) => {\n const splittedRoute = route.split('/');\n\n let acc = '';\n for (const [i, path] of splittedRoute.entries()) {\n if (!path && i === 0) continue;\n\n acc += path.includes('{') ? `/${getRoutePath(path)}` : `/${path}`;\n }\n\n return acc;\n};\n","import nodePath from 'node:path';\n\nimport {\n camel,\n type ClientBuilder,\n type ClientExtraFilesBuilder,\n type ClientFooterBuilder,\n type ClientGeneratorsBuilder,\n type ClientHeaderBuilder,\n type ContextSpec,\n generateMutatorImports,\n type GeneratorDependency,\n type GeneratorImport,\n type GeneratorVerbOptions,\n getFileInfo,\n getOrvalGeneratedTypes,\n getParamsInPath,\n type HonoHandlerStrategy,\n isObject,\n jsDoc,\n kebab,\n logWarning,\n type NormalizedMutator,\n type NormalizedOutputOptions,\n type OpenApiInfoObject,\n pascal,\n sanitize,\n getImportExtension,\n type Tsconfig,\n upath,\n} from '@orval/core';\nimport { generateZod } from '@orval/zod';\nimport fs from 'fs-extra';\n\nimport {\n type DesiredImports,\n type DesiredValidator,\n ensureTypeScript,\n extractHandlerBodies,\n reconcileHandlerFile,\n} from './handler-merge';\nimport { getRoute } from './route';\n\n// Warn at most once per run when the optional `typescript` peer is missing and a\n// non-`skip` strategy was requested, so the degraded behavior is never silent.\nlet warnedMissingTypeScript = false;\n\nconst ZVALIDATOR_SOURCE = fs\n .readFileSync(nodePath.join(import.meta.dirname, 'zValidator.ts'))\n .toString('utf8');\n\nconst HONO_DEPENDENCIES: GeneratorDependency[] = [\n {\n exports: [\n {\n name: 'Hono',\n values: true,\n },\n {\n name: 'Context',\n },\n {\n name: 'Env',\n },\n ],\n dependency: 'hono',\n },\n];\n\n/**\n * generateModuleSpecifier generates the specifier that _from_ would use to\n * import _to_. This is syntactical and does not validate the paths.\n *\n * @param from The filesystem path to the importer.\n * @param to If a filesystem path, it and _from_ must be use the same frame of\n * reference, such as process.cwd() or both be absolute. If only one is\n * absolute, the other must be relative to process.cwd().\n *\n * Otherwise, treated as a package name and returned directly.\n *\n * @param tsconfig Optional tsconfig used to derive the runtime import\n * extension. Under `module: 'nodenext'/'node16'` the source extension (e.g.\n * `.ts`) is rewritten to its runtime equivalent (e.g. `.js`); otherwise the\n * extension is dropped to match the rest of orval.\n *\n * @return A module specifier that can be used at _from_ to import _to_.\n */\nconst generateModuleSpecifier = (\n from: string,\n to: string,\n tsconfig?: Tsconfig,\n) => {\n if (to.startsWith('.') || nodePath.isAbsolute(to)) {\n const resolvedFrom = nodePath.resolve(from);\n const resolvedTo = nodePath.resolve(to);\n const relative = upath.getRelativeImportPath(resolvedFrom, resolvedTo);\n const sourceExt = nodePath.extname(to);\n return `${relative}${sourceExt ? getImportExtension(sourceExt, tsconfig) : ''}`;\n }\n\n // Not a relative or absolute file path. Import as-is.\n return to;\n};\n\nexport const getHonoDependencies = () => HONO_DEPENDENCIES;\n\nexport const getHonoHeader: ClientHeaderBuilder = ({\n verbOptions,\n output,\n tag,\n clientImplementation,\n}) => {\n const targetInfo = getFileInfo(output.target, {\n extension: output.fileExtension,\n });\n\n let handlers: string;\n\n const importHandlers = Object.values(verbOptions).filter((verbOption) =>\n clientImplementation.includes(`${verbOption.operationName}Handlers`),\n );\n\n if (output.override.hono.handlers) {\n const handlerFileInfo = getFileInfo(output.override.hono.handlers);\n handlers = importHandlers\n .map((verbOption) => {\n // Only `tags-split` puts each tag's client file inside its own\n // sub-directory. `tags` mode flattens them next to `target`, so the\n // import must be resolved from `targetInfo.dirname` directly.\n const isSplitDir = output.mode === 'tags-split';\n const tag = kebab(verbOption.tags[0] ?? 'default');\n\n const handlersPath = upath.relativeSafe(\n nodePath.join(targetInfo.dirname, isSplitDir ? tag : ''),\n nodePath.join(\n handlerFileInfo.dirname,\n `./${verbOption.operationName}`,\n ),\n );\n\n return `import { ${verbOption.operationName}Handlers } from '${handlersPath}';`;\n })\n .join('\\n');\n } else {\n const importHandlerNames = importHandlers\n .map((verbOption) => ` ${verbOption.operationName}Handlers`)\n .join(`, \\n`);\n\n handlers = `import {\\n${importHandlerNames}\\n} from './${tag ?? targetInfo.filename}.handlers';`;\n }\n\n return `${handlers}\\n\\nconst app = new Hono()\\n`;\n};\n\nexport const getHonoFooter: ClientFooterBuilder = () =>\n ';\\n\\nexport default app;\\n';\n\nconst generateHonoRoute = (\n { operationName, verb }: GeneratorVerbOptions,\n pathRoute: string,\n) => {\n const path = getRoute(pathRoute);\n\n return `\\n .${verb.toLowerCase()}('${path}', ...${operationName}Handlers)`;\n};\n\nexport const generateHono: ClientBuilder = (verbOptions, options) => {\n if (options.override.hono.compositeRoute) {\n return {\n implementation: '',\n imports: [],\n };\n }\n\n const routeImplementation = generateHonoRoute(verbOptions, options.pathRoute);\n\n return {\n implementation: `${routeImplementation}\\n`,\n imports: [\n ...verbOptions.params.flatMap((param) => param.imports),\n ...verbOptions.body.imports,\n ...(verbOptions.queryParams\n ? [\n {\n name: verbOptions.queryParams.schema.name,\n },\n ]\n : []),\n ],\n };\n};\n\n/**\n * getHonoHandlers generates TypeScript code for the given verbs and reports\n * whether the code requires zValidator.\n */\nconst DEFAULT_HANDLER_BODY = '\\n\\n ';\n\nconst FORM_CONTENT_TYPES = new Set([\n 'multipart/form-data',\n 'application/x-www-form-urlencoded',\n]);\n\n/**\n * Whether a request body uses a form encoding. Hono validates these with\n * `zValidator('form', …)` against `c.req.parseBody()`, not `'json'`.\n */\nconst isFormBody = (body: GeneratorVerbOptions['body']): boolean =>\n FORM_CONTENT_TYPES.has(body.contentType);\n\n/**\n * getDesiredValidators returns the `zValidator` targets (and their PascalCase zod\n * schema identifiers) required by a verb, in canonical order. This is the single\n * source of truth shared by fresh generation and the `smart` reconcile.\n */\nconst getDesiredValidators = (\n verbOption: GeneratorVerbOptions,\n validator: boolean | 'hono' | NormalizedMutator,\n): DesiredValidator[] => {\n if (!validator) return [];\n\n const pascalOperationName = pascal(verbOption.operationName);\n const validators: DesiredValidator[] = [];\n\n if (verbOption.headers) {\n validators.push({\n target: 'header',\n schema: `${pascalOperationName}Header`,\n });\n }\n if (verbOption.params.length > 0) {\n validators.push({\n target: 'param',\n schema: `${pascalOperationName}Params`,\n });\n }\n if (verbOption.queryParams) {\n validators.push({\n target: 'query',\n schema: `${pascalOperationName}QueryParams`,\n });\n }\n if (verbOption.body.definition) {\n validators.push({\n target: isFormBody(verbOption.body) ? 'form' : 'json',\n schema: `${pascalOperationName}Body`,\n });\n }\n if (\n validator !== 'hono' &&\n verbOption.response.originalSchema?.['200']?.content?.[\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n 'application/json'\n ]\n ) {\n validators.push({\n target: 'response',\n schema: `${pascalOperationName}Response`,\n });\n }\n\n return validators;\n};\n\nconst getHonoHandlers = (\n ...opts: {\n handlerName: string;\n contextTypeName: string;\n verbOption: GeneratorVerbOptions;\n validator: boolean | 'hono' | NormalizedMutator;\n /**\n * Optional async-handler body to splice into the generated wrapper. Used by\n * the `full` strategy to preserve user logic across regeneration.\n */\n bodyOverride?: string;\n }[]\n): [\n /** The combined TypeScript handler code snippets. */\n handlerCode: string,\n /** Whether any of the handler code snippets requires importing zValidator. */\n hasZValidator: boolean,\n] => {\n let code = '';\n let hasZValidator = false;\n\n for (const {\n handlerName,\n contextTypeName,\n verbOption,\n validator,\n bodyOverride,\n } of opts) {\n const currentValidator = getDesiredValidators(verbOption, validator)\n .map((v) => `zValidator('${v.target}', ${v.schema}),\\n`)\n .join('');\n\n const body = bodyOverride ?? DEFAULT_HANDLER_BODY;\n\n code += `\nexport const ${handlerName} = factory.createHandlers(\n${currentValidator}async (c: ${contextTypeName}) => {${body}},\n);`;\n\n hasZValidator ||= currentValidator !== '';\n }\n\n return [code, hasZValidator];\n};\n\nconst getZvalidatorImports = (\n verbOptions: GeneratorVerbOptions[],\n importPath: string,\n isHonoValidator: boolean,\n) => {\n const specifiers = [];\n\n for (const {\n operationName,\n headers,\n params,\n queryParams,\n body,\n response,\n } of verbOptions) {\n const pascalOperationName = pascal(operationName);\n\n if (headers) {\n specifiers.push(`${pascalOperationName}Header`);\n }\n\n if (params.length > 0) {\n specifiers.push(`${pascalOperationName}Params`);\n }\n\n if (queryParams) {\n specifiers.push(`${pascalOperationName}QueryParams`);\n }\n\n if (body.definition) {\n specifiers.push(`${pascalOperationName}Body`);\n }\n\n if (\n !isHonoValidator &&\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n response.originalSchema?.['200']?.content?.['application/json'] !=\n undefined\n ) {\n specifiers.push(`${pascalOperationName}Response`);\n }\n }\n\n return specifiers.length === 0\n ? ''\n : `import {\\n${specifiers.join(',\\n')}\\n} from '${importPath}'`;\n};\n\nconst getVerbOptionGroupByTag = (\n verbOptions: Record<string, GeneratorVerbOptions>,\n) => {\n const grouped: Record<string, GeneratorVerbOptions[]> = {};\n\n for (const value of Object.values(verbOptions)) {\n const tag = value.tags[0];\n // this is not always false\n // TODO look into types\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!grouped[tag]) {\n grouped[tag] = [];\n }\n grouped[tag].push(value);\n }\n\n return grouped;\n};\n\n/** Computes the orval-owned imports a handler file should contain. */\nconst buildDesiredImports = ({\n verbList,\n path,\n validatorModule,\n zodModule,\n contextModule,\n validator,\n tsconfig,\n}: {\n verbList: GeneratorVerbOptions[];\n path: string;\n validatorModule?: string;\n zodModule: string;\n contextModule: string;\n validator: boolean | 'hono';\n tsconfig?: Tsconfig;\n}): DesiredImports => {\n const contextNames = verbList.map(\n (verb) => `${pascal(verb.operationName)}Context`,\n );\n const zodNames = verbList.flatMap((verb) =>\n getDesiredValidators(verb, validator).map((v) => v.schema),\n );\n const hasValidators = zodNames.length > 0;\n\n return {\n factory: { names: ['createFactory'], module: 'hono/factory' },\n validator:\n hasValidators && validatorModule != undefined\n ? {\n names: ['zValidator'],\n module: generateModuleSpecifier(path, validatorModule, tsconfig),\n }\n : undefined,\n context: {\n names: contextNames,\n module: generateModuleSpecifier(path, contextModule, tsconfig),\n },\n zod: hasValidators\n ? {\n names: zodNames,\n module: generateModuleSpecifier(path, zodModule, tsconfig),\n }\n : undefined,\n };\n};\n\n/** Generates a complete handler file from scratch (no existing file to merge). */\nconst generateFreshHandlerFile = ({\n verbList,\n path,\n header,\n validatorModule,\n zodModule,\n contextModule,\n validator,\n bodyFor,\n tsconfig,\n}: {\n verbList: GeneratorVerbOptions[];\n path: string;\n header: string;\n validatorModule?: string;\n zodModule: string;\n contextModule: string;\n validator: boolean | 'hono';\n bodyFor?: (operationName: string) => string | undefined;\n tsconfig?: Tsconfig;\n}): string => {\n const [handlerCode, hasZValidator] = getHonoHandlers(\n ...verbList.map((verbOption) => ({\n handlerName: `${verbOption.operationName}Handlers`,\n contextTypeName: `${pascal(verbOption.operationName)}Context`,\n verbOption,\n validator,\n bodyOverride: bodyFor?.(verbOption.operationName),\n })),\n );\n\n const imports = [\"import { createFactory } from 'hono/factory';\"];\n\n if (hasZValidator && validatorModule != undefined) {\n imports.push(\n `import { zValidator } from '${generateModuleSpecifier(path, validatorModule, tsconfig)}';`,\n );\n }\n\n imports.push(\n `import { ${verbList\n .map((verb) => `${pascal(verb.operationName)}Context`)\n .join(\n ',\\n',\n )} } from '${generateModuleSpecifier(path, contextModule, tsconfig)}';`,\n );\n\n if (hasZValidator) {\n imports.push(\n getZvalidatorImports(\n verbList,\n generateModuleSpecifier(path, zodModule, tsconfig),\n validatorModule === '@hono/zod-validator',\n ),\n );\n }\n\n return `${header}${imports.filter((imp) => imp !== '').join('\\n')}\\n\\nconst factory = createFactory();${handlerCode}`;\n};\n\n/**\n * Generates or updates a handler file according to `strategy`:\n *\n * - a non-existent file is always freshly generated;\n * - `skip` leaves an existing file byte-for-byte unchanged;\n * - `full` rebuilds the preamble + validator chain and splices back user bodies\n * (drops custom imports/middleware/helpers — the thin-handler model);\n * - `smart` non-destructively reconciles orval-owned imports + validators and\n * appends handlers for new operations, preserving all user-authored code.\n */\nexport const generateHandlerFile = async ({\n verbs,\n path,\n header,\n validatorModule,\n zodModule,\n contextModule,\n strategy,\n tsconfig,\n}: {\n verbs: GeneratorVerbOptions[];\n path: string;\n header: string;\n validatorModule?: string;\n zodModule: string;\n contextModule: string;\n strategy: HonoHandlerStrategy;\n tsconfig?: Tsconfig;\n}) => {\n const validator =\n validatorModule === '@hono/zod-validator'\n ? ('hono' as const)\n : validatorModule != undefined;\n\n const verbList = Object.values(verbs);\n\n if (!fs.existsSync(path)) {\n return generateFreshHandlerFile({\n verbList,\n path,\n header,\n validatorModule,\n zodModule,\n contextModule,\n validator,\n tsconfig,\n });\n }\n\n const source = await fs.readFile(path, 'utf8');\n\n if (strategy === 'skip') {\n return source;\n }\n\n // `smart` and `full` parse the existing file with the TypeScript compiler API.\n // typescript is an optional peer dependency; without it we cannot safely\n // reconcile or splice, so we preserve the existing file untouched and warn.\n if (!(await ensureTypeScript())) {\n if (!warnedMissingTypeScript) {\n warnedMissingTypeScript = true;\n logWarning(\n `hono handlerGenerationStrategy '${strategy}' requires the optional peer dependency \"typescript\", which is not installed. Existing handler files are left unchanged (as with 'skip'). Install typescript to enable handler reconciliation.`,\n );\n }\n return source;\n }\n\n if (strategy === 'full') {\n const bodies = await extractHandlerBodies(source);\n // A parse failure yields `undefined` (not an empty map): preserve the file\n // rather than regenerate with empty bodies and drop the user's logic.\n if (!bodies) {\n return source;\n }\n return generateFreshHandlerFile({\n verbList,\n path,\n header,\n validatorModule,\n zodModule,\n contextModule,\n validator,\n bodyFor: (operationName) => bodies.get(`${operationName}Handlers`),\n tsconfig,\n });\n }\n\n return reconcileHandlerFile(source, {\n imports: buildDesiredImports({\n verbList,\n path,\n validatorModule,\n zodModule,\n contextModule,\n validator,\n tsconfig,\n }),\n handlers: verbList.map((verbOption) => ({\n handlerName: `${verbOption.operationName}Handlers`,\n validators: getDesiredValidators(verbOption, validator),\n stub: getHonoHandlers({\n handlerName: `${verbOption.operationName}Handlers`,\n contextTypeName: `${pascal(verbOption.operationName)}Context`,\n verbOption,\n validator,\n })[0],\n })),\n });\n};\n\nconst generateHandlerFiles = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpec,\n validatorModule: string,\n) => {\n const header = getHeader(output.override.header, getSpecInfo(context));\n const { extension, dirname, filename } = getFileInfo(output.target, {\n extension: output.fileExtension,\n });\n const strategy = output.override.hono.handlerGenerationStrategy;\n\n // This function _does not control_ where the .zod and .context modules land.\n // That determination is made elsewhere and this function must implement the\n // same conventions.\n\n if (output.override.hono.handlers) {\n // One file per operation in the user-provided directory.\n return Promise.all(\n Object.values(verbOptions).map(async (verbOption) => {\n const tag = kebab(verbOption.tags[0] ?? 'default');\n\n const path = nodePath.join(\n output.override.hono.handlers ?? '',\n `./${verbOption.operationName}` + extension,\n );\n\n // Mirror the layout used by generateZodFiles/generateContextFiles so\n // imports resolve to the actual emitted modules.\n let zodModule: string;\n let contextModule: string;\n if (output.mode === 'tags') {\n zodModule = nodePath.join(dirname, `${kebab(tag)}.zod${extension}`);\n contextModule = nodePath.join(\n dirname,\n `${kebab(tag)}.context${extension}`,\n );\n } else if (output.mode === 'tags-split') {\n zodModule = nodePath.join(dirname, tag, tag + '.zod' + extension);\n contextModule = nodePath.join(\n dirname,\n tag,\n tag + '.context' + extension,\n );\n } else {\n zodModule = nodePath.join(dirname, `${filename}.zod${extension}`);\n contextModule = nodePath.join(\n dirname,\n `${filename}.context${extension}`,\n );\n }\n\n return {\n content: await generateHandlerFile({\n path,\n header,\n verbs: [verbOption],\n validatorModule,\n zodModule,\n contextModule,\n strategy,\n tsconfig: output.tsconfig,\n }),\n path,\n };\n }),\n );\n }\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n // One file per operation _tag_ under dirname.\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n return Promise.all(\n Object.entries(groupByTags).map(async ([tag, verbs]) => {\n const handlerPath =\n output.mode === 'tags'\n ? nodePath.join(dirname, `${kebab(tag)}.handlers${extension}`)\n : nodePath.join(dirname, tag, tag + '.handlers' + extension);\n\n return {\n content: await generateHandlerFile({\n path: handlerPath,\n header,\n verbs,\n validatorModule,\n zodModule:\n output.mode === 'tags'\n ? nodePath.join(dirname, `${kebab(tag)}.zod${extension}`)\n : nodePath.join(dirname, tag, tag + '.zod' + extension),\n contextModule:\n output.mode === 'tags'\n ? nodePath.join(dirname, `${kebab(tag)}.context${extension}`)\n : nodePath.join(dirname, tag, tag + '.context' + extension),\n strategy,\n tsconfig: output.tsconfig,\n }),\n path: handlerPath,\n };\n }),\n );\n }\n\n // One file with all operations.\n const handlerPath = nodePath.join(\n dirname,\n `${filename}.handlers${extension}`,\n );\n\n return [\n {\n content: await generateHandlerFile({\n path: handlerPath,\n header,\n verbs: Object.values(verbOptions),\n validatorModule,\n zodModule: nodePath.join(dirname, `${filename}.zod${extension}`),\n contextModule: nodePath.join(\n dirname,\n `${filename}.context${extension}`,\n ),\n strategy,\n tsconfig: output.tsconfig,\n }),\n path: handlerPath,\n },\n ];\n};\n\nconst getContext = (verbOption: GeneratorVerbOptions) => {\n let paramType = '';\n if (verbOption.params.length > 0) {\n const params = getParamsInPath(verbOption.pathRoute).map((name) => {\n const param = verbOption.params.find(\n (p) => p.name === sanitize(camel(name), { es5keyword: true }),\n );\n const definition = param?.definition.split(':')[1];\n const required = param?.required ?? false;\n return {\n definition: `${name}${required ? '' : '?'}:${definition}`,\n };\n });\n paramType = `param: {\\n ${params\n .map((property) => property.definition)\n .join(',\\n ')},\\n },`;\n }\n\n const queryType = verbOption.queryParams\n ? `query: ${verbOption.queryParams.schema.name},`\n : '';\n const bodyType = verbOption.body.definition\n ? `${isFormBody(verbOption.body) ? 'form' : 'json'}: ${verbOption.body.definition},`\n : '';\n const hasIn = !!paramType || !!queryType || !!bodyType;\n\n return `export type ${pascal(\n verbOption.operationName,\n )}Context<E extends Env = any> = Context<E, '${getRoute(\n verbOption.pathRoute,\n )}'${\n hasIn\n ? `, { in: { ${paramType}${queryType}${bodyType} }, out: { ${paramType}${queryType}${bodyType} } }`\n : ''\n }>`;\n};\n\nconst getHeader = (\n option: false | ((info: OpenApiInfoObject) => string | string[]),\n info: OpenApiInfoObject,\n): string => {\n if (!option) {\n return '';\n }\n\n const header = option(info);\n\n return Array.isArray(header) ? jsDoc({ description: header }) : header;\n};\n\nconst getSpecInfo = (context: ContextSpec): OpenApiInfoObject =>\n context.spec.info ?? {\n title: 'API',\n version: '1.0.0',\n };\n\nconst generateContextFile = ({\n path,\n verbs,\n schemaModule,\n tsconfig,\n}: {\n path: string;\n verbs: GeneratorVerbOptions[];\n schemaModule: string;\n tsconfig?: Tsconfig;\n}) => {\n let content = `import type { Context, Env } from 'hono';\\n\\n`;\n\n const contexts = verbs.map((verb) => getContext(verb));\n\n const imps = new Set(\n verbs\n .flatMap((verb) => {\n const imports: GeneratorImport[] = [];\n if (verb.params.length > 0) {\n imports.push(...verb.params.flatMap((param) => param.imports));\n }\n\n if (verb.queryParams) {\n imports.push({\n name: verb.queryParams.schema.name,\n });\n }\n\n if (verb.body.definition) {\n imports.push(...verb.body.imports);\n }\n\n return imports;\n })\n .map((imp) => imp.name)\n .filter((imp) => contexts.some((context) => context.includes(imp))),\n );\n\n if (contexts.some((context) => context.includes('NonReadonly<'))) {\n content += getOrvalGeneratedTypes();\n content += '\\n';\n }\n\n if (imps.size > 0) {\n content += `import type {\\n${[...imps]\n .toSorted()\n .join(\n ',\\n ',\n )}\\n} from '${generateModuleSpecifier(path, schemaModule, tsconfig)}';\\n\\n`;\n }\n\n content += contexts.join('\\n');\n\n return content;\n};\n\nconst generateContextFiles = (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpec,\n schemaModule: string,\n) => {\n const header = getHeader(output.override.header, getSpecInfo(context));\n const { extension, dirname, filename } = getFileInfo(output.target, {\n extension: output.fileExtension,\n });\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n return Object.entries(groupByTags).map(([tag, verbs]) => {\n const path =\n output.mode === 'tags'\n ? nodePath.join(dirname, `${kebab(tag)}.context${extension}`)\n : nodePath.join(dirname, tag, tag + '.context' + extension);\n const code = generateContextFile({\n verbs,\n path,\n schemaModule: schemaModule,\n tsconfig: output.tsconfig,\n });\n return { content: `${header}${code}`, path };\n });\n }\n\n const path = nodePath.join(dirname, `${filename}.context${extension}`);\n const code = generateContextFile({\n verbs: Object.values(verbOptions),\n path,\n schemaModule: schemaModule,\n tsconfig: output.tsconfig,\n });\n\n return [\n {\n content: `${header}${code}`,\n path,\n },\n ];\n};\n\nconst generateZodFiles = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpec,\n) => {\n const { extension, dirname, filename } = getFileInfo(output.target, {\n extension: output.fileExtension,\n });\n\n const header = getHeader(output.override.header, getSpecInfo(context));\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n const builderContexts = await Promise.all(\n Object.entries(groupByTags).map(async ([tag, verbs]) => {\n const zods = await Promise.all(\n verbs.map(async (verbOption) =>\n generateZod(\n verbOption,\n {\n route: verbOption.route,\n pathRoute: verbOption.pathRoute,\n override: output.override,\n context,\n output: output.target,\n },\n output.client,\n ),\n ),\n );\n\n if (zods.every((z) => z.implementation === '')) {\n return {\n content: '',\n path: '',\n };\n }\n\n const allMutators = new Map(\n zods.flatMap((z) => z.mutators ?? []).map((m) => [m.name, m]),\n )\n .values()\n .toArray();\n\n const mutatorsImports = generateMutatorImports({\n mutators: allMutators,\n oneMore: output.mode === 'tags-split',\n });\n\n let content = `${header}import { z as zod } from 'zod';\\n${mutatorsImports}\\n`;\n\n const zodPath =\n output.mode === 'tags'\n ? nodePath.join(dirname, `${kebab(tag)}.zod${extension}`)\n : nodePath.join(dirname, tag, tag + '.zod' + extension);\n\n content += zods.map((zod) => zod.implementation).join('\\n');\n\n return {\n content,\n path: zodPath,\n };\n }),\n );\n\n return builderContexts.filter((context) => context.content !== '');\n }\n\n const zods = await Promise.all(\n Object.values(verbOptions).map(async (verbOption) =>\n generateZod(\n verbOption,\n {\n route: verbOption.route,\n pathRoute: verbOption.pathRoute,\n override: output.override,\n context,\n output: output.target,\n },\n output.client,\n ),\n ),\n );\n\n const allMutators = new Map(\n zods.flatMap((z) => z.mutators ?? []).map((m) => [m.name, m]),\n )\n .values()\n .toArray();\n\n const mutatorsImports = generateMutatorImports({\n mutators: allMutators,\n });\n\n let content = `${header}import { z as zod } from 'zod';\\n${mutatorsImports}\\n`;\n\n const zodPath = nodePath.join(dirname, `${filename}.zod${extension}`);\n\n content += zods.map((zod) => zod.implementation).join('\\n');\n\n return [\n {\n content,\n path: zodPath,\n },\n ];\n};\n\nconst generateZvalidator = (\n output: NormalizedOutputOptions,\n context: ContextSpec,\n) => {\n const header = getHeader(output.override.header, getSpecInfo(context));\n\n let validatorPath = output.override.hono.validatorOutputPath;\n if (!output.override.hono.validatorOutputPath) {\n const { extension, dirname, filename } = getFileInfo(output.target, {\n extension: output.fileExtension,\n });\n\n validatorPath = nodePath.join(dirname, `${filename}.validator${extension}`);\n }\n\n return {\n content: `${header}${ZVALIDATOR_SOURCE}`,\n path: validatorPath,\n };\n};\n\nconst generateCompositeRoutes = (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpec,\n) => {\n const targetInfo = getFileInfo(output.target, {\n extension: output.fileExtension,\n });\n const compositeRouteInfo = getFileInfo(output.override.hono.compositeRoute);\n\n const header = getHeader(output.override.header, getSpecInfo(context));\n\n const routes = Object.values(verbOptions)\n .map((verbOption) => {\n return generateHonoRoute(verbOption, verbOption.pathRoute);\n })\n .join('');\n\n const importHandlers = Object.values(verbOptions);\n\n let ImportHandlersImplementation: string;\n if (output.override.hono.handlers) {\n const handlerFileInfo = getFileInfo(output.override.hono.handlers);\n const operationNames = importHandlers.map(\n (verbOption) => verbOption.operationName,\n );\n\n ImportHandlersImplementation = operationNames\n .map((operationName) => {\n const importHandlerName = `${operationName}Handlers`;\n\n const handlersPath = generateModuleSpecifier(\n compositeRouteInfo.path,\n nodePath.join(\n handlerFileInfo.dirname,\n `./${operationName}${targetInfo.extension}`,\n ),\n output.tsconfig,\n );\n\n return `import { ${importHandlerName} } from '${handlersPath}';`;\n })\n .join('\\n');\n } else {\n const tags = importHandlers.map((verbOption) =>\n kebab(verbOption.tags[0] ?? 'default'),\n );\n const uniqueTags = tags.filter((t, i) => tags.indexOf(t) === i);\n\n ImportHandlersImplementation = uniqueTags\n .map((tag) => {\n const importHandlerNames = importHandlers\n .filter((verbOption) => verbOption.tags[0] === tag)\n .map((verbOption) => ` ${verbOption.operationName}Handlers`)\n .join(`, \\n`);\n\n const handlersPath = generateModuleSpecifier(\n compositeRouteInfo.path,\n nodePath.join(targetInfo.dirname, tag),\n output.tsconfig,\n );\n\n const handlersImportExt = getImportExtension(\n targetInfo.extension,\n output.tsconfig,\n );\n\n return `import {\\n${importHandlerNames}\\n} from '${handlersPath}/${tag}.handlers${handlersImportExt}';`;\n })\n .join('\\n');\n }\n\n const honoImport = `import { Hono } from 'hono';`;\n const honoInitialization = `\\nconst app = new Hono()`;\n const honoAppExport = `\\nexport default app;`;\n\n const content = `${header}${honoImport}\n${ImportHandlersImplementation}\n${honoInitialization}${routes};\n${honoAppExport}\n`;\n\n return [\n {\n content,\n path: output.override.hono.compositeRoute || '',\n },\n ];\n};\n\nexport const generateExtraFiles: ClientExtraFilesBuilder = async (\n verbOptions,\n output,\n context,\n) => {\n const { path, pathWithoutExtension, extension } = getFileInfo(output.target, {\n extension: output.fileExtension,\n });\n const validator = generateZvalidator(output, context);\n let schemaModule: string;\n\n if (output.schemas != undefined) {\n const schemasPath = (\n isObject(output.schemas) ? output.schemas.path : output.schemas\n ) as string;\n const basePath = getFileInfo(schemasPath).dirname;\n schemaModule = basePath;\n } else if (output.mode === 'single') {\n schemaModule = path;\n } else {\n schemaModule = `${pathWithoutExtension}.schemas${extension}`;\n }\n\n const contexts = generateContextFiles(\n verbOptions,\n output,\n context,\n schemaModule,\n );\n const compositeRoutes = output.override.hono.compositeRoute\n ? generateCompositeRoutes(verbOptions, output, context)\n : [];\n const [handlers, zods] = await Promise.all([\n generateHandlerFiles(verbOptions, output, context, validator.path),\n generateZodFiles(verbOptions, output, context),\n ]);\n\n return [\n ...handlers,\n ...contexts,\n ...zods,\n ...(output.override.hono.validator &&\n output.override.hono.validator !== 'hono'\n ? [validator]\n : []),\n ...compositeRoutes,\n ];\n};\n\nconst honoClientBuilder: ClientGeneratorsBuilder = {\n client: generateHono,\n dependencies: getHonoDependencies,\n header: getHonoHeader,\n footer: getHonoFooter,\n extraFiles: generateExtraFiles,\n};\n\nexport const builder = () => () => honoClientBuilder;\n\nexport default builder;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orval/hono",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.18.0",
|
|
4
4
|
"homepage": "https://orval.dev/docs/guides/hono",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/orval-labs/orval/issues"
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"./package.json": "./package.json"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@orval/core": "8.
|
|
27
|
-
"@orval/zod": "8.
|
|
26
|
+
"@orval/core": "8.18.0",
|
|
27
|
+
"@orval/zod": "8.18.0",
|
|
28
28
|
"fs-extra": "^11.3.2",
|
|
29
29
|
"remeda": "^2.33.6"
|
|
30
30
|
},
|