@codefast/cli 0.3.1-canary.5 → 0.3.1-canary.6

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/dist/index.js CHANGED
@@ -1,57 +1,33 @@
1
1
  #!/usr/bin/env node
2
2
  import * as __WEBPACK_EXTERNAL_MODULE_commander__ from "commander";
3
- import * as __WEBPACK_EXTERNAL_MODULE_node_child_process_27f17141__ from "node:child_process";
4
3
  import * as __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__ from "node:fs";
5
4
  import * as __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__ from "node:path";
5
+ import * as __WEBPACK_EXTERNAL_MODULE_node_child_process_27f17141__ from "node:child_process";
6
6
  import * as __WEBPACK_EXTERNAL_MODULE_node_readline_91c31510__ from "node:readline";
7
7
  import * as __WEBPACK_EXTERNAL_MODULE_glob__ from "glob";
8
8
  import * as __WEBPACK_EXTERNAL_MODULE_ts_morph_07c7ce60__ from "ts-morph";
9
9
  import * as __WEBPACK_EXTERNAL_MODULE_lodash_es_18c59938__ from "lodash-es";
10
10
  import * as __WEBPACK_EXTERNAL_MODULE_zod__ from "zod";
11
11
  import * as __WEBPACK_EXTERNAL_MODULE_node_url_e96de089__ from "node:url";
12
- const MAIN_DEPENDENCIES = [
13
- "@codefast/ui",
14
- "@codefast/hooks"
15
- ];
16
- const DEV_DEPENDENCIES = {
17
- commitLint: [
18
- "@commitlint/cli",
19
- "@commitlint/config-conventional",
20
- "@commitlint/types"
21
- ],
22
- gitTools: [
23
- "simple-git-hooks"
24
- ],
25
- formatting: [
26
- "prettier",
27
- "prettier-plugin-packagejson",
28
- "prettier-plugin-tailwindcss",
29
- "lint-staged"
30
- ],
31
- linting: [
32
- "@codefast/eslint-config"
33
- ]
34
- };
35
- const rl = __WEBPACK_EXTERNAL_MODULE_node_readline_91c31510__.createInterface({
12
+ const rl = __WEBPACK_EXTERNAL_MODULE_node_readline_91c31510__["default"].createInterface({
36
13
  input: process.stdin,
37
14
  output: process.stdout
38
15
  });
39
- function create_project_prompt(question) {
16
+ function utils_prompt(question) {
40
17
  return new Promise((resolve)=>{
41
18
  rl.question(question, (answer)=>{
42
19
  resolve(answer.trim());
43
20
  });
44
21
  });
45
22
  }
46
- function checkEnvironment() {
47
- try {
48
- (0, __WEBPACK_EXTERNAL_MODULE_node_child_process_27f17141__.execSync)("pnpm --version", {
49
- stdio: "ignore"
50
- });
51
- } catch {
52
- console.error("❌ PNPM chưa được cài đặt. Vui lòng cài đặt PNPM trước.");
53
- process.exit(1);
54
- }
23
+ function runCommand(command) {
24
+ (0, __WEBPACK_EXTERNAL_MODULE_node_child_process_27f17141__.execSync)(command, {
25
+ stdio: "inherit"
26
+ });
27
+ }
28
+ function writeConfigFile(filePath, content) {
29
+ __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].writeFileSync(filePath, content);
30
+ console.log(`📝 Created ${filePath}`);
55
31
  }
56
32
  function validateProjectName(name) {
57
33
  if (!name || /^\s*$/.test(name)) return {
@@ -76,13 +52,13 @@ function validateProjectName(name) {
76
52
  valid: false,
77
53
  error: `Project name "${name}" is a reserved system name.`
78
54
  };
79
- const fullPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__.resolve(process.cwd(), name);
80
- if (__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync(fullPath)) return {
55
+ const fullPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].resolve(process.cwd(), name);
56
+ if (__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(fullPath)) return {
81
57
  valid: false,
82
58
  error: `A directory named "${name}" already exists.`
83
59
  };
84
60
  try {
85
- __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.accessSync(process.cwd(), __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.constants.W_OK);
61
+ __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].accessSync(process.cwd(), __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].constants.W_OK);
86
62
  } catch {
87
63
  return {
88
64
  valid: false,
@@ -94,36 +70,67 @@ function validateProjectName(name) {
94
70
  };
95
71
  }
96
72
  async function getValidProjectName(initialName, attempts = 0, maxAttempts = 3) {
97
- const projectName = initialName ?? await create_project_prompt("Enter project name: ");
73
+ const projectName = initialName ?? await utils_prompt("Enter project name: ");
98
74
  const validation = validateProjectName(projectName);
99
75
  if (validation.valid) return projectName;
100
- if (attempts >= maxAttempts - 1) throw new Error("❌ Exceeded maximum attempts to enter a valid project name.");
76
+ if (attempts >= maxAttempts - 1) throw new Error(`❌ Exceeded maximum attempts to enter a valid project name.`);
101
77
  console.error(`❌ ${validation.error} (${maxAttempts - attempts - 1} attempts remaining)`);
102
78
  return getValidProjectName(void 0, attempts + 1, maxAttempts);
103
79
  }
104
- function runCommand(command) {
105
- (0, __WEBPACK_EXTERNAL_MODULE_node_child_process_27f17141__.execSync)(command, {
106
- stdio: "inherit"
107
- });
108
- }
109
- function writeConfigFile(filePath, content) {
110
- __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.writeFileSync(filePath, content);
111
- console.log(`📝 Created ${filePath}`);
112
- }
113
- function updatePostcssConfig(projectDir) {
114
- const postcssConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__.join(projectDir, "postcss.config.mjs");
115
- if (!__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync(postcssConfigPath)) return void console.warn("⚠️ postcss.config.mjs not found, skipping update.");
116
- let content = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.readFileSync(postcssConfigPath, "utf8");
117
- const typeComment = `/** @type {import('postcss-load-config').Config} */\n`;
118
- if (content.includes(typeComment)) console.log("📝 postcss.config.mjs already contains type comment, no changes made.");
119
- else {
120
- content = content.replace("const config = {", `${typeComment}const config = {`);
121
- __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.writeFileSync(postcssConfigPath, content);
122
- console.log("📝 Updated postcss.config.mjs with type comment.");
80
+ async function checkExistingProject(projectNameArg) {
81
+ const packageJsonPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(process.cwd(), "package.json");
82
+ const packageJsonExists = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(packageJsonPath);
83
+ if (packageJsonExists) {
84
+ console.log(`⚠️ A package.json file has been detected in the current directory.`);
85
+ const confirm = await utils_prompt("Do you want to continue configuring this existing project? [Y/n]: ");
86
+ if ("" === confirm || "y" === confirm.toLowerCase()) {
87
+ const packageJson = JSON.parse(__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].readFileSync(packageJsonPath, "utf8"));
88
+ const projectName = packageJson.name ?? await getValidProjectName(projectNameArg);
89
+ return {
90
+ projectName,
91
+ packageJsonExists
92
+ };
93
+ }
94
+ console.log("Aborting...");
95
+ throw new Error("User aborted the operation.");
123
96
  }
97
+ const projectName = await getValidProjectName(projectNameArg);
98
+ return {
99
+ projectName,
100
+ packageJsonExists
101
+ };
124
102
  }
125
- const configFiles = {
126
- "commitlint.config.mjs": `/**
103
+ const MAIN_DEPENDENCIES = [
104
+ "@codefast/ui",
105
+ "@codefast/hooks"
106
+ ];
107
+ const DEV_DEPENDENCIES = {
108
+ commitLint: [
109
+ "@commitlint/cli",
110
+ "@commitlint/config-conventional",
111
+ "@commitlint/types"
112
+ ],
113
+ gitTools: [
114
+ "simple-git-hooks"
115
+ ],
116
+ formatting: [
117
+ "prettier",
118
+ "prettier-plugin-packagejson",
119
+ "prettier-plugin-tailwindcss",
120
+ "lint-staged"
121
+ ],
122
+ linting: [
123
+ "@codefast/eslint-config"
124
+ ]
125
+ };
126
+ const PACKAGES_TO_REMOVE = [
127
+ "@eslint/eslintrc"
128
+ ];
129
+ const configGroups = {
130
+ linting: [
131
+ {
132
+ path: "commitlint.config.mjs",
133
+ content: `/**
127
134
  * @see https://commitlint.js.org/reference/configuration.html
128
135
  * @type {import('@commitlint/types').UserConfig}
129
136
  */
@@ -133,24 +140,25 @@ const config = {
133
140
  "body-max-line-length": [2, "always", 350],
134
141
  },
135
142
  };
136
-
137
143
  export default config;
138
144
  `,
139
- "prettier.config.mjs": `/**
140
- * @see https://prettier.io/docs/en/configuration.html
141
- * @type {import('prettier').Config}
145
+ description: "Commitlint configuration"
146
+ },
147
+ {
148
+ path: "eslint.config.mjs",
149
+ content: `import { config } from "@codefast/eslint-config/next";
150
+ /**
151
+ * @see https://eslint.org/docs/latest/use/configure/configuration-files
152
+ * @type {import('eslint').Linter.Config[]}
142
153
  */
143
- const config = {
144
- plugins: ["prettier-plugin-packagejson", "prettier-plugin-tailwindcss"],
145
- printWidth: 100,
146
- tailwindAttributes: ["classNames"],
147
- tailwindFunctions: ["tv"],
148
- };
149
-
150
- export default config;
154
+ const eslintConfig = [...config];
155
+ export default eslintConfig;
151
156
  `,
152
- "lint-staged.config.mjs": `import { relative } from "node:path";
153
-
157
+ description: "ESLint configuration for the project"
158
+ },
159
+ {
160
+ path: "lint-staged.config.mjs",
161
+ content: `import { relative } from "node:path";
154
162
  /**
155
163
  * Builds an ESLint command with the given filenames.
156
164
  *
@@ -162,7 +170,6 @@ function buildEslintCommand(filenames) {
162
170
  return \`next lint --fix --max-warnings 0 --file \${filenames.map((file) => relative(import.meta.dirname, file)).
163
171
  join(" --file ")}\`;
164
172
  }
165
-
166
173
  /**
167
174
  * @see https://www.npmjs.com/package/lint-staged
168
175
  * @type {import('lint-staged').Configuration}
@@ -171,138 +178,117 @@ const config = {
171
178
  "*.{js,mjs,jsx,ts,tsx}": [buildEslintCommand, "prettier --list-different --write"],
172
179
  "*.{json,css,md,mdx}": ["prettier --list-different --write"],
173
180
  };
174
-
175
181
  export default config;
176
182
  `,
177
- "eslint.config.mjs": `import { config } from "@codefast/eslint-config/next";
178
- /**
179
- * @see https://eslint.org/docs/latest/use/configure/configuration-files
180
- * @type {import('eslint').Linter.Config[]}
183
+ description: "Configure lint-staged for pre-commit checks"
184
+ }
185
+ ],
186
+ formatting: [
187
+ {
188
+ path: "prettier.config.mjs",
189
+ content: `/**
190
+ * @see https://prettier.io/docs/en/configuration.html
191
+ * @type {import('prettier').Config}
181
192
  */
182
- const eslintConfig = [...config];
183
-
184
- export default eslintConfig;
193
+ const config = {
194
+ plugins: ["prettier-plugin-packagejson", "prettier-plugin-tailwindcss"],
195
+ printWidth: 100,
196
+ tailwindAttributes: ["classNames"],
197
+ tailwindFunctions: ["tv"],
198
+ };
199
+ export default config;
185
200
  `,
186
- "src/lib/fonts.ts": `import { cn } from "@codefast/ui";
201
+ description: "Prettier configuration for source code formatting"
202
+ }
203
+ ],
204
+ styles: [
205
+ {
206
+ path: "src/lib/fonts.ts",
207
+ content: `import { cn } from "@codefast/ui";
187
208
  import { Geist, Geist_Mono as GeistMono } from "next/font/google";
188
-
189
209
  const fontGeistSans = Geist({
190
210
  subsets: ["latin"],
191
211
  variable: "--font-geist-sans",
192
212
  });
193
-
194
213
  const fontGeistMono = GeistMono({
195
214
  subsets: ["latin"],
196
215
  variable: "--font-geist-mono",
197
216
  });
198
-
199
217
  export const fontVariables = cn(fontGeistSans.variable, fontGeistMono.variable);
200
218
  `,
201
- "src/app/globals.css": `@import "tailwindcss";
202
-
219
+ description: "Font configuration for the application"
220
+ },
221
+ {
222
+ path: "src/app/globals.css",
223
+ content: `@import "tailwindcss";
203
224
  @import "@codefast/ui/styles.css";
204
-
205
225
  @source '../../node_modules/@codefast/ui';
206
-
207
226
  @custom-variant dark (&:where(.dark, .dark *));
208
-
209
- @theme inline {
210
- --font-sans: var(--font-geist-sans);
211
- --font-mono: var(--font-geist-mono);
212
- }
213
-
214
227
  @layer base {
215
228
  :root {
229
+ --font-sans: var(--font-geist-sans);
230
+ --font-mono: var(--font-geist-mono);
216
231
  --input: var(--color-neutral-200);
217
232
  --border: var(--color-neutral-200);
218
-
219
233
  --ring: var(--color-neutral-400);
220
-
221
234
  --background: var(--color-white);
222
235
  --foreground: var(--color-neutral-950);
223
-
224
236
  --primary: var(--color-sky-500);
225
237
  --primary-foreground: var(--color-neutral-50);
226
-
227
238
  --secondary: var(--color-neutral-100);
228
239
  --secondary-foreground: var(--color-neutral-900);
229
-
230
240
  --destructive: var(--color-red-600);
231
-
232
241
  --accent: var(--color-neutral-100);
233
242
  --accent-foreground: var(--color-neutral-900);
234
-
235
243
  --muted: var(--color-neutral-100);
236
244
  --muted-foreground: var(--color-neutral-500);
237
-
238
245
  --popover: var(--color-white);
239
246
  --popover-foreground: var(--color-neutral-950);
240
247
  --popover-overlay: --alpha(var(--color-neutral-900) / 20%);
241
-
242
248
  --card: var(--color-white);
243
249
  --card-foreground: var(--color-neutral-950);
244
-
245
250
  --sidebar: var(--color-neutral-50);
246
251
  --sidebar-foreground: var(--color-neutral-950);
247
-
248
252
  --sidebar-primary: var(--color-sky-500);
249
253
  --sidebar-primary-foreground: var(--color-neutral-50);
250
-
251
254
  --sidebar-accent: var(--color-neutral-100);
252
255
  --sidebar-accent-foreground: var(--color-neutral-900);
253
-
254
256
  --sidebar-border: var(--color-neutral-200);
255
257
  --sidebar-ring: var(--color-neutral-400);
256
-
257
258
  --chart-1: var(--color-orange-600);
258
259
  --chart-2: var(--color-teal-600);
259
260
  --chart-3: var(--color-cyan-600);
260
261
  --chart-4: var(--color-amber-600);
261
262
  --chart-5: var(--color-amber-500);
262
263
  }
263
-
264
264
  @variant dark {
265
265
  --input: var(--color-neutral-700);
266
266
  --border: --alpha(var(--color-neutral-700) / 50%);
267
-
268
267
  --ring: var(--color-neutral-500);
269
-
270
268
  --background: var(--color-neutral-950);
271
269
  --foreground: var(--color-neutral-50);
272
-
273
270
  --primary: var(--color-sky-700);
274
271
  --primary-foreground: var(--color-neutral-50);
275
-
276
272
  --secondary: var(--color-neutral-800);
277
273
  --secondary-foreground: var(--color-neutral-50);
278
-
279
274
  --destructive: var(--color-red-400);
280
-
281
275
  --accent: var(--color-neutral-700);
282
276
  --accent-foreground: var(--color-neutral-50);
283
-
284
277
  --muted: var(--color-neutral-800);
285
278
  --muted-foreground: var(--color-neutral-400);
286
-
287
279
  --popover: var(--color-neutral-800);
288
280
  --popover-foreground: var(--color-neutral-50);
289
281
  --popover-overlay: --alpha(var(--color-neutral-900) / 80%);
290
-
291
282
  --card: var(--color-neutral-900);
292
283
  --card-foreground: var(--color-neutral-50);
293
-
294
284
  --sidebar: var(--color-neutral-900);
295
285
  --sidebar-foreground: var(--color-neutral-50);
296
-
297
286
  --sidebar-primary: var(--color-sky-700);
298
287
  --sidebar-primary-foreground: var(--color-neutral-50);
299
-
300
288
  --sidebar-accent: var(--color-neutral-800);
301
289
  --sidebar-accent-foreground: var(--color-neutral-50);
302
-
303
290
  --sidebar-border: var(--color-neutral-800);
304
291
  --sidebar-ring: var(--color-neutral-600);
305
-
306
292
  --chart-1: var(--color-blue-700);
307
293
  --chart-2: var(--color-emerald-500);
308
294
  --chart-3: var(--color-amber-500);
@@ -310,11 +296,54 @@ export const fontVariables = cn(fontGeistSans.variable, fontGeistMono.variable);
310
296
  --chart-5: var(--color-rose-500);
311
297
  }
312
298
  }
313
- `
299
+ `,
300
+ description: "Global CSS variables for the application"
301
+ }
302
+ ]
314
303
  };
304
+ function updatePostcssConfig(projectDir) {
305
+ const postcssConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectDir, "postcss.config.mjs");
306
+ if (!__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(postcssConfigPath)) return void console.warn(`⚠️ postcss.config.mjs not found, skipping update.`);
307
+ let content = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].readFileSync(postcssConfigPath, "utf8");
308
+ const typeComment = `/** @type {import('postcss-load-config').Config} */\n`;
309
+ if (content.includes(typeComment)) console.log(`📝 postcss.config.mjs already contains type comment, no changes made.`);
310
+ else {
311
+ content = content.replace("const config = {", `${typeComment}const config = {`);
312
+ __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].writeFileSync(postcssConfigPath, content);
313
+ console.log(`📝 Updated postcss.config.mjs with type comment.`);
314
+ }
315
+ }
316
+ function updateLayoutFile(projectDir) {
317
+ const layoutPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectDir, "src/app/layout.tsx");
318
+ if (!__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(layoutPath)) return void console.warn(`⚠️ src/app/layout.tsx not found, skipping update.`);
319
+ let content = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].readFileSync(layoutPath, "utf8");
320
+ if (content.includes('<html className={cn(fontVariables, "antialiased")} lang="en">')) return void console.log(`📝 src/app/layout.tsx already uses fontVariables in html tag, no changes made.`);
321
+ const newImports = `import type { Metadata } from "next";
322
+
323
+ import { cn } from "@codefast/ui";
324
+
325
+ import { fontVariables } from "@/lib/fonts";
326
+ import "@/app/globals.css";`;
327
+ content = content.replaceAll(/import\s+{[^}]+}\s+from\s+["']next\/font\/google["'];\s*/g, "");
328
+ content = content.replace(/const\s+geistSans\s*=[^;]+;\s*const\s+geistMono\s*=[^;]+;\s*/, "");
329
+ content = content.replace(/import\s+type\s+{[^}]+}\s+from\s+["']next["'];\s*import\s+["']\.\/globals\.css["'];\s*/, newImports);
330
+ const htmlRegex = /<html\s+lang="en"\s*>/;
331
+ const newHtml = '<html className={cn(fontVariables, "antialiased")} lang="en">';
332
+ content = content.replace(htmlRegex, newHtml);
333
+ const bodyRegex = /<body\s+className={`[^`]*`}\s*>/;
334
+ const newBody = "<body>";
335
+ content = content.replace(bodyRegex, newBody);
336
+ try {
337
+ __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].writeFileSync(layoutPath, content);
338
+ console.log(`📝 Updated src/app/layout.tsx to use fontVariables in html tag and removed className from body`);
339
+ } catch (error) {
340
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
341
+ console.warn(`⚠️ Failed to update src/app/layout.tsx: ${errorMessage}`);
342
+ }
343
+ }
315
344
  function updatePackageJson(projectDir) {
316
- const packageJsonPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__.join(projectDir, "package.json");
317
- const packageJson = JSON.parse(__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.readFileSync(packageJsonPath, "utf8"));
345
+ const packageJsonPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectDir, "package.json");
346
+ const packageJson = JSON.parse(__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].readFileSync(packageJsonPath, "utf8"));
318
347
  packageJson.scripts = {
319
348
  ...packageJson.scripts,
320
349
  format: 'prettier --write "**/*.{js,mjs,jsx,ts,tsx,json,css,md,mdx}"',
@@ -325,67 +354,99 @@ function updatePackageJson(projectDir) {
325
354
  "pre-commit": "pnpm lint-staged",
326
355
  "commit-msg": "pnpm commitlint --edit"
327
356
  };
328
- __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
329
- console.log("📝 Updated package.json");
357
+ __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
358
+ console.log(`📝 Updated package.json`);
330
359
  }
331
- function createNextProject(projectName) {
332
- console.log("📦 Creating Next.js project...");
333
- const flags = '--ts --tailwind --eslint --app --turbo --use-pnpm --src-dir --turbopack --import-alias "@/*"';
334
- runCommand(`npx create-next-app@latest ${projectName} ${flags}`);
360
+ function createConfigFiles(projectDir) {
361
+ console.log(`\n📝 Creating configuration files...`);
362
+ for (const [category, configs] of Object.entries(configGroups)){
363
+ console.log(`\n📂 Setting up ${category} configurations:`);
364
+ for (const { path: filePath, content, description } of configs){
365
+ const fullPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectDir, filePath);
366
+ const dir = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].dirname(fullPath);
367
+ if (!__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(dir)) __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].mkdirSync(dir, {
368
+ recursive: true
369
+ });
370
+ writeConfigFile(fullPath, content);
371
+ if (description) console.log(` ℹ️ ${filePath}: ${description}`);
372
+ }
373
+ }
335
374
  }
336
375
  function installDependencies() {
337
- console.log("📚 Installing dependencies...");
376
+ console.log(`\n📚 Installing dependencies...`);
338
377
  if (MAIN_DEPENDENCIES.length > 0) runCommand(`pnpm add ${MAIN_DEPENDENCIES.join(" ")}`);
339
378
  const allDevDependencies = Object.values(DEV_DEPENDENCIES).flat().join(" ");
340
379
  if (allDevDependencies) runCommand(`pnpm add -D ${allDevDependencies}`);
341
380
  }
342
- function createConfigFiles(projectDir) {
343
- console.log(`\n📝 Creating configuration files...`);
344
- for (const [filePath, content] of Object.entries(configFiles)){
345
- const fullPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__.join(projectDir, filePath);
346
- const dir = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__.dirname(fullPath);
347
- if (!__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync(dir)) __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.mkdirSync(dir, {
348
- recursive: true
381
+ function cleanupPackages() {
382
+ console.log(`\n🧹 Cleaning up unnecessary packages...`);
383
+ const packageJsonPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__.join(process.cwd(), "package.json");
384
+ if (!__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync(packageJsonPath)) return void console.warn(`⚠️ package.json not found, skipping cleanup.`);
385
+ let packageJson;
386
+ try {
387
+ packageJson = JSON.parse(__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.readFileSync(packageJsonPath, "utf8"));
388
+ } catch (error) {
389
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
390
+ console.warn(`⚠️ Error reading package.json: ${errorMessage}, skipping cleanup.`);
391
+ return;
392
+ }
393
+ const dependencies = packageJson.dependencies ?? {};
394
+ const devDependencies = packageJson.devDependencies ?? {};
395
+ const packagesToRemove = PACKAGES_TO_REMOVE.filter((pkg)=>pkg in dependencies || pkg in devDependencies);
396
+ if (packagesToRemove.length > 0) runCommand(`pnpm remove ${packagesToRemove.join(" ")}`);
397
+ else console.log(`ℹ️ No unnecessary packages found in package.json to remove.`);
398
+ }
399
+ function checkEnvironment() {
400
+ try {
401
+ (0, __WEBPACK_EXTERNAL_MODULE_node_child_process_27f17141__.execSync)("pnpm --version", {
402
+ stdio: "ignore"
349
403
  });
350
- writeConfigFile(fullPath, content);
404
+ } catch {
405
+ console.error(`❌ PNPM chưa được cài đặt. Vui lòng cài đặt PNPM trước.`);
406
+ process.exit(1);
351
407
  }
352
408
  }
409
+ function createNextProject(projectName) {
410
+ console.log(`📦 Creating Next.js project...`);
411
+ const flags = '--ts --tailwind --eslint --app --turbo --use-pnpm --src-dir --turbopack --import-alias "@/*"';
412
+ runCommand(`npx create-next-app@latest ${projectName} ${flags}`);
413
+ }
353
414
  function createProjectCommand(program) {
354
415
  program.command("create-project [name]").description("Create a new Next.js project with recommended setup").action(async (projectNameArg)=>{
355
416
  try {
356
417
  checkEnvironment();
357
- const projectName = await getValidProjectName(projectNameArg);
358
- console.log(`\n🚀 Starting project creation for ${projectName}...\n`);
359
- const packageJsonExists = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__.join(process.cwd(), "package.json"));
360
- if (packageJsonExists) console.log(`📦 A package.json file has been detected. Skipping the Next.js project creation step.`);
361
- else {
418
+ const { projectName, packageJsonExists } = await checkExistingProject(projectNameArg);
419
+ if (!packageJsonExists) {
420
+ console.log(`\n🚀 Starting project creation for ${projectName}...\n`);
362
421
  createNextProject(projectName);
363
422
  process.chdir(projectName);
364
423
  console.log(`📂 Moved to ${projectName}`);
365
424
  }
425
+ updateLayoutFile(process.cwd());
366
426
  updatePostcssConfig(process.cwd());
367
427
  installDependencies();
428
+ cleanupPackages();
368
429
  createConfigFiles(process.cwd());
369
430
  updatePackageJson(process.cwd());
370
431
  console.log(`\n🔄 Activating git hooks...`);
371
432
  runCommand("pnpm simple-git-hooks");
372
433
  console.log(`\n📝 Formatting files with Prettier...`);
373
434
  runCommand("pnpm format");
374
- console.log(`\n✅ Project created successfully!`);
435
+ console.log(`\n✅ Project ${packageJsonExists ? "configured" : "created"} successfully!`);
375
436
  console.log(`- Project: ${projectName}`);
376
437
  console.log("- Next.js with TypeScript");
377
438
  console.log("- TailwindCSS and @codefast/ui");
378
439
  console.log("- ESLint, Prettier, Commitlint, and Git Hooks");
379
440
  console.log("- Lint-staged for pre-commit checks");
380
- console.log(`\n📁 Project directory: ${__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__.resolve(process.cwd())}`);
441
+ console.log(`\n📁 Project directory: ${process.cwd()}`);
381
442
  console.log(`\n🚀 To start development:`);
382
443
  console.log(`cd ${projectName} && pnpm dev`);
383
- rl.close();
384
444
  } catch (error) {
385
445
  const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
386
446
  console.error(`\n❌ An error occurred: ${errorMessage}`);
387
- rl.close();
388
447
  process.exit(1);
448
+ } finally{
449
+ rl.close();
389
450
  }
390
451
  });
391
452
  }