feat: support CLI arguments for npx quartz create (#421)

* feat(cli): add new args for content + link resolve

* feat(cli): validate cmd args

* feat(cli): add chalk + error code to errors

* feat(cli): support for setup/link via args

* refactor(cli): use yargs choices instead of manual

Scrap manual check if arguments are valid, use yargs "choices" field instead.

* feat(cli): add in-dir argument+ handle errors

add new "in-directory" argument, used if "setup" is "copy" or "symlink" to determine source. add error handling for invalid permutations of arguments or non existent path

* feat(cli): dynamically use cli or provided args

use "in-directory" arg as `originalFolder` if available, otherwise get it from manual cli process

* run format

* fix: use process.exit instead of return

* refactor: split CommonArgv and CreateArgv

* refactor(cli): rename create args, use ${} syntax

* fix(cli): fix link resolution strategy arg

* format

* feat(consistency): allow partial cmd args
This commit is contained in:
Ben Schlegel 2023-08-26 22:21:44 +02:00 committed by GitHub
parent 74c3ebb7bd
commit ad4145fb10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -43,6 +43,27 @@ const CommonArgv = {
},
}
const CreateArgv = {
...CommonArgv,
source: {
string: true,
alias: ["s"],
describe: "source directory to copy/create symlink from",
},
strategy: {
string: true,
alias: ["X"],
choices: ["new", "copy", "symlink"],
describe: "strategy for content folder setup",
},
links: {
string: true,
alias: ["l"],
choices: ["absolute", "shortest", "relative"],
describe: "strategy to resolve links",
},
}
const SyncArgv = {
...CommonArgv,
commit: {
@ -147,11 +168,59 @@ yargs(hideBin(process.argv))
.scriptName("quartz")
.version(version)
.usage("$0 <cmd> [args]")
.command("create", "Initialize Quartz", CommonArgv, async (argv) => {
.command("create", "Initialize Quartz", CreateArgv, async (argv) => {
console.log()
intro(chalk.bgGreen.black(` Quartz v${version} `))
const contentFolder = path.join(cwd, argv.directory)
const setupStrategy = exitIfCancel(
let setupStrategy = argv.strategy?.toLowerCase()
let linkResolutionStrategy = argv.links?.toLowerCase()
const sourceDirectory = argv.source
// If all cmd arguments were provided, check if theyre valid
if (setupStrategy && linkResolutionStrategy) {
// If setup isn't, "new", source argument is required
if (setupStrategy !== "new") {
// Error handling
if (!sourceDirectory) {
outro(
chalk.red(
`Setup strategies (arg '${chalk.yellow(
`-${CreateArgv.strategy.alias[0]}`,
)}') other than '${chalk.yellow(
"new",
)}' require content folder argument ('${chalk.yellow(
`-${CreateArgv.source.alias[0]}`,
)}') to be set`,
),
)
process.exit(1)
} else {
if (!fs.existsSync(sourceDirectory)) {
outro(
chalk.red(
`Input directory to copy/symlink 'content' from not found ('${chalk.yellow(
sourceDirectory,
)}', invalid argument "${chalk.yellow(`-${CreateArgv.source.alias[0]}`)})`,
),
)
process.exit(1)
} else if (!fs.lstatSync(sourceDirectory).isDirectory()) {
outro(
chalk.red(
`Source directory to copy/symlink 'content' from is not a directory (found file at '${chalk.yellow(
sourceDirectory,
)}', invalid argument ${chalk.yellow(`-${CreateArgv.source.alias[0]}`)}")`,
),
)
process.exit(1)
}
}
}
}
// Use cli process if cmd args werent provided
if (!setupStrategy) {
setupStrategy = exitIfCancel(
await select({
message: `Choose how to initialize the content in \`${contentFolder}\``,
options: [
@ -165,6 +234,7 @@ yargs(hideBin(process.argv))
],
}),
)
}
async function rmContentFolder() {
const contentStat = await fs.promises.lstat(contentFolder)
@ -177,7 +247,11 @@ yargs(hideBin(process.argv))
await fs.promises.unlink(path.join(contentFolder, ".gitkeep"))
if (setupStrategy === "copy" || setupStrategy === "symlink") {
const originalFolder = escapePath(
let originalFolder = sourceDirectory
// If input directory was not passed, use cli
if (!sourceDirectory) {
originalFolder = escapePath(
exitIfCancel(
await text({
message: "Enter the full path to existing content folder",
@ -194,6 +268,7 @@ yargs(hideBin(process.argv))
}),
),
)
}
await rmContentFolder()
if (setupStrategy === "copy") {
@ -217,8 +292,10 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started.
)
}
// Use cli process if cmd args werent provided
if (!linkResolutionStrategy) {
// get a preferred link resolution strategy
const linkResolutionStrategy = exitIfCancel(
linkResolutionStrategy = exitIfCancel(
await select({
message: `Choose how Quartz should resolve links in your content. You can change this later in \`quartz.config.ts\`.`,
options: [
@ -240,6 +317,7 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started.
],
}),
)
}
// now, do config changes
const configFilePath = path.join(cwd, "quartz.config.ts")