@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 +61 -0
- package/package.json +5 -2
- package/src/index.js +91 -37
- package/templates/base-project/apps/web/railway.json +1 -0
- package/templates/base-project/apps/worker/README.md +690 -0
- package/templates/base-project/apps/worker/package.json +1 -0
- package/templates/base-project/apps/worker/src/index.js +190 -5
- package/templates/base-project/apps/worker/src/index.test.js +278 -0
- package/templates/base-project/packages/db/package.json +0 -3
- package/templates/base-project/packages/db/prisma/seed.js +119 -0
- package/templates/base-project/packages/db/prisma.config.ts +1 -0
- package/templates/config/src/index.js +1 -1
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.
|
|
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:
|
|
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
|
-
.
|
|
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
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
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
|
-
|
|
457
|
+
features = response.features;
|
|
405
458
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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,
|