pastel
pastel copied to clipboard
Option `alias` doesn't work in combination with `zod.default()`/`zod.optional()`
I'm trying to define an alias for an option, but it's not working if used with neither zod.default()
nor zod.optional()
.
Try it out: https://codesandbox.io/p/devbox/infallible-jones-ys358t?file=/string-default-alias/source/commands/index.tsx:6,1
Run npm run build
(maybe followed by npm link
) and then da -h
.
Works 👍
export const options = zod.object({
name: zod
.string()
.describe(option({alias: 'n', description: 'Name'})),
});
Outputs:
❭ sda -h
Usage: sda [options]
Options:
-n, --name <name> Name
-v, --version Show version number
-h, --help Show help
Doesn't work 👎
export const options = zod.object({
name: zod
.string()
.default('Stranger')
.describe(option({alias: 'n', description: 'Name'})),
});
and
export const options = zod.object({
name: zod
.string()
.optional()
.describe(option({alias: 'n', description: 'Name'})),
});
Outputs:
❭ sda -h
Usage: sda [options]
Options:
--name [name] Name (default: 1)
-v, --version Show version number
-h, --help Show help
(default only in the first case, obviously)
Same thing happens with zod.number()
, so not isolated to zod.string()
.
@vadimdemedes I started looking into it. Even though I lack knowledge of Zod's internals, judging by generate-options.ts#L66C3-L89C52:
Code
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}`;
my best guess is by reassigning optionSchema
to _def.innerType
, we lose the special __parsel
prefix of description
, causing the config lookup to "fail".
getAlias()
is the only config lookup from there on, so I suppose it supports that theory?
Potential fixes:
- Move
getAlias()
before the reassignment - Store the original "raw"
description
value and pass that togetAlias()
I might be missing something, though.
@vadimdemedes I'll gladly help out here if you could just give your thoughts on the matter.