@kubb/plugin-zod
Version:
Zod schema generator plugin for Kubb, creating type-safe validation schemas from OpenAPI specifications for runtime data validation.
268 lines (265 loc) • 8.28 kB
JavaScript
import { t as __name } from "./chunk-eQyhnF5A.js";
import { n as Operations, t as Zod } from "./components-BdH8vk4k.js";
import path from "node:path";
import { SchemaGenerator, schemaKeywords } from "@kubb/plugin-oas";
import { pluginTsName } from "@kubb/plugin-ts";
import { useMode, usePluginManager } from "@kubb/core/hooks";
import { createReactGenerator } from "@kubb/plugin-oas/generators";
import { useOas, useOperationManager, useSchemaManager } from "@kubb/plugin-oas/hooks";
import { getBanner, getFooter } from "@kubb/plugin-oas/utils";
import { File, Fragment } from "@kubb/react-fabric";
import { jsx, jsxs } from "@kubb/react-fabric/jsx-runtime";
//#region src/generators/operationsGenerator.tsx
const operationsGenerator = createReactGenerator({
name: "operations",
Operations({ operations, generator, plugin }) {
const { key: pluginKey, options: { output, importPath } } = plugin;
const pluginManager = usePluginManager();
const oas = useOas();
const { getFile, groupSchemasByName } = useOperationManager(generator);
const name = "operations";
const file = pluginManager.getFile({
name,
extname: ".ts",
pluginKey
});
const transformedOperations = operations.map((operation) => ({
operation,
data: groupSchemasByName(operation, { type: "function" })
}));
const imports = Object.entries(transformedOperations).map(([key, { data, operation }]) => {
const names = [
data.request,
...Object.values(data.responses),
...Object.values(data.parameters)
].filter(Boolean);
return /* @__PURE__ */ jsx(File.Import, {
name: names,
root: file.path,
path: getFile(operation).path
}, key);
}).filter(Boolean);
return /* @__PURE__ */ jsxs(File, {
baseName: file.baseName,
path: file.path,
meta: file.meta,
banner: getBanner({
oas,
output,
config: pluginManager.config
}),
footer: getFooter({
oas,
output
}),
children: [
/* @__PURE__ */ jsx(File.Import, {
isTypeOnly: true,
name: ["z"],
path: importPath
}),
imports,
/* @__PURE__ */ jsx(Operations, {
name,
operations: transformedOperations
})
]
});
}
});
//#endregion
//#region src/generators/zodGenerator.tsx
const zodGenerator = createReactGenerator({
name: "zod",
Operation({ config, operation, generator, plugin }) {
const { options, options: { coercion: globalCoercion, inferred, typed, mapper, wrapOutput, version, mini } } = plugin;
const mode = useMode();
const pluginManager = usePluginManager();
const oas = useOas();
const { getSchemas, getFile, getGroup } = useOperationManager(generator);
const schemaManager = useSchemaManager();
const file = getFile(operation);
const schemas = getSchemas(operation);
const schemaGenerator = new SchemaGenerator(options, {
fabric: generator.context.fabric,
oas,
plugin,
pluginManager,
events: generator.context.events,
mode,
override: options.override
});
const operationSchemas = [
schemas.pathParams,
schemas.queryParams,
schemas.headerParams,
schemas.statusCodes,
schemas.request,
schemas.response
].flat().filter(Boolean);
const mapOperationSchema = ({ name, schema: schemaObject, description, keysToOmit, ...options$1 }) => {
const hasProperties = Object.keys(schemaObject || {}).length > 0;
const hasDefaults = Object.values(schemaObject.properties || {}).some((prop) => prop && Object.hasOwn(prop, "default"));
const optional = !(Array.isArray(schemaObject?.required) ? schemaObject.required.length > 0 : !!schemaObject?.required) && !hasDefaults && hasProperties && name.includes("Params");
if (!optional && Array.isArray(schemaObject.required) && !schemaObject.required.length) schemaObject.required = Object.entries(schemaObject.properties || {}).filter(([_key, value]) => value && Object.hasOwn(value, "default")).map(([key]) => key);
const tree = [...schemaGenerator.parse({
schema: schemaObject,
name,
parentName: null
}), optional ? { keyword: schemaKeywords.optional } : void 0].filter(Boolean);
const imports = schemaManager.getImports(tree);
const group = options$1.operation ? getGroup(options$1.operation) : void 0;
const coercion = name.includes("Params") ? {
numbers: true,
strings: false,
dates: true
} : globalCoercion;
const zod = {
name: schemaManager.getName(name, { type: "function" }),
inferTypeName: schemaManager.getName(name, { type: "type" }),
file: schemaManager.getFile(name)
};
const type = {
name: schemaManager.getName(name, {
type: "type",
pluginKey: [pluginTsName]
}),
file: schemaManager.getFile(options$1.operationName || name, {
pluginKey: [pluginTsName],
group
})
};
return /* @__PURE__ */ jsxs(Fragment, { children: [
typed && /* @__PURE__ */ jsx(File.Import, {
isTypeOnly: true,
root: file.path,
path: type.file.path,
name: [type.name]
}),
typed && version === "3" && /* @__PURE__ */ jsx(File.Import, {
name: ["ToZod"],
root: file.path,
path: path.resolve(config.root, config.output.path, ".kubb/ToZod.ts")
}),
imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
root: file.path,
path: imp.path,
name: imp.name
}, [
imp.path,
imp.name,
imp.isTypeOnly
].join("-"))),
/* @__PURE__ */ jsx(Zod, {
name: zod.name,
typeName: typed ? type.name : void 0,
inferTypeName: inferred ? zod.inferTypeName : void 0,
description,
tree,
schema: schemaObject,
mapper,
coercion,
keysToOmit,
wrapOutput,
version: plugin.options.version,
emptySchemaType: plugin.options.emptySchemaType,
mini
})
] });
};
return /* @__PURE__ */ jsxs(File, {
baseName: file.baseName,
path: file.path,
meta: file.meta,
banner: getBanner({
oas,
output: plugin.options.output,
config: pluginManager.config
}),
footer: getFooter({
oas,
output: plugin.options.output
}),
children: [/* @__PURE__ */ jsx(File.Import, {
name: ["z"],
path: plugin.options.importPath
}), operationSchemas.map(mapOperationSchema)]
});
},
Schema({ config, schema, plugin }) {
const { getName, getFile, getImports } = useSchemaManager();
const { options: { output, emptySchemaType, coercion, inferred, typed, mapper, importPath, wrapOutput, version, mini } } = plugin;
const pluginManager = usePluginManager();
const oas = useOas();
const imports = getImports(schema.tree);
const zod = {
name: getName(schema.name, { type: "function" }),
inferTypeName: getName(schema.name, { type: "type" }),
file: getFile(schema.name)
};
const type = {
name: getName(schema.name, {
type: "type",
pluginKey: [pluginTsName]
}),
file: getFile(schema.name, { pluginKey: [pluginTsName] })
};
return /* @__PURE__ */ jsxs(File, {
baseName: zod.file.baseName,
path: zod.file.path,
meta: zod.file.meta,
banner: getBanner({
oas,
output,
config: pluginManager.config
}),
footer: getFooter({
oas,
output
}),
children: [
/* @__PURE__ */ jsx(File.Import, {
name: ["z"],
path: importPath
}),
typed && /* @__PURE__ */ jsx(File.Import, {
isTypeOnly: true,
root: zod.file.path,
path: type.file.path,
name: [type.name]
}),
typed && version === "3" && /* @__PURE__ */ jsx(File.Import, {
name: ["ToZod"],
root: zod.file.path,
path: path.resolve(config.root, config.output.path, ".kubb/ToZod.ts")
}),
imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
root: zod.file.path,
path: imp.path,
name: imp.name
}, [
imp.path,
imp.name,
imp.isTypeOnly
].join("-"))),
/* @__PURE__ */ jsx(Zod, {
name: zod.name,
typeName: typed ? type.name : void 0,
inferTypeName: inferred ? zod.inferTypeName : void 0,
description: schema.value.description,
tree: schema.tree,
schema: schema.value,
mapper,
coercion,
wrapOutput,
version,
emptySchemaType,
mini
})
]
});
}
});
//#endregion
export { operationsGenerator as n, zodGenerator as t };
//# sourceMappingURL=generators-BP4elkVx.js.map