create-blitzpack 0.1.1 → 0.1.4
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 +52 -0
- package/dist/index.js +59 -19
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# create-blitzpack
|
|
2
|
+
|
|
3
|
+
CLI tool to scaffold a new Blitzpack project - full-stack TypeScript monorepo with Next.js and Fastify.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm create blitzpack
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Options
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm create blitzpack [project-name] [options]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- `[project-name]` - Name of the project (prompted if not provided)
|
|
18
|
+
- `--skip-git` - Skip git initialization
|
|
19
|
+
- `--skip-install` - Skip dependency installation
|
|
20
|
+
- `--dry-run` - Preview changes without creating files
|
|
21
|
+
|
|
22
|
+
## What You Get
|
|
23
|
+
|
|
24
|
+
- **Web**: Next.js 16 + React 19 + Tailwind CSS v4 + shadcn/ui
|
|
25
|
+
- **API**: Fastify 5 + Prisma 7 + PostgreSQL + Better Auth
|
|
26
|
+
- **Monorepo**: Turborepo + pnpm workspaces
|
|
27
|
+
- **Production-ready**: Auth, admin dashboard, logging, validation, testing, Docker
|
|
28
|
+
|
|
29
|
+
## Requirements
|
|
30
|
+
|
|
31
|
+
- Node.js ≥20.0.0
|
|
32
|
+
- pnpm ≥9.0.0
|
|
33
|
+
- Docker (for PostgreSQL)
|
|
34
|
+
|
|
35
|
+
## Next Steps
|
|
36
|
+
|
|
37
|
+
After scaffolding:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cd your-project
|
|
41
|
+
docker compose up -d # Start PostgreSQL
|
|
42
|
+
pnpm db:migrate # Run migrations
|
|
43
|
+
pnpm dev # Start development
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Documentation
|
|
47
|
+
|
|
48
|
+
Full documentation: [github.com/CarboxyDev/blitzpack](https://github.com/CarboxyDev/blitzpack)
|
|
49
|
+
|
|
50
|
+
## License
|
|
51
|
+
|
|
52
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
+
import { readFileSync } from "fs";
|
|
6
|
+
import { dirname, join } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
5
8
|
|
|
6
9
|
// src/commands/create.ts
|
|
7
10
|
import chalk2 from "chalk";
|
|
8
11
|
import { spawn } from "child_process";
|
|
9
12
|
import fs3 from "fs-extra";
|
|
10
13
|
import ora from "ora";
|
|
11
|
-
import
|
|
14
|
+
import path4 from "path";
|
|
15
|
+
import prompts2 from "prompts";
|
|
12
16
|
|
|
13
17
|
// src/git.ts
|
|
14
18
|
import { execSync } from "child_process";
|
|
@@ -49,11 +53,18 @@ var DEFAULT_DESCRIPTION = "A full-stack TypeScript monorepo built with Blitzpack
|
|
|
49
53
|
|
|
50
54
|
// src/utils.ts
|
|
51
55
|
import chalk from "chalk";
|
|
56
|
+
import path from "path";
|
|
52
57
|
import validatePackageName from "validate-npm-package-name";
|
|
58
|
+
function getCurrentDirName() {
|
|
59
|
+
return path.basename(process.cwd());
|
|
60
|
+
}
|
|
53
61
|
function toSlug(name) {
|
|
54
62
|
return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
55
63
|
}
|
|
56
64
|
function validateProjectName(name) {
|
|
65
|
+
if (name === ".") {
|
|
66
|
+
return { valid: true };
|
|
67
|
+
}
|
|
57
68
|
const result = validatePackageName(name);
|
|
58
69
|
if (result.validForNewPackages) {
|
|
59
70
|
return { valid: true };
|
|
@@ -73,19 +84,25 @@ function printSuccess(projectName, targetDir) {
|
|
|
73
84
|
console.log();
|
|
74
85
|
console.log(chalk.bold(" Next steps:"));
|
|
75
86
|
console.log();
|
|
76
|
-
|
|
87
|
+
let stepNumber = 1;
|
|
88
|
+
if (targetDir !== ".") {
|
|
89
|
+
console.log(chalk.cyan(` ${stepNumber}.`), `cd ${targetDir}`);
|
|
90
|
+
stepNumber++;
|
|
91
|
+
}
|
|
77
92
|
console.log(
|
|
78
|
-
chalk.cyan(
|
|
93
|
+
chalk.cyan(` ${stepNumber}.`),
|
|
79
94
|
"docker compose up -d",
|
|
80
95
|
chalk.dim(" # Start PostgreSQL")
|
|
81
96
|
);
|
|
97
|
+
stepNumber++;
|
|
82
98
|
console.log(
|
|
83
|
-
chalk.cyan(
|
|
99
|
+
chalk.cyan(` ${stepNumber}.`),
|
|
84
100
|
"pnpm db:migrate",
|
|
85
101
|
chalk.dim(" # Run database migrations")
|
|
86
102
|
);
|
|
103
|
+
stepNumber++;
|
|
87
104
|
console.log(
|
|
88
|
-
chalk.cyan(
|
|
105
|
+
chalk.cyan(` ${stepNumber}.`),
|
|
89
106
|
"pnpm dev",
|
|
90
107
|
chalk.dim(" # Start dev servers")
|
|
91
108
|
);
|
|
@@ -144,19 +161,22 @@ async function getProjectOptions(providedName, flags = {}) {
|
|
|
144
161
|
console.log(`Invalid project name: ${validation.problems?.[0]}`);
|
|
145
162
|
return null;
|
|
146
163
|
}
|
|
164
|
+
const useCurrentDir = projectName === ".";
|
|
165
|
+
const actualProjectName = useCurrentDir ? getCurrentDirName() : projectName;
|
|
147
166
|
return {
|
|
148
|
-
projectName,
|
|
149
|
-
projectSlug: toSlug(
|
|
167
|
+
projectName: actualProjectName,
|
|
168
|
+
projectSlug: toSlug(actualProjectName),
|
|
150
169
|
projectDescription: response.projectDescription || DEFAULT_DESCRIPTION,
|
|
151
170
|
skipGit: flags.skipGit || false,
|
|
152
|
-
skipInstall: flags.skipInstall || false
|
|
171
|
+
skipInstall: flags.skipInstall || false,
|
|
172
|
+
useCurrentDir
|
|
153
173
|
};
|
|
154
174
|
}
|
|
155
175
|
|
|
156
176
|
// src/template.ts
|
|
157
177
|
import fs from "fs-extra";
|
|
158
178
|
import { downloadTemplate } from "giget";
|
|
159
|
-
import
|
|
179
|
+
import path2 from "path";
|
|
160
180
|
var GITHUB_REPO = "github:CarboxyDev/blitzpack";
|
|
161
181
|
var POST_DOWNLOAD_EXCLUDES = [
|
|
162
182
|
"create-blitzpack",
|
|
@@ -165,7 +185,7 @@ var POST_DOWNLOAD_EXCLUDES = [
|
|
|
165
185
|
];
|
|
166
186
|
async function cleanupExcludes(targetDir) {
|
|
167
187
|
for (const exclude of POST_DOWNLOAD_EXCLUDES) {
|
|
168
|
-
const fullPath =
|
|
188
|
+
const fullPath = path2.join(targetDir, exclude);
|
|
169
189
|
if (await fs.pathExists(fullPath)) {
|
|
170
190
|
await fs.remove(fullPath);
|
|
171
191
|
}
|
|
@@ -181,7 +201,7 @@ async function downloadAndPrepareTemplate(targetDir) {
|
|
|
181
201
|
|
|
182
202
|
// src/transform.ts
|
|
183
203
|
import fs2 from "fs-extra";
|
|
184
|
-
import
|
|
204
|
+
import path3 from "path";
|
|
185
205
|
function transformPackageJson(content, vars, filePath) {
|
|
186
206
|
const pkg = JSON.parse(content);
|
|
187
207
|
if (filePath === "package.json") {
|
|
@@ -259,7 +279,7 @@ Built with [Blitzpack](https://github.com/CarboxyDev/blitzpack)
|
|
|
259
279
|
}
|
|
260
280
|
async function transformFiles(targetDir, vars) {
|
|
261
281
|
for (const relativePath of REPLACEABLE_FILES) {
|
|
262
|
-
const filePath =
|
|
282
|
+
const filePath = path3.join(targetDir, relativePath);
|
|
263
283
|
if (!await fs2.pathExists(filePath)) {
|
|
264
284
|
continue;
|
|
265
285
|
}
|
|
@@ -289,8 +309,8 @@ var ENV_FILES = [
|
|
|
289
309
|
];
|
|
290
310
|
async function copyEnvFiles(targetDir) {
|
|
291
311
|
for (const { from, to } of ENV_FILES) {
|
|
292
|
-
const source =
|
|
293
|
-
const dest =
|
|
312
|
+
const source = path4.join(targetDir, from);
|
|
313
|
+
const dest = path4.join(targetDir, to);
|
|
294
314
|
if (await fs3.pathExists(source)) {
|
|
295
315
|
await fs3.copy(source, dest);
|
|
296
316
|
}
|
|
@@ -338,7 +358,7 @@ async function create(projectName, flags) {
|
|
|
338
358
|
if (!options) {
|
|
339
359
|
return;
|
|
340
360
|
}
|
|
341
|
-
const targetDir =
|
|
361
|
+
const targetDir = options.useCurrentDir ? process.cwd() : path4.resolve(process.cwd(), options.projectName);
|
|
342
362
|
if (flags.dryRun) {
|
|
343
363
|
printDryRun({
|
|
344
364
|
projectName: options.projectName,
|
|
@@ -353,8 +373,20 @@ async function create(projectName, flags) {
|
|
|
353
373
|
if (await fs3.pathExists(targetDir)) {
|
|
354
374
|
const files = await fs3.readdir(targetDir);
|
|
355
375
|
if (files.length > 0) {
|
|
356
|
-
|
|
357
|
-
|
|
376
|
+
if (options.useCurrentDir) {
|
|
377
|
+
const { confirm } = await prompts2({
|
|
378
|
+
type: "confirm",
|
|
379
|
+
name: "confirm",
|
|
380
|
+
message: `Current directory is not empty. Continue?`,
|
|
381
|
+
initial: false
|
|
382
|
+
});
|
|
383
|
+
if (!confirm) {
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
} else {
|
|
387
|
+
printError(`Directory "${options.projectName}" is not empty`);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
358
390
|
}
|
|
359
391
|
}
|
|
360
392
|
const spinner = ora();
|
|
@@ -390,7 +422,10 @@ async function create(projectName, flags) {
|
|
|
390
422
|
);
|
|
391
423
|
}
|
|
392
424
|
}
|
|
393
|
-
printSuccess(
|
|
425
|
+
printSuccess(
|
|
426
|
+
options.projectName,
|
|
427
|
+
options.useCurrentDir ? "." : options.projectName
|
|
428
|
+
);
|
|
394
429
|
} catch (error) {
|
|
395
430
|
spinner.fail();
|
|
396
431
|
printError(
|
|
@@ -401,8 +436,13 @@ async function create(projectName, flags) {
|
|
|
401
436
|
}
|
|
402
437
|
|
|
403
438
|
// src/index.ts
|
|
439
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
440
|
+
var __dirname = dirname(__filename);
|
|
441
|
+
var packageJson = JSON.parse(
|
|
442
|
+
readFileSync(join(__dirname, "../package.json"), "utf-8")
|
|
443
|
+
);
|
|
404
444
|
var program = new Command();
|
|
405
|
-
program.name("create-blitzpack").description("Create a new Blitzpack project").version(
|
|
445
|
+
program.name("create-blitzpack").description("Create a new Blitzpack project").version(packageJson.version).argument("[project-name]", "Name of the project").option("--skip-git", "Skip git initialization").option("--skip-install", "Skip dependency installation").option("--dry-run", "Show what would be done without making changes").action(
|
|
406
446
|
async (projectName, options) => {
|
|
407
447
|
await create(projectName, options);
|
|
408
448
|
}
|