zod-opts
Version:
node.js CLI option parser / validator using Zod
106 lines (105 loc) • 4.03 kB
TypeScript
import { type z, type ZodArrayDef, type ZodBooleanDef, type ZodDefaultDef, type ZodEffectsDef, type ZodEnumDef, type ZodNumberDef, type ZodObject, type ZodOptionalDef, type ZodRawShape, type ZodStringDef, type ZodType, type ZodTypeAny, type ZodUnionDef } from "zod";
export type ZodDef = ZodNumberDef | ZodStringDef | ZodUnionDef | ZodBooleanDef | ZodEnumDef | ZodArrayDef | ZodOptionalDef | ZodDefaultDef | ZodEffectsDef;
export declare const BASE_TYPES: readonly ["number", "string", "boolean"];
export type BaseType = (typeof BASE_TYPES)[number];
export type BaseTypeT = number | string | boolean;
export interface Option {
type: ZodTypeAny;
argumentName?: string;
alias?: string;
description?: string;
}
export type Options = Record<string, Option>;
export interface PositionalArgument {
name: string;
type: ZodTypeAny;
description?: string;
}
export type PositionalArguments = [] | [PositionalArgument, ...PositionalArgument[]];
export type OptionsToZodShape<T extends Options> = {
[Key in keyof T]: T[Key]["type"];
};
export type PositionalArgumentsToShape<T, TAcc = {}> = T extends [
infer Head,
...infer Rest
] ? Head extends {
name: infer Name;
type: infer ZodType;
} ? Name extends string ? PositionalArgumentsToShape<Rest, {
[Key in Name]: ZodType;
} & TAcc> : TAcc : TAcc : TAcc;
export type GenerateZodShape<TOptions, TPositionalArguments> = (TOptions extends Options ? OptionsToZodShape<TOptions> : {}) & (TPositionalArguments extends PositionalArguments ? PositionalArgumentsToShape<TPositionalArguments> : {});
export interface ParseResultMatch<T> {
type: "match";
parsed: T;
help: string;
commandName?: string;
}
export interface ParseResultError {
type: "error";
error: Error;
help: string;
exitCode: 1;
commandName?: string;
}
export interface ParseResultHelp {
type: "help";
help: string;
exitCode: 0;
commandName?: string;
}
export interface ParseResultVersion {
type: "version";
help: string;
exitCode: 0;
}
export type ParseResult<T> = ParseResultMatch<T> | ParseResultError | ParseResultHelp | ParseResultVersion;
export interface InternalOption {
type: BaseType;
name: string;
alias?: string;
argumentName?: string;
description?: string;
required: boolean;
defaultValue?: string | number | string[] | number[] | boolean;
isArray: boolean;
enumValues?: string[];
}
export interface InternalPositionalArgument {
type: "string" | "number";
name: string;
description?: string;
required: boolean;
isArray: boolean;
defaultValue?: string | number | string[] | number[];
enumValues?: string[];
}
export interface InternalCommand {
name: string;
description?: string;
options: InternalOption[];
positionalArgs: InternalPositionalArgument[];
}
export type Handler<T extends ZodRawShape> = (arg0: ParseResultMatch<z.infer<ZodObject<T>>> | ParseResultError | ParseResultHelp | ParseResultVersion) => void;
export type ValidateCallback<T extends ZodRawShape> = (parsed: z.infer<ZodObject<T>>) => true | string;
export interface FormatValidOption {
name: string;
value: string | number | boolean | string[] | number[] | undefined;
}
export interface FormatValidPositionalArgument {
name: string;
value: string | number | string[] | number[] | undefined;
}
type Try<A, B, C> = A extends B ? A : C;
type NarrowRaw<T> = (T extends Function ? T : never) | (T extends string | number | bigint | boolean ? T : never) | (T extends [] ? [] : never) | {
[K in keyof T]: K extends "description" ? T[K] : NarrowNotZod<T[K]>;
};
type NarrowNotZod<T> = Try<T, ZodType, NarrowRaw<T>>;
/**
* Utility to infer the embedded primitive type of any type
* Same as `as const` but without setting the object as readonly and without needing the user to use it
* @param T - type to infer the embedded type of
* @see - thank you tannerlinsley for this idea
*/
export type Narrow<T> = Try<T, [], NarrowNotZod<T>>;
export {};