@abyrd9/harbor-cli 2.0.1 โ 2.1.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/README.md +28 -13
- package/dist/index.js +65 -28
- package/harbor.package-json.schema.json +96 -0
- package/harbor.schema.json +92 -0
- package/package.json +10 -23
- package/scripts/dev.sh +22 -9
- package/dist/harbor +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Harbor CLI
|
|
2
2
|
|
|
3
|
-
A CLI tool for managing local development services with ease. Harbor helps you orchestrate multiple development services in tmux
|
|
3
|
+
A CLI tool for managing local development services with ease. Harbor helps you orchestrate multiple development services in a tmux session, perfect for microservices and polyglot projects.
|
|
4
4
|
|
|
5
5
|
## โจ Features
|
|
6
6
|
|
|
@@ -10,7 +10,8 @@ A CLI tool for managing local development services with ease. Harbor helps you o
|
|
|
10
10
|
- ๐ **Dependency Management**: Automatically checks for required system dependencies
|
|
11
11
|
- ๐ฏ **Multi-Language Support**: Works with Node.js, Go, Rust, Python, PHP, Java, and more
|
|
12
12
|
- ๐ฅ๏ธ **Tmux Integration**: Professional terminal multiplexing for service management
|
|
13
|
-
-
|
|
13
|
+
- ๐ **Service Logging**: Stream service output to log files for monitoring and debugging
|
|
14
|
+
- ๐ท๏ธ **Custom Session Names**: Configure unique tmux session names
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
16
17
|
|
|
@@ -63,22 +64,33 @@ Create a dedicated configuration file:
|
|
|
63
64
|
{
|
|
64
65
|
"services": [
|
|
65
66
|
{
|
|
66
|
-
"name": "
|
|
67
|
-
"path": "./
|
|
67
|
+
"name": "database",
|
|
68
|
+
"path": "./db",
|
|
69
|
+
"preStage": {
|
|
70
|
+
"command": "docker-compose up -d postgres",
|
|
71
|
+
"wait": 5,
|
|
72
|
+
"timeout": 60
|
|
73
|
+
},
|
|
68
74
|
"command": "npm run dev",
|
|
69
|
-
"log": true
|
|
75
|
+
"log": true,
|
|
76
|
+
"maxLogLines": 500
|
|
70
77
|
},
|
|
71
78
|
{
|
|
72
79
|
"name": "api",
|
|
73
80
|
"path": "./go-api",
|
|
81
|
+
"preStage": {
|
|
82
|
+
"command": "go mod download",
|
|
83
|
+
"wait": 2
|
|
84
|
+
},
|
|
74
85
|
"command": "go run .",
|
|
75
86
|
"log": true,
|
|
76
87
|
"maxLogLines": 500
|
|
77
88
|
},
|
|
78
89
|
{
|
|
79
|
-
"name": "
|
|
80
|
-
"path": "./
|
|
81
|
-
"command": "
|
|
90
|
+
"name": "frontend",
|
|
91
|
+
"path": "./vite-frontend",
|
|
92
|
+
"command": "npm run dev",
|
|
93
|
+
"log": true
|
|
82
94
|
}
|
|
83
95
|
],
|
|
84
96
|
"before": [
|
|
@@ -96,7 +108,8 @@ Create a dedicated configuration file:
|
|
|
96
108
|
"path": "./",
|
|
97
109
|
"command": "echo 'Development environment ready!'"
|
|
98
110
|
}
|
|
99
|
-
]
|
|
111
|
+
],
|
|
112
|
+
"sessionName": "my-project-dev"
|
|
100
113
|
}
|
|
101
114
|
```
|
|
102
115
|
|
|
@@ -137,14 +150,16 @@ Store configuration directly in your `package.json`:
|
|
|
137
150
|
}
|
|
138
151
|
```
|
|
139
152
|
|
|
153
|
+
|
|
154
|
+
|
|
140
155
|
## Commands
|
|
141
156
|
|
|
142
157
|
| Command | Description |
|
|
143
158
|
|---------|-------------|
|
|
144
|
-
| `harbor dock` | Initialize
|
|
145
|
-
| `harbor moor` | Scan for and add new services to existing configuration |
|
|
146
|
-
| `harbor launch` | Start all services in tmux
|
|
147
|
-
| `harbor --help` | Show help
|
|
159
|
+
| `harbor dock` | Initialize Harbor config by auto-discovering services in your project |
|
|
160
|
+
| `harbor moor` | Scan for and add new services to your existing Harbor configuration |
|
|
161
|
+
| `harbor launch` | Start all services in a tmux session with pre-stage commands |
|
|
162
|
+
| `harbor --help` | Show comprehensive help with feature descriptions |
|
|
148
163
|
| `harbor --version` | Show version information |
|
|
149
164
|
|
|
150
165
|
### Command Options
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { chmodSync } from 'node:fs';
|
|
|
7
7
|
import { readFileSync } from 'node:fs';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import os from 'node:os';
|
|
10
|
+
import readline from 'node:readline';
|
|
10
11
|
// Read version from package.json
|
|
11
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
13
|
const __dirname = path.dirname(__filename);
|
|
@@ -160,6 +161,35 @@ async function checkDependencies() {
|
|
|
160
161
|
throw new Error('Please install missing dependencies before continuing');
|
|
161
162
|
}
|
|
162
163
|
}
|
|
164
|
+
function promptConfigLocation() {
|
|
165
|
+
const rl = readline.createInterface({
|
|
166
|
+
input: process.stdin,
|
|
167
|
+
output: process.stdout,
|
|
168
|
+
});
|
|
169
|
+
return new Promise((resolve) => {
|
|
170
|
+
console.log('\nFound package.json. Where would you like to store harbor config?');
|
|
171
|
+
console.log(' 1. package.json (keeps everything in one place)');
|
|
172
|
+
console.log(' 2. harbor.json (separate config file, auto-IntelliSense)\n');
|
|
173
|
+
const ask = () => {
|
|
174
|
+
rl.question('Enter choice (1 or 2): ', (answer) => {
|
|
175
|
+
const choice = answer.trim();
|
|
176
|
+
if (choice === '1') {
|
|
177
|
+
rl.close();
|
|
178
|
+
resolve('package.json');
|
|
179
|
+
}
|
|
180
|
+
else if (choice === '2') {
|
|
181
|
+
rl.close();
|
|
182
|
+
resolve('harbor.json');
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
console.log('Please enter 1 or 2');
|
|
186
|
+
ask();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
};
|
|
190
|
+
ask();
|
|
191
|
+
});
|
|
192
|
+
}
|
|
163
193
|
const possibleProjectFiles = [
|
|
164
194
|
'package.json', // Node.js projects
|
|
165
195
|
'go.mod', // Go projects
|
|
@@ -176,12 +206,19 @@ program
|
|
|
176
206
|
.description(`A CLI tool for managing your project's local development services
|
|
177
207
|
|
|
178
208
|
Harbor helps you manage multiple local development services with ease.
|
|
179
|
-
It provides a simple way to configure and run your services in tmux
|
|
209
|
+
It provides a simple way to configure and run your services in a tmux session.
|
|
210
|
+
|
|
211
|
+
Features:
|
|
212
|
+
โ
Automatic service discovery for Node.js, Go, Rust, Python, PHP, Java
|
|
213
|
+
โ
Pre-stage commands for setup before main service starts
|
|
214
|
+
โ
Configurable tmux session names
|
|
215
|
+
โ
Service logging with file output for monitoring and debugging
|
|
216
|
+
โ
Before/after script execution
|
|
180
217
|
|
|
181
218
|
Available Commands:
|
|
182
|
-
dock Initialize a new Harbor project
|
|
183
|
-
moor Add new services to
|
|
184
|
-
launch Start all services in tmux
|
|
219
|
+
dock Initialize a new Harbor project by scanning directories
|
|
220
|
+
moor Add new services to existing Harbor configuration
|
|
221
|
+
launch Start all services in a tmux session with pre-stage commands`)
|
|
185
222
|
.version(packageJson.version)
|
|
186
223
|
.action(async () => await checkDependencies())
|
|
187
224
|
.addHelpCommand(false);
|
|
@@ -190,10 +227,7 @@ if (process.argv.length <= 2) {
|
|
|
190
227
|
program.help();
|
|
191
228
|
}
|
|
192
229
|
program.command('dock')
|
|
193
|
-
.description(
|
|
194
|
-
- harbor.json configuration file (or harbor field in package.json)
|
|
195
|
-
|
|
196
|
-
This is typically the first command you'll run in a new project.`)
|
|
230
|
+
.description('Initialize Harbor config by auto-discovering services in your project')
|
|
197
231
|
.option('-p, --path <path>', 'The path to the root of your project', './')
|
|
198
232
|
.action(async (options) => {
|
|
199
233
|
try {
|
|
@@ -214,7 +248,7 @@ This is typically the first command you'll run in a new project.`)
|
|
|
214
248
|
}
|
|
215
249
|
});
|
|
216
250
|
program.command('moor')
|
|
217
|
-
.description('
|
|
251
|
+
.description('Scan for and add new services to your existing Harbor configuration')
|
|
218
252
|
.option('-p, --path <path>', 'The path to the root of your project', './')
|
|
219
253
|
.action(async (options) => {
|
|
220
254
|
try {
|
|
@@ -233,9 +267,7 @@ program.command('moor')
|
|
|
233
267
|
}
|
|
234
268
|
});
|
|
235
269
|
program.command('launch')
|
|
236
|
-
.description(
|
|
237
|
-
|
|
238
|
-
Note: This command will stop any active Caddy processes, including those from other Harbor projects.`)
|
|
270
|
+
.description('Start all services in a tmux session with pre-stage commands')
|
|
239
271
|
.action(async () => {
|
|
240
272
|
try {
|
|
241
273
|
await checkDependencies();
|
|
@@ -250,7 +282,7 @@ program.parse();
|
|
|
250
282
|
function fileExists(path) {
|
|
251
283
|
return fs.existsSync(`${process.cwd()}/${path}`);
|
|
252
284
|
}
|
|
253
|
-
function isProjectDirectory(dirPath) {
|
|
285
|
+
export function isProjectDirectory(dirPath) {
|
|
254
286
|
return possibleProjectFiles.some(file => {
|
|
255
287
|
try {
|
|
256
288
|
return fs.existsSync(path.join(process.cwd(), dirPath, file));
|
|
@@ -260,7 +292,7 @@ function isProjectDirectory(dirPath) {
|
|
|
260
292
|
}
|
|
261
293
|
});
|
|
262
294
|
}
|
|
263
|
-
function validateConfig(config) {
|
|
295
|
+
export function validateConfig(config) {
|
|
264
296
|
if (!Array.isArray(config.services)) {
|
|
265
297
|
return 'Services must be an array';
|
|
266
298
|
}
|
|
@@ -323,28 +355,21 @@ async function generateDevFile(dirPath) {
|
|
|
323
355
|
const packageData = await fs.promises.readFile('package.json', 'utf-8');
|
|
324
356
|
const packageJson = JSON.parse(packageData);
|
|
325
357
|
if (packageJson.harbor) {
|
|
358
|
+
// Existing harbor config in package.json, use it
|
|
326
359
|
config = packageJson.harbor;
|
|
327
360
|
writeToPackageJson = true;
|
|
328
361
|
console.log('Found existing harbor config in package.json, scanning for new services...');
|
|
329
362
|
}
|
|
330
|
-
else if (fileExists('package.json')) {
|
|
331
|
-
// If package.json exists but no harbor config, use it
|
|
332
|
-
writeToPackageJson = true;
|
|
333
|
-
config = {
|
|
334
|
-
services: [],
|
|
335
|
-
before: [],
|
|
336
|
-
after: [],
|
|
337
|
-
};
|
|
338
|
-
console.log('Creating new harbor config in package.json...');
|
|
339
|
-
}
|
|
340
363
|
else {
|
|
341
|
-
//
|
|
364
|
+
// package.json exists but no harbor config - ask user where to store it
|
|
365
|
+
const choice = await promptConfigLocation();
|
|
366
|
+
writeToPackageJson = choice === 'package.json';
|
|
342
367
|
config = {
|
|
343
368
|
services: [],
|
|
344
369
|
before: [],
|
|
345
370
|
after: [],
|
|
346
371
|
};
|
|
347
|
-
console.log(
|
|
372
|
+
console.log(`Creating new harbor config in ${choice}...`);
|
|
348
373
|
}
|
|
349
374
|
}
|
|
350
375
|
catch (err) {
|
|
@@ -404,10 +429,22 @@ async function generateDevFile(dirPath) {
|
|
|
404
429
|
packageJson.harbor = config;
|
|
405
430
|
await fs.promises.writeFile('package.json', JSON.stringify(packageJson, null, 2), 'utf-8');
|
|
406
431
|
console.log('\npackage.json updated successfully with harbor configuration');
|
|
432
|
+
console.log('\n๐ก Tip: To enable IntelliSense for the harbor config in package.json,');
|
|
433
|
+
console.log(' add this to your .vscode/settings.json:');
|
|
434
|
+
console.log(' {');
|
|
435
|
+
console.log(' "json.schemas": [{');
|
|
436
|
+
console.log(' "fileMatch": ["package.json"],');
|
|
437
|
+
console.log(' "url": "https://raw.githubusercontent.com/Abyrd9/harbor-cli/main/harbor.package-json.schema.json"');
|
|
438
|
+
console.log(' }]');
|
|
439
|
+
console.log(' }');
|
|
407
440
|
}
|
|
408
441
|
else {
|
|
409
|
-
// Write to harbor.json
|
|
410
|
-
|
|
442
|
+
// Write to harbor.json with $schema for IntelliSense
|
|
443
|
+
const configWithSchema = {
|
|
444
|
+
$schema: 'https://raw.githubusercontent.com/Abyrd9/harbor-cli/main/harbor.schema.json',
|
|
445
|
+
...config,
|
|
446
|
+
};
|
|
447
|
+
await fs.promises.writeFile('harbor.json', JSON.stringify(configWithSchema, null, 2), 'utf-8');
|
|
411
448
|
console.log('\nharbor.json created successfully');
|
|
412
449
|
}
|
|
413
450
|
console.log('\nImportant:');
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/Abyrd9/harbor-cli/main/harbor.package-json.schema.json",
|
|
4
|
+
"title": "Harbor Configuration in package.json",
|
|
5
|
+
"description": "Schema extension for the 'harbor' property in package.json",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"harbor": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"description": "Harbor CLI configuration for orchestrating local development services",
|
|
11
|
+
"required": ["services"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"services": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"description": "List of development services to run",
|
|
16
|
+
"items": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"required": ["name", "path"],
|
|
19
|
+
"properties": {
|
|
20
|
+
"name": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Display name for the service (shown in the terminal UI)"
|
|
23
|
+
},
|
|
24
|
+
"path": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "Relative path to the service directory from the project root"
|
|
27
|
+
},
|
|
28
|
+
"command": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Command to start the service (e.g., 'bun run dev', 'go run .')"
|
|
31
|
+
},
|
|
32
|
+
"log": {
|
|
33
|
+
"type": "boolean",
|
|
34
|
+
"description": "Whether to log output to a file in .harbor/logs/",
|
|
35
|
+
"default": false
|
|
36
|
+
},
|
|
37
|
+
"maxLogLines": {
|
|
38
|
+
"type": "integer",
|
|
39
|
+
"description": "Maximum number of lines to keep in the log file",
|
|
40
|
+
"minimum": 1
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"additionalProperties": false
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"sessionName": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"description": "Custom name for tmux session (default: local-dev-test)",
|
|
49
|
+
"pattern": "^[a-zA-Z0-9_-]+$"
|
|
50
|
+
},
|
|
51
|
+
"before": {
|
|
52
|
+
"type": "array",
|
|
53
|
+
"description": "Scripts to run before starting services",
|
|
54
|
+
"items": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"required": ["path", "command"],
|
|
57
|
+
"properties": {
|
|
58
|
+
"path": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"description": "Relative path to run the command from"
|
|
61
|
+
},
|
|
62
|
+
"command": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"description": "Command to execute"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"additionalProperties": false
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"after": {
|
|
71
|
+
"type": "array",
|
|
72
|
+
"description": "Scripts to run after all services stop",
|
|
73
|
+
"items": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"required": ["path", "command"],
|
|
76
|
+
"properties": {
|
|
77
|
+
"path": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"description": "Relative path to run the command from"
|
|
80
|
+
},
|
|
81
|
+
"command": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"description": "Command to execute"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"additionalProperties": false
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"additionalProperties": false
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/Abyrd9/harbor-cli/main/harbor.schema.json",
|
|
4
|
+
"title": "Harbor Configuration",
|
|
5
|
+
"description": "Configuration schema for Harbor CLI - a tool for running multiple development services",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["services"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "JSON Schema reference for IDE IntelliSense"
|
|
12
|
+
},
|
|
13
|
+
"services": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"description": "List of development services to run",
|
|
16
|
+
"items": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"required": ["name", "path"],
|
|
19
|
+
"properties": {
|
|
20
|
+
"name": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Display name for the service (shown in the terminal UI)"
|
|
23
|
+
},
|
|
24
|
+
"path": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "Relative path to the service directory from the project root"
|
|
27
|
+
},
|
|
28
|
+
"command": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Command to start the service (e.g., 'bun run dev', 'go run .')"
|
|
31
|
+
},
|
|
32
|
+
"log": {
|
|
33
|
+
"type": "boolean",
|
|
34
|
+
"description": "Whether to log output to a file in .harbor/logs/",
|
|
35
|
+
"default": false
|
|
36
|
+
},
|
|
37
|
+
"maxLogLines": {
|
|
38
|
+
"type": "integer",
|
|
39
|
+
"description": "Maximum number of lines to keep in the log file",
|
|
40
|
+
"minimum": 1
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"additionalProperties": false
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"sessionName": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"description": "Custom name for the tmux session (default: local-dev-test)",
|
|
49
|
+
"pattern": "^[a-zA-Z0-9_-]+$"
|
|
50
|
+
},
|
|
51
|
+
"before": {
|
|
52
|
+
"type": "array",
|
|
53
|
+
"description": "Scripts to run before starting services",
|
|
54
|
+
"items": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"required": ["path", "command"],
|
|
57
|
+
"properties": {
|
|
58
|
+
"path": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"description": "Relative path to run the command from"
|
|
61
|
+
},
|
|
62
|
+
"command": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"description": "Command to execute"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"additionalProperties": false
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"after": {
|
|
71
|
+
"type": "array",
|
|
72
|
+
"description": "Scripts to run after all services stop",
|
|
73
|
+
"items": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"required": ["path", "command"],
|
|
76
|
+
"properties": {
|
|
77
|
+
"path": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"description": "Relative path to run the command from"
|
|
80
|
+
},
|
|
81
|
+
"command": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"description": "Command to execute"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"additionalProperties": false
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"additionalProperties": false
|
|
91
|
+
}
|
|
92
|
+
|
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abyrd9/harbor-cli",
|
|
3
|
-
"version": "2.0
|
|
4
|
-
"description": "A CLI tool for orchestrating local development services in tmux
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "A CLI tool for orchestrating local development services in a tmux session. 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"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
-
"scripts"
|
|
11
|
+
"scripts",
|
|
12
|
+
"harbor.schema.json",
|
|
13
|
+
"harbor.package-json.schema.json"
|
|
12
14
|
],
|
|
13
15
|
"scripts": {
|
|
14
16
|
"check": "bunx npm-check -u",
|
|
@@ -16,6 +18,8 @@
|
|
|
16
18
|
"prepare": "bun run build",
|
|
17
19
|
"start": "bun dist/index.js",
|
|
18
20
|
"harbor": "bun dist/index.js",
|
|
21
|
+
"test": "vitest",
|
|
22
|
+
"test:watch": "vitest --watch",
|
|
19
23
|
"release": "bash release.sh"
|
|
20
24
|
},
|
|
21
25
|
"keywords": [
|
|
@@ -43,25 +47,8 @@
|
|
|
43
47
|
"devDependencies": {
|
|
44
48
|
"@types/node": "^24.0.3",
|
|
45
49
|
"bun-types": "latest",
|
|
46
|
-
"typescript": "^5.8.3"
|
|
50
|
+
"typescript": "^5.8.3",
|
|
51
|
+
"vitest": "^4.0.16"
|
|
47
52
|
},
|
|
48
|
-
"main": "index.js"
|
|
49
|
-
"harbor": {
|
|
50
|
-
"services": [
|
|
51
|
-
{
|
|
52
|
-
"name": "web",
|
|
53
|
-
"path": "test-services/web",
|
|
54
|
-
"command": "bun run dev",
|
|
55
|
-
"log": true,
|
|
56
|
-
"maxLogLines": 500
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
"name": "go-api",
|
|
60
|
-
"path": "test-services/go-api",
|
|
61
|
-
"command": "go run .",
|
|
62
|
-
"log": true,
|
|
63
|
-
"maxLogLines": 500
|
|
64
|
-
}
|
|
65
|
-
]
|
|
66
|
-
}
|
|
53
|
+
"main": "index.js"
|
|
67
54
|
}
|
package/scripts/dev.sh
CHANGED
|
@@ -20,8 +20,20 @@ cleanup_logs() {
|
|
|
20
20
|
start_log_trim() {
|
|
21
21
|
local log_file="$1"
|
|
22
22
|
local max_lines="$2"
|
|
23
|
-
#
|
|
24
|
-
|
|
23
|
+
# Start background log trimmer process
|
|
24
|
+
{
|
|
25
|
+
while true; do
|
|
26
|
+
sleep 5
|
|
27
|
+
if [ -f "$log_file" ]; then
|
|
28
|
+
lines=$(wc -l < "$log_file")
|
|
29
|
+
if [ "$lines" -gt $max_lines ]; then
|
|
30
|
+
tail -n $max_lines "$log_file" > "${log_file}.tmp" && \
|
|
31
|
+
cat "${log_file}.tmp" > "$log_file" && \
|
|
32
|
+
rm "${log_file}.tmp"
|
|
33
|
+
fi
|
|
34
|
+
fi
|
|
35
|
+
done
|
|
36
|
+
} &
|
|
25
37
|
}
|
|
26
38
|
|
|
27
39
|
trap cleanup_logs EXIT
|
|
@@ -72,15 +84,15 @@ tmux bind-key -T copy-mode-vi v send-keys -X begin-selection
|
|
|
72
84
|
tmux bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel
|
|
73
85
|
tmux bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "pbcopy"
|
|
74
86
|
|
|
75
|
-
# Set easier window navigation shortcuts
|
|
76
|
-
tmux bind-key -n Left select-window -t :-
|
|
77
|
-
tmux bind-key -n Right select-window -t :+
|
|
87
|
+
# Set easier window navigation shortcuts (Shift+Left/Right to switch windows)
|
|
88
|
+
tmux bind-key -n S-Left select-window -t :-
|
|
89
|
+
tmux bind-key -n S-Right select-window -t :+
|
|
78
90
|
|
|
79
91
|
# Configure status bar
|
|
80
92
|
tmux set-option -g status-position top
|
|
81
93
|
tmux set-option -g status-style bg="#1c1917",fg="#a8a29e"
|
|
82
94
|
tmux set-option -g status-left ""
|
|
83
|
-
tmux set-option -g status-right "#[fg=#a8a29e]
|
|
95
|
+
tmux set-option -g status-right "#[fg=#a8a29e]shift+โ/โ switch ยท ctrl+q close ยท #[fg=white]%H:%M#[default]"
|
|
84
96
|
tmux set-window-option -g window-status-current-format "\
|
|
85
97
|
#[fg=#6366f1, bg=#1c1917] โ
|
|
86
98
|
#[fg=#6366f1, bg=#1c1917, bold] #W
|
|
@@ -124,9 +136,10 @@ while read service; do
|
|
|
124
136
|
if [ "$log" = "true" ]; then
|
|
125
137
|
log_file="$repo_root/.harbor/${session_name}-${name}.log"
|
|
126
138
|
: > "$log_file"
|
|
127
|
-
#
|
|
128
|
-
|
|
129
|
-
tmux
|
|
139
|
+
# Use pipe-pane to capture ALL terminal output (works with any program, no buffering issues)
|
|
140
|
+
tmux new-window -t "$session_name":$window_index -n "$name"
|
|
141
|
+
tmux pipe-pane -t "$session_name":$window_index "cat >> \"$log_file\""
|
|
142
|
+
tmux send-keys -t "$session_name":$window_index "cd \"$path\" && $command" C-m
|
|
130
143
|
# Start background process to trim logs if they get too large
|
|
131
144
|
start_log_trim "$log_file" "$effective_max_lines"
|
|
132
145
|
else
|
package/dist/harbor
DELETED
|
Binary file
|