Flatten the repo: move everything out of app/ to the root
Now that the CLI and the Next.js app are one package, nesting it inside app/ served no purpose - the repo root itself becomes the published npm package. Merges app/.gitignore and app/README.md into the root versions, drops the now-duplicate app/LICENSE, and updates path references (README, docs/ARCHITECTURE.md, docs/CONFIG_REFERENCE.md, package.json's repository.directory) that assumed the app/ nesting. Also fixes a real bug this surfaced: the in-app docs viewer resolved docs/ relative to process.cwd(), which only worked by accident when the CLI happened to be invoked from app/'s parent directory. A first attempt at fixing it with import.meta.dirname broke instead, for the same cross-module-graph reason config-path resolution already documented - Next compiles Route Handlers through a separate module graph that doesn't preserve source-relative import.meta paths. Fixed by exposing the app root via TRIGGERSHELL_APP_ROOT (set once in server.ts, where import.meta *does* resolve correctly), the same pattern already used for TRIGGERSHELL_CONFIG_PATH. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import { Command } from "commander";
|
||||
import { doctorCommand } from "./commands/doctor";
|
||||
import { initCommand } from "./commands/init";
|
||||
import { serviceInstallCommand, serviceStatusCommand, serviceUninstallCommand } from "./commands/service";
|
||||
import { startCommand } from "./commands/start";
|
||||
import { usersAddCommand, usersAddTokenCommand } from "./commands/users";
|
||||
import { validateCommand } from "./commands/validate";
|
||||
import { getVersion } from "./version";
|
||||
|
||||
const program = new Command("triggershell")
|
||||
.version(getVersion())
|
||||
.description("Launch the TriggerShell web app: run your configured shell scripts from a browser.");
|
||||
|
||||
program
|
||||
.command("init [path]")
|
||||
.description("Scaffold a new triggershell.yml (and .env, if auth is enabled)")
|
||||
.option("--port <port>", "Port the web app will listen on.", (v) => Number(v), 4173)
|
||||
.option("--no-auth", "Disable built-in login for the web app.")
|
||||
.option("--force", "Overwrite an existing config file.", false)
|
||||
.action(initCommand);
|
||||
|
||||
program
|
||||
.command("validate")
|
||||
.description("Validate a config file against the full schema.")
|
||||
.option("-c, --config <path>", "Path to the config file.")
|
||||
.action(validateCommand);
|
||||
|
||||
program
|
||||
.command("start")
|
||||
.description("Run the web app in production mode.")
|
||||
.option("-c, --config <path>", "Path to the config file.")
|
||||
.option("--port <port>", "Override the port from the config file.", (v) => Number(v))
|
||||
.option("--host <host>", "Override the host from the config file.")
|
||||
.option("--no-browser", "Don't open a browser automatically.")
|
||||
.action(startCommand);
|
||||
|
||||
program
|
||||
.command("doctor")
|
||||
.description("Print diagnostic info about your environment and config.")
|
||||
.option("-c, --config <path>", "Path to the config file.")
|
||||
.action(doctorCommand);
|
||||
|
||||
const users = program.command("users").description("Manage auth users and API tokens defined in your config file.");
|
||||
|
||||
users
|
||||
.command("add <username>")
|
||||
.description("Hash a password with argon2id and wire it up for auth.users.")
|
||||
.option("-c, --config <path>", "Path to the config file (used to locate .env).")
|
||||
.option("--inline", "Print the raw hash to paste into the config instead of storing it in .env.", false)
|
||||
.action(usersAddCommand);
|
||||
|
||||
users
|
||||
.command("add-token <name>")
|
||||
.description("Generate an API token and wire its hash up for auth.tokens.")
|
||||
.option("-c, --config <path>", "Path to the config file (used to locate .env).")
|
||||
.option("--inline", "Print the raw hash to paste into the config instead of storing it in .env.", false)
|
||||
.action(usersAddTokenCommand);
|
||||
|
||||
const service = program.command("service").description("Manage the systemd service (Linux only).");
|
||||
|
||||
service
|
||||
.command("install")
|
||||
.description("Install a systemd unit that runs `triggershell start`.")
|
||||
.option("-c, --config <path>", "Path to the config file.")
|
||||
.option("--port <port>", "Override the port from the config file.", (v) => Number(v))
|
||||
.option("--host <host>", "Override the host from the config file.")
|
||||
.option("--system", "Install a system-wide unit instead of a per-user one.", false)
|
||||
.action(serviceInstallCommand);
|
||||
|
||||
service
|
||||
.command("uninstall")
|
||||
.description("Stop, disable, and remove the systemd unit.")
|
||||
.option("--system", "Target the system-wide unit instead of the per-user one.", false)
|
||||
.action(serviceUninstallCommand);
|
||||
|
||||
service
|
||||
.command("status")
|
||||
.description("Show the systemd unit's status.")
|
||||
.option("--system", "Target the system-wide unit instead of the per-user one.", false)
|
||||
.action(serviceStatusCommand);
|
||||
|
||||
if (process.argv.length <= 2) {
|
||||
program.outputHelp();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await program.parseAsync(process.argv);
|
||||
Reference in New Issue
Block a user