|
3 | 3 | import os from "node:os" |
4 | 4 | import { massarg } from "massarg" |
5 | 5 | import chalk from "chalk" |
6 | | -import { LogLevel, ScaffoldCmdConfig } from "./types" |
| 6 | +import { ListCommandCliOptions, LogLevel, ScaffoldCmdConfig } from "./types" |
7 | 7 | import { Scaffold } from "./scaffold" |
8 | 8 | import path from "node:path" |
9 | 9 | import fs from "node:fs/promises" |
10 | | -import { parseAppendData, parseConfigFile } from "./config" |
| 10 | +import { getConfigFile, parseAppendData, parseConfigFile } from "./config" |
11 | 11 | import { log } from "./logger" |
| 12 | +import { MassargCommand } from "massarg/command" |
12 | 13 |
|
13 | 14 | export async function parseCliArgs(args = process.argv.slice(2)) { |
14 | 15 | const isProjectRoot = Boolean(await fs.stat(path.join(__dirname, "package.json")).catch(() => false)) |
15 | 16 | const pkgFile = await fs.readFile(path.resolve(__dirname, isProjectRoot ? "." : "..", "package.json")) |
16 | 17 | const pkg = JSON.parse(pkgFile.toString()) |
17 | 18 | const isVersionFlag = args.includes("--version") || args.includes("-v") |
18 | | - const isConfigProvided = |
19 | | - args.includes("--config") || args.includes("-c") || args.includes("--git") || args.includes("-g") || isVersionFlag |
| 19 | + const isConfigFileProvided = args.includes("--config") || args.includes("-c") |
| 20 | + const isGitProvided = args.includes("--git") || args.includes("-g") |
| 21 | + const isConfigProvided = isConfigFileProvided || isGitProvided || isVersionFlag |
20 | 22 |
|
21 | 23 | return massarg<ScaffoldCmdConfig>({ |
22 | 24 | name: pkg.name, |
@@ -46,24 +48,20 @@ export async function parseCliArgs(args = process.argv.slice(2)) { |
46 | 48 | aliases: ["n"], |
47 | 49 | description: |
48 | 50 | "Name to be passed to the generated files. `{{name}}` and other data parameters inside " + |
49 | | - "contents and file names will be replaced accordingly. You may omit the `--name` or `-n` for this specific option.", |
| 51 | + "contents and file names will be replaced accordingly. You may omit the `--name` or `-n` " + |
| 52 | + "for this specific option.", |
50 | 53 | isDefault: true, |
51 | 54 | required: !isConfigProvided, |
52 | 55 | }) |
53 | 56 | .option({ |
54 | 57 | name: "config", |
55 | 58 | aliases: ["c"], |
56 | | - description: |
57 | | - "Filename to load config from instead of passing arguments to CLI or using a Node.js " + |
58 | | - "script. See examples for syntax. This can also work in conjunction with `--git` or `--github` to point " + |
59 | | - "to remote files, and with `--key` to denote which key to select from the file.", |
| 59 | + description: "Filename or directory to load config from", |
60 | 60 | }) |
61 | 61 | .option({ |
62 | 62 | name: "git", |
63 | 63 | aliases: ["g"], |
64 | | - description: |
65 | | - "Git URL to load config from instead of passing arguments to CLI or using a Node.js script. See " + |
66 | | - "examples for syntax.", |
| 64 | + description: "Git URL or GitHub path to load a template from.", |
67 | 65 | }) |
68 | 66 | .option({ |
69 | 67 | name: "key", |
@@ -159,6 +157,67 @@ export async function parseCliArgs(args = process.argv.slice(2)) { |
159 | 157 | aliases: ["v"], |
160 | 158 | description: "Display version.", |
161 | 159 | }) |
| 160 | + .command( |
| 161 | + new MassargCommand<ListCommandCliOptions>({ |
| 162 | + name: "list", |
| 163 | + aliases: ["ls"], |
| 164 | + description: "List all available templates for a given config. See `list -h` for more information.", |
| 165 | + run: async (_config) => { |
| 166 | + const tmpPath = path.resolve(os.tmpdir(), `scaffold-config-${Date.now()}`) |
| 167 | + const config = { |
| 168 | + templates: [], |
| 169 | + name: "", |
| 170 | + version: false, |
| 171 | + output: "", |
| 172 | + subdir: false, |
| 173 | + overwrite: false, |
| 174 | + dryRun: false, |
| 175 | + ..._config, |
| 176 | + config: _config.config ?? (!_config.git ? process.cwd() : undefined), |
| 177 | + } |
| 178 | + try { |
| 179 | + const file = await getConfigFile(config, tmpPath) |
| 180 | + console.log(chalk.underline`Available templates:\n`) |
| 181 | + console.log(Object.keys(file).join("\n")) |
| 182 | + } catch (e) { |
| 183 | + const message = "message" in (e as any) ? (e as any).message : e?.toString() |
| 184 | + log(config, LogLevel.error, message) |
| 185 | + } finally { |
| 186 | + log(config, LogLevel.debug, "Cleaning up temporary files...", tmpPath) |
| 187 | + await fs.rm(tmpPath, { recursive: true, force: true }) |
| 188 | + } |
| 189 | + }, |
| 190 | + }) |
| 191 | + .option({ |
| 192 | + name: "config", |
| 193 | + aliases: ["c"], |
| 194 | + description: "Filename or directory to load config from. Defaults to current working directory.", |
| 195 | + }) |
| 196 | + .option({ |
| 197 | + name: "git", |
| 198 | + aliases: ["g"], |
| 199 | + description: "Git URL or GitHub path to load a template from.", |
| 200 | + }) |
| 201 | + .option({ |
| 202 | + name: "log-level", |
| 203 | + aliases: ["l"], |
| 204 | + defaultValue: LogLevel.none, |
| 205 | + description: |
| 206 | + "Determine amount of logs to display. The values are: " + |
| 207 | + `${chalk.bold`\`none | debug | info | warn | error\``}. ` + |
| 208 | + "The provided level will display messages of the same level or higher.", |
| 209 | + parse: (v) => { |
| 210 | + const val = v.toLowerCase() |
| 211 | + if (!(val in LogLevel)) { |
| 212 | + throw new Error(`Invalid log level: ${val}, must be one of: ${Object.keys(LogLevel).join(", ")}`) |
| 213 | + } |
| 214 | + return val |
| 215 | + }, |
| 216 | + }) |
| 217 | + .help({ |
| 218 | + bindOption: true, |
| 219 | + }), |
| 220 | + ) |
162 | 221 | .example({ |
163 | 222 | description: "Usage with config file", |
164 | 223 | input: "simple-scaffold -c scaffold.cmd.js --key component", |
|
0 commit comments