create-rigg 0.0.7 → 0.1.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
@@ -5,9 +5,9 @@
5
5
  <a href="https://www.npmjs.com/package/create-rigg"><img src="https://img.shields.io/npm/v/create-rigg.svg" alt="Version"></a>
6
6
  </p>
7
7
 
8
- **Create Node.js projects with a Unified Toolchain**
8
+ **Create Node.js projects with a modern 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
+ I really like what [VoidZero](https://voidzero.dev) and [Vite+](https://github.com/voidzero-dev/vite-plus) are doing for web development. **rigg** brings the same toolchain to every Node.js project outside the browser. Use it for backends, 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 in 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
  };
@@ -94,6 +109,15 @@ const PKG_MANAGERS = [
94
109
  ];
95
110
  //#endregion
96
111
  //#region src/index.ts
112
+ const THEME = [[
113
+ 251,
114
+ 146,
115
+ 60
116
+ ], [
117
+ 236,
118
+ 72,
119
+ 153
120
+ ]];
97
121
  /** Creates a colored gradient text effect */
98
122
  function gradient(text, stops, whiteRange) {
99
123
  const chars = [...text];
@@ -127,17 +151,22 @@ function addArgs(pkgManager, packages, dev) {
127
151
  ...packages
128
152
  ] : [cmd, ...packages];
129
153
  }
130
- /** Runs a command synchronously, exiting the process if it fails. */
154
+ /** Runs a command asynchronously, exiting the process if it fails. */
131
155
  function run(cmd, args, opts) {
132
- const result = spawn.sync(cmd, args, {
133
- stdio: "ignore",
134
- ...opts
156
+ return new Promise((resolve, reject) => {
157
+ const result = spawn(cmd, args, {
158
+ stdio: "ignore",
159
+ ...opts
160
+ });
161
+ result.on("error", reject);
162
+ result.on("close", (code) => {
163
+ if (code !== 0) {
164
+ p.cancel(`${cmd} ${args.join(" ")} failed with exit code ${code}`);
165
+ process.exit(code ?? 1);
166
+ }
167
+ resolve();
168
+ });
135
169
  });
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
170
  }
142
171
  /** Recursively copies a directory, renaming _gitignore to .gitignore. */
143
172
  function copyDir(src, dest) {
@@ -194,36 +223,38 @@ async function confirmOverwrite(projectName, targetDir) {
194
223
  p.cancel("Cancelled");
195
224
  process.exit(0);
196
225
  }
197
- fs.rmSync(targetDir, {
226
+ const spin = p.spinner();
227
+ spin.start("Removing existing files...");
228
+ await fs.promises.rm(targetDir, {
198
229
  recursive: true,
199
230
  force: true
200
231
  });
232
+ spin.stop("Removed existing files");
201
233
  }
202
234
  /** Copies the base template, sets the package name, and writes the framework starter code. */
203
- function scaffoldFiles(options, targetDir) {
235
+ async function scaffoldFiles(options, targetDir) {
236
+ const spin = p.spinner();
237
+ spin.start("Generating project...");
238
+ /** Copy the base template to the target directory. */
204
239
  const directory = path.dirname(fileURLToPath(import.meta.url));
205
240
  copyDir(path.join(directory, "..", "template"), targetDir);
241
+ /** Set the package name in the package.json file. */
206
242
  const pkgJsonPath = path.join(targetDir, "package.json");
207
243
  const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
208
244
  pkg.name = options.projectName;
209
245
  fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2) + "\n");
246
+ /** Create the src directory and write the framework starter code. */
210
247
  fs.mkdirSync(path.join(targetDir, "src"), { recursive: true });
211
248
  fs.writeFileSync(path.join(targetDir, "src", "index.ts"), FRAMEWORK_INDEX[options.framework]);
249
+ spin.stop("Project generated");
212
250
  }
213
251
  /** Installs shared dev dependencies and any framework-specific packages. */
214
- function installDependencies(options, targetDir) {
252
+ async function installDependencies(options, targetDir) {
215
253
  const { pkgManager, framework, verbose } = options;
216
254
  const stdio = verbose ? "inherit" : "ignore";
217
- p.log.step(`Installing dependencies with ${gradient(pkgManager, [[
218
- 168,
219
- 85,
220
- 247
221
- ], [
222
- 99,
223
- 102,
224
- 241
225
- ]])}...`);
226
- run(pkgManager, addArgs(pkgManager, [
255
+ const depSpin = p.spinner();
256
+ depSpin.start(`Installing dependencies with ${gradient(pkgManager, THEME)}...`);
257
+ await run(pkgManager, addArgs(pkgManager, [
227
258
  "@types/node",
228
259
  "oxfmt",
229
260
  "oxlint",
@@ -235,64 +266,42 @@ function installDependencies(options, targetDir) {
235
266
  cwd: targetDir,
236
267
  stdio
237
268
  });
269
+ depSpin.stop(`Dependencies installed with ${gradient(pkgManager, THEME)}`);
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, THEME)}...`);
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, THEME)} installed`);
257
284
  }
258
285
  }
259
286
  /** Prints the gradient intro. */
260
287
  function showIntro() {
261
- p.intro(pc.bold(gradient("rigg - The Unified Toolchain Starter for Node.js", [
262
- [
263
- 255,
264
- 255,
265
- 255
266
- ],
267
- [
268
- 168,
269
- 85,
270
- 247
271
- ],
272
- [
273
- 99,
274
- 102,
275
- 241
276
- ]
277
- ], [0, 6])));
288
+ p.intro(pc.bold(gradient("rigg - Node.js projects with a modern toolchain", [[
289
+ 255,
290
+ 255,
291
+ 255
292
+ ], ...THEME], [0, 6])));
278
293
  }
279
294
  /** Prints the gradient outro with next steps. */
280
295
  function showOutro(options) {
281
296
  const { projectName, framework, pkgManager } = options;
282
297
  const frameworkLabel = FRAMEWORK_LABELS[framework];
283
- const title = gradient(frameworkLabel !== "None" ? `Created ${projectName} with ${frameworkLabel}` : `Created ${projectName}`, [[
284
- 168,
285
- 85,
286
- 247
287
- ], [
288
- 99,
289
- 102,
290
- 241
291
- ]], [8, 8 + projectName.length]);
298
+ const title = gradient(frameworkLabel !== "None" ? `Created ${projectName} with ${frameworkLabel}` : `Created ${projectName}`, THEME, [8, 8 + projectName.length]);
292
299
  const devCmd = pkgManager === "npm" ? "npm run dev" : `${pkgManager} dev`;
293
300
  p.outro(`${title}\n\n ${pc.dim("Now run:")}\n cd ${projectName}\n ${devCmd}`);
294
301
  }
295
- /** Takes the CLI args and resolves all inputs into a single options object. */
302
+ /**
303
+ * Resolves options either from CLI args or user prompts.
304
+ */
296
305
  async function resolveOptions(argv) {
297
306
  const projectName = await resolveProjectName(argv._[0]);
298
307
  await confirmOverwrite(projectName, path.resolve(process.cwd(), projectName));
@@ -303,9 +312,15 @@ async function resolveOptions(argv) {
303
312
  verbose: argv.verbose ?? false
304
313
  };
305
314
  }
306
- function initializeGit(options, targetDir) {
307
- p.log.step("Initializing git repository");
308
- run("git", [
315
+ async function initializeGit(options, targetDir) {
316
+ const git = spawn.sync("git", ["--version"], { stdio: "ignore" });
317
+ if (git.error || git.status !== 0) {
318
+ p.log.info("Git not found. Skipping repository initialization.");
319
+ return;
320
+ }
321
+ const spin = p.spinner();
322
+ spin.start("Initializing git repository...");
323
+ await run("git", [
309
324
  "init",
310
325
  "-b",
311
326
  "main"
@@ -313,14 +328,19 @@ function initializeGit(options, targetDir) {
313
328
  cwd: targetDir,
314
329
  stdio: options.verbose ? "inherit" : "ignore"
315
330
  });
331
+ spin.stop("Git repository initialized");
316
332
  }
317
- function formatCode(options, targetDir) {
318
- p.log.step("Formatting code");
333
+ /**
334
+ * Creates oxlint+oxfmt configuration files and formats the code.
335
+ */
336
+ async function formatCode(options, targetDir) {
319
337
  const { pkgManager, verbose } = options;
320
338
  const stdio = verbose ? "inherit" : "ignore";
321
339
  const execCmd = pkgManager === "bun" ? "x" : "exec";
322
340
  const sep = pkgManager === "npm" || pkgManager === "yarn" ? ["--"] : [];
323
- run(pkgManager, [
341
+ const spin = p.spinner();
342
+ spin.start("Formatting code...");
343
+ await run(pkgManager, [
324
344
  execCmd,
325
345
  "oxlint",
326
346
  ...sep,
@@ -329,7 +349,7 @@ function formatCode(options, targetDir) {
329
349
  cwd: targetDir,
330
350
  stdio
331
351
  });
332
- run(pkgManager, [
352
+ await run(pkgManager, [
333
353
  execCmd,
334
354
  "oxfmt",
335
355
  ...sep,
@@ -338,7 +358,7 @@ function formatCode(options, targetDir) {
338
358
  cwd: targetDir,
339
359
  stdio
340
360
  });
341
- run(pkgManager, [
361
+ await run(pkgManager, [
342
362
  execCmd,
343
363
  "oxfmt",
344
364
  ...sep,
@@ -347,6 +367,7 @@ function formatCode(options, targetDir) {
347
367
  cwd: targetDir,
348
368
  stdio
349
369
  });
370
+ spin.stop("Code formatted");
350
371
  }
351
372
  async function main() {
352
373
  const argv = mri(process.argv.slice(2), {
@@ -360,10 +381,10 @@ async function main() {
360
381
  showIntro();
361
382
  const options = await resolveOptions(argv);
362
383
  const targetDir = path.resolve(process.cwd(), options.projectName);
363
- scaffoldFiles(options, targetDir);
364
- initializeGit(options, targetDir);
365
- installDependencies(options, targetDir);
366
- formatCode(options, targetDir);
384
+ await scaffoldFiles(options, targetDir);
385
+ await initializeGit(options, targetDir);
386
+ await installDependencies(options, targetDir);
387
+ await formatCode(options, targetDir);
367
388
  showOutro(options);
368
389
  }
369
390
  main().catch((err) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-rigg",
3
- "version": "0.0.7",
4
- "description": "Create Node.js TypeScript projects with a Unified Toolchain",
3
+ "version": "0.1.0",
4
+ "description": "Create Node.js TypeScript projects using the Vite+ Toolchain - for everything outside the browser.",
5
5
  "keywords": [
6
6
  "backend",
7
7
  "create-rigg",
@@ -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
+ }
@@ -1,6 +1,14 @@
1
1
  {
2
- "name": "create-rigg",
2
+ "name": "rigg-project",
3
3
  "version": "0.0.0",
4
+ "description": "Create Node.js TypeScript projects with a Unified Toolchain",
5
+ "keywords": [],
6
+ "license": "",
7
+ "author": "",
8
+ "repository": {
9
+ "type": "",
10
+ "url": ""
11
+ },
4
12
  "type": "module",
5
13
  "scripts": {
6
14
  "dev": "tsx src/index.ts",