@cruxgarden/cli 0.0.6 → 0.0.8
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/lib/commands.js +138 -30
- package/package.json +5 -2
package/lib/commands.js
CHANGED
|
@@ -16,23 +16,40 @@ export function showBanner() {
|
|
|
16
16
|
// Check if banner was already shown in this shell session
|
|
17
17
|
if (process.env.CRUX_BANNER_SHOWN) return;
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
██║
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
██║
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
19
|
+
const bannerLines = [
|
|
20
|
+
" ██████╗██████╗ ██╗ ██╗██╗ ██╗",
|
|
21
|
+
"██╔════╝██╔══██╗██║ ██║╚██╗██╔╝",
|
|
22
|
+
"██║ ██████╔╝██║ ██║ ╚███╔╝",
|
|
23
|
+
"██║ ██╔══██╗██║ ██║ ██╔██╗",
|
|
24
|
+
"╚██████╗██║ ██║╚██████╔╝██╔╝ ██╗",
|
|
25
|
+
" ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝",
|
|
26
|
+
"",
|
|
27
|
+
" ██████╗ █████╗ ██████╗ ██████╗ ███████╗███╗ ██╗",
|
|
28
|
+
"██╔════╝ ██╔══██╗██╔══██╗██╔══██╗██╔════╝████╗ ██║",
|
|
29
|
+
"██║ ███╗███████║██████╔╝██║ ██║█████╗ ██╔██╗ ██║",
|
|
30
|
+
"██║ ██║██╔══██║██╔══██╗██║ ██║██╔══╝ ██║╚██╗██║",
|
|
31
|
+
"╚██████╔╝██║ ██║██║ ██║██████╔╝███████╗██║ ╚████║",
|
|
32
|
+
" ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚═╝ ╚═══╝"
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
// Randomly pick a color from the CLI color palette
|
|
36
|
+
const colors = [
|
|
37
|
+
chalk.hex(SUCCESS_GREEN), // Green
|
|
38
|
+
chalk.cyan, // Cyan
|
|
39
|
+
chalk.yellow, // Yellow
|
|
40
|
+
chalk.magenta, // Magenta
|
|
41
|
+
chalk.blue, // Blue
|
|
42
|
+
chalk.red, // Red
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const randomColor = colors[Math.floor(Math.random() * colors.length)];
|
|
46
|
+
|
|
47
|
+
// Print each line with the same random color
|
|
48
|
+
console.log();
|
|
49
|
+
bannerLines.forEach((line) => {
|
|
50
|
+
console.log(randomColor(line));
|
|
51
|
+
});
|
|
52
|
+
|
|
36
53
|
console.log(chalk.gray(" Nursery Environment - Demo & Trial\n"));
|
|
37
54
|
|
|
38
55
|
// Set environment variable so it persists for this shell session
|
|
@@ -89,7 +106,8 @@ function runCommandAsync(command, options = {}) {
|
|
|
89
106
|
);
|
|
90
107
|
reject(error);
|
|
91
108
|
} else {
|
|
92
|
-
|
|
109
|
+
// Return both stdout and stderr since Docker commands often write to stderr
|
|
110
|
+
resolve({ stdout, stderr, combined: stdout + stderr });
|
|
93
111
|
}
|
|
94
112
|
});
|
|
95
113
|
|
|
@@ -117,11 +135,36 @@ function askConfirmation(question) {
|
|
|
117
135
|
});
|
|
118
136
|
}
|
|
119
137
|
|
|
138
|
+
function checkDockerAvailable() {
|
|
139
|
+
try {
|
|
140
|
+
execSync("docker info", { stdio: "pipe" });
|
|
141
|
+
return true;
|
|
142
|
+
} catch (error) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function ensureDockerRunning() {
|
|
148
|
+
if (!checkDockerAvailable()) {
|
|
149
|
+
console.error(
|
|
150
|
+
chalk.red(
|
|
151
|
+
"\n✗ Docker is not running or not installed.\n",
|
|
152
|
+
),
|
|
153
|
+
);
|
|
154
|
+
console.log(chalk.gray("Please ensure Docker is installed and running:"));
|
|
155
|
+
console.log(chalk.gray(" • Start Docker Desktop, or"));
|
|
156
|
+
console.log(chalk.gray(" • Start the Docker daemon\n"));
|
|
157
|
+
console.log(chalk.gray("Then try your command again.\n"));
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
120
162
|
// ============================================================================
|
|
121
163
|
// Nursery Environment Commands
|
|
122
164
|
// ============================================================================
|
|
123
165
|
|
|
124
166
|
export async function startNursery(options) {
|
|
167
|
+
ensureDockerRunning();
|
|
125
168
|
const spinner = ora("Starting Crux Garden Nursery environment...").start();
|
|
126
169
|
|
|
127
170
|
try {
|
|
@@ -144,12 +187,21 @@ export async function startNursery(options) {
|
|
|
144
187
|
spinner.text =
|
|
145
188
|
"Starting nursery services (api, postgres, redis)...";
|
|
146
189
|
await runCommandAsync(
|
|
147
|
-
"docker-compose -f docker-compose.nursery.yml up -d --remove-orphans
|
|
190
|
+
"docker-compose -f docker-compose.nursery.yml up -d --remove-orphans",
|
|
148
191
|
{
|
|
149
192
|
silent: true,
|
|
150
193
|
},
|
|
151
194
|
);
|
|
152
195
|
|
|
196
|
+
// Clean up the migrations container if it exists (cross-platform)
|
|
197
|
+
await runCommandAsync(
|
|
198
|
+
"docker rm cruxgarden-nursery-migrations",
|
|
199
|
+
{
|
|
200
|
+
silent: true,
|
|
201
|
+
ignoreError: true,
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
|
|
153
205
|
spinner.succeed("Crux Garden Nursery environment started!");
|
|
154
206
|
console.log(
|
|
155
207
|
chalk.hex(SUCCESS_GREEN)("\n✓ API running on:"),
|
|
@@ -198,6 +250,7 @@ export async function startNursery(options) {
|
|
|
198
250
|
}
|
|
199
251
|
|
|
200
252
|
export async function stopNursery() {
|
|
253
|
+
ensureDockerRunning();
|
|
201
254
|
const spinner = ora("Stopping Crux Garden Nursery environment...").start();
|
|
202
255
|
await runCommandAsync("docker-compose -f docker-compose.nursery.yml down", {
|
|
203
256
|
silent: true,
|
|
@@ -212,6 +265,7 @@ export async function stopNursery() {
|
|
|
212
265
|
}
|
|
213
266
|
|
|
214
267
|
export async function logsNursery(options) {
|
|
268
|
+
ensureDockerRunning();
|
|
215
269
|
if (options.follow) {
|
|
216
270
|
console.log(
|
|
217
271
|
chalk.gray("Following nursery logs (press Ctrl+C to exit)...\n"),
|
|
@@ -236,6 +290,7 @@ export async function logsNursery(options) {
|
|
|
236
290
|
}
|
|
237
291
|
|
|
238
292
|
export async function cleanNursery() {
|
|
293
|
+
ensureDockerRunning();
|
|
239
294
|
console.log(
|
|
240
295
|
chalk.yellow(
|
|
241
296
|
"\n⚠️ This will delete all nursery containers and volumes (including data)!\n",
|
|
@@ -273,6 +328,7 @@ export async function cleanNursery() {
|
|
|
273
328
|
}
|
|
274
329
|
|
|
275
330
|
export async function purgeNursery() {
|
|
331
|
+
ensureDockerRunning();
|
|
276
332
|
console.log(
|
|
277
333
|
chalk.yellow(
|
|
278
334
|
"\n⚠️ This will delete ALL nursery resources (containers, volumes, AND images)!\n",
|
|
@@ -316,24 +372,62 @@ export async function purgeNursery() {
|
|
|
316
372
|
}
|
|
317
373
|
|
|
318
374
|
export async function updateNursery() {
|
|
375
|
+
ensureDockerRunning();
|
|
319
376
|
const spinner = ora(
|
|
320
|
-
"
|
|
377
|
+
"Checking for latest Crux Garden API image from ghcr.io...",
|
|
321
378
|
).start();
|
|
322
379
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
380
|
+
try {
|
|
381
|
+
// Get the current local image digest before pulling
|
|
382
|
+
const beforeResult = await runCommandAsync(
|
|
383
|
+
"docker images --digests --format '{{.Digest}}' ghcr.io/cruxgarden/api:latest",
|
|
384
|
+
{ silent: true, ignoreError: true }
|
|
385
|
+
);
|
|
386
|
+
const digestBefore = beforeResult?.combined?.trim() || beforeResult?.stdout?.trim() || "";
|
|
326
387
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
388
|
+
// Pull latest images
|
|
389
|
+
spinner.text = "Pulling latest images...";
|
|
390
|
+
await runCommandAsync("docker-compose -f docker-compose.nursery.yml pull", {
|
|
391
|
+
silent: true,
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// Get the image digest after pulling
|
|
395
|
+
const afterResult = await runCommandAsync(
|
|
396
|
+
"docker images --digests --format '{{.Digest}}' ghcr.io/cruxgarden/api:latest",
|
|
397
|
+
{ silent: true, ignoreError: true }
|
|
398
|
+
);
|
|
399
|
+
const digestAfter = afterResult?.combined?.trim() || afterResult?.stdout?.trim() || "";
|
|
400
|
+
|
|
401
|
+
// Compare digests to see if image was updated
|
|
402
|
+
if (digestBefore && digestAfter && digestBefore === digestAfter) {
|
|
403
|
+
spinner.succeed("Nursery image is already up-to-date!");
|
|
404
|
+
console.log(
|
|
405
|
+
chalk.gray("\nYou're running the latest version."),
|
|
406
|
+
);
|
|
407
|
+
} else if (digestAfter) {
|
|
408
|
+
spinner.succeed("Latest nursery image downloaded!");
|
|
409
|
+
console.log(
|
|
410
|
+
chalk.gray("\nRun"),
|
|
411
|
+
chalk.cyan("crux nursery restart"),
|
|
412
|
+
chalk.gray("to use the new image."),
|
|
413
|
+
);
|
|
414
|
+
} else {
|
|
415
|
+
spinner.succeed("Images pulled successfully!");
|
|
416
|
+
console.log(
|
|
417
|
+
chalk.gray("\nRun"),
|
|
418
|
+
chalk.cyan("crux nursery restart"),
|
|
419
|
+
chalk.gray("to use the latest images."),
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
} catch (error) {
|
|
423
|
+
spinner.fail("Failed to update images");
|
|
424
|
+
throw error;
|
|
425
|
+
}
|
|
333
426
|
console.log();
|
|
334
427
|
}
|
|
335
428
|
|
|
336
429
|
export async function resetNursery() {
|
|
430
|
+
ensureDockerRunning();
|
|
337
431
|
console.log(
|
|
338
432
|
chalk.yellow(
|
|
339
433
|
"\n⚠️ This will delete all nursery data and start fresh with the latest image!\n",
|
|
@@ -371,9 +465,18 @@ export async function resetNursery() {
|
|
|
371
465
|
// Start fresh
|
|
372
466
|
spinner.text = "Starting fresh nursery environment...";
|
|
373
467
|
await runCommandAsync(
|
|
374
|
-
"docker-compose -f docker-compose.nursery.yml up -d --remove-orphans
|
|
468
|
+
"docker-compose -f docker-compose.nursery.yml up -d --remove-orphans",
|
|
469
|
+
{
|
|
470
|
+
silent: true,
|
|
471
|
+
},
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
// Clean up the migrations container if it exists (cross-platform)
|
|
475
|
+
await runCommandAsync(
|
|
476
|
+
"docker rm cruxgarden-nursery-migrations",
|
|
375
477
|
{
|
|
376
478
|
silent: true,
|
|
479
|
+
ignoreError: true,
|
|
377
480
|
},
|
|
378
481
|
);
|
|
379
482
|
|
|
@@ -406,12 +509,14 @@ export async function restartNursery() {
|
|
|
406
509
|
}
|
|
407
510
|
|
|
408
511
|
export async function statusNursery() {
|
|
512
|
+
ensureDockerRunning();
|
|
409
513
|
console.log(chalk.bold("\nCrux Garden Nursery Environment Status:\n"));
|
|
410
514
|
runCommand("docker-compose -f docker-compose.nursery.yml ps");
|
|
411
515
|
console.log();
|
|
412
516
|
}
|
|
413
517
|
|
|
414
518
|
export async function connectNurseryDb() {
|
|
519
|
+
ensureDockerRunning();
|
|
415
520
|
console.log(chalk.gray("Connecting to Nursery PostgreSQL...\n"));
|
|
416
521
|
runCommand(
|
|
417
522
|
"docker exec -it cruxgarden-nursery-postgres psql -U cruxgarden -d cruxgarden",
|
|
@@ -419,16 +524,19 @@ export async function connectNurseryDb() {
|
|
|
419
524
|
}
|
|
420
525
|
|
|
421
526
|
export async function connectNurseryRedis() {
|
|
527
|
+
ensureDockerRunning();
|
|
422
528
|
console.log(chalk.gray("Connecting to Nursery Redis...\n"));
|
|
423
529
|
runCommand("docker exec -it cruxgarden-nursery-redis redis-cli");
|
|
424
530
|
}
|
|
425
531
|
|
|
426
532
|
export async function connectNurseryApi() {
|
|
533
|
+
ensureDockerRunning();
|
|
427
534
|
console.log(chalk.gray("Opening shell in Nursery API container...\n"));
|
|
428
535
|
runCommand("docker exec -it cruxgarden-nursery-api sh");
|
|
429
536
|
}
|
|
430
537
|
|
|
431
538
|
export async function stopNurseryDb() {
|
|
539
|
+
ensureDockerRunning();
|
|
432
540
|
const spinner = ora("Stopping nursery database services...").start();
|
|
433
541
|
await runCommandAsync(
|
|
434
542
|
"docker-compose -f docker-compose.nursery.yml stop postgres redis",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cruxgarden/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Crux Garden CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
"docker:nursery:db:stop": "cd docker && docker-compose -f docker-compose.nursery.yml stop postgres redis",
|
|
20
20
|
"docker:nursery:redis:connect": "docker exec -it cruxgarden-nursery-redis redis-cli",
|
|
21
21
|
"docker:nursery:db:connect": "docker exec -it cruxgarden-nursery-postgres psql -U cruxgarden -d cruxgarden",
|
|
22
|
-
"docker:nursery:api:connect": "docker exec -it cruxgarden-nursery-api sh"
|
|
22
|
+
"docker:nursery:api:connect": "docker exec -it cruxgarden-nursery-api sh",
|
|
23
|
+
"publish:patch": "npm version patch && npm publish && git push && git push --tags",
|
|
24
|
+
"publish:minor": "npm version minor && npm publish && git push && git push --tags",
|
|
25
|
+
"publish:major": "npm version major && npm publish && git push && git push --tags"
|
|
23
26
|
},
|
|
24
27
|
"engines": {
|
|
25
28
|
"node": ">=18.0.0"
|