type Prettify<T> = { [K in keyof T] : T[K] } & {};
type ExtractPositionalType<T> = T extends PositionalSchema<infer U> ? U : never;
type ExtractPositionalTypes<T extends readonly PositionalSchema<any>[]> = { readonly [K in keyof T] : ExtractPositionalType<T[K]> };
type SchemaType = "string" | "number" | "boolean" | "array" | "object";
interface BaseSchema<T = any> {
	_type: SchemaType;
	_output: T;
	_input: unknown;
	parse(value: unknown, path?: string): T;
	optional(): Schema<T | undefined>;
	default(value: T): Schema<T>;
	transform<U>(fn: (value: T) => U): Schema<U>;
	describe(description: string): this;
	alias(alias: string): this;
	example(example: string): this;
	_description?: string;
	_alias?: string;
	_example?: string;
	_isOptional?: boolean;
	_defaultValue?: T;
}
type Schema<T = any> = BaseSchema<T>;
interface StringSchemaBase<T extends string = string> extends BaseSchema<T> {
	min(length: number): this;
	max(length: number): this;
	regex(pattern: RegExp, message?: string): this;
	choices<const U extends readonly string[]>(choices: U): StringSchema<U[number]>;
	_minLength?: number;
	_maxLength?: number;
	_regex?: {
		pattern: RegExp
		message?: string
	};
	_choices?: readonly string[];
}
type StringSchema<T extends string = string> = StringSchemaBase<T>;
interface NumberSchema extends BaseSchema<number> {
	min(value: number): this;
	max(value: number): this;
	int(): this;
	positive(): this;
	negative(): this;
	_min?: number;
	_max?: number;
	_isInt?: boolean;
	_isPositive?: boolean;
	_isNegative?: boolean;
}
interface BooleanSchema extends BaseSchema<boolean> {}
interface ArraySchema<T> extends BaseSchema<T[]> {
	min(length: number): this;
	max(length: number): this;
	_itemSchema: Schema<T>;
	_minLength?: number;
	_maxLength?: number;
}
interface ObjectSchema<T extends Record<string, any>> extends BaseSchema<T> {
	_shape: { [K in keyof T] : Schema<T[K]> };
}
interface PositionalSchema<T = string> extends BaseSchema<T> {
	_name: string;
}
interface Command<
	TOptions extends Record<string, Schema> = any,
	TPositionals extends readonly PositionalSchema<any>[] = readonly []
> {
	name: string;
	description?: string;
	usage?: string;
	example?: string | string[];
	options: TOptions;
	positionals?: PositionalSchema<any>[];
	action: (args: {
		options: Prettify<{ [K in keyof TOptions] : TOptions[K]["_output"] }>
		positionals: ExtractPositionalTypes<TPositionals>
	}) => void | Promise<void>;
}
interface CommandBuilder<
	TOptions extends Record<string, Schema>,
	TPositionals extends readonly PositionalSchema<any>[] = readonly []
> {
	description(desc: string): this;
	usage(usage: string): this;
	example(example: string | string[]): this;
	positional<T>(name: string, schema?: Schema<T>): CommandBuilder<TOptions, [...TPositionals, PositionalSchema<T>]>;
	action(fn: (args: {
		options: Prettify<{ [K in keyof TOptions] : TOptions[K]["_output"] }>
		positionals: ExtractPositionalTypes<TPositionals>
	}) => void | Promise<void>): Command<TOptions, TPositionals>;
}
interface CLI<
	TOptions extends Record<string, Schema> = Record<string, never>,
	TPositionals extends readonly PositionalSchema<any>[] = readonly []
> {
	name(name: string): this;
	version(version: string): this;
	description(description: string): this;
	usage(usage: string): this;
	example(example: string | string[]): this;
	option<
		K extends string,
		S extends Schema
	>(name: K, schema: S): CLI<TOptions & { [P in K] : S }, TPositionals>;
	positional<T>(name: string, schema?: Schema<T>): CLI<TOptions, [...TPositionals, PositionalSchema<T>]>;
	command<T extends Record<string, Schema> = Record<string, never>>(name: string, options?: T): CommandBuilder<T>;
	parse(argv?: string[]): {
		options: Prettify<{ [K in keyof TOptions] : TOptions[K]["_output"] }>
		positionals: ExtractPositionalTypes<TPositionals>
	} | undefined;
	_name?: string;
	_version?: string;
	_description?: string;
	_usage?: string;
	_examples?: string[];
	_options: TOptions;
	_positionals?: PositionalSchema<any>[];
	_commands: Command<any, any>[];
}
declare const z: {
	string: () => StringSchema
	number: () => NumberSchema
	boolean: () => BooleanSchema
	array: <T>(schema: Schema<T>) => ArraySchema<T>
	object: <T extends Record<string, Schema>>(shape: T) => ObjectSchema<{ [K in keyof T] : T[K]["_output"] }>
};
declare function cli(): CLI<Record<string, never>, readonly []>;
export { z, cli };
