tunnckoCore/zodest(新しいタブで開きます)
主要言語: TypeScript
Modern Zod-based CLI builder, fully type-safe, super lightweight and flexible.
- star 数
- 250
- watcher 数
- 1
- fork 数
- 1
- issue 数
- 7
- 最終更新
- 2026/02/21
主要言語: TypeScript
Modern Zod-based CLI builder, fully type-safe, super lightweight and flexible.
Modern Zod-based CLI builder, fully type-safe, super lightweight and flexible.
npm install zodest zod # or yarn add zodest zod # or pnpm add zodest zod # or bun add zodest zod
import { z } from 'zod'; import { defineCommand, defineConfig, defineOptions } from 'zodest/config'; import { processConfig } from 'zodest'; const globalOptions = defineOptions( z.object({ verbose: z.boolean().default(false), }), ); const config = defineConfig({ globalOptions, commands: { serve: defineCommand({ description: 'Start development server', options: defineOptions( z.object({ port: z.coerce.number().min(1024).default(3000), }), { p: 'port' }, // aliases, type-safe with the schema ), args: z.array(z.string()), action(options, args) { console.log('Server starting on port', options.port); }, }), }, }); // Process CLI arguments, returns the matching command const result = processConfig(config, process.argv.slice(2)); console.log('result:', result._kind, result); // => result._kind == 'serve', the matching command's name // in `result` there's also `result.globalOptions`, and so on, all type-safe // call the command result.command.action(result.options, result.args);
Commands are the basic building blocks. Each command can have:
const myCommand = defineCommand({ description: 'My command description', options: defineOptions( z.object({ force: z.boolean().default(false), }), ), args: z.string().min(3), aliases: ['mc', 'mycmd'], action(options, args) { // Fully typed options and args }, });
Shared options across all commands:
const globalOptions = defineOptions( z.object({ debug: z.boolean().default(false), config: z.string().optional(), }), { d: 'debug', // aliases c: 'config', }, );
Support for namespaced commands:
const config = defineConfig({ commands: { 'user add': defineCommand({...}), 'user remove': defineCommand({...}), 'user list': defineCommand({...}), } });
Create reusable command sets:
import { withGlobalOptions } from 'zodest/config'; const userCommands = withGlobalOptions(globalOptions, (gopts) => ({ userAdd: defineCommand({...}), userRemove: defineCommand({...}), })); // Use in any CLI const config = defineConfig({ globalOptions, commands: (gopts) => ({ ...userCommands(gopts), // Add more commands }) });
Creates a type-safe CLI configuration.
Defines a new command with options, arguments, and an action.
Creates a type-safe options definition with optional aliases.
Processes command line arguments against the configuration.
Creates a command preset with access to global options.
Returns all available commands from the configuration.
const command = defineCommand({ description: 'Complex command', options: defineOptions( z.object({ mode: z.enum(['development', 'production']), port: z.coerce.number().min(1024), }), ), args: z.tuple([z.string(), z.coerce.number()]), action(options, [path, num]) { // path is string, num is number }, });
NOTE: mixing grouped commands with non-grouped ones breaks the defaultCommand inference of the
grouped commands, so you must use as any to mute TypeScript, or use a command from non-grouped
commands
const config = defineConfig({ defaultCommand: 'serve', commands: { serve: defineCommand({...}) dev: defineCommand({...}) } });
const devCommands = withGlobalOptions(globalOptions, (gopts) => ({ serve: defineCommand({...}), build: defineCommand({...}), })); const dbCommands = withGlobalOptions(globalOptions, (gopts) => ({ 'db migrate': defineCommand({...}), 'db seed': defineCommand({...}), })); const config = defineConfig({ globalOptions, commands: (gopts) => ({ ...devCommands(gopts), ...dbCommands(gopts), }) });
Apache-2.0