zod-opts
Version:
node.js CLI option parser / validator using Zod
157 lines • 5.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.positionalArgumentToInternal = exports.optionToInternal = exports.toInternalTypeForZodUnion = exports.toInternalType = exports.getDefaultValue = void 0;
const zod_1 = require("zod");
const type_1 = require("./type");
const util_1 = require("./util");
function getDefaultValue(def) {
const defaultValue = "defaultValue" in def ? def.defaultValue() : undefined;
if (![...type_1.BASE_TYPES, "undefined"].includes(typeof defaultValue) &&
!Array.isArray(defaultValue)) {
throw new Error(`Unsupported default value: ${JSON.stringify(defaultValue)}`);
}
if (Array.isArray(defaultValue)) {
if (defaultValue.length === 0) {
return defaultValue;
}
if (!["string", "number"].includes(typeof defaultValue[0])) {
throw new Error(`Unsupported default value: ${JSON.stringify(defaultValue)}`);
}
if ((0, util_1.uniq)(defaultValue.map((v) => typeof v)).length > 1) {
throw new Error(`Unsupported default value: ${JSON.stringify(defaultValue)}`);
}
}
return defaultValue;
}
exports.getDefaultValue = getDefaultValue;
function isZodOptional(def) {
if (def.typeName === zod_1.ZodFirstPartyTypeKind.ZodOptional) {
return true;
}
if ("innerType" in def) {
return isZodOptional(def.innerType._def);
}
return false;
}
function isRequired(def) {
if (isZodOptional(def)) {
return false;
}
const defaultValue = getDefaultValue(def);
if (defaultValue !== undefined) {
return false;
}
if (def.typeName === zod_1.ZodFirstPartyTypeKind.ZodUnion) {
return !def.options.some((option) => {
return !isRequired(option._def);
});
}
return true;
}
function resolveInnerType(def) {
if ([
zod_1.ZodFirstPartyTypeKind.ZodOptional,
zod_1.ZodFirstPartyTypeKind.ZodDefault,
].includes(def.typeName)) {
const innerDef = "innerType" in def ? def.innerType._def : def;
return resolveInnerType(innerDef);
}
if (def.typeName === "ZodEffects") {
return resolveInnerType(def.schema._def);
}
return def;
}
function toInternalType(def, isPositional = false) {
const solvedDef = resolveInnerType(def);
switch (solvedDef.typeName) {
case zod_1.ZodFirstPartyTypeKind.ZodNumber:
return "number";
case zod_1.ZodFirstPartyTypeKind.ZodString:
return "string";
case zod_1.ZodFirstPartyTypeKind.ZodBoolean:
if (isPositional) {
throw new Error(`Unsupported zod type (positional argument): ${solvedDef.typeName}`);
}
return "boolean";
case zod_1.ZodFirstPartyTypeKind.ZodEnum:
return "string";
case zod_1.ZodFirstPartyTypeKind.ZodUnion:
return toInternalTypeForZodUnion(solvedDef);
case zod_1.ZodFirstPartyTypeKind.ZodArray:
return toInternalTypeForZodArray(solvedDef);
default:
throw new Error(`Unsupported zod type: ${solvedDef.typeName}`);
}
}
exports.toInternalType = toInternalType;
function toInternalTypeForZodUnion(def) {
const types = (0, util_1.uniq)(def.options.flatMap((option) => {
return [toInternalType(option._def)];
}));
if (types.length !== 1) {
throw new Error("Union types are not same");
}
return types[0];
}
exports.toInternalTypeForZodUnion = toInternalTypeForZodUnion;
function toInternalTypeForZodArray(def) {
const typeName = def.type._def.typeName;
switch (typeName) {
case zod_1.ZodFirstPartyTypeKind.ZodString:
return "string";
case zod_1.ZodFirstPartyTypeKind.ZodNumber:
return "number";
default:
throw new Error(`Unsupported zod type: Array of ${typeName}`);
}
}
function getEnumValues(def) {
const solvedDef = resolveInnerType(def);
if (solvedDef.typeName !== zod_1.ZodFirstPartyTypeKind.ZodEnum) {
return undefined;
}
return solvedDef.values;
}
function optionToInternal(option, name) {
var _a;
// sequence of this is important. It changes exception.
const zodType = option.type;
const def = zodType._def;
const defaultValue = getDefaultValue(def);
const internalType = toInternalType(def);
const description = (_a = option.description) !== null && _a !== void 0 ? _a : ("description" in zodType ? zodType.description : undefined);
const enumValues = getEnumValues(def);
return {
type: internalType,
name,
alias: option.alias,
argumentName: option.argumentName,
description,
required: isRequired(def),
isArray: def.typeName === "ZodArray",
defaultValue,
enumValues,
};
}
exports.optionToInternal = optionToInternal;
function positionalArgumentToInternal(option) {
var _a;
// sequence of this is important. It changes exception.
const zodType = option.type;
const def = zodType._def;
const defaultValue = getDefaultValue(def);
const internalType = toInternalType(def, true);
const description = (_a = option.description) !== null && _a !== void 0 ? _a : ("description" in zodType ? zodType.description : undefined);
const enumValues = getEnumValues(def);
return {
type: internalType,
name: option.name,
description,
required: isRequired(def),
isArray: def.typeName === "ZodArray",
defaultValue,
enumValues,
};
}
exports.positionalArgumentToInternal = positionalArgumentToInternal;
//# sourceMappingURL=zod_util.js.map