@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/CHANGELOG.md +12 -0
- package/dist/index.cjs +216 -154
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +215 -154
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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
|
|
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
|
|
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
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
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(
|
|
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
|
|
105
|
-
(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
|
126
|
-
"
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
|
144
|
-
|
|
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
|
-
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
332
|
-
console.log(
|
|
333
|
-
const
|
|
334
|
-
|
|
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(
|
|
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
|
|
343
|
-
console.log(`\n
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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
|
-
|
|
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
|
|
358
|
-
|
|
359
|
-
|
|
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: ${
|
|
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
|
}
|