hono-takibi 0.9.99992 → 0.9.99993
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.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readConfig } from "./config/index.js";
|
|
3
3
|
import { r as setFormatOptions } from "./emit-CFR63U4L.js";
|
|
4
|
-
import { n as parseOpenAPI, r as takibi, t as makeJob } from "./shared-
|
|
4
|
+
import { n as parseOpenAPI, r as takibi, t as makeJob } from "./shared-DC4zuL9A.js";
|
|
5
5
|
import { existsSync } from "node:fs";
|
|
6
6
|
import { resolve } from "node:path";
|
|
7
7
|
//#region src/cli/index.ts
|
|
@@ -594,6 +594,19 @@ function numericFaker(schema, range) {
|
|
|
594
594
|
`fractionDigits: ${fractionDigits}`
|
|
595
595
|
]).join(", ")} })`;
|
|
596
596
|
}
|
|
597
|
+
function resolveRef(schema, schemas) {
|
|
598
|
+
if (!schema.$ref) return schema;
|
|
599
|
+
const name = schema.$ref.split("/").at(-1);
|
|
600
|
+
return (name ? schemas?.[name] : void 0) ?? schema;
|
|
601
|
+
}
|
|
602
|
+
function isKnownScalar(schema, schemas) {
|
|
603
|
+
const resolved = resolveRef(schema, schemas);
|
|
604
|
+
if (resolved.enum || resolved.const !== void 0) return true;
|
|
605
|
+
if (resolved.properties || resolved.type === "object") return false;
|
|
606
|
+
if (resolved.allOf && resolved.allOf.length > 0) return resolved.allOf.every((s) => isKnownScalar(s, schemas));
|
|
607
|
+
if (resolved.oneOf || resolved.anyOf || resolved.type === "array") return false;
|
|
608
|
+
return typeof resolved.type === "string";
|
|
609
|
+
}
|
|
597
610
|
function schemaToFaker(schema, propertyName, options = {}) {
|
|
598
611
|
if (options.useExamples && schema.example !== void 0) return JSON.stringify(schema.example);
|
|
599
612
|
if (schema.const !== void 0) return `${JSON.stringify(schema.const)} as const`;
|
|
@@ -616,8 +629,19 @@ function schemaToFaker(schema, propertyName, options = {}) {
|
|
|
616
629
|
if (schema.type === "object" && schema.properties) return `{ ${renderProps(schema.properties, schema.required)} }`;
|
|
617
630
|
if (schema.type === "object" && !schema.properties && schema.additionalProperties) return "{}";
|
|
618
631
|
if (schema.allOf && schema.allOf.length > 0) {
|
|
619
|
-
|
|
620
|
-
|
|
632
|
+
if (!schema.properties && schema.allOf.every((s) => isKnownScalar(s, options.schemas))) {
|
|
633
|
+
const [only] = schema.allOf;
|
|
634
|
+
if (schema.allOf.length === 1 && only) return schemaToFaker(only, propertyName, options);
|
|
635
|
+
return schemaToFaker(schema.allOf.map((s) => resolveRef(s, options.schemas)).reduce((acc, s) => ({
|
|
636
|
+
...acc,
|
|
637
|
+
...s
|
|
638
|
+
}), {}), propertyName, options);
|
|
639
|
+
}
|
|
640
|
+
const merged = schema.allOf.filter((s) => !isKnownScalar(s, options.schemas)).map((s) => `...${schemaToFaker(s, propertyName, options)}`).join(", ");
|
|
641
|
+
if (schema.properties) {
|
|
642
|
+
const props = renderProps(schema.properties, schema.required);
|
|
643
|
+
return merged.length > 0 ? `{ ${merged}, ${props} }` : `{ ${props} }`;
|
|
644
|
+
}
|
|
621
645
|
return `{ ${merged} }`;
|
|
622
646
|
}
|
|
623
647
|
const union = schema.oneOf && schema.oneOf.length > 0 ? schema.oneOf : schema.anyOf && schema.anyOf.length > 0 ? schema.anyOf : void 0;
|
|
@@ -710,11 +734,37 @@ function detectCircularSchemas$1(schemas) {
|
|
|
710
734
|
}
|
|
711
735
|
return circular;
|
|
712
736
|
}
|
|
737
|
+
function collectSchemaRefs$1(node, refs) {
|
|
738
|
+
if (Array.isArray(node)) {
|
|
739
|
+
for (const item of node) collectSchemaRefs$1(item, refs);
|
|
740
|
+
return refs;
|
|
741
|
+
}
|
|
742
|
+
if (node !== null && typeof node === "object") for (const [key, value] of Object.entries(node)) if (key === "$ref" && typeof value === "string" && value.includes("/components/schemas/")) {
|
|
743
|
+
const name = value.split("/").at(-1);
|
|
744
|
+
if (name) refs.add(name);
|
|
745
|
+
} else collectSchemaRefs$1(value, refs);
|
|
746
|
+
return refs;
|
|
747
|
+
}
|
|
748
|
+
function schemaClosure(roots, schemas) {
|
|
749
|
+
const used = /* @__PURE__ */ new Set();
|
|
750
|
+
const stack = [...roots];
|
|
751
|
+
while (stack.length > 0) {
|
|
752
|
+
const name = stack.pop();
|
|
753
|
+
if (name === void 0 || used.has(name)) continue;
|
|
754
|
+
used.add(name);
|
|
755
|
+
const schema = schemas[name];
|
|
756
|
+
if (schema) {
|
|
757
|
+
for (const ref of collectSchemaRefs$1(schema, /* @__PURE__ */ new Set())) if (!used.has(ref)) stack.push(ref);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
return used;
|
|
761
|
+
}
|
|
713
762
|
function makeMockFunction(name, schema, schemas, isCircular) {
|
|
714
763
|
const mockBody = schemaToFaker(schema, void 0, { schemas });
|
|
715
764
|
const returnType = isCircular ? ": any" : "";
|
|
716
765
|
const sanitized = name.replace(/\./g, "");
|
|
717
|
-
|
|
766
|
+
const schemaConst = toIdentifierPascalCase(ensureSuffix(name, "Schema"));
|
|
767
|
+
return `function mock${sanitized}()${returnType}{return ${schema["x-brand"] ? `${mockBody} as z.infer<typeof ${schemaConst}>` : mockBody}}`;
|
|
718
768
|
}
|
|
719
769
|
function extractSecurityInfo(opSecurity, globalSecurity, securitySchemes) {
|
|
720
770
|
return (opSecurity ?? globalSecurity ?? []).flatMap((secDef) => Object.keys(secDef).flatMap((schemeName) => {
|
|
@@ -834,7 +884,67 @@ function makeAuthCheck(security, has401) {
|
|
|
834
884
|
if (authChecks.length === 0) return "";
|
|
835
885
|
return `if(!(${authChecks.join(" || ")})){return c.json({ message: 'Unauthorized' }, 401)}`;
|
|
836
886
|
}
|
|
837
|
-
function
|
|
887
|
+
function extractMediaExample(media, components) {
|
|
888
|
+
if (media.example !== void 0) return media.example;
|
|
889
|
+
if (!media.examples) return void 0;
|
|
890
|
+
const first = Object.values(media.examples)[0];
|
|
891
|
+
if (!first) return void 0;
|
|
892
|
+
if ("$ref" in first && typeof first.$ref === "string") {
|
|
893
|
+
const name = first.$ref.split("/").at(-1);
|
|
894
|
+
const resolved = name ? components?.examples?.[name] : void 0;
|
|
895
|
+
return resolved && "value" in resolved ? resolved.value : void 0;
|
|
896
|
+
}
|
|
897
|
+
return "value" in first ? first.value : void 0;
|
|
898
|
+
}
|
|
899
|
+
const PAGE_PARAM_NAMES = [
|
|
900
|
+
"page",
|
|
901
|
+
"pageNumber",
|
|
902
|
+
"page_number"
|
|
903
|
+
];
|
|
904
|
+
const OFFSET_PARAM_NAMES = ["offset", "skip"];
|
|
905
|
+
const ROWS_PARAM_NAMES = [
|
|
906
|
+
"rows",
|
|
907
|
+
"limit",
|
|
908
|
+
"perPage",
|
|
909
|
+
"per_page",
|
|
910
|
+
"pageSize",
|
|
911
|
+
"page_size",
|
|
912
|
+
"size",
|
|
913
|
+
"take"
|
|
914
|
+
];
|
|
915
|
+
function detectPagination(operation) {
|
|
916
|
+
if (operation["x-pagination"] !== true) return void 0;
|
|
917
|
+
const queryParams = (operation.parameters ?? []).filter((p) => "in" in p && p.in === "query");
|
|
918
|
+
const rows = queryParams.find((p) => ROWS_PARAM_NAMES.includes(p.name));
|
|
919
|
+
if (!rows) return void 0;
|
|
920
|
+
const pageParam = queryParams.find((p) => PAGE_PARAM_NAMES.includes(p.name));
|
|
921
|
+
const offsetParam = pageParam ? void 0 : queryParams.find((p) => OFFSET_PARAM_NAMES.includes(p.name));
|
|
922
|
+
const cursor = pageParam ?? offsetParam;
|
|
923
|
+
if (!cursor) return void 0;
|
|
924
|
+
const defaultRows = typeof rows.schema?.default === "number" ? rows.schema.default : 20;
|
|
925
|
+
return {
|
|
926
|
+
rowsParam: rows.name,
|
|
927
|
+
cursorParam: cursor.name,
|
|
928
|
+
offsetStyle: offsetParam !== void 0,
|
|
929
|
+
defaultRows
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
function makeHandlerBody(args) {
|
|
933
|
+
const { statusCode, jsonSchema, textSchema, schemas, allRefs, exampleValue, exampleCast, pagination } = args;
|
|
934
|
+
if (exampleValue !== void 0) {
|
|
935
|
+
const cast = exampleCast ? ` as z.infer<typeof ${exampleCast}>` : "";
|
|
936
|
+
return `return c.json(${JSON.stringify(exampleValue)}${cast}, ${statusCode})`;
|
|
937
|
+
}
|
|
938
|
+
if (pagination && jsonSchema?.type === "array" && jsonSchema.items) {
|
|
939
|
+
collectRefs(jsonSchema, allRefs);
|
|
940
|
+
const itemFaker = schemaToFaker(Array.isArray(jsonSchema.items) ? jsonSchema.items[0] : jsonSchema.items, void 0, { schemas });
|
|
941
|
+
const startExpr = pagination.offsetStyle ? `const start = query.${pagination.cursorParam} ?? 0` : `const page = query.${pagination.cursorParam} ?? 1\nconst start = (page - 1) * rows`;
|
|
942
|
+
return `const query = c.req.valid('query')
|
|
943
|
+
const rows = query.${pagination.rowsParam} ?? ${pagination.defaultRows}
|
|
944
|
+
${startExpr}
|
|
945
|
+
const items = Array.from({ length: ${pagination.totalConst} }, () => (${itemFaker}))
|
|
946
|
+
return c.json(items.slice(start, start + rows), ${statusCode})`;
|
|
947
|
+
}
|
|
838
948
|
if (jsonSchema) {
|
|
839
949
|
collectRefs(jsonSchema, allRefs);
|
|
840
950
|
return `return c.json(${schemaToFaker(jsonSchema, void 0, { schemas })}, ${statusCode})`;
|
|
@@ -860,7 +970,26 @@ function makeMock(openapi, basePath, options = {}) {
|
|
|
860
970
|
const successResponse = success?.response;
|
|
861
971
|
const jsonMedia = successResponse?.content?.["application/json"];
|
|
862
972
|
const textMedia = successResponse?.content?.["text/plain"];
|
|
863
|
-
const
|
|
973
|
+
const jsonSchema = jsonMedia && isMediaWithSchema(jsonMedia) ? jsonMedia.schema : void 0;
|
|
974
|
+
const textSchema = textMedia && isMediaWithSchema(textMedia) ? textMedia.schema : void 0;
|
|
975
|
+
const exampleValue = jsonMedia ? extractMediaExample(jsonMedia, openapi.components) : void 0;
|
|
976
|
+
const exampleCast = exampleValue !== void 0 && jsonSchema?.$ref ? toIdentifierPascalCase(ensureSuffix(jsonSchema.$ref.split("/").at(-1) ?? "", "Schema")) : void 0;
|
|
977
|
+
const pag = detectPagination(operation);
|
|
978
|
+
const pagination = pag && exampleValue === void 0 && jsonSchema?.type === "array" && jsonSchema.items ? {
|
|
979
|
+
totalConst: `${routeId}Total`,
|
|
980
|
+
...pag
|
|
981
|
+
} : void 0;
|
|
982
|
+
const handlerBody = makeHandlerBody({
|
|
983
|
+
statusCode,
|
|
984
|
+
jsonSchema,
|
|
985
|
+
textSchema,
|
|
986
|
+
schemas,
|
|
987
|
+
allRefs,
|
|
988
|
+
exampleValue,
|
|
989
|
+
exampleCast,
|
|
990
|
+
pagination
|
|
991
|
+
});
|
|
992
|
+
const paginationDecl = pagination ? `const ${pagination.totalConst} = faker.number.int({ min: 0, max: ${Math.min(pagination.defaultRows * 3, 3e3)} })` : "";
|
|
864
993
|
const authCheck = makeAuthCheck(security, operation.responses?.[String(401)] !== void 0);
|
|
865
994
|
const handler = `const ${routeId}RouteHandler: RouteHandler<typeof ${routeId}Route> = async (${handlerBody.includes("c.") || authCheck !== "" ? "c" : "_c"}) => {${authCheck}${handlerBody}}`;
|
|
866
995
|
return [{
|
|
@@ -870,17 +999,34 @@ function makeMock(openapi, basePath, options = {}) {
|
|
|
870
999
|
path: p,
|
|
871
1000
|
requiresAuth
|
|
872
1001
|
},
|
|
873
|
-
handler
|
|
1002
|
+
handler,
|
|
1003
|
+
paginationDecl
|
|
874
1004
|
}];
|
|
875
1005
|
}));
|
|
876
1006
|
const routeMetas = processed.map(({ entry }) => entry);
|
|
877
1007
|
const handlers = processed.map(({ handler }) => handler);
|
|
1008
|
+
const paginationDecls = processed.flatMap(({ paginationDecl }) => paginationDecl.length > 0 ? [paginationDecl] : []);
|
|
878
1009
|
const allDeps = /* @__PURE__ */ new Set();
|
|
879
1010
|
for (const ref of allRefs) collectAllDependencies(ref, schemas, allDeps);
|
|
880
1011
|
const sortedRefs = topologicalSort(allDeps, schemas);
|
|
881
1012
|
const circularSchemas = detectCircularSchemas$1(schemas);
|
|
882
1013
|
const mockFunctions = sortedRefs.filter((refName) => schemas[refName]).map((refName) => makeMockFunction(refName, schemas[refName], schemas, circularSchemas.has(refName)));
|
|
883
|
-
const
|
|
1014
|
+
const rootRefs = collectSchemaRefs$1(filteredOpenapi.paths, /* @__PURE__ */ new Set());
|
|
1015
|
+
if (openapi.components) {
|
|
1016
|
+
collectSchemaRefs$1(openapi.components.responses, rootRefs);
|
|
1017
|
+
collectSchemaRefs$1(openapi.components.parameters, rootRefs);
|
|
1018
|
+
collectSchemaRefs$1(openapi.components.requestBodies, rootRefs);
|
|
1019
|
+
collectSchemaRefs$1(openapi.components.headers, rootRefs);
|
|
1020
|
+
collectSchemaRefs$1(openapi.components.callbacks, rootRefs);
|
|
1021
|
+
collectSchemaRefs$1(openapi.components.pathItems, rootRefs);
|
|
1022
|
+
collectSchemaRefs$1(openapi.components.links, rootRefs);
|
|
1023
|
+
}
|
|
1024
|
+
const usedSchemaNames = schemaClosure(rootRefs, schemas);
|
|
1025
|
+
const filteredComponents = openapi.components ? {
|
|
1026
|
+
...openapi.components,
|
|
1027
|
+
schemas: Object.fromEntries(Object.entries(schemas).filter(([name]) => usedSchemaNames.has(name)))
|
|
1028
|
+
} : void 0;
|
|
1029
|
+
const components = filteredComponents ? componentsCode(filteredComponents, {
|
|
884
1030
|
exportSchemasTypes: false,
|
|
885
1031
|
exportSchemas: false,
|
|
886
1032
|
exportParametersTypes: false,
|
|
@@ -913,6 +1059,7 @@ export default app`;
|
|
|
913
1059
|
components,
|
|
914
1060
|
routes,
|
|
915
1061
|
mockFunctions.join("\n\n"),
|
|
1062
|
+
paginationDecls.join("\n"),
|
|
916
1063
|
handlersJoined,
|
|
917
1064
|
appCode
|
|
918
1065
|
].filter((s) => s.length > 0).join("\n\n");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parseConfig } from "../config/index.js";
|
|
2
2
|
import { r as setFormatOptions } from "../emit-CFR63U4L.js";
|
|
3
3
|
import { f as isRecord } from "../guard-zvkMUVYD.js";
|
|
4
|
-
import { n as parseOpenAPI, t as makeJob } from "../shared-
|
|
4
|
+
import { n as parseOpenAPI, t as makeJob } from "../shared-DC4zuL9A.js";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import fsp from "node:fs/promises";
|
|
7
7
|
//#region src/vite-plugin/index.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hono-takibi",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.99993",
|
|
4
4
|
"description": "Hono Takibi is a code generator from OpenAPI to @hono/zod-openapi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hono",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"zod": "^4.4.3"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@types/node": "^26.0.
|
|
66
|
+
"@types/node": "^26.0.1",
|
|
67
67
|
"@typespec/http": "^1.13.0",
|
|
68
68
|
"@typespec/rest": "^0.83.0",
|
|
69
69
|
"@typespec/versioning": "^0.83.0",
|