bindler 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +232 -54
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
8
8
|
|
|
9
9
|
// src/cli.ts
|
|
10
10
|
import { Command } from "commander";
|
|
11
|
-
import
|
|
11
|
+
import chalk31 from "chalk";
|
|
12
12
|
|
|
13
13
|
// src/commands/new.ts
|
|
14
14
|
import { existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
@@ -284,6 +284,25 @@ function isPortAvailable(port) {
|
|
|
284
284
|
const usedPorts = new Set(getUsedPorts());
|
|
285
285
|
return !usedPorts.has(port);
|
|
286
286
|
}
|
|
287
|
+
function checkPortInUse(port) {
|
|
288
|
+
const lsofResult = execCommandSafe(`lsof -i :${port} -P -n 2>/dev/null | grep LISTEN`);
|
|
289
|
+
if (lsofResult.success && lsofResult.output) {
|
|
290
|
+
const match = lsofResult.output.match(/^(\S+)\s+(\d+)/);
|
|
291
|
+
if (match) {
|
|
292
|
+
return { inUse: true, process: `${match[1]} (PID ${match[2]})` };
|
|
293
|
+
}
|
|
294
|
+
return { inUse: true };
|
|
295
|
+
}
|
|
296
|
+
const ssResult = execCommandSafe(`ss -tlnp 2>/dev/null | grep ":${port} "`);
|
|
297
|
+
if (ssResult.success && ssResult.output) {
|
|
298
|
+
const match = ssResult.output.match(/users:\(\("([^"]+)",pid=(\d+)/);
|
|
299
|
+
if (match) {
|
|
300
|
+
return { inUse: true, process: `${match[1]} (PID ${match[2]})` };
|
|
301
|
+
}
|
|
302
|
+
return { inUse: true };
|
|
303
|
+
}
|
|
304
|
+
return { inUse: false };
|
|
305
|
+
}
|
|
287
306
|
function getPortsTable() {
|
|
288
307
|
const config = readConfig();
|
|
289
308
|
return config.projects.filter((p) => p.type === "npm" && p.port).map((p) => ({
|
|
@@ -570,18 +589,17 @@ function startProject(project) {
|
|
|
570
589
|
}
|
|
571
590
|
const pm2Name = getPm2ProcessName(project.name);
|
|
572
591
|
const existingProcess = getProcessByName(project.name);
|
|
573
|
-
const envVars = [];
|
|
574
|
-
if (project.env) {
|
|
575
|
-
for (const [key, value] of Object.entries(project.env)) {
|
|
576
|
-
envVars.push(`${key}=${value}`);
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
592
|
let command;
|
|
580
593
|
if (existingProcess) {
|
|
581
594
|
command = `pm2 restart "${pm2Name}"`;
|
|
582
595
|
} else {
|
|
583
|
-
|
|
584
|
-
|
|
596
|
+
let startCmd = project.start;
|
|
597
|
+
if (project.env && Object.keys(project.env).length > 0) {
|
|
598
|
+
const envPrefix = Object.entries(project.env).map(([key, value]) => `${key}=${escapeShellArg(value)}`).join(" ");
|
|
599
|
+
startCmd = `${envPrefix} ${project.start}`;
|
|
600
|
+
}
|
|
601
|
+
const escapedCmd = startCmd.replace(/'/g, "'\\''");
|
|
602
|
+
command = `pm2 start 'bash -c "${escapedCmd}"' --name "${pm2Name}" --cwd "${project.path}"`;
|
|
585
603
|
}
|
|
586
604
|
const result = execCommandSafe(command);
|
|
587
605
|
if (!result.success) {
|
|
@@ -590,6 +608,12 @@ function startProject(project) {
|
|
|
590
608
|
execCommandSafe("pm2 save");
|
|
591
609
|
return { success: true };
|
|
592
610
|
}
|
|
611
|
+
function escapeShellArg(arg) {
|
|
612
|
+
if (/[^a-zA-Z0-9_\-=]/.test(arg)) {
|
|
613
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
614
|
+
}
|
|
615
|
+
return arg;
|
|
616
|
+
}
|
|
593
617
|
function stopProject(name) {
|
|
594
618
|
const pm2Name = getPm2ProcessName(name);
|
|
595
619
|
const result = execCommandSafe(`pm2 stop "${pm2Name}"`);
|
|
@@ -981,7 +1005,17 @@ async function newCommand(options) {
|
|
|
981
1005
|
if (yamlDefaults.environments) project.environments = yamlDefaults.environments;
|
|
982
1006
|
if (answers.type === "npm") {
|
|
983
1007
|
const scripts = existsSync6(answers.path) ? getPackageJsonScripts(answers.path) : [];
|
|
984
|
-
|
|
1008
|
+
let suggestedPort = yamlDefaults.port || findAvailablePort();
|
|
1009
|
+
const portCheck = checkPortInUse(suggestedPort);
|
|
1010
|
+
if (portCheck.inUse) {
|
|
1011
|
+
for (let p = suggestedPort + 1; p <= 9e3; p++) {
|
|
1012
|
+
const check = checkPortInUse(p);
|
|
1013
|
+
if (!check.inUse) {
|
|
1014
|
+
suggestedPort = p;
|
|
1015
|
+
break;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
985
1019
|
const npmAnswers = await inquirer.prompt([
|
|
986
1020
|
{
|
|
987
1021
|
type: "input",
|
|
@@ -993,6 +1027,11 @@ async function newCommand(options) {
|
|
|
993
1027
|
if (!validatePort(port)) {
|
|
994
1028
|
return "Invalid port. Use a number between 1024 and 65535.";
|
|
995
1029
|
}
|
|
1030
|
+
const inUseCheck = checkPortInUse(port);
|
|
1031
|
+
if (inUseCheck.inUse) {
|
|
1032
|
+
const processInfo = inUseCheck.process ? ` by ${inUseCheck.process}` : "";
|
|
1033
|
+
return `Port ${port} is already in use${processInfo}. Choose another port.`;
|
|
1034
|
+
}
|
|
996
1035
|
return true;
|
|
997
1036
|
},
|
|
998
1037
|
filter: (input) => parseInt(input, 10)
|
|
@@ -1048,7 +1087,23 @@ async function newCommand(options) {
|
|
|
1048
1087
|
project.local = true;
|
|
1049
1088
|
}
|
|
1050
1089
|
if (project.type === "npm") {
|
|
1051
|
-
|
|
1090
|
+
let port = options.port || findAvailablePort();
|
|
1091
|
+
const portCheck = checkPortInUse(port);
|
|
1092
|
+
if (portCheck.inUse) {
|
|
1093
|
+
const processInfo = portCheck.process ? ` by ${portCheck.process}` : "";
|
|
1094
|
+
console.log(chalk2.yellow(`Warning: Port ${port} is already in use${processInfo}`));
|
|
1095
|
+
if (!options.port) {
|
|
1096
|
+
for (let p = port + 1; p <= 9e3; p++) {
|
|
1097
|
+
const check = checkPortInUse(p);
|
|
1098
|
+
if (!check.inUse) {
|
|
1099
|
+
port = p;
|
|
1100
|
+
console.log(chalk2.dim(` Using port ${port} instead`));
|
|
1101
|
+
break;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
project.port = port;
|
|
1052
1107
|
project.start = options.start || "npm start";
|
|
1053
1108
|
project.env = { PORT: String(project.port) };
|
|
1054
1109
|
}
|
|
@@ -1876,6 +1931,26 @@ Try running with sudo: ${chalk12.cyan("sudo bindler apply")}`));
|
|
|
1876
1931
|
process.exit(1);
|
|
1877
1932
|
}
|
|
1878
1933
|
console.log(chalk12.green(" \u2713 Nginx reloaded successfully"));
|
|
1934
|
+
const listenPort = parseInt(defaults.nginxListen.split(":").pop() || "80", 10);
|
|
1935
|
+
const portCheck = execCommandSafe(`lsof -i :${listenPort} -P -n 2>/dev/null | grep LISTEN | grep nginx`);
|
|
1936
|
+
if (!portCheck.success || !portCheck.output) {
|
|
1937
|
+
const isPrivilegedPort = listenPort < 1024;
|
|
1938
|
+
console.log(chalk12.yellow(`
|
|
1939
|
+
\u26A0 Nginx is not listening on port ${listenPort}`));
|
|
1940
|
+
if (isPrivilegedPort) {
|
|
1941
|
+
console.log(chalk12.dim(` Port ${listenPort} requires root privileges.
|
|
1942
|
+
`));
|
|
1943
|
+
console.log(chalk12.cyan(" Solutions:\n"));
|
|
1944
|
+
console.log(chalk12.white(" Option 1: Restart nginx with sudo (recommended for port 80)"));
|
|
1945
|
+
console.log(chalk12.dim(" sudo pkill nginx && sudo nginx\n"));
|
|
1946
|
+
console.log(chalk12.white(" Option 2: Use a non-privileged port (no sudo needed)"));
|
|
1947
|
+
console.log(chalk12.dim(" bindler config set nginxListen 8080"));
|
|
1948
|
+
console.log(chalk12.dim(" bindler apply"));
|
|
1949
|
+
console.log(chalk12.dim(" # Then access via http://hostname:8080\n"));
|
|
1950
|
+
} else {
|
|
1951
|
+
console.log(chalk12.dim(" Try restarting nginx: brew services restart nginx"));
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1879
1954
|
} else {
|
|
1880
1955
|
console.log(chalk12.yellow(" - Skipped nginx reload (--no-reload)"));
|
|
1881
1956
|
}
|
|
@@ -2258,7 +2333,7 @@ async function infoCommand() {
|
|
|
2258
2333
|
`));
|
|
2259
2334
|
console.log(chalk15.white(" Manage multiple projects behind Cloudflare Tunnel"));
|
|
2260
2335
|
console.log(chalk15.white(" with Nginx and PM2\n"));
|
|
2261
|
-
console.log(chalk15.dim(" Version: ") + chalk15.white("1.
|
|
2336
|
+
console.log(chalk15.dim(" Version: ") + chalk15.white("1.6.0"));
|
|
2262
2337
|
console.log(chalk15.dim(" Author: ") + chalk15.white("alfaoz"));
|
|
2263
2338
|
console.log(chalk15.dim(" License: ") + chalk15.white("MIT"));
|
|
2264
2339
|
console.log(chalk15.dim(" GitHub: ") + chalk15.cyan("https://github.com/alfaoz/bindler"));
|
|
@@ -2723,12 +2798,18 @@ async function initCommand() {
|
|
|
2723
2798
|
}
|
|
2724
2799
|
}
|
|
2725
2800
|
console.log(chalk18.bold("\n1. Choose your setup:\n"));
|
|
2801
|
+
const hasCloudflared = isCloudflaredInstalled();
|
|
2802
|
+
const defaultMode = hasCloudflared ? "tunnel" : "direct";
|
|
2803
|
+
if (!hasCloudflared) {
|
|
2804
|
+
console.log(chalk18.dim(" cloudflared not detected - suggesting direct mode for VPS\n"));
|
|
2805
|
+
}
|
|
2726
2806
|
const { mode } = await inquirer4.prompt([
|
|
2727
2807
|
{
|
|
2728
2808
|
type: "list",
|
|
2729
2809
|
name: "mode",
|
|
2730
2810
|
message: "How will you expose your projects?",
|
|
2731
|
-
|
|
2811
|
+
default: defaultMode,
|
|
2812
|
+
choices: hasCloudflared ? [
|
|
2732
2813
|
{
|
|
2733
2814
|
name: "Cloudflare Tunnel (recommended for home servers)",
|
|
2734
2815
|
value: "tunnel"
|
|
@@ -2741,6 +2822,19 @@ async function initCommand() {
|
|
|
2741
2822
|
name: "Local only (development, no internet access)",
|
|
2742
2823
|
value: "local"
|
|
2743
2824
|
}
|
|
2825
|
+
] : [
|
|
2826
|
+
{
|
|
2827
|
+
name: "Direct (VPS with public IP, port 80/443) - recommended",
|
|
2828
|
+
value: "direct"
|
|
2829
|
+
},
|
|
2830
|
+
{
|
|
2831
|
+
name: "Cloudflare Tunnel (requires cloudflared)",
|
|
2832
|
+
value: "tunnel"
|
|
2833
|
+
},
|
|
2834
|
+
{
|
|
2835
|
+
name: "Local only (development, no internet access)",
|
|
2836
|
+
value: "local"
|
|
2837
|
+
}
|
|
2744
2838
|
]
|
|
2745
2839
|
}
|
|
2746
2840
|
]);
|
|
@@ -3846,8 +3940,89 @@ Process exited with code ${code}`));
|
|
|
3846
3940
|
});
|
|
3847
3941
|
}
|
|
3848
3942
|
|
|
3849
|
-
// src/
|
|
3943
|
+
// src/commands/config.ts
|
|
3850
3944
|
import chalk29 from "chalk";
|
|
3945
|
+
var VALID_KEYS = [
|
|
3946
|
+
"nginxListen",
|
|
3947
|
+
"projectsRoot",
|
|
3948
|
+
"tunnelName",
|
|
3949
|
+
"mode",
|
|
3950
|
+
"applyCloudflareDnsRoutes",
|
|
3951
|
+
"sslEnabled",
|
|
3952
|
+
"sslEmail"
|
|
3953
|
+
];
|
|
3954
|
+
async function configCommand(action, key, value) {
|
|
3955
|
+
if (!action || action === "list") {
|
|
3956
|
+
const defaults = getDefaults();
|
|
3957
|
+
console.log(chalk29.blue("Current configuration:\n"));
|
|
3958
|
+
for (const [k, v] of Object.entries(defaults)) {
|
|
3959
|
+
console.log(` ${chalk29.cyan(k)}: ${chalk29.white(String(v))}`);
|
|
3960
|
+
}
|
|
3961
|
+
console.log(chalk29.dim("\nUse `bindler config set <key> <value>` to change a setting."));
|
|
3962
|
+
return;
|
|
3963
|
+
}
|
|
3964
|
+
if (action === "get") {
|
|
3965
|
+
if (!key) {
|
|
3966
|
+
console.error(chalk29.red("Usage: bindler config get <key>"));
|
|
3967
|
+
console.log(chalk29.dim(`
|
|
3968
|
+
Available keys: ${VALID_KEYS.join(", ")}`));
|
|
3969
|
+
process.exit(1);
|
|
3970
|
+
}
|
|
3971
|
+
const defaults = getDefaults();
|
|
3972
|
+
const configKey = key;
|
|
3973
|
+
if (!(configKey in defaults)) {
|
|
3974
|
+
console.error(chalk29.red(`Unknown config key: ${key}`));
|
|
3975
|
+
console.log(chalk29.dim(`
|
|
3976
|
+
Available keys: ${VALID_KEYS.join(", ")}`));
|
|
3977
|
+
process.exit(1);
|
|
3978
|
+
}
|
|
3979
|
+
console.log(defaults[configKey]);
|
|
3980
|
+
return;
|
|
3981
|
+
}
|
|
3982
|
+
if (action === "set") {
|
|
3983
|
+
if (!key || value === void 0) {
|
|
3984
|
+
console.error(chalk29.red("Usage: bindler config set <key> <value>"));
|
|
3985
|
+
console.log(chalk29.dim(`
|
|
3986
|
+
Available keys: ${VALID_KEYS.join(", ")}`));
|
|
3987
|
+
console.log(chalk29.dim("\nExamples:"));
|
|
3988
|
+
console.log(chalk29.dim(" bindler config set nginxListen 8080"));
|
|
3989
|
+
console.log(chalk29.dim(" bindler config set mode tunnel"));
|
|
3990
|
+
process.exit(1);
|
|
3991
|
+
}
|
|
3992
|
+
const configKey = key;
|
|
3993
|
+
if (!VALID_KEYS.includes(configKey)) {
|
|
3994
|
+
console.error(chalk29.red(`Unknown config key: ${key}`));
|
|
3995
|
+
console.log(chalk29.dim(`
|
|
3996
|
+
Available keys: ${VALID_KEYS.join(", ")}`));
|
|
3997
|
+
process.exit(1);
|
|
3998
|
+
}
|
|
3999
|
+
const config = readConfig();
|
|
4000
|
+
let parsedValue = value;
|
|
4001
|
+
if (configKey === "applyCloudflareDnsRoutes" || configKey === "sslEnabled") {
|
|
4002
|
+
parsedValue = value === "true" || value === "1";
|
|
4003
|
+
} else if (configKey === "mode") {
|
|
4004
|
+
if (value !== "tunnel" && value !== "direct") {
|
|
4005
|
+
console.error(chalk29.red('Mode must be "tunnel" or "direct"'));
|
|
4006
|
+
process.exit(1);
|
|
4007
|
+
}
|
|
4008
|
+
parsedValue = value;
|
|
4009
|
+
}
|
|
4010
|
+
config.defaults[configKey] = parsedValue;
|
|
4011
|
+
writeConfig(config);
|
|
4012
|
+
console.log(chalk29.green(`\u2713 Set ${key} = ${parsedValue}`));
|
|
4013
|
+
console.log(chalk29.dim("\nRun `bindler apply` to apply changes."));
|
|
4014
|
+
return;
|
|
4015
|
+
}
|
|
4016
|
+
console.error(chalk29.red(`Unknown action: ${action}`));
|
|
4017
|
+
console.log(chalk29.dim("\nUsage:"));
|
|
4018
|
+
console.log(chalk29.dim(" bindler config # list all settings"));
|
|
4019
|
+
console.log(chalk29.dim(" bindler config get <key> # get a setting"));
|
|
4020
|
+
console.log(chalk29.dim(" bindler config set <key> <value> # set a setting"));
|
|
4021
|
+
process.exit(1);
|
|
4022
|
+
}
|
|
4023
|
+
|
|
4024
|
+
// src/lib/update-check.ts
|
|
4025
|
+
import chalk30 from "chalk";
|
|
3851
4026
|
import { existsSync as existsSync14, readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5 } from "fs";
|
|
3852
4027
|
import { join as join9 } from "path";
|
|
3853
4028
|
import { homedir as homedir4 } from "os";
|
|
@@ -3900,28 +4075,28 @@ async function checkForUpdates() {
|
|
|
3900
4075
|
const cache = readCache();
|
|
3901
4076
|
const now = Date.now();
|
|
3902
4077
|
if (now - cache.lastCheck < CHECK_INTERVAL) {
|
|
3903
|
-
if (cache.latestVersion && compareVersions("1.
|
|
4078
|
+
if (cache.latestVersion && compareVersions("1.6.0", cache.latestVersion) < 0) {
|
|
3904
4079
|
showUpdateMessage(cache.latestVersion);
|
|
3905
4080
|
}
|
|
3906
4081
|
return;
|
|
3907
4082
|
}
|
|
3908
4083
|
fetchLatestVersion().then((latestVersion) => {
|
|
3909
4084
|
writeCache({ lastCheck: now, latestVersion });
|
|
3910
|
-
if (latestVersion && compareVersions("1.
|
|
4085
|
+
if (latestVersion && compareVersions("1.6.0", latestVersion) < 0) {
|
|
3911
4086
|
showUpdateMessage(latestVersion);
|
|
3912
4087
|
}
|
|
3913
4088
|
});
|
|
3914
4089
|
}
|
|
3915
4090
|
function showUpdateMessage(latestVersion) {
|
|
3916
4091
|
console.log("");
|
|
3917
|
-
console.log(
|
|
3918
|
-
console.log(
|
|
4092
|
+
console.log(chalk30.yellow(` Update available: ${"1.6.0"} \u2192 ${latestVersion}`));
|
|
4093
|
+
console.log(chalk30.dim(` Run: npm update -g bindler`));
|
|
3919
4094
|
console.log("");
|
|
3920
4095
|
}
|
|
3921
4096
|
|
|
3922
4097
|
// src/cli.ts
|
|
3923
4098
|
var program = new Command();
|
|
3924
|
-
program.name("bindler").description("Manage multiple projects behind Cloudflare Tunnel with Nginx and PM2").version("1.
|
|
4099
|
+
program.name("bindler").description("Manage multiple projects behind Cloudflare Tunnel with Nginx and PM2").version("1.6.0");
|
|
3925
4100
|
program.hook("preAction", async () => {
|
|
3926
4101
|
try {
|
|
3927
4102
|
initConfig();
|
|
@@ -3940,73 +4115,73 @@ program.command("status").description("Show detailed status of all projects").ac
|
|
|
3940
4115
|
});
|
|
3941
4116
|
program.command("start [name]").description("Start an npm project with PM2").option("-a, --all", "Start all npm projects").action(async (name, options) => {
|
|
3942
4117
|
if (!name && !options.all) {
|
|
3943
|
-
console.log(
|
|
3944
|
-
console.log(
|
|
3945
|
-
console.log(
|
|
3946
|
-
console.log(
|
|
4118
|
+
console.log(chalk31.red("Usage: bindler start <name> or bindler start --all"));
|
|
4119
|
+
console.log(chalk31.dim("\nExamples:"));
|
|
4120
|
+
console.log(chalk31.dim(" bindler start myapp"));
|
|
4121
|
+
console.log(chalk31.dim(" bindler start --all # start all npm projects"));
|
|
3947
4122
|
process.exit(1);
|
|
3948
4123
|
}
|
|
3949
4124
|
await startCommand(name, options);
|
|
3950
4125
|
});
|
|
3951
4126
|
program.command("stop [name]").description("Stop an npm project").option("-a, --all", "Stop all npm projects").action(async (name, options) => {
|
|
3952
4127
|
if (!name && !options.all) {
|
|
3953
|
-
console.log(
|
|
3954
|
-
console.log(
|
|
3955
|
-
console.log(
|
|
3956
|
-
console.log(
|
|
4128
|
+
console.log(chalk31.red("Usage: bindler stop <name> or bindler stop --all"));
|
|
4129
|
+
console.log(chalk31.dim("\nExamples:"));
|
|
4130
|
+
console.log(chalk31.dim(" bindler stop myapp"));
|
|
4131
|
+
console.log(chalk31.dim(" bindler stop --all # stop all npm projects"));
|
|
3957
4132
|
process.exit(1);
|
|
3958
4133
|
}
|
|
3959
4134
|
await stopCommand(name, options);
|
|
3960
4135
|
});
|
|
3961
4136
|
program.command("restart [name]").description("Restart an npm project").option("-a, --all", "Restart all npm projects").action(async (name, options) => {
|
|
3962
4137
|
if (!name && !options.all) {
|
|
3963
|
-
console.log(
|
|
3964
|
-
console.log(
|
|
3965
|
-
console.log(
|
|
3966
|
-
console.log(
|
|
4138
|
+
console.log(chalk31.red("Usage: bindler restart <name> or bindler restart --all"));
|
|
4139
|
+
console.log(chalk31.dim("\nExamples:"));
|
|
4140
|
+
console.log(chalk31.dim(" bindler restart myapp"));
|
|
4141
|
+
console.log(chalk31.dim(" bindler restart --all # restart all npm projects"));
|
|
3967
4142
|
process.exit(1);
|
|
3968
4143
|
}
|
|
3969
4144
|
await restartCommand(name, options);
|
|
3970
4145
|
});
|
|
3971
4146
|
program.command("logs [name]").description("Show logs for an npm project").option("-f, --follow", "Follow log output").option("-l, --lines <n>", "Number of lines to show", "200").action(async (name, options) => {
|
|
3972
4147
|
if (!name) {
|
|
3973
|
-
console.log(
|
|
3974
|
-
console.log(
|
|
3975
|
-
console.log(
|
|
3976
|
-
console.log(
|
|
3977
|
-
console.log(
|
|
4148
|
+
console.log(chalk31.red("Usage: bindler logs <name>"));
|
|
4149
|
+
console.log(chalk31.dim("\nExamples:"));
|
|
4150
|
+
console.log(chalk31.dim(" bindler logs myapp"));
|
|
4151
|
+
console.log(chalk31.dim(" bindler logs myapp --follow"));
|
|
4152
|
+
console.log(chalk31.dim(" bindler logs myapp --lines 500"));
|
|
3978
4153
|
process.exit(1);
|
|
3979
4154
|
}
|
|
3980
4155
|
await logsCommand(name, { ...options, lines: parseInt(options.lines, 10) });
|
|
3981
4156
|
});
|
|
3982
4157
|
program.command("update [name]").description("Update project configuration").option("-h, --hostname <hostname>", "New hostname").option("--port <port>", "New port number").option("-s, --start <command>", "New start command").option("-p, --path <path>", "New project path").option("-e, --env <vars...>", "Environment variables (KEY=value)").option("--enable", "Enable the project").option("--disable", "Disable the project").action(async (name, options) => {
|
|
3983
4158
|
if (!name) {
|
|
3984
|
-
console.log(
|
|
3985
|
-
console.log(
|
|
3986
|
-
console.log(
|
|
3987
|
-
console.log(
|
|
3988
|
-
console.log(
|
|
4159
|
+
console.log(chalk31.red("Usage: bindler update <name> [options]"));
|
|
4160
|
+
console.log(chalk31.dim("\nExamples:"));
|
|
4161
|
+
console.log(chalk31.dim(" bindler update myapp --hostname newapp.example.com"));
|
|
4162
|
+
console.log(chalk31.dim(" bindler update myapp --port 4000"));
|
|
4163
|
+
console.log(chalk31.dim(" bindler update myapp --disable"));
|
|
3989
4164
|
process.exit(1);
|
|
3990
4165
|
}
|
|
3991
4166
|
await updateCommand(name, options);
|
|
3992
4167
|
});
|
|
3993
4168
|
program.command("edit [name]").description("Edit project configuration in $EDITOR").action(async (name) => {
|
|
3994
4169
|
if (!name) {
|
|
3995
|
-
console.log(
|
|
3996
|
-
console.log(
|
|
3997
|
-
console.log(
|
|
3998
|
-
console.log(
|
|
4170
|
+
console.log(chalk31.red("Usage: bindler edit <name>"));
|
|
4171
|
+
console.log(chalk31.dim("\nOpens the project config in your $EDITOR"));
|
|
4172
|
+
console.log(chalk31.dim("\nExample:"));
|
|
4173
|
+
console.log(chalk31.dim(" bindler edit myapp"));
|
|
3999
4174
|
process.exit(1);
|
|
4000
4175
|
}
|
|
4001
4176
|
await editCommand(name);
|
|
4002
4177
|
});
|
|
4003
4178
|
program.command("remove [name]").alias("rm").description("Remove a project from registry").option("-f, --force", "Skip confirmation").option("--apply", "Apply nginx config after removing").action(async (name, options) => {
|
|
4004
4179
|
if (!name) {
|
|
4005
|
-
console.log(
|
|
4006
|
-
console.log(
|
|
4007
|
-
console.log(
|
|
4008
|
-
console.log(
|
|
4009
|
-
console.log(
|
|
4180
|
+
console.log(chalk31.red("Usage: bindler remove <name>"));
|
|
4181
|
+
console.log(chalk31.dim("\nExamples:"));
|
|
4182
|
+
console.log(chalk31.dim(" bindler remove myapp"));
|
|
4183
|
+
console.log(chalk31.dim(" bindler remove myapp --force # skip confirmation"));
|
|
4184
|
+
console.log(chalk31.dim(" bindler rm myapp # alias"));
|
|
4010
4185
|
process.exit(1);
|
|
4011
4186
|
}
|
|
4012
4187
|
await removeCommand(name, options);
|
|
@@ -4025,10 +4200,10 @@ program.command("info").description("Show bindler information and stats").action
|
|
|
4025
4200
|
});
|
|
4026
4201
|
program.command("check [hostname]").description("Check DNS propagation and HTTP accessibility for a hostname").option("-v, --verbose", "Show verbose output").action(async (hostname, options) => {
|
|
4027
4202
|
if (!hostname) {
|
|
4028
|
-
console.log(
|
|
4029
|
-
console.log(
|
|
4030
|
-
console.log(
|
|
4031
|
-
console.log(
|
|
4203
|
+
console.log(chalk31.red("Usage: bindler check <hostname>"));
|
|
4204
|
+
console.log(chalk31.dim("\nExamples:"));
|
|
4205
|
+
console.log(chalk31.dim(" bindler check myapp.example.com"));
|
|
4206
|
+
console.log(chalk31.dim(" bindler check myapp # uses project name"));
|
|
4032
4207
|
process.exit(1);
|
|
4033
4208
|
}
|
|
4034
4209
|
await checkCommand(hostname, options);
|
|
@@ -4072,5 +4247,8 @@ program.command("clone [source] [new-name]").description("Clone a project config
|
|
|
4072
4247
|
program.command("dev [name]").description("Start a project in development mode with hot reload").option("-p, --port <port>", "Override port number").option("-h, --hostname <hostname>", "Override hostname").action(async (name, options) => {
|
|
4073
4248
|
await devCommand(name, options);
|
|
4074
4249
|
});
|
|
4250
|
+
program.command("config [action] [key] [value]").description("View or modify bindler configuration").action(async (action, key, value) => {
|
|
4251
|
+
await configCommand(action, key, value);
|
|
4252
|
+
});
|
|
4075
4253
|
program.parse();
|
|
4076
4254
|
//# sourceMappingURL=cli.js.map
|