@abyrd9/harbor-cli 1.1.0 ā 1.1.1
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/index.js +132 -8
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { spawn } from 'node:child_process';
|
|
|
6
6
|
import { chmodSync } from 'node:fs';
|
|
7
7
|
import { readFileSync } from 'node:fs';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import os from 'node:os';
|
|
9
10
|
// Read version from package.json
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
12
|
const __dirname = path.dirname(__filename);
|
|
@@ -24,8 +25,107 @@ const requiredDependencies = [
|
|
|
24
25
|
requiredFor: 'JSON processing in service management',
|
|
25
26
|
},
|
|
26
27
|
];
|
|
28
|
+
function detectOS() {
|
|
29
|
+
const platform = os.platform();
|
|
30
|
+
const arch = os.arch();
|
|
31
|
+
const isWindows = platform === 'win32';
|
|
32
|
+
const isMac = platform === 'darwin';
|
|
33
|
+
const isLinux = platform === 'linux';
|
|
34
|
+
// Check if running in WSL
|
|
35
|
+
let isWSL = false;
|
|
36
|
+
if (isLinux) {
|
|
37
|
+
try {
|
|
38
|
+
const release = fs.readFileSync('/proc/version', 'utf-8');
|
|
39
|
+
isWSL = release.toLowerCase().includes('microsoft') || release.toLowerCase().includes('wsl');
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// If we can't read /proc/version, assume not WSL
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
platform,
|
|
47
|
+
arch,
|
|
48
|
+
isWindows,
|
|
49
|
+
isMac,
|
|
50
|
+
isLinux,
|
|
51
|
+
isWSL,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function getInstallInstructions(dependency, osInfo) {
|
|
55
|
+
const instructions = [];
|
|
56
|
+
if (dependency === 'tmux') {
|
|
57
|
+
if (osInfo.isMac) {
|
|
58
|
+
instructions.push('š macOS:');
|
|
59
|
+
instructions.push(' ⢠Using Homebrew: brew install tmux');
|
|
60
|
+
instructions.push(' ⢠Using MacPorts: sudo port install tmux');
|
|
61
|
+
instructions.push(' ⢠Manual: https://github.com/tmux/tmux/wiki/Installing');
|
|
62
|
+
}
|
|
63
|
+
else if (osInfo.isLinux) {
|
|
64
|
+
if (osInfo.isWSL) {
|
|
65
|
+
instructions.push('š§ WSL/Linux:');
|
|
66
|
+
instructions.push(' ⢠Ubuntu/Debian: sudo apt update && sudo apt install tmux');
|
|
67
|
+
instructions.push(' ⢠CentOS/RHEL: sudo yum install tmux');
|
|
68
|
+
instructions.push(' ⢠Fedora: sudo dnf install tmux');
|
|
69
|
+
instructions.push(' ⢠Arch: sudo pacman -S tmux');
|
|
70
|
+
instructions.push(' ⢠openSUSE: sudo zypper install tmux');
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
instructions.push('š§ Linux:');
|
|
74
|
+
instructions.push(' ⢠Ubuntu/Debian: sudo apt update && sudo apt install tmux');
|
|
75
|
+
instructions.push(' ⢠CentOS/RHEL: sudo yum install tmux');
|
|
76
|
+
instructions.push(' ⢠Fedora: sudo dnf install tmux');
|
|
77
|
+
instructions.push(' ⢠Arch: sudo pacman -S tmux');
|
|
78
|
+
instructions.push(' ⢠openSUSE: sudo zypper install tmux');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (osInfo.isWindows) {
|
|
82
|
+
instructions.push('šŖ Windows:');
|
|
83
|
+
instructions.push(' ⢠Using Chocolatey: choco install tmux');
|
|
84
|
+
instructions.push(' ⢠Using Scoop: scoop install tmux');
|
|
85
|
+
instructions.push(' ⢠Using WSL: Install in WSL and use from there');
|
|
86
|
+
instructions.push(' ⢠Manual: https://github.com/tmux/tmux/wiki/Installing');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else if (dependency === 'jq') {
|
|
90
|
+
if (osInfo.isMac) {
|
|
91
|
+
instructions.push('š macOS:');
|
|
92
|
+
instructions.push(' ⢠Using Homebrew: brew install jq');
|
|
93
|
+
instructions.push(' ⢠Using MacPorts: sudo port install jq');
|
|
94
|
+
instructions.push(' ⢠Using Fink: fink install jq');
|
|
95
|
+
instructions.push(' ⢠Manual: https://jqlang.org/download/');
|
|
96
|
+
}
|
|
97
|
+
else if (osInfo.isLinux) {
|
|
98
|
+
if (osInfo.isWSL) {
|
|
99
|
+
instructions.push('š§ WSL/Linux:');
|
|
100
|
+
instructions.push(' ⢠Ubuntu/Debian: sudo apt update && sudo apt install jq');
|
|
101
|
+
instructions.push(' ⢠CentOS/RHEL: sudo yum install jq');
|
|
102
|
+
instructions.push(' ⢠Fedora: sudo dnf install jq');
|
|
103
|
+
instructions.push(' ⢠Arch: sudo pacman -S jq');
|
|
104
|
+
instructions.push(' ⢠openSUSE: sudo zypper install jq');
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
instructions.push('š§ Linux:');
|
|
108
|
+
instructions.push(' ⢠Ubuntu/Debian: sudo apt update && sudo apt install jq');
|
|
109
|
+
instructions.push(' ⢠CentOS/RHEL: sudo yum install jq');
|
|
110
|
+
instructions.push(' ⢠Fedora: sudo dnf install jq');
|
|
111
|
+
instructions.push(' ⢠Arch: sudo pacman -S jq');
|
|
112
|
+
instructions.push(' ⢠openSUSE: sudo zypper install jq');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if (osInfo.isWindows) {
|
|
116
|
+
instructions.push('šŖ Windows:');
|
|
117
|
+
instructions.push(' ⢠Using winget: winget install jqlang.jq');
|
|
118
|
+
instructions.push(' ⢠Using Chocolatey: choco install jq');
|
|
119
|
+
instructions.push(' ⢠Using Scoop: scoop install jq');
|
|
120
|
+
instructions.push(' ⢠Using WSL: Install in WSL and use from there');
|
|
121
|
+
instructions.push(' ⢠Manual: https://jqlang.org/download/');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return instructions;
|
|
125
|
+
}
|
|
27
126
|
async function checkDependencies() {
|
|
28
127
|
const missingDeps = [];
|
|
128
|
+
const osInfo = detectOS();
|
|
29
129
|
for (const dep of requiredDependencies) {
|
|
30
130
|
try {
|
|
31
131
|
await new Promise((resolve, reject) => {
|
|
@@ -44,10 +144,19 @@ async function checkDependencies() {
|
|
|
44
144
|
}
|
|
45
145
|
if (missingDeps.length > 0) {
|
|
46
146
|
console.log('ā Missing required dependencies:');
|
|
147
|
+
console.log(`\nš„ļø Detected OS: ${osInfo.platform} ${osInfo.arch}${osInfo.isWSL ? ' (WSL)' : ''}`);
|
|
47
148
|
for (const dep of missingDeps) {
|
|
48
|
-
console.log(`\n${dep.name} (required for ${dep.requiredFor})`);
|
|
49
|
-
|
|
149
|
+
console.log(`\nš¦ ${dep.name} (required for ${dep.requiredFor})`);
|
|
150
|
+
const instructions = getInstallInstructions(dep.name, osInfo);
|
|
151
|
+
if (instructions.length > 0) {
|
|
152
|
+
console.log(' Installation options:');
|
|
153
|
+
instructions.forEach(instruction => console.log(instruction));
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
console.log(` General instructions: ${dep.installMsg}`);
|
|
157
|
+
}
|
|
50
158
|
}
|
|
159
|
+
console.log('\nš” After installing the dependencies, run Harbor again.');
|
|
51
160
|
throw new Error('Please install missing dependencies before continuing');
|
|
52
161
|
}
|
|
53
162
|
}
|
|
@@ -88,6 +197,7 @@ This is typically the first command you'll run in a new project.`)
|
|
|
88
197
|
.option('-p, --path <path>', 'The path to the root of your project', './')
|
|
89
198
|
.action(async (options) => {
|
|
90
199
|
try {
|
|
200
|
+
await checkDependencies();
|
|
91
201
|
const configExists = checkHasHarborConfig();
|
|
92
202
|
if (configExists) {
|
|
93
203
|
console.log('ā Error: Harbor project already initialized');
|
|
@@ -107,20 +217,34 @@ program.command('moor')
|
|
|
107
217
|
.description('Add new services to your harbor configuration')
|
|
108
218
|
.option('-p, --path <path>', 'The path to the root of your project', './')
|
|
109
219
|
.action(async (options) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
220
|
+
try {
|
|
221
|
+
await checkDependencies();
|
|
222
|
+
if (!checkHasHarborConfig()) {
|
|
223
|
+
console.log('ā No harbor configuration found');
|
|
224
|
+
console.log('\nTo initialize a new Harbor project, please use:');
|
|
225
|
+
console.log(' harbor dock');
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
await generateDevFile(options.path);
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
console.log('ā Error:', err instanceof Error ? err.message : 'Unknown error');
|
|
114
232
|
process.exit(1);
|
|
115
233
|
}
|
|
116
|
-
await generateDevFile(options.path);
|
|
117
234
|
});
|
|
118
235
|
program.command('launch')
|
|
119
236
|
.description(`Launch your services in the harbor terminal multiplexer (Using tmux)
|
|
120
237
|
|
|
121
238
|
Note: This command will stop any active Caddy processes, including those from other Harbor projects.`)
|
|
122
239
|
.action(async () => {
|
|
123
|
-
|
|
240
|
+
try {
|
|
241
|
+
await checkDependencies();
|
|
242
|
+
await runServices();
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
console.log('ā Error:', err instanceof Error ? err.message : 'Unknown error');
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
124
248
|
});
|
|
125
249
|
program.parse();
|
|
126
250
|
function fileExists(path) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abyrd9/harbor-cli",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "A CLI tool for
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "A CLI tool for orchestrating local development services in tmux sessions. Perfect for microservices and polyglot projects with automatic service discovery and before/after script support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"harbor": "dist/index.js"
|