Add validators schema and code templates
This commit is contained in:
69
src/validators/schema.ts
Normal file
69
src/validators/schema.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
import { CLISpec, Option, Command, Argument, Example } from '../types/spec.js';
|
||||||
|
|
||||||
|
const optionSchema: z.ZodType<Option> = z.object({
|
||||||
|
name: z.string().min(1, 'Option name is required'),
|
||||||
|
short: z.string().optional(),
|
||||||
|
description: z.string().min(1, 'Option description is required'),
|
||||||
|
type: z.enum(['string', 'number', 'boolean', 'array']),
|
||||||
|
required: z.boolean().optional(),
|
||||||
|
default: z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]).optional(),
|
||||||
|
choices: z.array(z.union([z.string(), z.number()])).optional(),
|
||||||
|
implies: z.array(z.string()).optional(),
|
||||||
|
conflicts: z.array(z.string()).optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const argumentSchema: z.ZodType<Argument> = z.object({
|
||||||
|
name: z.string().min(1, 'Argument name is required'),
|
||||||
|
description: z.string().min(1, 'Argument description is required'),
|
||||||
|
required: z.boolean().optional(),
|
||||||
|
variadic: z.boolean().optional(),
|
||||||
|
choices: z.array(z.string()).optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const exampleSchema: z.ZodType<Example> = z.object({
|
||||||
|
description: z.string().min(1, 'Example description is required'),
|
||||||
|
command: z.string().min(1, 'Example command is required'),
|
||||||
|
output: z.string().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const commandSchema: z.ZodType<Command> = z.lazy(() =>
|
||||||
|
z.object({
|
||||||
|
name: z.string().min(1, 'Command name is required'),
|
||||||
|
description: z.string().min(1, 'Command description is required'),
|
||||||
|
aliases: z.array(z.string()).optional(),
|
||||||
|
options: z.array(optionSchema).optional(),
|
||||||
|
arguments: z.array(argumentSchema).optional(),
|
||||||
|
subcommands: z.array(z.lazy(() => commandSchema)).optional(),
|
||||||
|
examples: z.array(exampleSchema).optional(),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
export const cliSpecSchema: z.ZodType<CLISpec> = z.object({
|
||||||
|
name: z.string().min(1, 'CLI name is required'),
|
||||||
|
version: z.string().regex(/^\d+\.\d+\.\d+/, 'Version must be semantic (e.g., 1.0.0)'),
|
||||||
|
description: z.string().min(1, 'Description is required'),
|
||||||
|
author: z.string().optional(),
|
||||||
|
license: z.string().optional(),
|
||||||
|
homepage: z.string().url().optional().or(z.string().optional()),
|
||||||
|
bin: z.string().optional(),
|
||||||
|
globalOptions: z.array(optionSchema).optional(),
|
||||||
|
commands: z.array(commandSchema).min(1, 'At least one command is required'),
|
||||||
|
examples: z.array(exampleSchema).optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export function validateSpec(spec: unknown): { success: true; data: CLISpec } | { success: false; errors: string[] } {
|
||||||
|
const result = cliSpecSchema.safeParse(spec);
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
return { success: true, data: result.data };
|
||||||
|
}
|
||||||
|
|
||||||
|
const errors: string[] = [];
|
||||||
|
for (const issue of result.error.issues) {
|
||||||
|
const path = issue.path.join('.');
|
||||||
|
errors.push(`${path ? `${path}: ` : ''}${issue.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: false, errors };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user