create-reactivite 1.3.0 → 1.4.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.
Files changed (3) hide show
  1. package/README.md +56 -1
  2. package/index.js +157 -34
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -4,7 +4,7 @@ A modern frontend boilerplate generator. On run it asks which template you want,
4
4
 
5
5
  ## 🚀 Templates
6
6
 
7
- When you run the CLI you pick one of two templates:
7
+ When you run the CLI you pick one of three templates:
8
8
 
9
9
  | Template | Stack |
10
10
  | --- | --- |
@@ -48,6 +48,32 @@ npx create-reactivite .
48
48
 
49
49
  Dependencies install automatically (`pnpm`, falling back to `npm`).
50
50
 
51
+ ## 🛠️ CLI usage
52
+
53
+ The CLI runs interactively (prompts) or non-interactively (flags) — flags skip the matching prompt, so it works in scripts and CI.
54
+
55
+ ```
56
+ npx create-reactivite [name] [options]
57
+ ```
58
+
59
+ | Argument / Flag | Alias | Description |
60
+ | --- | --- | --- |
61
+ | `name` | | Project folder. Use `.` to scaffold into the current directory. Omit to be prompted. Must be lowercase letters, digits, `-` `.` `_` `~`. |
62
+ | `--template <name>` | `-t` | `template` · `template2` · `template3`. Omit to be prompted. |
63
+ | `--help` | `-h` | Print usage and exit. |
64
+ | `--version` | `-v` | Print version and exit. |
65
+
66
+ ```bash
67
+ # fully non-interactive (no prompts)
68
+ npx create-reactivite my-app --template template2
69
+ npx create-reactivite my-app -t template3
70
+
71
+ npx create-reactivite --help
72
+ npx create-reactivite --version
73
+ ```
74
+
75
+ After copying the template the CLI sets `name` in the new `package.json`, removes any bundled lockfile (fresh resolve), runs `git init`, then installs dependencies.
76
+
51
77
  ---
52
78
 
53
79
  ## ⚛️ Template 1 — React + Vite
@@ -215,6 +241,35 @@ npx shadcn@latest add button
215
241
  npx shadcn@latest add form
216
242
  ```
217
243
 
244
+ ## 🔄 Maintaining template versions
245
+
246
+ This repo ships a Claude Code skill that bumps every template's dependencies to their latest published versions in one shot — useful when keeping the scaffolds current.
247
+
248
+ ```
249
+ /update-template-deps
250
+ ```
251
+
252
+ It runs `npm-check-updates` inside `template/`, `template2/` and `template3/`, rewrites each `package.json` to the latest, and reports what changed — flagging **major** bumps that need a build check. The generator's own root `package.json` is left untouched.
253
+
254
+ You can also run the helper directly:
255
+
256
+ ```bash
257
+ # all templates, latest (includes majors)
258
+ node .claude/skills/update-template-deps/update-deps.mjs
259
+
260
+ # safe — no major bumps
261
+ node .claude/skills/update-template-deps/update-deps.mjs --target minor
262
+
263
+ # a single template
264
+ node .claude/skills/update-template-deps/update-deps.mjs --template template2
265
+ ```
266
+
267
+ After a major bump, verify the affected template still builds before publishing:
268
+
269
+ ```bash
270
+ cd template2 && pnpm install && pnpm build
271
+ ```
272
+
218
273
  ## 🤝 Contributing
219
274
 
220
275
  Contributions welcome — open a PR.
package/index.js CHANGED
@@ -15,6 +15,53 @@ const __dirname = path.dirname(__filename);
15
15
  const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
16
16
  const dim = (s) => `\x1b[2m${s}\x1b[0m`;
17
17
 
18
+ // Mövcud template-lər (CLI seçim + --template flag validasiyası üçün)
19
+ const TEMPLATES = ["template", "template2", "template3"];
20
+
21
+ // 🧩 argv parse — `name` positional + `--template/-t <val>` + `--help/--version`
22
+ const parseArgs = (argv) => {
23
+ const args = { _: [], template: undefined, help: false, version: false };
24
+ for (let i = 0; i < argv.length; i++) {
25
+ const a = argv[i];
26
+ if (a === "--help" || a === "-h") args.help = true;
27
+ else if (a === "--version" || a === "-v") args.version = true;
28
+ else if (a === "--template" || a === "-t") args.template = argv[++i];
29
+ else if (a.startsWith("--template=")) args.template = a.split("=")[1];
30
+ else if (!a.startsWith("-")) args._.push(a);
31
+ }
32
+ return args;
33
+ };
34
+
35
+ const printHelp = () => {
36
+ console.log(`
37
+ ${cyan("create-reactivite")} — scaffold React / Next.js / Rspack apps
38
+
39
+ ${dim("Usage:")}
40
+ npx create-reactivite [name] [options]
41
+
42
+ ${dim("Options:")}
43
+ -t, --template <name> ${TEMPLATES.join(" | ")}
44
+ -h, --help Show this help
45
+ -v, --version Show version
46
+
47
+ ${dim("Examples:")}
48
+ npx create-reactivite my-app
49
+ npx create-reactivite my-app --template template2
50
+ npx create-reactivite .
51
+ `);
52
+ };
53
+
54
+ const getVersion = () => {
55
+ try {
56
+ const pkg = JSON.parse(
57
+ fs.readFileSync(path.join(__dirname, "package.json"), "utf8")
58
+ );
59
+ return pkg.version;
60
+ } catch {
61
+ return "unknown";
62
+ }
63
+ };
64
+
18
65
  // 🧩 Banner — CLI açılışında göstərilir
19
66
  const printBanner = () => {
20
67
  try {
@@ -27,42 +74,92 @@ const printBanner = () => {
27
74
  };
28
75
 
29
76
  (async () => {
77
+ const argv = parseArgs(process.argv.slice(2));
78
+
79
+ // --version / --help erkən çıxış (banner olmadan)
80
+ if (argv.version) {
81
+ console.log(getVersion());
82
+ process.exit(0);
83
+ }
84
+ if (argv.help) {
85
+ printHelp();
86
+ process.exit(0);
87
+ }
88
+
30
89
  printBanner();
31
90
 
32
- const { projectName } = await prompts({
33
- type: "text",
34
- name: "projectName",
35
- message: "Project name:",
36
- initial: "my-react-app",
37
- });
38
-
39
- // 🧩 0. Hansı template istifadə olunacaq — istifadəçi seçir
40
- const { template } = await prompts({
41
- type: "select",
42
- name: "template",
43
- message: "Pick a template:",
44
- choices: [
45
- {
46
- title: "React + Vite (Tailwind v4, shadcn/ui, React Router)",
47
- value: "template",
48
- },
49
- {
50
- title:
51
- "Next.js 16 (App Router, i18n, TanStack Query, orval, Zustand, husky)",
52
- value: "template2",
53
- },
54
- {
55
- title: "Rspack (minimal React + TypeScript starter)",
56
- value: "template3",
57
- },
58
- ],
59
- initial: 0,
60
- });
61
-
62
- // İstifadəçi seçimi ləğv etdisə (Ctrl+C) — çıx
63
- if (!template) {
64
- console.log("❌ Operation cancelled.");
65
- process.exit(1);
91
+ const nameRegex = /^[a-z0-9-~][a-z0-9-._~]*$/;
92
+
93
+ // 🧩 Layihə adı — argv-dən gəlirsə validasiya et, yoxsa soruş
94
+ let projectName = argv._[0];
95
+ if (projectName !== undefined) {
96
+ if (
97
+ projectName !== "." &&
98
+ projectName !== "./" &&
99
+ !nameRegex.test(projectName)
100
+ ) {
101
+ console.error(
102
+ `❌ Invalid project name "${projectName}" (lowercase letters, digits, - . _ ~ only)`
103
+ );
104
+ process.exit(1);
105
+ }
106
+ } else {
107
+ const res = await prompts({
108
+ type: "text",
109
+ name: "projectName",
110
+ message: "Project name:",
111
+ initial: "my-react-app",
112
+ // npm paket adı qaydası: kiçik hərf, rəqəm, - . _ ~ (və `.` current dir)
113
+ validate: (name) =>
114
+ name === "." || name === "./" || nameRegex.test(name)
115
+ ? true
116
+ : "Invalid name (lowercase letters, digits, - . _ ~ only)",
117
+ });
118
+ projectName = res.projectName;
119
+ // Ctrl+C name promptunda — çıx
120
+ if (projectName === undefined) {
121
+ console.log("❌ Operation cancelled.");
122
+ process.exit(1);
123
+ }
124
+ }
125
+
126
+ // 🧩 0. Template — argv-dən gəlirsə validasiya et, yoxsa soruş
127
+ let template = argv.template;
128
+ if (template !== undefined) {
129
+ if (!TEMPLATES.includes(template)) {
130
+ console.error(
131
+ `❌ Unknown template "${template}". Valid: ${TEMPLATES.join(", ")}`
132
+ );
133
+ process.exit(1);
134
+ }
135
+ } else {
136
+ const res = await prompts({
137
+ type: "select",
138
+ name: "template",
139
+ message: "Pick a template:",
140
+ choices: [
141
+ {
142
+ title: "React + Vite (Tailwind v4, shadcn/ui, React Router)",
143
+ value: "template",
144
+ },
145
+ {
146
+ title:
147
+ "Next.js 16 (App Router, i18n, TanStack Query, orval, Zustand, husky)",
148
+ value: "template2",
149
+ },
150
+ {
151
+ title: "Rspack (minimal React + TypeScript starter)",
152
+ value: "template3",
153
+ },
154
+ ],
155
+ initial: 0,
156
+ });
157
+ template = res.template;
158
+ // İstifadəçi seçimi ləğv etdisə (Ctrl+C) — çıx
159
+ if (!template) {
160
+ console.log("❌ Operation cancelled.");
161
+ process.exit(1);
162
+ }
66
163
  }
67
164
 
68
165
  // 🧩 1. Target folderı müəyyən edirik
@@ -108,6 +205,32 @@ const printBanner = () => {
108
205
  fs.renameSync(gitignoreSrc, path.join(targetPath, ".gitignore"));
109
206
  }
110
207
 
208
+ // 🧩 3a. Layihənin adını target package.json-a yazırıq
209
+ // (template-dən gələn ad `template`/`template2`/`template3` olur)
210
+ const pkgPath = path.join(targetPath, "package.json");
211
+ if (!isCurrentDir && fs.existsSync(pkgPath)) {
212
+ try {
213
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
214
+ pkg.name = projectName;
215
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
216
+ } catch {
217
+ // package.json oxunmadı — keç
218
+ }
219
+ }
220
+
221
+ // 🧩 3b. Köhnə lockfile-ları silirik ki, fresh resolve olsun
222
+ for (const lock of ["pnpm-lock.yaml", "package-lock.json", "yarn.lock"]) {
223
+ const lockPath = path.join(targetPath, lock);
224
+ if (fs.existsSync(lockPath)) fs.rmSync(lockPath);
225
+ }
226
+
227
+ // 🧩 3c. git repo init (husky `prepare` skriptinin də işləməsi üçün)
228
+ try {
229
+ await execa("git", ["init"], { cwd: targetPath });
230
+ } catch {
231
+ // git yoxdursa — keç
232
+ }
233
+
111
234
  // 🧩 4. Asılılıqları quraşdırırıq
112
235
  console.log("📥 Installing dependencies...");
113
236
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-reactivite",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "⚡ Scaffold modern frontend projects in seconds — pick a template: React + Vite or Next.js 16 (App Router). Both ship Tailwind v4, shadcn/ui, TypeScript and a clean, production-ready structure. The Next.js template adds i18n, TanStack Query, axios/orval, Zustand, husky and Vitest. Zero setup hassle.",
5
5
  "bin": {
6
6
  "create-reactivite": "./index.js"
@@ -51,4 +51,4 @@
51
51
  "url": "https://github.com/jsznpm"
52
52
  },
53
53
  "license": "MIT"
54
- }
54
+ }