fix: improve CLI error handling and user guidance
- Add Node.js >= 22 runtime version check before any imports - Add EADDRINUSE error handlers for HTTP and WebSocket servers - Fix misleading 'Couldn't parse Quartz configuration' error message - Add actionable guidance to sync/upgrade/push failure messages - Add --concurrency validation (must be >= 1)
This commit is contained in:
@@ -1,4 +1,12 @@
|
|||||||
#!/usr/bin/env -S node --no-deprecation
|
#!/usr/bin/env -S node --no-deprecation
|
||||||
|
const [major] = process.versions.node.split(".").map(Number)
|
||||||
|
if (major < 22) {
|
||||||
|
console.error(
|
||||||
|
`\nQuartz requires Node.js >= 22, but you are running Node.js ${process.version}.\n` +
|
||||||
|
`Please upgrade: https://nodejs.org/\n`,
|
||||||
|
)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
import yargs from "yargs"
|
import yargs from "yargs"
|
||||||
import { hideBin } from "yargs/helpers"
|
import { hideBin } from "yargs/helpers"
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -320,6 +320,11 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started.
|
|||||||
* @param {*} argv arguments for `build`
|
* @param {*} argv arguments for `build`
|
||||||
*/
|
*/
|
||||||
export async function handleBuild(argv) {
|
export async function handleBuild(argv) {
|
||||||
|
if (argv.concurrency !== undefined && argv.concurrency < 1) {
|
||||||
|
console.error("Concurrency must be at least 1")
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
if (argv.serve) {
|
if (argv.serve) {
|
||||||
argv.watch = true
|
argv.watch = true
|
||||||
}
|
}
|
||||||
@@ -409,7 +414,9 @@ export async function handleBuild(argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await ctx.rebuild().catch((err) => {
|
const result = await ctx.rebuild().catch((err) => {
|
||||||
console.error(`${styleText("red", "Couldn't parse Quartz configuration:")} ${fp}`)
|
console.error(
|
||||||
|
`${styleText("red", "Failed to build Quartz.")} Check for syntax errors in your configuration or plugins.`,
|
||||||
|
)
|
||||||
console.log(`Reason: ${styleText("gray", err.message ?? String(err))}`)
|
console.log(`Reason: ${styleText("gray", err.message ?? String(err))}`)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
})
|
||||||
@@ -545,8 +552,26 @@ export async function handleBuild(argv) {
|
|||||||
return serve()
|
return serve()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
server.on("error", (err) => {
|
||||||
|
if (err.code === "EADDRINUSE") {
|
||||||
|
console.error(
|
||||||
|
`Port ${argv.port} is already in use. Try a different port with --port <number>`,
|
||||||
|
)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
throw err
|
||||||
|
})
|
||||||
server.listen(argv.port)
|
server.listen(argv.port)
|
||||||
const wss = new WebSocketServer({ port: argv.wsPort })
|
const wss = new WebSocketServer({ port: argv.wsPort })
|
||||||
|
wss.on("error", (err) => {
|
||||||
|
if (err.code === "EADDRINUSE") {
|
||||||
|
console.error(
|
||||||
|
`WebSocket port ${argv.wsPort} is already in use. Try a different port with --wsPort <number>`,
|
||||||
|
)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
throw err
|
||||||
|
})
|
||||||
wss.on("connection", (ws) => connections.push(ws))
|
wss.on("connection", (ws) => connections.push(ws))
|
||||||
console.log(
|
console.log(
|
||||||
styleText(
|
styleText(
|
||||||
@@ -623,7 +648,10 @@ export async function handleUpgrade(argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!pullOk) {
|
if (!pullOk) {
|
||||||
console.log(styleText("red", "An error occurred above while pulling updates."))
|
console.log(
|
||||||
|
styleText("red", "An error occurred while pulling updates.") +
|
||||||
|
"\nCheck your network connection and git credentials. If you see merge conflicts, resolve them manually and run `npx quartz sync --no-pull`.",
|
||||||
|
)
|
||||||
await popContentFolder(contentFolder)
|
await popContentFolder(contentFolder)
|
||||||
if (fs.existsSync(lockfileBackup)) fs.unlinkSync(lockfileBackup)
|
if (fs.existsSync(lockfileBackup)) fs.unlinkSync(lockfileBackup)
|
||||||
return
|
return
|
||||||
@@ -669,7 +697,10 @@ export async function handleUpgrade(argv) {
|
|||||||
if (res.status === 0) {
|
if (res.status === 0) {
|
||||||
console.log(styleText("green", "Dependencies updated!"))
|
console.log(styleText("green", "Dependencies updated!"))
|
||||||
} else {
|
} else {
|
||||||
console.log(styleText("red", "An error occurred above while installing dependencies."))
|
console.log(
|
||||||
|
styleText("red", "An error occurred while installing dependencies.") +
|
||||||
|
"\nTry running `npm install` manually to see detailed errors.",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Restoring plugins from lockfile...")
|
console.log("Restoring plugins from lockfile...")
|
||||||
@@ -738,7 +769,10 @@ export async function handleSync(argv) {
|
|||||||
try {
|
try {
|
||||||
gitPull(ORIGIN_NAME, QUARTZ_SOURCE_BRANCH)
|
gitPull(ORIGIN_NAME, QUARTZ_SOURCE_BRANCH)
|
||||||
} catch {
|
} catch {
|
||||||
console.log(styleText("red", "An error occurred above while pulling updates."))
|
console.log(
|
||||||
|
styleText("red", "An error occurred while pulling updates from your repository.") +
|
||||||
|
"\nCheck your network connection and git credentials.",
|
||||||
|
)
|
||||||
await popContentFolder(contentFolder)
|
await popContentFolder(contentFolder)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -753,7 +787,8 @@ export async function handleSync(argv) {
|
|||||||
})
|
})
|
||||||
if (res.status !== 0) {
|
if (res.status !== 0) {
|
||||||
console.log(
|
console.log(
|
||||||
styleText("red", `An error occurred above while pushing to remote ${ORIGIN_NAME}.`),
|
styleText("red", `An error occurred while pushing to remote ${ORIGIN_NAME}.`) +
|
||||||
|
"\nCheck that you have push access to the remote repository.",
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user