Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions playground/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
description: "Deployment provider",
valueHint: "foo|bar|baz|qux",
},
port: {
type: "string",
description: "Port number to listen on",
required: true,
validate(value) {
return Number(value) >= 1 && Number(value) <= 65_536 ? true : "Port number must be greater than 1 and less than 65536"
},
}

Check warning on line 62 in playground/commands/deploy.ts

View check run for this annotation

Codecov / codecov/patch

playground/commands/deploy.ts#L55-L62

Added lines #L55 - L62 were not covered by tests
},
run({ args }) {
consola.log("Build");
Expand Down
17 changes: 17 additions & 0 deletions src/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,20 @@
}
return args;
}

export function resolveArgsValidate(
parsedArgs: ParsedArgs,
argsDef: ArgsDef,
): string | undefined {
for (const [name, argDef] of Object.entries(argsDef || {})) {
const value = parsedArgs[name] as never;
if (argDef.validate) {
const word = argDef.validate(value) || "";
if (argDef.required && typeof word === "string") {
return (
Copy link

@janniks janniks May 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should validate always fail and show the failure string if it's a string (even if not an required arg)?

`Argument validation failed: ${name}` + (word ? ` - ${word}` : "")
);
}
}
}
}

Check warning on line 125 in src/args.ts

View check run for this annotation

Codecov / codecov/patch

src/args.ts#L109-L125

Added lines #L109 - L125 were not covered by tests
7 changes: 5 additions & 2 deletions src/command.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { CommandContext, CommandDef, ArgsDef } from "./types";
import { CLIError, resolveValue } from "./_utils";
import { parseArgs } from "./args";
import { parseArgs, resolveArgsValidate } from "./args";

Check warning on line 3 in src/command.ts

View check run for this annotation

Codecov / codecov/patch

src/command.ts#L3

Added line #L3 was not covered by tests

export function defineCommand<T extends ArgsDef = ArgsDef>(
def: CommandDef<T>,
Expand Down Expand Up @@ -59,7 +59,10 @@
throw new CLIError(`No command specified.`, "E_NO_COMMAND");
}
}

const word = resolveArgsValidate(parsedArgs, cmdArgs);
if (word) {
throw new CLIError(word, "E_VALIDATE_FAILED");
}

Check warning on line 65 in src/command.ts

View check run for this annotation

Codecov / codecov/patch

src/command.ts#L62-L65

Added lines #L62 - L65 were not covered by tests
// Handle main command
if (typeof cmd.run === "function") {
result = await cmd.run(context);
Expand Down
9 changes: 9 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
alias?: string | string[];
default?: VT;
required?: boolean;
validate?: (value: ParsedArgType<T>) => boolean | string;

Check warning on line 18 in src/types.ts

View check run for this annotation

Codecov / codecov/patch

src/types.ts#L18

Added line #L18 was not covered by tests
options?: (string | number)[];
};

Expand Down Expand Up @@ -70,6 +71,14 @@
> &
Record<string, string | number | boolean | string[]>;

export type ParsedArgType<T extends ArgType = ArgType> = T extends "positional"
? string
: T extends "string"
? string
: T extends "boolean"
? boolean
: string | boolean;

Check warning on line 81 in src/types.ts

View check run for this annotation

Codecov / codecov/patch

src/types.ts#L74-L81

Added lines #L74 - L81 were not covered by tests
// ----- Command -----

// Command: Shared
Expand Down