@cruxgarden/cli 0.0.14 → 0.0.17
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/.github/banner.jpg +0 -0
- package/README.md +6 -20
- package/bin/crux.js +2 -9
- package/docker/docker-compose.nursery.yml +0 -11
- package/lib/commands.js +9 -73
- package/package.json +1 -1
package/.github/banner.jpg
CHANGED
|
Binary file
|
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ Start the Nursery environment:
|
|
|
78
78
|
crux nursery start
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
The
|
|
81
|
+
The API will be available at `http://localhost:3000` with demo data loaded.
|
|
82
82
|
|
|
83
83
|
View logs:
|
|
84
84
|
|
|
@@ -98,22 +98,21 @@ All commands are scoped under `crux nursery`:
|
|
|
98
98
|
|
|
99
99
|
### `crux nursery start`
|
|
100
100
|
|
|
101
|
-
Start the Nursery environment (
|
|
101
|
+
Start the Nursery environment (API, PostgreSQL, Redis with demo data).
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
104
|
crux nursery start
|
|
105
105
|
|
|
106
106
|
# With inline environment variables
|
|
107
|
-
crux nursery start API_PORT=3001
|
|
107
|
+
crux nursery start API_PORT=3001
|
|
108
108
|
|
|
109
109
|
# With options and environment variables
|
|
110
|
-
crux nursery start --
|
|
110
|
+
crux nursery start --db-only JWT_SECRET=my-secret
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
**Options:**
|
|
114
114
|
|
|
115
115
|
- `--db-only` - Start only database services (PostgreSQL and Redis)
|
|
116
|
-
- `--api-only` - Start only API services (API, PostgreSQL, Redis) without the App
|
|
117
116
|
|
|
118
117
|
**Environment Variables:**
|
|
119
118
|
|
|
@@ -138,7 +137,6 @@ crux nursery restart
|
|
|
138
137
|
**Options:**
|
|
139
138
|
|
|
140
139
|
- `--db-only` - Restart only database services (PostgreSQL and Redis)
|
|
141
|
-
- `--api-only` - Restart only API services (API, PostgreSQL, Redis) without the App
|
|
142
140
|
|
|
143
141
|
### `crux nursery status`
|
|
144
142
|
|
|
@@ -235,14 +233,6 @@ Connect to Nursery Redis with `redis-cli`.
|
|
|
235
233
|
crux nursery redis connect
|
|
236
234
|
```
|
|
237
235
|
|
|
238
|
-
### `crux nursery api start`
|
|
239
|
-
|
|
240
|
-
Start only Nursery API services (API, PostgreSQL, Redis) without the App.
|
|
241
|
-
|
|
242
|
-
```bash
|
|
243
|
-
crux nursery api start
|
|
244
|
-
```
|
|
245
|
-
|
|
246
236
|
### `crux nursery api connect`
|
|
247
237
|
|
|
248
238
|
Open a shell in the Nursery API container.
|
|
@@ -262,7 +252,6 @@ The Nursery is a production-like demo environment that:
|
|
|
262
252
|
|
|
263
253
|
**Services:**
|
|
264
254
|
|
|
265
|
-
- **App**: `http://localhost:8080` - Crux Garden Web Application
|
|
266
255
|
- **API**: `http://localhost:3000` - Crux Garden API (published image with demo data)
|
|
267
256
|
- **PostgreSQL**: `localhost:5432` - Database
|
|
268
257
|
- **Redis**: `localhost:6379` - Cache
|
|
@@ -278,7 +267,6 @@ Create a `.env` file in your working directory:
|
|
|
278
267
|
```bash
|
|
279
268
|
# Port Mappings
|
|
280
269
|
API_PORT=3000 # External API port
|
|
281
|
-
APP_PORT=8080 # External App port
|
|
282
270
|
POSTGRES_PORT=5432 # External PostgreSQL port
|
|
283
271
|
REDIS_PORT=6379 # External Redis port
|
|
284
272
|
|
|
@@ -320,7 +308,7 @@ Pass environment variables directly on the command line:
|
|
|
320
308
|
|
|
321
309
|
```bash
|
|
322
310
|
# Override ports
|
|
323
|
-
crux nursery start API_PORT=3001
|
|
311
|
+
crux nursery start API_PORT=3001
|
|
324
312
|
|
|
325
313
|
# Override database connection
|
|
326
314
|
crux nursery start DATABASE_URL=postgresql://user:pass@external-host:5432/db
|
|
@@ -347,8 +335,7 @@ Use the Nursery environment for demos, trials, or showcasing features:
|
|
|
347
335
|
# First time setup - pulls images and starts with demo data
|
|
348
336
|
crux nursery start
|
|
349
337
|
|
|
350
|
-
#
|
|
351
|
-
# Or access the API directly at http://localhost:3000
|
|
338
|
+
# Access the API at http://localhost:3000
|
|
352
339
|
|
|
353
340
|
# Stop (keeps data for next demo)
|
|
354
341
|
crux nursery stop
|
|
@@ -400,7 +387,6 @@ If you get an error about ports being in use, stop any existing services:
|
|
|
400
387
|
|
|
401
388
|
```bash
|
|
402
389
|
# Check what's using the ports
|
|
403
|
-
lsof -i :8080 # Nursery App
|
|
404
390
|
lsof -i :3000 # Nursery API
|
|
405
391
|
lsof -i :5432 # Nursery PostgreSQL
|
|
406
392
|
lsof -i :6379 # Nursery Redis
|
package/bin/crux.js
CHANGED
|
@@ -38,9 +38,8 @@ const nursery = program
|
|
|
38
38
|
|
|
39
39
|
nursery
|
|
40
40
|
.command("start [env...]")
|
|
41
|
-
.description("Start the Nursery environment (
|
|
41
|
+
.description("Start the Nursery environment (api, postgres, redis)")
|
|
42
42
|
.option("--db-only", "Start only database services (postgres, redis)")
|
|
43
|
-
.option("--api-only", "Start only API services (api, postgres, redis) without app")
|
|
44
43
|
.option("--no-banner", "Hide the startup banner")
|
|
45
44
|
.action((envVars, options) => {
|
|
46
45
|
if (!options.noBanner) showBanner();
|
|
@@ -56,7 +55,6 @@ nursery
|
|
|
56
55
|
.command("restart [env...]")
|
|
57
56
|
.description("Restart the Nursery environment")
|
|
58
57
|
.option("--db-only", "Restart only database services (postgres, redis)")
|
|
59
|
-
.option("--api-only", "Restart only API services (api, postgres, redis) without app")
|
|
60
58
|
.action((envVars, options) => restartNursery(options, envVars));
|
|
61
59
|
|
|
62
60
|
nursery
|
|
@@ -84,7 +82,7 @@ nursery
|
|
|
84
82
|
|
|
85
83
|
nursery
|
|
86
84
|
.command("update")
|
|
87
|
-
.description("Download the latest
|
|
85
|
+
.description("Download the latest images from ghcr.io")
|
|
88
86
|
.action(updateNursery);
|
|
89
87
|
|
|
90
88
|
nursery
|
|
@@ -125,11 +123,6 @@ nurseryRedis
|
|
|
125
123
|
// Nursery API commands
|
|
126
124
|
const nurseryApi = nursery.command("api").description("Manage Nursery API");
|
|
127
125
|
|
|
128
|
-
nurseryApi
|
|
129
|
-
.command("start [env...]")
|
|
130
|
-
.description("Start only Nursery API services (api, postgres, redis) without app")
|
|
131
|
-
.action((envVars) => startNursery({ apiOnly: true }, envVars));
|
|
132
|
-
|
|
133
126
|
nurseryApi
|
|
134
127
|
.command("connect")
|
|
135
128
|
.description("Open a shell in the Nursery API container")
|
|
@@ -109,17 +109,6 @@ services:
|
|
|
109
109
|
retries: 3
|
|
110
110
|
start_period: 40s
|
|
111
111
|
|
|
112
|
-
# Crux Garden App - Web Application
|
|
113
|
-
app:
|
|
114
|
-
image: ghcr.io/cruxgarden/app:latest
|
|
115
|
-
container_name: cruxgarden-nursery-app
|
|
116
|
-
restart: unless-stopped
|
|
117
|
-
depends_on:
|
|
118
|
-
api:
|
|
119
|
-
condition: service_healthy
|
|
120
|
-
ports:
|
|
121
|
-
- "${APP_PORT:-8080}:80"
|
|
122
|
-
|
|
123
112
|
volumes:
|
|
124
113
|
postgres_data_nursery:
|
|
125
114
|
redis_data_nursery:
|
package/lib/commands.js
CHANGED
|
@@ -210,7 +210,6 @@ export async function startNursery(options, envVars) {
|
|
|
210
210
|
const envFileFlag = getEnvFileFlag();
|
|
211
211
|
|
|
212
212
|
// Get actual port values from environment
|
|
213
|
-
const appPort = process.env.APP_PORT || "8080";
|
|
214
213
|
const apiPort = process.env.API_PORT || "3000";
|
|
215
214
|
const postgresPort = process.env.POSTGRES_PORT || "5432";
|
|
216
215
|
const redisPort = process.env.REDIS_PORT || "6379";
|
|
@@ -231,46 +230,9 @@ export async function startNursery(options, envVars) {
|
|
|
231
230
|
chalk.hex(SUCCESS_GREEN)("✓ Redis running on:"),
|
|
232
231
|
`localhost:${redisPort}`,
|
|
233
232
|
);
|
|
234
|
-
} else if (options.apiOnly) {
|
|
235
|
-
spinner.text =
|
|
236
|
-
"Starting nursery API services (api, postgres, redis)...";
|
|
237
|
-
await runCommandAsync(
|
|
238
|
-
`docker-compose ${envFileFlag} -f docker-compose.nursery.yml up -d --remove-orphans postgres redis migrations api`,
|
|
239
|
-
{
|
|
240
|
-
silent: true,
|
|
241
|
-
},
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
// Clean up the migrations container if it exists (cross-platform)
|
|
245
|
-
await runCommandAsync(
|
|
246
|
-
"docker rm cruxgarden-nursery-migrations",
|
|
247
|
-
{
|
|
248
|
-
silent: true,
|
|
249
|
-
ignoreError: true,
|
|
250
|
-
},
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
spinner.succeed("Crux Garden Nursery API services started!");
|
|
254
|
-
console.log(
|
|
255
|
-
chalk.hex(SUCCESS_GREEN)("\n✓ API running on:"),
|
|
256
|
-
`http://localhost:${apiPort}`,
|
|
257
|
-
);
|
|
258
|
-
console.log(
|
|
259
|
-
chalk.hex(SUCCESS_GREEN)("✓ PostgreSQL running on:"),
|
|
260
|
-
`localhost:${postgresPort}`,
|
|
261
|
-
);
|
|
262
|
-
console.log(
|
|
263
|
-
chalk.hex(SUCCESS_GREEN)("✓ Redis running on:"),
|
|
264
|
-
`localhost:${redisPort}`,
|
|
265
|
-
);
|
|
266
|
-
console.log(
|
|
267
|
-
chalk.yellow(
|
|
268
|
-
"\nℹ Nursery includes demo data for trials and showcases",
|
|
269
|
-
),
|
|
270
|
-
);
|
|
271
233
|
} else {
|
|
272
234
|
spinner.text =
|
|
273
|
-
"Starting nursery services (
|
|
235
|
+
"Starting nursery services (api, postgres, redis)...";
|
|
274
236
|
await runCommandAsync(
|
|
275
237
|
`docker-compose ${envFileFlag} -f docker-compose.nursery.yml up -d --remove-orphans`,
|
|
276
238
|
{
|
|
@@ -289,11 +251,7 @@ export async function startNursery(options, envVars) {
|
|
|
289
251
|
|
|
290
252
|
spinner.succeed("Crux Garden Nursery environment started!");
|
|
291
253
|
console.log(
|
|
292
|
-
chalk.hex(SUCCESS_GREEN)("\n✓
|
|
293
|
-
`http://localhost:${appPort}`,
|
|
294
|
-
);
|
|
295
|
-
console.log(
|
|
296
|
-
chalk.hex(SUCCESS_GREEN)("✓ API running on:"),
|
|
254
|
+
chalk.hex(SUCCESS_GREEN)("\n✓ API running on:"),
|
|
297
255
|
`http://localhost:${apiPort}`,
|
|
298
256
|
);
|
|
299
257
|
console.log(
|
|
@@ -474,54 +432,37 @@ export async function updateNursery() {
|
|
|
474
432
|
const envFileFlag = getEnvFileFlag();
|
|
475
433
|
|
|
476
434
|
try {
|
|
477
|
-
// Get the current local image
|
|
435
|
+
// Get the current local image digest before pulling
|
|
478
436
|
const apiBeforeResult = await runCommandAsync(
|
|
479
437
|
"docker images --digests --format '{{.Digest}}' ghcr.io/cruxgarden/api:latest",
|
|
480
438
|
{ silent: true, ignoreError: true }
|
|
481
439
|
);
|
|
482
440
|
const apiDigestBefore = apiBeforeResult?.combined?.trim() || apiBeforeResult?.stdout?.trim() || "";
|
|
483
441
|
|
|
484
|
-
const appBeforeResult = await runCommandAsync(
|
|
485
|
-
"docker images --digests --format '{{.Digest}}' ghcr.io/cruxgarden/app:latest",
|
|
486
|
-
{ silent: true, ignoreError: true }
|
|
487
|
-
);
|
|
488
|
-
const appDigestBefore = appBeforeResult?.combined?.trim() || appBeforeResult?.stdout?.trim() || "";
|
|
489
|
-
|
|
490
442
|
// Pull latest images
|
|
491
443
|
spinner.text = "Pulling latest images...";
|
|
492
444
|
await runCommandAsync(`docker-compose ${envFileFlag} -f docker-compose.nursery.yml pull`, {
|
|
493
445
|
silent: true,
|
|
494
446
|
});
|
|
495
447
|
|
|
496
|
-
// Get the image
|
|
448
|
+
// Get the image digest after pulling
|
|
497
449
|
const apiAfterResult = await runCommandAsync(
|
|
498
450
|
"docker images --digests --format '{{.Digest}}' ghcr.io/cruxgarden/api:latest",
|
|
499
451
|
{ silent: true, ignoreError: true }
|
|
500
452
|
);
|
|
501
453
|
const apiDigestAfter = apiAfterResult?.combined?.trim() || apiAfterResult?.stdout?.trim() || "";
|
|
502
454
|
|
|
503
|
-
|
|
504
|
-
"docker images --digests --format '{{.Digest}}' ghcr.io/cruxgarden/app:latest",
|
|
505
|
-
{ silent: true, ignoreError: true }
|
|
506
|
-
);
|
|
507
|
-
const appDigestAfter = appAfterResult?.combined?.trim() || appAfterResult?.stdout?.trim() || "";
|
|
508
|
-
|
|
509
|
-
// Check which images were updated
|
|
455
|
+
// Check if image was updated
|
|
510
456
|
const apiUpdated = apiDigestBefore && apiDigestAfter && apiDigestBefore !== apiDigestAfter;
|
|
511
|
-
const appUpdated = appDigestBefore && appDigestAfter && appDigestBefore !== appDigestAfter;
|
|
512
457
|
|
|
513
|
-
if (!apiUpdated &&
|
|
458
|
+
if (!apiUpdated && apiDigestAfter) {
|
|
514
459
|
spinner.succeed("Nursery images are already up-to-date!");
|
|
515
460
|
console.log(
|
|
516
461
|
chalk.gray("\nYou're running the latest version."),
|
|
517
462
|
);
|
|
518
463
|
} else {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
if (appUpdated) updatedImages.push("App");
|
|
522
|
-
|
|
523
|
-
if (updatedImages.length > 0) {
|
|
524
|
-
spinner.succeed(`Latest nursery images downloaded! (${updatedImages.join(", ")} updated)`);
|
|
464
|
+
if (apiUpdated) {
|
|
465
|
+
spinner.succeed("Latest nursery images downloaded! (API updated)");
|
|
525
466
|
} else {
|
|
526
467
|
spinner.succeed("Images pulled successfully!");
|
|
527
468
|
}
|
|
@@ -570,7 +511,6 @@ export async function resetNursery(envVars) {
|
|
|
570
511
|
const envFileFlag = getEnvFileFlag();
|
|
571
512
|
|
|
572
513
|
// Get actual port values from environment
|
|
573
|
-
const appPort = process.env.APP_PORT || "8080";
|
|
574
514
|
const apiPort = process.env.API_PORT || "3000";
|
|
575
515
|
const postgresPort = process.env.POSTGRES_PORT || "5432";
|
|
576
516
|
const redisPort = process.env.REDIS_PORT || "6379";
|
|
@@ -612,11 +552,7 @@ export async function resetNursery(envVars) {
|
|
|
612
552
|
|
|
613
553
|
spinner.succeed("Nursery environment reset complete!");
|
|
614
554
|
console.log(
|
|
615
|
-
chalk.hex(SUCCESS_GREEN)("\n✓
|
|
616
|
-
`http://localhost:${appPort}`,
|
|
617
|
-
);
|
|
618
|
-
console.log(
|
|
619
|
-
chalk.hex(SUCCESS_GREEN)("✓ API running on:"),
|
|
555
|
+
chalk.hex(SUCCESS_GREEN)("\n✓ API running on:"),
|
|
620
556
|
`http://localhost:${apiPort}`,
|
|
621
557
|
);
|
|
622
558
|
console.log(
|