UNPKG

zod-opts

Version:

node.js CLI option parser / validator using Zod

105 lines (104 loc) 3.7 kB
import { type z, type ZodObject, type ZodRawShape, type ZodType, type ZodTypeAny } from "zod"; 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 {};