@codefast/cli 0.3.1-canary.4 โ 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 +26 -0
- package/dist/index.cjs +474 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +472 -56
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,13 +1,455 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as __WEBPACK_EXTERNAL_MODULE_commander__ from "commander";
|
|
3
|
-
import * as
|
|
3
|
+
import * as __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__ from "node:fs";
|
|
4
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
|
+
import * as __WEBPACK_EXTERNAL_MODULE_node_readline_91c31510__ from "node:readline";
|
|
7
|
+
import * as __WEBPACK_EXTERNAL_MODULE_glob__ from "glob";
|
|
5
8
|
import * as __WEBPACK_EXTERNAL_MODULE_ts_morph_07c7ce60__ from "ts-morph";
|
|
6
9
|
import * as __WEBPACK_EXTERNAL_MODULE_lodash_es_18c59938__ from "lodash-es";
|
|
7
|
-
import * as __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__ from "node:fs";
|
|
8
10
|
import * as __WEBPACK_EXTERNAL_MODULE_zod__ from "zod";
|
|
9
|
-
import * as __WEBPACK_EXTERNAL_MODULE_chalk__ from "chalk";
|
|
10
11
|
import * as __WEBPACK_EXTERNAL_MODULE_node_url_e96de089__ from "node:url";
|
|
12
|
+
const rl = __WEBPACK_EXTERNAL_MODULE_node_readline_91c31510__["default"].createInterface({
|
|
13
|
+
input: process.stdin,
|
|
14
|
+
output: process.stdout
|
|
15
|
+
});
|
|
16
|
+
function utils_prompt(question) {
|
|
17
|
+
return new Promise((resolve)=>{
|
|
18
|
+
rl.question(question, (answer)=>{
|
|
19
|
+
resolve(answer.trim());
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
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}`);
|
|
31
|
+
}
|
|
32
|
+
function validateProjectName(name) {
|
|
33
|
+
if (!name || /^\s*$/.test(name)) return {
|
|
34
|
+
valid: false,
|
|
35
|
+
error: "Project name cannot be empty or contain only whitespace."
|
|
36
|
+
};
|
|
37
|
+
if (name.length > 100) return {
|
|
38
|
+
valid: false,
|
|
39
|
+
error: "Project name is too long (maximum 100 characters)."
|
|
40
|
+
};
|
|
41
|
+
const npmNameRegex = /^[a-z0-9-~][a-z0-9-._~]*$/;
|
|
42
|
+
if (!npmNameRegex.test(name)) return {
|
|
43
|
+
valid: false,
|
|
44
|
+
error: "Project name must be URL-friendly (letters, numbers, hyphens, underscores, dots; no @ or scoped packages)."
|
|
45
|
+
};
|
|
46
|
+
if ("." === name || ".." === name) return {
|
|
47
|
+
valid: false,
|
|
48
|
+
error: "Project name cannot be '.' or '..'."
|
|
49
|
+
};
|
|
50
|
+
const reservedNames = /^(?<reserved>CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$/i;
|
|
51
|
+
if (reservedNames.test(name)) return {
|
|
52
|
+
valid: false,
|
|
53
|
+
error: `Project name "${name}" is a reserved system name.`
|
|
54
|
+
};
|
|
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 {
|
|
57
|
+
valid: false,
|
|
58
|
+
error: `A directory named "${name}" already exists.`
|
|
59
|
+
};
|
|
60
|
+
try {
|
|
61
|
+
__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].accessSync(process.cwd(), __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].constants.W_OK);
|
|
62
|
+
} catch {
|
|
63
|
+
return {
|
|
64
|
+
valid: false,
|
|
65
|
+
error: "Cannot create project: No write permission in current directory."
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
valid: true
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async function getValidProjectName(initialName, attempts = 0, maxAttempts = 3) {
|
|
73
|
+
const projectName = initialName ?? await utils_prompt("Enter project name: ");
|
|
74
|
+
const validation = validateProjectName(projectName);
|
|
75
|
+
if (validation.valid) return projectName;
|
|
76
|
+
if (attempts >= maxAttempts - 1) throw new Error(`โ Exceeded maximum attempts to enter a valid project name.`);
|
|
77
|
+
console.error(`โ ${validation.error} (${maxAttempts - attempts - 1} attempts remaining)`);
|
|
78
|
+
return getValidProjectName(void 0, attempts + 1, maxAttempts);
|
|
79
|
+
}
|
|
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.");
|
|
96
|
+
}
|
|
97
|
+
const projectName = await getValidProjectName(projectNameArg);
|
|
98
|
+
return {
|
|
99
|
+
projectName,
|
|
100
|
+
packageJsonExists
|
|
101
|
+
};
|
|
102
|
+
}
|
|
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: `/**
|
|
134
|
+
* @see https://commitlint.js.org/reference/configuration.html
|
|
135
|
+
* @type {import('@commitlint/types').UserConfig}
|
|
136
|
+
*/
|
|
137
|
+
const config = {
|
|
138
|
+
extends: ["@commitlint/config-conventional"],
|
|
139
|
+
rules: {
|
|
140
|
+
"body-max-line-length": [2, "always", 350],
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
export default config;
|
|
144
|
+
`,
|
|
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[]}
|
|
153
|
+
*/
|
|
154
|
+
const eslintConfig = [...config];
|
|
155
|
+
export default eslintConfig;
|
|
156
|
+
`,
|
|
157
|
+
description: "ESLint configuration for the project"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
path: "lint-staged.config.mjs",
|
|
161
|
+
content: `import { relative } from "node:path";
|
|
162
|
+
/**
|
|
163
|
+
* Builds an ESLint command with the given filenames.
|
|
164
|
+
*
|
|
165
|
+
* @param {string[]} filenames - An array of filenames to be passed to the
|
|
166
|
+
* ESLint command.
|
|
167
|
+
* @returns {string} - The generated ESLint command.
|
|
168
|
+
*/
|
|
169
|
+
function buildEslintCommand(filenames) {
|
|
170
|
+
return \`next lint --fix --max-warnings 0 --file \${filenames.map((file) => relative(import.meta.dirname, file)).
|
|
171
|
+
join(" --file ")}\`;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* @see https://www.npmjs.com/package/lint-staged
|
|
175
|
+
* @type {import('lint-staged').Configuration}
|
|
176
|
+
*/
|
|
177
|
+
const config = {
|
|
178
|
+
"*.{js,mjs,jsx,ts,tsx}": [buildEslintCommand, "prettier --list-different --write"],
|
|
179
|
+
"*.{json,css,md,mdx}": ["prettier --list-different --write"],
|
|
180
|
+
};
|
|
181
|
+
export default config;
|
|
182
|
+
`,
|
|
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}
|
|
192
|
+
*/
|
|
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;
|
|
200
|
+
`,
|
|
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";
|
|
208
|
+
import { Geist, Geist_Mono as GeistMono } from "next/font/google";
|
|
209
|
+
const fontGeistSans = Geist({
|
|
210
|
+
subsets: ["latin"],
|
|
211
|
+
variable: "--font-geist-sans",
|
|
212
|
+
});
|
|
213
|
+
const fontGeistMono = GeistMono({
|
|
214
|
+
subsets: ["latin"],
|
|
215
|
+
variable: "--font-geist-mono",
|
|
216
|
+
});
|
|
217
|
+
export const fontVariables = cn(fontGeistSans.variable, fontGeistMono.variable);
|
|
218
|
+
`,
|
|
219
|
+
description: "Font configuration for the application"
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
path: "src/app/globals.css",
|
|
223
|
+
content: `@import "tailwindcss";
|
|
224
|
+
@import "@codefast/ui/styles.css";
|
|
225
|
+
@source '../../node_modules/@codefast/ui';
|
|
226
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
227
|
+
@layer base {
|
|
228
|
+
:root {
|
|
229
|
+
--font-sans: var(--font-geist-sans);
|
|
230
|
+
--font-mono: var(--font-geist-mono);
|
|
231
|
+
--input: var(--color-neutral-200);
|
|
232
|
+
--border: var(--color-neutral-200);
|
|
233
|
+
--ring: var(--color-neutral-400);
|
|
234
|
+
--background: var(--color-white);
|
|
235
|
+
--foreground: var(--color-neutral-950);
|
|
236
|
+
--primary: var(--color-sky-500);
|
|
237
|
+
--primary-foreground: var(--color-neutral-50);
|
|
238
|
+
--secondary: var(--color-neutral-100);
|
|
239
|
+
--secondary-foreground: var(--color-neutral-900);
|
|
240
|
+
--destructive: var(--color-red-600);
|
|
241
|
+
--accent: var(--color-neutral-100);
|
|
242
|
+
--accent-foreground: var(--color-neutral-900);
|
|
243
|
+
--muted: var(--color-neutral-100);
|
|
244
|
+
--muted-foreground: var(--color-neutral-500);
|
|
245
|
+
--popover: var(--color-white);
|
|
246
|
+
--popover-foreground: var(--color-neutral-950);
|
|
247
|
+
--popover-overlay: --alpha(var(--color-neutral-900) / 20%);
|
|
248
|
+
--card: var(--color-white);
|
|
249
|
+
--card-foreground: var(--color-neutral-950);
|
|
250
|
+
--sidebar: var(--color-neutral-50);
|
|
251
|
+
--sidebar-foreground: var(--color-neutral-950);
|
|
252
|
+
--sidebar-primary: var(--color-sky-500);
|
|
253
|
+
--sidebar-primary-foreground: var(--color-neutral-50);
|
|
254
|
+
--sidebar-accent: var(--color-neutral-100);
|
|
255
|
+
--sidebar-accent-foreground: var(--color-neutral-900);
|
|
256
|
+
--sidebar-border: var(--color-neutral-200);
|
|
257
|
+
--sidebar-ring: var(--color-neutral-400);
|
|
258
|
+
--chart-1: var(--color-orange-600);
|
|
259
|
+
--chart-2: var(--color-teal-600);
|
|
260
|
+
--chart-3: var(--color-cyan-600);
|
|
261
|
+
--chart-4: var(--color-amber-600);
|
|
262
|
+
--chart-5: var(--color-amber-500);
|
|
263
|
+
}
|
|
264
|
+
@variant dark {
|
|
265
|
+
--input: var(--color-neutral-700);
|
|
266
|
+
--border: --alpha(var(--color-neutral-700) / 50%);
|
|
267
|
+
--ring: var(--color-neutral-500);
|
|
268
|
+
--background: var(--color-neutral-950);
|
|
269
|
+
--foreground: var(--color-neutral-50);
|
|
270
|
+
--primary: var(--color-sky-700);
|
|
271
|
+
--primary-foreground: var(--color-neutral-50);
|
|
272
|
+
--secondary: var(--color-neutral-800);
|
|
273
|
+
--secondary-foreground: var(--color-neutral-50);
|
|
274
|
+
--destructive: var(--color-red-400);
|
|
275
|
+
--accent: var(--color-neutral-700);
|
|
276
|
+
--accent-foreground: var(--color-neutral-50);
|
|
277
|
+
--muted: var(--color-neutral-800);
|
|
278
|
+
--muted-foreground: var(--color-neutral-400);
|
|
279
|
+
--popover: var(--color-neutral-800);
|
|
280
|
+
--popover-foreground: var(--color-neutral-50);
|
|
281
|
+
--popover-overlay: --alpha(var(--color-neutral-900) / 80%);
|
|
282
|
+
--card: var(--color-neutral-900);
|
|
283
|
+
--card-foreground: var(--color-neutral-50);
|
|
284
|
+
--sidebar: var(--color-neutral-900);
|
|
285
|
+
--sidebar-foreground: var(--color-neutral-50);
|
|
286
|
+
--sidebar-primary: var(--color-sky-700);
|
|
287
|
+
--sidebar-primary-foreground: var(--color-neutral-50);
|
|
288
|
+
--sidebar-accent: var(--color-neutral-800);
|
|
289
|
+
--sidebar-accent-foreground: var(--color-neutral-50);
|
|
290
|
+
--sidebar-border: var(--color-neutral-800);
|
|
291
|
+
--sidebar-ring: var(--color-neutral-600);
|
|
292
|
+
--chart-1: var(--color-blue-700);
|
|
293
|
+
--chart-2: var(--color-emerald-500);
|
|
294
|
+
--chart-3: var(--color-amber-500);
|
|
295
|
+
--chart-4: var(--color-purple-500);
|
|
296
|
+
--chart-5: var(--color-rose-500);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
`,
|
|
300
|
+
description: "Global CSS variables for the application"
|
|
301
|
+
}
|
|
302
|
+
]
|
|
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
|
+
}
|
|
344
|
+
function updatePackageJson(projectDir) {
|
|
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"));
|
|
347
|
+
packageJson.scripts = {
|
|
348
|
+
...packageJson.scripts,
|
|
349
|
+
format: 'prettier --write "**/*.{js,mjs,jsx,ts,tsx,json,css,md,mdx}"',
|
|
350
|
+
"format:check": 'prettier --check "**/*.{js,mjs,jsx,ts,tsx,json,css,md,mdx}"',
|
|
351
|
+
"lint:check": "next lint --max-warnings 0"
|
|
352
|
+
};
|
|
353
|
+
packageJson["simple-git-hooks"] = {
|
|
354
|
+
"pre-commit": "pnpm lint-staged",
|
|
355
|
+
"commit-msg": "pnpm commitlint --edit"
|
|
356
|
+
};
|
|
357
|
+
__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
358
|
+
console.log(`๐ Updated package.json`);
|
|
359
|
+
}
|
|
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
|
+
}
|
|
374
|
+
}
|
|
375
|
+
function installDependencies() {
|
|
376
|
+
console.log(`\n๐ Installing dependencies...`);
|
|
377
|
+
if (MAIN_DEPENDENCIES.length > 0) runCommand(`pnpm add ${MAIN_DEPENDENCIES.join(" ")}`);
|
|
378
|
+
const allDevDependencies = Object.values(DEV_DEPENDENCIES).flat().join(" ");
|
|
379
|
+
if (allDevDependencies) runCommand(`pnpm add -D ${allDevDependencies}`);
|
|
380
|
+
}
|
|
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"
|
|
403
|
+
});
|
|
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);
|
|
407
|
+
}
|
|
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
|
+
}
|
|
414
|
+
function createProjectCommand(program) {
|
|
415
|
+
program.command("create-project [name]").description("Create a new Next.js project with recommended setup").action(async (projectNameArg)=>{
|
|
416
|
+
try {
|
|
417
|
+
checkEnvironment();
|
|
418
|
+
const { projectName, packageJsonExists } = await checkExistingProject(projectNameArg);
|
|
419
|
+
if (!packageJsonExists) {
|
|
420
|
+
console.log(`\n๐ Starting project creation for ${projectName}...\n`);
|
|
421
|
+
createNextProject(projectName);
|
|
422
|
+
process.chdir(projectName);
|
|
423
|
+
console.log(`๐ Moved to ${projectName}`);
|
|
424
|
+
}
|
|
425
|
+
updateLayoutFile(process.cwd());
|
|
426
|
+
updatePostcssConfig(process.cwd());
|
|
427
|
+
installDependencies();
|
|
428
|
+
cleanupPackages();
|
|
429
|
+
createConfigFiles(process.cwd());
|
|
430
|
+
updatePackageJson(process.cwd());
|
|
431
|
+
console.log(`\n๐ Activating git hooks...`);
|
|
432
|
+
runCommand("pnpm simple-git-hooks");
|
|
433
|
+
console.log(`\n๐ Formatting files with Prettier...`);
|
|
434
|
+
runCommand("pnpm format");
|
|
435
|
+
console.log(`\nโ
Project ${packageJsonExists ? "configured" : "created"} successfully!`);
|
|
436
|
+
console.log(`- Project: ${projectName}`);
|
|
437
|
+
console.log("- Next.js with TypeScript");
|
|
438
|
+
console.log("- TailwindCSS and @codefast/ui");
|
|
439
|
+
console.log("- ESLint, Prettier, Commitlint, and Git Hooks");
|
|
440
|
+
console.log("- Lint-staged for pre-commit checks");
|
|
441
|
+
console.log(`\n๐ Project directory: ${process.cwd()}`);
|
|
442
|
+
console.log(`\n๐ To start development:`);
|
|
443
|
+
console.log(`cd ${projectName} && pnpm dev`);
|
|
444
|
+
} catch (error) {
|
|
445
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
446
|
+
console.error(`\nโ An error occurred: ${errorMessage}`);
|
|
447
|
+
process.exit(1);
|
|
448
|
+
} finally{
|
|
449
|
+
rl.close();
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
11
453
|
function makeRegexPrefixesToRemove(prefixes) {
|
|
12
454
|
const prefixPattern = prefixes.join("|");
|
|
13
455
|
return new RegExp(`^.?\\/?(?:${prefixPattern})\\/(.*)$`);
|
|
@@ -254,120 +696,92 @@ async function findAllPackages(config) {
|
|
|
254
696
|
ignore: DEFAULT_IGNORE_PATTERN
|
|
255
697
|
});
|
|
256
698
|
}
|
|
257
|
-
function processPackage(packageJsonPath, options
|
|
699
|
+
function processPackage(packageJsonPath, options) {
|
|
258
700
|
const packageDir = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].dirname(packageJsonPath);
|
|
259
701
|
const packageJson = readPackageJson(packageJsonPath);
|
|
260
702
|
if (!packageJson) {
|
|
261
|
-
|
|
703
|
+
console.error(`Failed to read ${packageJsonPath}`);
|
|
262
704
|
return false;
|
|
263
705
|
}
|
|
264
706
|
const packageName = packageJson.name;
|
|
265
707
|
if (options.packageFilter && packageName !== options.packageFilter) {
|
|
266
|
-
|
|
708
|
+
console.debug(`Skipping ${packageName} (does not match filter)`);
|
|
267
709
|
return false;
|
|
268
710
|
}
|
|
269
|
-
|
|
711
|
+
console.info(`Processing package: ${packageName}`);
|
|
270
712
|
const config = getConfig(options.configPath);
|
|
271
713
|
const packageConfig = getPackageConfig(packageName, config);
|
|
272
714
|
const srcIndexPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(packageDir, packageConfig.srcIndexPath);
|
|
273
715
|
if (!fileExists(srcIndexPath)) {
|
|
274
|
-
|
|
716
|
+
console.error(`Source file not found at ${srcIndexPath}`);
|
|
275
717
|
return false;
|
|
276
718
|
}
|
|
277
|
-
|
|
719
|
+
console.info(`Analyzing imports from ${srcIndexPath}...`);
|
|
278
720
|
const { imports } = analyzeImports(srcIndexPath, packageConfig);
|
|
279
721
|
if (0 === imports.length) {
|
|
280
|
-
|
|
722
|
+
console.warn(`No imports found to analyze in ${packageName}`);
|
|
281
723
|
return false;
|
|
282
724
|
}
|
|
283
|
-
|
|
725
|
+
console.log(`Analysis complete. Found ${imports.length} subpath exports.`);
|
|
284
726
|
saveExportsAnalysis(packageDir, {
|
|
285
727
|
imports
|
|
286
728
|
});
|
|
287
729
|
const newExports = generateExports(packageName, imports, packageJson.exports, config);
|
|
288
730
|
const currentExportsCount = packageJson.exports ? Object.keys(packageJson.exports).length : 0;
|
|
289
731
|
const newExportsCount = Object.keys(newExports).length;
|
|
290
|
-
|
|
732
|
+
console.info(`Exports: ${currentExportsCount} -> ${newExportsCount}`);
|
|
291
733
|
if (options.dryRun) {
|
|
292
734
|
saveExportsPreview(packageDir, newExports);
|
|
293
|
-
|
|
294
|
-
|
|
735
|
+
console.warn("Saved exports preview to .exports-analysis");
|
|
736
|
+
console.warn(`Dry run: no changes saved for ${packageName}`);
|
|
295
737
|
return true;
|
|
296
738
|
}
|
|
297
|
-
if (backupPackageJson(packageJsonPath))
|
|
739
|
+
if (backupPackageJson(packageJsonPath)) console.log(`Backed up ${packageJsonPath}`);
|
|
298
740
|
const updatedPackageJson = {
|
|
299
741
|
...packageJson,
|
|
300
742
|
exports: newExports
|
|
301
743
|
};
|
|
302
744
|
if (savePackageJson(packageJsonPath, updatedPackageJson)) {
|
|
303
|
-
|
|
745
|
+
console.log(`Updated exports for ${packageName}`);
|
|
304
746
|
return true;
|
|
305
747
|
}
|
|
306
|
-
|
|
748
|
+
console.error(`Failed to update ${packageJsonPath}`);
|
|
307
749
|
return false;
|
|
308
750
|
}
|
|
309
|
-
async function processAllPackages(options
|
|
751
|
+
async function processAllPackages(options) {
|
|
310
752
|
try {
|
|
311
|
-
|
|
753
|
+
console.info("Searching for packages...");
|
|
312
754
|
const config = getConfig(options.configPath);
|
|
313
755
|
const packageJsonPaths = await findAllPackages(config);
|
|
314
|
-
if (0 === packageJsonPaths.length) return void
|
|
315
|
-
|
|
756
|
+
if (0 === packageJsonPaths.length) return void console.warn("No packages found.");
|
|
757
|
+
console.log(`Found ${packageJsonPaths.length} packages.`);
|
|
316
758
|
let successCount = 0;
|
|
317
759
|
let skipCount = 0;
|
|
318
760
|
let errorCount = 0;
|
|
319
761
|
for (const packageJsonPath of packageJsonPaths){
|
|
320
|
-
const result = processPackage(packageJsonPath, options
|
|
762
|
+
const result = processPackage(packageJsonPath, options);
|
|
321
763
|
if (result) successCount++;
|
|
322
764
|
else if (options.packageFilter) skipCount++;
|
|
323
765
|
else errorCount++;
|
|
324
766
|
}
|
|
325
|
-
|
|
326
|
-
|
|
767
|
+
console.log("Completed exports update.");
|
|
768
|
+
console.info(`Stats: ${successCount} succeeded, ${skipCount} skipped, ${errorCount} failed`);
|
|
327
769
|
} catch (error) {
|
|
328
|
-
|
|
770
|
+
console.error("Error processing packages:", error);
|
|
329
771
|
throw error;
|
|
330
772
|
}
|
|
331
773
|
}
|
|
332
|
-
class Logger {
|
|
333
|
-
verbose;
|
|
334
|
-
constructor(options = {}){
|
|
335
|
-
this.verbose = options.verbose ?? false;
|
|
336
|
-
}
|
|
337
|
-
info(message, ...args) {
|
|
338
|
-
console.log(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].blue(message), ...args);
|
|
339
|
-
}
|
|
340
|
-
success(message, ...args) {
|
|
341
|
-
console.log(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].green(message), ...args);
|
|
342
|
-
}
|
|
343
|
-
warn(message, ...args) {
|
|
344
|
-
console.log(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].yellow(message), ...args);
|
|
345
|
-
}
|
|
346
|
-
error(message, ...args) {
|
|
347
|
-
console.error(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].red(message), ...args);
|
|
348
|
-
}
|
|
349
|
-
debug(message, ...args) {
|
|
350
|
-
if (this.verbose) console.log(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].gray(message), ...args);
|
|
351
|
-
}
|
|
352
|
-
table(data) {
|
|
353
|
-
console.table(data);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
774
|
function createUpdateExportsCommand(program) {
|
|
357
|
-
program.command("update-exports").description("Updates exports for all packages").option("-p, --package <package>", "Filter by package name").option("-d, --dry-run", "Run without making changes").option("-
|
|
775
|
+
program.command("update-exports").description("Updates exports for all packages").option("-p, --package <package>", "Filter by package name").option("-d, --dry-run", "Run without making changes").option("-c, --config <path>", "Path to configuration file").action(async (options)=>{
|
|
358
776
|
const processorOptions = {
|
|
359
777
|
packageFilter: options.package,
|
|
360
778
|
dryRun: Boolean(options.dryRun),
|
|
361
|
-
verbose: Boolean(options.verbose),
|
|
362
779
|
configPath: options.config
|
|
363
780
|
};
|
|
364
|
-
const logger = new Logger({
|
|
365
|
-
verbose: processorOptions.verbose
|
|
366
|
-
});
|
|
367
781
|
try {
|
|
368
|
-
await processAllPackages(processorOptions
|
|
782
|
+
await processAllPackages(processorOptions);
|
|
369
783
|
} catch (error) {
|
|
370
|
-
|
|
784
|
+
console.error("Error processing packages:", error);
|
|
371
785
|
process.exit(1);
|
|
372
786
|
}
|
|
373
787
|
});
|
|
@@ -385,7 +799,9 @@ function main() {
|
|
|
385
799
|
const program = new __WEBPACK_EXTERNAL_MODULE_commander__.Command();
|
|
386
800
|
program.name("codefast").description("CodeFast CLI - A development toolkit for CodeFast.").version(getPackageVersion(), "-v, --version", "display CLI version");
|
|
387
801
|
createUpdateExportsCommand(program);
|
|
802
|
+
createProjectCommand(program);
|
|
388
803
|
program.action(()=>{
|
|
804
|
+
console.log('Use "codefast create-project" to create a new Next.js project.');
|
|
389
805
|
console.log('Use "codefast update-exports" to update exports.');
|
|
390
806
|
console.log('Run "codefast --help" to see all available commands.');
|
|
391
807
|
program.help();
|