@techstream/quark-create-app 1.7.0 → 1.8.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 CHANGED
@@ -42,6 +42,67 @@ Aliases:
42
42
  - `create-quark-app`
43
43
  - `quark-update`
44
44
 
45
+ ## Usage with Flags
46
+
47
+ The CLI supports non-interactive mode with custom options for automation and CI/CD workflows.
48
+
49
+ ### Non-Interactive Mode
50
+
51
+ Skip all interactive prompts and use defaults:
52
+
53
+ ```bash
54
+ # Create project without prompts
55
+ npx @techstream/quark-create-app my-app --no-prompts
56
+ ```
57
+
58
+ ### Custom Features
59
+
60
+ Specify which optional packages to include (default: `ui,jobs`):
61
+
62
+ ```bash
63
+ # Only include UI package
64
+ npx @techstream/quark-create-app my-app --no-prompts --features ui
65
+
66
+ # Include both UI and Jobs
67
+ npx @techstream/quark-create-app my-app --no-prompts --features ui,jobs
68
+
69
+ # Minimal setup (no optional packages)
70
+ npx @techstream/quark-create-app my-app --no-prompts --features ""
71
+ ```
72
+
73
+ ### Skip Installation Steps
74
+
75
+ Create the project structure without running package installation:
76
+
77
+ ```bash
78
+ # Create project but skip pnpm install
79
+ npx @techstream/quark-create-app my-app --no-prompts --skip-install
80
+
81
+ # Useful for CI/CD where you'll install dependencies separately
82
+ ```
83
+
84
+ ### Docker Cleanup
85
+
86
+ Control whether to remove Docker volumes from previous cleanup:
87
+
88
+ ```bash
89
+ # Keep Docker working directories (useful in CI/CD)
90
+ npx @techstream/quark-create-app my-app --no-prompts --skip-docker
91
+ ```
92
+
93
+ ### Complete Example: Full Automation
94
+
95
+ ```bash
96
+ # Create, install, and setup everything automatically
97
+ npx @techstream/quark-create-app my-app \
98
+ --no-prompts \
99
+ --features ui,jobs \
100
+ && cd my-app \
101
+ && docker compose up -d \
102
+ && pnpm db:migrate \
103
+ && pnpm dev
104
+ ```
105
+
45
106
  ## Common Tasks
46
107
 
47
108
  - **Update Quark packages**: `quark-update` or `pnpm update @techstream/quark-*`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techstream/quark-create-app",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "quark-create-app": "src/index.js",
@@ -33,7 +33,10 @@
33
33
  "test": "node test-cli.js",
34
34
  "test:build": "node test-build.js",
35
35
  "test:e2e": "node test-e2e.js",
36
+ "test:e2e:full": "node test-e2e-full.js",
36
37
  "test:integration": "node test-integration.js",
37
- "test:all": "node test-all.js"
38
+ "test:flags": "node --test test-flags.js",
39
+ "test:all": "node test-all.js",
40
+ "check:perf": "node scripts/check-e2e-perf.js"
38
41
  }
39
42
  }
package/src/index.js CHANGED
@@ -254,7 +254,15 @@ function validateProjectName(name) {
254
254
 
255
255
  program
256
256
  .argument("<project-name>", "Name of the project to create")
257
- .action(async (projectName) => {
257
+ .option(
258
+ "--no-prompts",
259
+ "Skip interactive prompts and use default/provided values",
260
+ )
261
+ .option(
262
+ "--features <features>",
263
+ "Comma-separated list of optional features to include (ui,jobs)",
264
+ )
265
+ .action(async (projectName, options) => {
258
266
  console.log(
259
267
  chalk.blue.bold(
260
268
  `\n\uD83D\uDE80 Creating your new Quark project: ${projectName}\n`,
@@ -314,16 +322,25 @@ program
314
322
 
315
323
  // Check if directory already exists
316
324
  if (await fs.pathExists(targetDir)) {
317
- const { overwrite } = await prompts({
318
- type: "confirm",
319
- name: "overwrite",
320
- message: `Directory "${projectName}" already exists. Remove it and recreate?`,
321
- initial: false,
322
- });
325
+ if (!options.prompts) {
326
+ // In non-interactive mode, automatically remove existing directory
327
+ console.log(
328
+ chalk.yellow(
329
+ ` Directory "${projectName}" already exists. Removing... (non-interactive mode)`,
330
+ ),
331
+ );
332
+ } else {
333
+ const { overwrite } = await prompts({
334
+ type: "confirm",
335
+ name: "overwrite",
336
+ message: `Directory "${projectName}" already exists. Remove it and recreate?`,
337
+ initial: false,
338
+ });
323
339
 
324
- if (!overwrite) {
325
- console.log(chalk.yellow("Aborted."));
326
- process.exit(1);
340
+ if (!overwrite) {
341
+ console.log(chalk.yellow("Aborted."));
342
+ process.exit(1);
343
+ }
327
344
  }
328
345
 
329
346
  // Stop any running Docker containers for this project
@@ -379,35 +396,72 @@ program
379
396
  }
380
397
 
381
398
  // Step 5: Ask which optional features to eject
382
- console.log(chalk.cyan("\n 🎯 Configuring optional features...\n"));
383
- const response = await prompts([
384
- {
385
- type: "multiselect",
386
- name: "features",
387
- message: "Which optional packages would you like to include?",
388
- instructions: false,
389
- choices: [
390
- {
391
- title: "UI Components (packages/ui)",
392
- value: "ui",
393
- selected: true,
394
- },
395
- {
396
- title: "Job Definitions (packages/jobs)",
397
- value: "jobs",
398
- selected: true,
399
- },
400
- ],
401
- },
402
- ]);
399
+ let features;
400
+ if (!options.prompts && options.features) {
401
+ // Parse features from CLI flag
402
+ console.log(chalk.cyan("\n 🎯 Configuring optional features..."));
403
+ const validFeatures = ["ui", "jobs"];
404
+ features = options.features
405
+ .split(",")
406
+ .map((f) => f.trim())
407
+ .filter((f) => f.length > 0);
408
+
409
+ // Validate features
410
+ const invalidFeatures = features.filter(
411
+ (f) => !validFeatures.includes(f),
412
+ );
413
+ if (invalidFeatures.length > 0) {
414
+ throw new Error(
415
+ `Invalid features: ${invalidFeatures.join(", ")}. Valid options are: ${validFeatures.join(", ")}`,
416
+ );
417
+ }
418
+
419
+ console.log(
420
+ chalk.green(
421
+ ` Selected features: ${features.join(", ") || "none"} (non-interactive mode)`,
422
+ ),
423
+ );
424
+ } else if (!options.prompts) {
425
+ // Use defaults when --no-prompts is set without --features
426
+ console.log(chalk.cyan("\n 🎯 Configuring optional features..."));
427
+ features = ["ui", "jobs"]; // Default to both
428
+ console.log(
429
+ chalk.green(
430
+ ` Using default features: ${features.join(", ")} (non-interactive mode)`,
431
+ ),
432
+ );
433
+ } else {
434
+ // Interactive prompt
435
+ console.log(chalk.cyan("\n 🎯 Configuring optional features...\n"));
436
+ const response = await prompts([
437
+ {
438
+ type: "multiselect",
439
+ name: "features",
440
+ message: "Which optional packages would you like to include?",
441
+ instructions: false,
442
+ choices: [
443
+ {
444
+ title: "UI Components (packages/ui)",
445
+ value: "ui",
446
+ selected: true,
447
+ },
448
+ {
449
+ title: "Job Definitions (packages/jobs)",
450
+ value: "jobs",
451
+ selected: true,
452
+ },
453
+ ],
454
+ },
455
+ ]);
403
456
 
404
- const { features } = response;
457
+ features = response.features;
405
458
 
406
- // Handle prompt cancellation (Ctrl+C)
407
- if (!features) {
408
- console.log(chalk.yellow("\n\u26A0\uFE0F Setup cancelled."));
409
- await fs.remove(targetDir);
410
- process.exit(0);
459
+ // Handle prompt cancellation (Ctrl+C)
460
+ if (!features) {
461
+ console.log(chalk.yellow("\n\u26A0\uFE0F Setup cancelled."));
462
+ await fs.remove(targetDir);
463
+ process.exit(0);
464
+ }
411
465
  }
412
466
 
413
467
  // Step 6: Copy selected optional packages
@@ -6,6 +6,7 @@
6
6
  "watchPatterns": ["apps/web/**", "packages/**"]
7
7
  },
8
8
  "deploy": {
9
+ "releaseCommand": "pnpm --filter @techstream/quark-db exec prisma migrate deploy",
9
10
  "startCommand": "node apps/web/.next/standalone/server.js",
10
11
  "healthcheckPath": "/api/health",
11
12
  "healthcheckTimeout": 30,