@jsnix/pastel
Version:
Framework for effortlessly building Ink apps
100 lines • 4.13 kB
JavaScript
import { isDeepStrictEqual } from 'node:util';
import { Option } from 'commander';
import decamelize from 'decamelize';
import { ZodArray, ZodBoolean, ZodDefault, ZodEnum, ZodNumber, ZodOptional, ZodSet, } from 'zod';
import plur from 'plur';
const getConfig = (value) => {
return value?.startsWith('__pastel_option_config__')
? JSON.parse(value.replace('__pastel_option_config__', ''))
: undefined;
};
const getDescription = (value) => {
return getConfig(value)?.description ?? value;
};
const getDefaultValueDescription = (value) => {
return getConfig(value)?.defaultValueDescription;
};
const getValueDescription = (value) => {
return getConfig(value)?.valueDescription;
};
const getAlias = (value) => {
return getConfig(value)?.alias;
};
export default function generateOptions(optionsSchema) {
let isOptionalByDefault = false;
if (optionsSchema instanceof ZodOptional) {
isOptionalByDefault = true;
optionsSchema = optionsSchema._def.innerType;
}
const options = [];
for (let [name, optionSchema] of Object.entries(optionsSchema._def.shape())) {
name = decamelize(name, { separator: '-' });
let defaultValue;
let defaultValueDescription = getDefaultValueDescription(optionSchema.description);
const description = getDescription(optionSchema.description);
let valueDescription = getValueDescription(optionSchema.description);
let isOptional = isOptionalByDefault;
// Unwrap zod.string().optional()
if (optionSchema instanceof ZodOptional) {
isOptional = true;
optionSchema = optionSchema._def.innerType;
}
// Unwrap zod.string().optional().default()
if (optionSchema instanceof ZodDefault) {
isOptional = true;
defaultValue = optionSchema._def.defaultValue();
optionSchema = optionSchema._def.innerType;
}
// Unwrap zod.string().default().optional()
if (optionSchema instanceof ZodOptional) {
isOptional = true;
optionSchema = optionSchema._def.innerType;
}
const alias = getAlias(optionSchema.description);
let flag = `--${name}`;
if (optionSchema instanceof ZodBoolean && defaultValue === true) {
flag = `--no-${name}`;
}
else if (alias) {
flag = `-${alias}, --${name}`;
}
const expectsValue = !(optionSchema instanceof ZodBoolean);
if (expectsValue) {
const isVariadic = optionSchema instanceof ZodArray || optionSchema instanceof ZodSet;
valueDescription ||= isVariadic ? plur(name) : name;
const rest = isVariadic ? '...' : '';
flag +=
isOptional || defaultValue
? ` [${valueDescription}${rest}]`
: ` <${valueDescription}${rest}>`;
}
const option = new Option(flag, description);
if (optionSchema instanceof ZodNumber) {
option.argParser(value => Number.parseFloat(value));
}
if (optionSchema instanceof ZodEnum) {
option.choices(optionSchema._def.values);
}
if (optionSchema instanceof ZodBoolean && defaultValue === undefined) {
defaultValue = false;
}
if (optionSchema instanceof ZodSet) {
option.argParser((value, previousValue) => {
const joinPreviousValue = previousValue instanceof Set &&
!isDeepStrictEqual(previousValue, defaultValue);
return joinPreviousValue
? new Set([...previousValue, value])
: new Set([value]);
});
}
if (defaultValue !== undefined) {
if (!defaultValueDescription && defaultValue instanceof Set) {
defaultValueDescription = JSON.stringify([...defaultValue]);
}
option.default(defaultValue, defaultValueDescription);
}
options.push(option);
}
return options;
}
//# sourceMappingURL=generate-options.js.map