create-rigg 0.0.7 → 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.
Files changed (3) hide show
  1. package/README.md +3 -3
  2. package/dist/index.mjs +86 -45
  3. package/package.json +15 -14
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  **Create Node.js projects with a Unified Toolchain**
9
9
 
10
- rigg sets up a Node.js TypeScript project with the same opinionated toolchain as [Vite+](https://github.com/voidzero-dev/vite-plus), just without the web parts. Use it for backend projects, CLIs, libraries, scripts. Whatever you're building.
10
+ rigg sets up a new Node.js TypeScript project with the same opinionated toolchain as [Vite+](https://github.com/voidzero-dev/vite-plus), just without the web parts. Use it for backend projects, CLIs, libraries, scripts. Whatever you're building.
11
11
 
12
12
  ## Create a new project with rigg
13
13
 
@@ -18,15 +18,15 @@ npm create rigg@latest
18
18
 
19
19
  ## What you get
20
20
 
21
- A project created with rigg gets most of the same tools from the Vite+ toolchain.
21
+ A project created with rigg gets most of the same tools as the Vite+ toolchain.
22
22
 
23
23
  | Tool | Role |
24
24
  | -------------------------------------------------- | ------------------ |
25
25
  | [Vitest](https://vitest.dev) | Testing |
26
26
  | [Oxlint](https://oxc.rs/docs/guide/usage/linter) | Linting |
27
27
  | [Oxfmt](https://oxc.rs/docs/guide/usage/formatter) | Formatting |
28
- | [tsx](https://tsx.is) | Dev-mode execution |
29
28
  | [tsdown](https://tsdown.dev) | Build |
29
+ | [tsx](https://tsx.is) | Dev-mode execution |
30
30
 
31
31
  ### Backend framework
32
32
 
package/dist/index.mjs CHANGED
@@ -15,7 +15,7 @@ const FRAMEWORKS = [
15
15
  {
16
16
  value: "hono",
17
17
  label: "Hono",
18
- hint: "recommended"
18
+ hint: "recommended framework"
19
19
  },
20
20
  {
21
21
  value: "fastify",
@@ -50,6 +50,7 @@ const FRAMEWORK_DEPS = {
50
50
  devDeps: ["@types/express"]
51
51
  }
52
52
  };
53
+ /** Starter code (index.ts) for each framework. */
53
54
  const FRAMEWORK_INDEX = {
54
55
  none: `console.log('Hello from rigg!')\n`,
55
56
  hono: `import { Hono } from 'hono'
@@ -65,22 +66,36 @@ serve(app, (info) => {
65
66
  `,
66
67
  fastify: `import Fastify from 'fastify'
67
68
 
68
- const fastify = Fastify({ logger: true })
69
+ const fastify = Fastify({
70
+ logger: true,
71
+ })
72
+
73
+ fastify.get('/', async (request, reply) => {
74
+ return { hello: 'world' }
75
+ })
69
76
 
70
- fastify.get('/', async () => ({ hello: 'world' }))
77
+ const start = async () => {
78
+ try {
79
+ await fastify.listen({ port: 3000 })
80
+ } catch (err) {
81
+ fastify.log.error(err)
82
+ process.exit(1)
83
+ }
84
+ }
71
85
 
72
- fastify.listen({ port: 3000 })
86
+ start()
73
87
  `,
74
88
  express: `import express from 'express'
75
89
 
76
90
  const app = express()
91
+ const port = 3000
77
92
 
78
93
  app.get('/', (req, res) => {
79
94
  res.send('Hello World')
80
95
  })
81
96
 
82
- app.listen(3000, () => {
83
- console.log('Server running on http://localhost:3000')
97
+ app.listen(port, () => {
98
+ console.log(\`Server running on http://localhost:\${port}\`)
84
99
  })
85
100
  `
86
101
  };
@@ -127,17 +142,22 @@ function addArgs(pkgManager, packages, dev) {
127
142
  ...packages
128
143
  ] : [cmd, ...packages];
129
144
  }
130
- /** Runs a command synchronously, exiting the process if it fails. */
145
+ /** Runs a command asynchronously, exiting the process if it fails. */
131
146
  function run(cmd, args, opts) {
132
- const result = spawn.sync(cmd, args, {
133
- stdio: "ignore",
134
- ...opts
147
+ return new Promise((resolve, reject) => {
148
+ const result = spawn(cmd, args, {
149
+ stdio: "ignore",
150
+ ...opts
151
+ });
152
+ result.on("error", reject);
153
+ result.on("close", (code) => {
154
+ if (code !== 0) {
155
+ p.cancel(`${cmd} ${args.join(" ")} failed with exit code ${code}`);
156
+ process.exit(code ?? 1);
157
+ }
158
+ resolve();
159
+ });
135
160
  });
136
- if (result.error) throw result.error;
137
- if (result.status != null && result.status !== 0) {
138
- p.cancel(`${cmd} ${args.join(" ")} failed with exit code ${result.status}`);
139
- process.exit(result.status);
140
- }
141
161
  }
142
162
  /** Recursively copies a directory, renaming _gitignore to .gitignore. */
143
163
  function copyDir(src, dest) {
@@ -194,27 +214,36 @@ async function confirmOverwrite(projectName, targetDir) {
194
214
  p.cancel("Cancelled");
195
215
  process.exit(0);
196
216
  }
197
- fs.rmSync(targetDir, {
217
+ const spin = p.spinner();
218
+ spin.start("Removing existing files...");
219
+ await fs.promises.rm(targetDir, {
198
220
  recursive: true,
199
221
  force: true
200
222
  });
223
+ spin.stop("Removed existing files");
201
224
  }
202
225
  /** Copies the base template, sets the package name, and writes the framework starter code. */
203
- function scaffoldFiles(options, targetDir) {
226
+ async function scaffoldFiles(options, targetDir) {
227
+ const spin = p.spinner();
228
+ spin.start("Generating project...");
229
+ /** Copy the base template to the target directory. */
204
230
  const directory = path.dirname(fileURLToPath(import.meta.url));
205
231
  copyDir(path.join(directory, "..", "template"), targetDir);
232
+ /** Set the package name in the package.json file. */
206
233
  const pkgJsonPath = path.join(targetDir, "package.json");
207
234
  const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
208
235
  pkg.name = options.projectName;
209
236
  fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2) + "\n");
237
+ /** Create the src directory and write the framework starter code. */
210
238
  fs.mkdirSync(path.join(targetDir, "src"), { recursive: true });
211
239
  fs.writeFileSync(path.join(targetDir, "src", "index.ts"), FRAMEWORK_INDEX[options.framework]);
240
+ spin.stop("Project generated");
212
241
  }
213
242
  /** Installs shared dev dependencies and any framework-specific packages. */
214
- function installDependencies(options, targetDir) {
243
+ async function installDependencies(options, targetDir) {
215
244
  const { pkgManager, framework, verbose } = options;
216
245
  const stdio = verbose ? "inherit" : "ignore";
217
- p.log.step(`Installing dependencies with ${gradient(pkgManager, [[
246
+ const gradientStops = [[
218
247
  168,
219
248
  85,
220
249
  247
@@ -222,8 +251,10 @@ function installDependencies(options, targetDir) {
222
251
  99,
223
252
  102,
224
253
  241
225
- ]])}...`);
226
- run(pkgManager, addArgs(pkgManager, [
254
+ ]];
255
+ const depSpin = p.spinner();
256
+ depSpin.start(`Installing dependencies with ${gradient(pkgManager, gradientStops)}...`);
257
+ await run(pkgManager, addArgs(pkgManager, [
227
258
  "@types/node",
228
259
  "oxfmt",
229
260
  "oxlint",
@@ -235,25 +266,21 @@ function installDependencies(options, targetDir) {
235
266
  cwd: targetDir,
236
267
  stdio
237
268
  });
269
+ depSpin.stop(`Dependencies installed with ${gradient(pkgManager, gradientStops)}`);
238
270
  if (framework !== "none") {
239
- p.log.step(`Installing ${gradient(FRAMEWORK_LABELS[framework], [[
240
- 168,
241
- 85,
242
- 247
243
- ], [
244
- 99,
245
- 102,
246
- 241
247
- ]])}...`);
271
+ const frameworkName = FRAMEWORK_LABELS[framework];
272
+ const frameworkSpin = p.spinner();
273
+ frameworkSpin.start(`Installing ${gradient(frameworkName, gradientStops)}...`);
248
274
  const { deps, devDeps } = FRAMEWORK_DEPS[framework];
249
- if (deps.length > 0) run(pkgManager, addArgs(pkgManager, deps, false), {
275
+ if (deps.length > 0) await run(pkgManager, addArgs(pkgManager, deps, false), {
250
276
  cwd: targetDir,
251
277
  stdio
252
278
  });
253
- if (devDeps.length > 0) run(pkgManager, addArgs(pkgManager, devDeps, true), {
279
+ if (devDeps.length > 0) await run(pkgManager, addArgs(pkgManager, devDeps, true), {
254
280
  cwd: targetDir,
255
281
  stdio
256
282
  });
283
+ frameworkSpin.stop(`${gradient(frameworkName, gradientStops)} installed`);
257
284
  }
258
285
  }
259
286
  /** Prints the gradient intro. */
@@ -292,7 +319,9 @@ function showOutro(options) {
292
319
  const devCmd = pkgManager === "npm" ? "npm run dev" : `${pkgManager} dev`;
293
320
  p.outro(`${title}\n\n ${pc.dim("Now run:")}\n cd ${projectName}\n ${devCmd}`);
294
321
  }
295
- /** Takes the CLI args and resolves all inputs into a single options object. */
322
+ /**
323
+ * Resolves options either from CLI args or user prompts.
324
+ */
296
325
  async function resolveOptions(argv) {
297
326
  const projectName = await resolveProjectName(argv._[0]);
298
327
  await confirmOverwrite(projectName, path.resolve(process.cwd(), projectName));
@@ -303,9 +332,15 @@ async function resolveOptions(argv) {
303
332
  verbose: argv.verbose ?? false
304
333
  };
305
334
  }
306
- function initializeGit(options, targetDir) {
307
- p.log.step("Initializing git repository");
308
- run("git", [
335
+ async function initializeGit(options, targetDir) {
336
+ const git = spawn.sync("git", ["--version"], { stdio: "ignore" });
337
+ if (git.error || git.status !== 0) {
338
+ p.log.info("Git not found. Skipping repository initialization.");
339
+ return;
340
+ }
341
+ const spin = p.spinner();
342
+ spin.start("Initializing git repository...");
343
+ await run("git", [
309
344
  "init",
310
345
  "-b",
311
346
  "main"
@@ -313,14 +348,19 @@ function initializeGit(options, targetDir) {
313
348
  cwd: targetDir,
314
349
  stdio: options.verbose ? "inherit" : "ignore"
315
350
  });
351
+ spin.stop("Git repository initialized");
316
352
  }
317
- function formatCode(options, targetDir) {
318
- p.log.step("Formatting code");
353
+ /**
354
+ * Creates oxlint+oxfmt configuration files and formats the code.
355
+ */
356
+ async function formatCode(options, targetDir) {
319
357
  const { pkgManager, verbose } = options;
320
358
  const stdio = verbose ? "inherit" : "ignore";
321
359
  const execCmd = pkgManager === "bun" ? "x" : "exec";
322
360
  const sep = pkgManager === "npm" || pkgManager === "yarn" ? ["--"] : [];
323
- run(pkgManager, [
361
+ const spin = p.spinner();
362
+ spin.start("Formatting code...");
363
+ await run(pkgManager, [
324
364
  execCmd,
325
365
  "oxlint",
326
366
  ...sep,
@@ -329,7 +369,7 @@ function formatCode(options, targetDir) {
329
369
  cwd: targetDir,
330
370
  stdio
331
371
  });
332
- run(pkgManager, [
372
+ await run(pkgManager, [
333
373
  execCmd,
334
374
  "oxfmt",
335
375
  ...sep,
@@ -338,7 +378,7 @@ function formatCode(options, targetDir) {
338
378
  cwd: targetDir,
339
379
  stdio
340
380
  });
341
- run(pkgManager, [
381
+ await run(pkgManager, [
342
382
  execCmd,
343
383
  "oxfmt",
344
384
  ...sep,
@@ -347,6 +387,7 @@ function formatCode(options, targetDir) {
347
387
  cwd: targetDir,
348
388
  stdio
349
389
  });
390
+ spin.stop("Code formatted");
350
391
  }
351
392
  async function main() {
352
393
  const argv = mri(process.argv.slice(2), {
@@ -360,10 +401,10 @@ async function main() {
360
401
  showIntro();
361
402
  const options = await resolveOptions(argv);
362
403
  const targetDir = path.resolve(process.cwd(), options.projectName);
363
- scaffoldFiles(options, targetDir);
364
- initializeGit(options, targetDir);
365
- installDependencies(options, targetDir);
366
- formatCode(options, targetDir);
404
+ await scaffoldFiles(options, targetDir);
405
+ await initializeGit(options, targetDir);
406
+ await installDependencies(options, targetDir);
407
+ await formatCode(options, targetDir);
367
408
  showOutro(options);
368
409
  }
369
410
  main().catch((err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-rigg",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "Create Node.js TypeScript projects with a Unified Toolchain",
5
5
  "keywords": [
6
6
  "backend",
@@ -38,17 +38,6 @@
38
38
  "template"
39
39
  ],
40
40
  "type": "module",
41
- "scripts": {
42
- "test": "vitest",
43
- "lint": "oxlint",
44
- "lint:fix": "oxlint --fix",
45
- "fmt": "oxfmt",
46
- "fmt:check": "oxfmt --check",
47
- "check": "oxlint && oxfmt --check && tsc --noEmit",
48
- "dev": "tsx src/index.ts",
49
- "build": "tsdown src/index.ts",
50
- "prepublishOnly": "git diff --exit-code && git diff --cached --exit-code && oxlint && oxfmt && tsc --noEmit && vitest run && pnpm build"
51
- },
52
41
  "dependencies": {
53
42
  "@clack/prompts": "^1.1.0",
54
43
  "cross-spawn": "^7.0.6",
@@ -65,5 +54,17 @@
65
54
  "typescript": "^6.0.2",
66
55
  "vitest": "^4.1.2"
67
56
  },
68
- "packageManager": "pnpm@10.30.3"
69
- }
57
+ "engines": {
58
+ "node": ">=22.12.0"
59
+ },
60
+ "scripts": {
61
+ "test": "vitest",
62
+ "lint": "oxlint",
63
+ "lint:fix": "oxlint --fix",
64
+ "fmt": "oxfmt",
65
+ "fmt:check": "oxfmt --check",
66
+ "check": "oxlint && oxfmt --check && tsc --noEmit",
67
+ "dev": "tsx src/index.ts",
68
+ "build": "tsdown src/index.ts"
69
+ }
70
+ }