-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcommand-utils.ts
76 lines (68 loc) · 2.65 KB
/
command-utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { Command, Option } from "@commander-js/extra-typings";
import { glob } from "glob";
import type { Options } from "../options.ts";
import { localsConventionChoices } from "../options.ts";
import { version } from "../version.ts";
import { loadFileConfig } from "./config.ts";
// eslint-disable-next-line quotes -- Module must be quotes
declare module "@commander-js/extra-typings" {
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -- Extending class
interface Command {
cssTypedAction: typeof cssTypedAction;
}
}
/** Creates css-typed command with global options. */
export function createCssTypedCommand() {
const command = new Command()
.argument(`[pattern]`, `Glob path for CSS files to target.`)
.option(`-c, --config <file>`, `Custom path to the configuration file.`)
.addOption(
new Option(
`--localsConvention <value>`,
`Style of exported classnames. See https://github.com/connorjs/css-typed/tree/v${version}#localsConvention`,
)
.choices(localsConventionChoices)
.default(`dashesOnly` as const),
)
.option(
`-o, --outdir <outDirectory>`,
`Root directory for generated CSS declaration files.`,
);
command.cssTypedAction = cssTypedAction.bind(command);
return command;
}
/** Standardizes global option handling and simplifies action interface. */
function cssTypedAction(
this: Command<[string | undefined], Partial<Options> & { config?: string }>,
fileHandler: (files: string[], options: Options) => Promise<void>,
) {
return this.action(
async (cliPattern, { config: cliConfigPath, ...cliOptions }, program) => {
// Load file configuration first
const configResult = await loadFileConfig(cliConfigPath);
if (configResult?.filepath) {
// We loaded the file
console.debug(
`[debug] Reading configuration from ${configResult.filepath}.`,
);
} else if (cliConfigPath) {
// We did not load the file, but we expected to with `-c/--config`, so error
return program.error(`[error] Failed to parse ${cliConfigPath}.`);
}
// Remove pattern argument from file config, if present.
const { pattern: filePattern, ...fileConfig } =
configResult?.config ?? {};
// Resolve options from file config and CLI. CLI overrides file config.
const options: Options = { ...fileConfig, ...cliOptions };
// Pattern is required. CLI overrides file config.
const pattern = cliPattern ?? filePattern;
if (!pattern) {
// Match commander error message
return program.error(`[error] Missing required argument 'pattern'`);
}
// Find the files and delegate them to the callback
const files = await glob(pattern);
return fileHandler(files, options);
},
);
}