@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 CHANGED
@@ -1,5 +1,31 @@
1
1
  # @codefast/cli
2
2
 
3
+ ## 0.3.1-canary.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [`ed2ba2c`](https://github.com/codefastlabs/codefast/commit/ed2ba2cd81cfbf5764fe4631b9de9a5dcaa6ddfa) Thanks [@thevuong](https://github.com/thevuong)! - feat(cli): add cleanup step to remove unnecessary packages
8
+
9
+ - [`ee7c42f`](https://github.com/codefastlabs/codefast/commit/ee7c42f2ad157288c11e2cfbc2d2dbb52be8a6b5) Thanks [@thevuong](https://github.com/thevuong)! - feat(cli): update layout.tsx with fontVariables support
10
+
11
+ - [`53b416f`](https://github.com/codefastlabs/codefast/commit/53b416f7cb45c7d6d5834aa853c59c38ca1fbba8) Thanks [@thevuong](https://github.com/thevuong)! - feat(cli): modularize project creation functionalities
12
+
13
+ - [`24a767b`](https://github.com/codefastlabs/codefast/commit/24a767b8be3bb0cbe63a3ab3b13ab64130341218) Thanks [@thevuong](https://github.com/thevuong)! - refactor(cli): improve config file handling in project setup
14
+
15
+ ## 0.3.1-canary.5
16
+
17
+ ### Patch Changes
18
+
19
+ - [`f5b9777`](https://github.com/codefastlabs/codefast/commit/f5b977794956920183e2b132633e61cac4be4fdb) Thanks [@thevuong](https://github.com/thevuong)! - feat(cli): skip Next.js project creation if package.json exists
20
+
21
+ - [`77ccc05`](https://github.com/codefastlabs/codefast/commit/77ccc0556a1da4ee934af56fe8aef66eec0e1cf0) Thanks [@thevuong](https://github.com/thevuong)! - feat: support optional values in change handlers
22
+
23
+ - [`876c1cb`](https://github.com/codefastlabs/codefast/commit/876c1cb7d7ff7691096da7cc19faa44ddcffea70) Thanks [@thevuong](https://github.com/thevuong)! - refactor(cli): remove logger utility and update logging usage
24
+
25
+ - [`9e7aa7c`](https://github.com/codefastlabs/codefast/commit/9e7aa7c40e8d68257fbcd62ddb8fc7e2f6fcc895) Thanks [@thevuong](https://github.com/thevuong)! - chore(dependencies): update dependencies to latest versions
26
+
27
+ - [`80bd1ad`](https://github.com/codefastlabs/codefast/commit/80bd1ad5282d489b2da9f84d373adc40a9b24dc2) Thanks [@thevuong](https://github.com/thevuong)! - feat(cli): add enhanced project creation command
28
+
3
29
  ## 0.3.1-canary.4
4
30
 
5
31
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -26,9 +26,455 @@ var __webpack_require__ = {};
26
26
  })();
27
27
  var __webpack_exports__ = {};
28
28
  const external_commander_namespaceObject = require("commander");
29
- const external_glob_namespaceObject = require("glob");
29
+ const external_node_fs_namespaceObject = require("node:fs");
30
+ var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
30
31
  const external_node_path_namespaceObject = require("node:path");
31
32
  var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
33
+ const external_node_child_process_namespaceObject = require("node:child_process");
34
+ const external_node_readline_namespaceObject = require("node:readline");
35
+ var external_node_readline_default = /*#__PURE__*/ __webpack_require__.n(external_node_readline_namespaceObject);
36
+ const rl = external_node_readline_default().createInterface({
37
+ input: process.stdin,
38
+ output: process.stdout
39
+ });
40
+ function utils_prompt(question) {
41
+ return new Promise((resolve)=>{
42
+ rl.question(question, (answer)=>{
43
+ resolve(answer.trim());
44
+ });
45
+ });
46
+ }
47
+ function runCommand(command) {
48
+ (0, external_node_child_process_namespaceObject.execSync)(command, {
49
+ stdio: "inherit"
50
+ });
51
+ }
52
+ function writeConfigFile(filePath, content) {
53
+ external_node_fs_default().writeFileSync(filePath, content);
54
+ console.log(`๐Ÿ“ Created ${filePath}`);
55
+ }
56
+ function validateProjectName(name) {
57
+ if (!name || /^\s*$/.test(name)) return {
58
+ valid: false,
59
+ error: "Project name cannot be empty or contain only whitespace."
60
+ };
61
+ if (name.length > 100) return {
62
+ valid: false,
63
+ error: "Project name is too long (maximum 100 characters)."
64
+ };
65
+ const npmNameRegex = /^[a-z0-9-~][a-z0-9-._~]*$/;
66
+ if (!npmNameRegex.test(name)) return {
67
+ valid: false,
68
+ error: "Project name must be URL-friendly (letters, numbers, hyphens, underscores, dots; no @ or scoped packages)."
69
+ };
70
+ if ("." === name || ".." === name) return {
71
+ valid: false,
72
+ error: "Project name cannot be '.' or '..'."
73
+ };
74
+ const reservedNames = /^(?<reserved>CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$/i;
75
+ if (reservedNames.test(name)) return {
76
+ valid: false,
77
+ error: `Project name "${name}" is a reserved system name.`
78
+ };
79
+ const fullPath = external_node_path_default().resolve(process.cwd(), name);
80
+ if (external_node_fs_default().existsSync(fullPath)) return {
81
+ valid: false,
82
+ error: `A directory named "${name}" already exists.`
83
+ };
84
+ try {
85
+ external_node_fs_default().accessSync(process.cwd(), external_node_fs_default().constants.W_OK);
86
+ } catch {
87
+ return {
88
+ valid: false,
89
+ error: "Cannot create project: No write permission in current directory."
90
+ };
91
+ }
92
+ return {
93
+ valid: true
94
+ };
95
+ }
96
+ async function getValidProjectName(initialName, attempts = 0, maxAttempts = 3) {
97
+ const projectName = initialName ?? await utils_prompt("Enter project name: ");
98
+ const validation = validateProjectName(projectName);
99
+ if (validation.valid) return projectName;
100
+ if (attempts >= maxAttempts - 1) throw new Error(`โŒ Exceeded maximum attempts to enter a valid project name.`);
101
+ console.error(`โŒ ${validation.error} (${maxAttempts - attempts - 1} attempts remaining)`);
102
+ return getValidProjectName(void 0, attempts + 1, maxAttempts);
103
+ }
104
+ async function checkExistingProject(projectNameArg) {
105
+ const packageJsonPath = external_node_path_default().join(process.cwd(), "package.json");
106
+ const packageJsonExists = external_node_fs_default().existsSync(packageJsonPath);
107
+ if (packageJsonExists) {
108
+ console.log(`โš ๏ธ A package.json file has been detected in the current directory.`);
109
+ const confirm = await utils_prompt("Do you want to continue configuring this existing project? [Y/n]: ");
110
+ if ("" === confirm || "y" === confirm.toLowerCase()) {
111
+ const packageJson = JSON.parse(external_node_fs_default().readFileSync(packageJsonPath, "utf8"));
112
+ const projectName = packageJson.name ?? await getValidProjectName(projectNameArg);
113
+ return {
114
+ projectName,
115
+ packageJsonExists
116
+ };
117
+ }
118
+ console.log("Aborting...");
119
+ throw new Error("User aborted the operation.");
120
+ }
121
+ const projectName = await getValidProjectName(projectNameArg);
122
+ return {
123
+ projectName,
124
+ packageJsonExists
125
+ };
126
+ }
127
+ const MAIN_DEPENDENCIES = [
128
+ "@codefast/ui",
129
+ "@codefast/hooks"
130
+ ];
131
+ const DEV_DEPENDENCIES = {
132
+ commitLint: [
133
+ "@commitlint/cli",
134
+ "@commitlint/config-conventional",
135
+ "@commitlint/types"
136
+ ],
137
+ gitTools: [
138
+ "simple-git-hooks"
139
+ ],
140
+ formatting: [
141
+ "prettier",
142
+ "prettier-plugin-packagejson",
143
+ "prettier-plugin-tailwindcss",
144
+ "lint-staged"
145
+ ],
146
+ linting: [
147
+ "@codefast/eslint-config"
148
+ ]
149
+ };
150
+ const PACKAGES_TO_REMOVE = [
151
+ "@eslint/eslintrc"
152
+ ];
153
+ const configGroups = {
154
+ linting: [
155
+ {
156
+ path: "commitlint.config.mjs",
157
+ content: `/**
158
+ * @see https://commitlint.js.org/reference/configuration.html
159
+ * @type {import('@commitlint/types').UserConfig}
160
+ */
161
+ const config = {
162
+ extends: ["@commitlint/config-conventional"],
163
+ rules: {
164
+ "body-max-line-length": [2, "always", 350],
165
+ },
166
+ };
167
+ export default config;
168
+ `,
169
+ description: "Commitlint configuration"
170
+ },
171
+ {
172
+ path: "eslint.config.mjs",
173
+ content: `import { config } from "@codefast/eslint-config/next";
174
+ /**
175
+ * @see https://eslint.org/docs/latest/use/configure/configuration-files
176
+ * @type {import('eslint').Linter.Config[]}
177
+ */
178
+ const eslintConfig = [...config];
179
+ export default eslintConfig;
180
+ `,
181
+ description: "ESLint configuration for the project"
182
+ },
183
+ {
184
+ path: "lint-staged.config.mjs",
185
+ content: `import { relative } from "node:path";
186
+ /**
187
+ * Builds an ESLint command with the given filenames.
188
+ *
189
+ * @param {string[]} filenames - An array of filenames to be passed to the
190
+ * ESLint command.
191
+ * @returns {string} - The generated ESLint command.
192
+ */
193
+ function buildEslintCommand(filenames) {
194
+ return \`next lint --fix --max-warnings 0 --file \${filenames.map((file) => relative(import.meta.dirname, file)).
195
+ join(" --file ")}\`;
196
+ }
197
+ /**
198
+ * @see https://www.npmjs.com/package/lint-staged
199
+ * @type {import('lint-staged').Configuration}
200
+ */
201
+ const config = {
202
+ "*.{js,mjs,jsx,ts,tsx}": [buildEslintCommand, "prettier --list-different --write"],
203
+ "*.{json,css,md,mdx}": ["prettier --list-different --write"],
204
+ };
205
+ export default config;
206
+ `,
207
+ description: "Configure lint-staged for pre-commit checks"
208
+ }
209
+ ],
210
+ formatting: [
211
+ {
212
+ path: "prettier.config.mjs",
213
+ content: `/**
214
+ * @see https://prettier.io/docs/en/configuration.html
215
+ * @type {import('prettier').Config}
216
+ */
217
+ const config = {
218
+ plugins: ["prettier-plugin-packagejson", "prettier-plugin-tailwindcss"],
219
+ printWidth: 100,
220
+ tailwindAttributes: ["classNames"],
221
+ tailwindFunctions: ["tv"],
222
+ };
223
+ export default config;
224
+ `,
225
+ description: "Prettier configuration for source code formatting"
226
+ }
227
+ ],
228
+ styles: [
229
+ {
230
+ path: "src/lib/fonts.ts",
231
+ content: `import { cn } from "@codefast/ui";
232
+ import { Geist, Geist_Mono as GeistMono } from "next/font/google";
233
+ const fontGeistSans = Geist({
234
+ subsets: ["latin"],
235
+ variable: "--font-geist-sans",
236
+ });
237
+ const fontGeistMono = GeistMono({
238
+ subsets: ["latin"],
239
+ variable: "--font-geist-mono",
240
+ });
241
+ export const fontVariables = cn(fontGeistSans.variable, fontGeistMono.variable);
242
+ `,
243
+ description: "Font configuration for the application"
244
+ },
245
+ {
246
+ path: "src/app/globals.css",
247
+ content: `@import "tailwindcss";
248
+ @import "@codefast/ui/styles.css";
249
+ @source '../../node_modules/@codefast/ui';
250
+ @custom-variant dark (&:where(.dark, .dark *));
251
+ @layer base {
252
+ :root {
253
+ --font-sans: var(--font-geist-sans);
254
+ --font-mono: var(--font-geist-mono);
255
+ --input: var(--color-neutral-200);
256
+ --border: var(--color-neutral-200);
257
+ --ring: var(--color-neutral-400);
258
+ --background: var(--color-white);
259
+ --foreground: var(--color-neutral-950);
260
+ --primary: var(--color-sky-500);
261
+ --primary-foreground: var(--color-neutral-50);
262
+ --secondary: var(--color-neutral-100);
263
+ --secondary-foreground: var(--color-neutral-900);
264
+ --destructive: var(--color-red-600);
265
+ --accent: var(--color-neutral-100);
266
+ --accent-foreground: var(--color-neutral-900);
267
+ --muted: var(--color-neutral-100);
268
+ --muted-foreground: var(--color-neutral-500);
269
+ --popover: var(--color-white);
270
+ --popover-foreground: var(--color-neutral-950);
271
+ --popover-overlay: --alpha(var(--color-neutral-900) / 20%);
272
+ --card: var(--color-white);
273
+ --card-foreground: var(--color-neutral-950);
274
+ --sidebar: var(--color-neutral-50);
275
+ --sidebar-foreground: var(--color-neutral-950);
276
+ --sidebar-primary: var(--color-sky-500);
277
+ --sidebar-primary-foreground: var(--color-neutral-50);
278
+ --sidebar-accent: var(--color-neutral-100);
279
+ --sidebar-accent-foreground: var(--color-neutral-900);
280
+ --sidebar-border: var(--color-neutral-200);
281
+ --sidebar-ring: var(--color-neutral-400);
282
+ --chart-1: var(--color-orange-600);
283
+ --chart-2: var(--color-teal-600);
284
+ --chart-3: var(--color-cyan-600);
285
+ --chart-4: var(--color-amber-600);
286
+ --chart-5: var(--color-amber-500);
287
+ }
288
+ @variant dark {
289
+ --input: var(--color-neutral-700);
290
+ --border: --alpha(var(--color-neutral-700) / 50%);
291
+ --ring: var(--color-neutral-500);
292
+ --background: var(--color-neutral-950);
293
+ --foreground: var(--color-neutral-50);
294
+ --primary: var(--color-sky-700);
295
+ --primary-foreground: var(--color-neutral-50);
296
+ --secondary: var(--color-neutral-800);
297
+ --secondary-foreground: var(--color-neutral-50);
298
+ --destructive: var(--color-red-400);
299
+ --accent: var(--color-neutral-700);
300
+ --accent-foreground: var(--color-neutral-50);
301
+ --muted: var(--color-neutral-800);
302
+ --muted-foreground: var(--color-neutral-400);
303
+ --popover: var(--color-neutral-800);
304
+ --popover-foreground: var(--color-neutral-50);
305
+ --popover-overlay: --alpha(var(--color-neutral-900) / 80%);
306
+ --card: var(--color-neutral-900);
307
+ --card-foreground: var(--color-neutral-50);
308
+ --sidebar: var(--color-neutral-900);
309
+ --sidebar-foreground: var(--color-neutral-50);
310
+ --sidebar-primary: var(--color-sky-700);
311
+ --sidebar-primary-foreground: var(--color-neutral-50);
312
+ --sidebar-accent: var(--color-neutral-800);
313
+ --sidebar-accent-foreground: var(--color-neutral-50);
314
+ --sidebar-border: var(--color-neutral-800);
315
+ --sidebar-ring: var(--color-neutral-600);
316
+ --chart-1: var(--color-blue-700);
317
+ --chart-2: var(--color-emerald-500);
318
+ --chart-3: var(--color-amber-500);
319
+ --chart-4: var(--color-purple-500);
320
+ --chart-5: var(--color-rose-500);
321
+ }
322
+ }
323
+ `,
324
+ description: "Global CSS variables for the application"
325
+ }
326
+ ]
327
+ };
328
+ function updatePostcssConfig(projectDir) {
329
+ const postcssConfigPath = external_node_path_default().join(projectDir, "postcss.config.mjs");
330
+ if (!external_node_fs_default().existsSync(postcssConfigPath)) return void console.warn(`โš ๏ธ postcss.config.mjs not found, skipping update.`);
331
+ let content = external_node_fs_default().readFileSync(postcssConfigPath, "utf8");
332
+ const typeComment = `/** @type {import('postcss-load-config').Config} */\n`;
333
+ if (content.includes(typeComment)) console.log(`๐Ÿ“ postcss.config.mjs already contains type comment, no changes made.`);
334
+ else {
335
+ content = content.replace("const config = {", `${typeComment}const config = {`);
336
+ external_node_fs_default().writeFileSync(postcssConfigPath, content);
337
+ console.log(`๐Ÿ“ Updated postcss.config.mjs with type comment.`);
338
+ }
339
+ }
340
+ function updateLayoutFile(projectDir) {
341
+ const layoutPath = external_node_path_default().join(projectDir, "src/app/layout.tsx");
342
+ if (!external_node_fs_default().existsSync(layoutPath)) return void console.warn(`โš ๏ธ src/app/layout.tsx not found, skipping update.`);
343
+ let content = external_node_fs_default().readFileSync(layoutPath, "utf8");
344
+ 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.`);
345
+ const newImports = `import type { Metadata } from "next";
346
+
347
+ import { cn } from "@codefast/ui";
348
+
349
+ import { fontVariables } from "@/lib/fonts";
350
+ import "@/app/globals.css";`;
351
+ content = content.replaceAll(/import\s+{[^}]+}\s+from\s+["']next\/font\/google["'];\s*/g, "");
352
+ content = content.replace(/const\s+geistSans\s*=[^;]+;\s*const\s+geistMono\s*=[^;]+;\s*/, "");
353
+ content = content.replace(/import\s+type\s+{[^}]+}\s+from\s+["']next["'];\s*import\s+["']\.\/globals\.css["'];\s*/, newImports);
354
+ const htmlRegex = /<html\s+lang="en"\s*>/;
355
+ const newHtml = '<html className={cn(fontVariables, "antialiased")} lang="en">';
356
+ content = content.replace(htmlRegex, newHtml);
357
+ const bodyRegex = /<body\s+className={`[^`]*`}\s*>/;
358
+ const newBody = "<body>";
359
+ content = content.replace(bodyRegex, newBody);
360
+ try {
361
+ external_node_fs_default().writeFileSync(layoutPath, content);
362
+ console.log(`๐Ÿ“ Updated src/app/layout.tsx to use fontVariables in html tag and removed className from body`);
363
+ } catch (error) {
364
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
365
+ console.warn(`โš ๏ธ Failed to update src/app/layout.tsx: ${errorMessage}`);
366
+ }
367
+ }
368
+ function updatePackageJson(projectDir) {
369
+ const packageJsonPath = external_node_path_default().join(projectDir, "package.json");
370
+ const packageJson = JSON.parse(external_node_fs_default().readFileSync(packageJsonPath, "utf8"));
371
+ packageJson.scripts = {
372
+ ...packageJson.scripts,
373
+ format: 'prettier --write "**/*.{js,mjs,jsx,ts,tsx,json,css,md,mdx}"',
374
+ "format:check": 'prettier --check "**/*.{js,mjs,jsx,ts,tsx,json,css,md,mdx}"',
375
+ "lint:check": "next lint --max-warnings 0"
376
+ };
377
+ packageJson["simple-git-hooks"] = {
378
+ "pre-commit": "pnpm lint-staged",
379
+ "commit-msg": "pnpm commitlint --edit"
380
+ };
381
+ external_node_fs_default().writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
382
+ console.log(`๐Ÿ“ Updated package.json`);
383
+ }
384
+ function createConfigFiles(projectDir) {
385
+ console.log(`\n๐Ÿ“ Creating configuration files...`);
386
+ for (const [category, configs] of Object.entries(configGroups)){
387
+ console.log(`\n๐Ÿ“‚ Setting up ${category} configurations:`);
388
+ for (const { path: filePath, content, description } of configs){
389
+ const fullPath = external_node_path_default().join(projectDir, filePath);
390
+ const dir = external_node_path_default().dirname(fullPath);
391
+ if (!external_node_fs_default().existsSync(dir)) external_node_fs_default().mkdirSync(dir, {
392
+ recursive: true
393
+ });
394
+ writeConfigFile(fullPath, content);
395
+ if (description) console.log(` โ„น๏ธ ${filePath}: ${description}`);
396
+ }
397
+ }
398
+ }
399
+ function installDependencies() {
400
+ console.log(`\n๐Ÿ“š Installing dependencies...`);
401
+ if (MAIN_DEPENDENCIES.length > 0) runCommand(`pnpm add ${MAIN_DEPENDENCIES.join(" ")}`);
402
+ const allDevDependencies = Object.values(DEV_DEPENDENCIES).flat().join(" ");
403
+ if (allDevDependencies) runCommand(`pnpm add -D ${allDevDependencies}`);
404
+ }
405
+ function cleanupPackages() {
406
+ console.log(`\n๐Ÿงน Cleaning up unnecessary packages...`);
407
+ const packageJsonPath = external_node_path_namespaceObject.join(process.cwd(), "package.json");
408
+ if (!external_node_fs_namespaceObject.existsSync(packageJsonPath)) return void console.warn(`โš ๏ธ package.json not found, skipping cleanup.`);
409
+ let packageJson;
410
+ try {
411
+ packageJson = JSON.parse(external_node_fs_namespaceObject.readFileSync(packageJsonPath, "utf8"));
412
+ } catch (error) {
413
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
414
+ console.warn(`โš ๏ธ Error reading package.json: ${errorMessage}, skipping cleanup.`);
415
+ return;
416
+ }
417
+ const dependencies = packageJson.dependencies ?? {};
418
+ const devDependencies = packageJson.devDependencies ?? {};
419
+ const packagesToRemove = PACKAGES_TO_REMOVE.filter((pkg)=>pkg in dependencies || pkg in devDependencies);
420
+ if (packagesToRemove.length > 0) runCommand(`pnpm remove ${packagesToRemove.join(" ")}`);
421
+ else console.log(`โ„น๏ธ No unnecessary packages found in package.json to remove.`);
422
+ }
423
+ function checkEnvironment() {
424
+ try {
425
+ (0, external_node_child_process_namespaceObject.execSync)("pnpm --version", {
426
+ stdio: "ignore"
427
+ });
428
+ } catch {
429
+ console.error(`โŒ PNPM chฦฐa ฤ‘ฦฐแปฃc cร i ฤ‘แบทt. Vui lรฒng cร i ฤ‘แบทt PNPM trฦฐแป›c.`);
430
+ process.exit(1);
431
+ }
432
+ }
433
+ function createNextProject(projectName) {
434
+ console.log(`๐Ÿ“ฆ Creating Next.js project...`);
435
+ const flags = '--ts --tailwind --eslint --app --turbo --use-pnpm --src-dir --turbopack --import-alias "@/*"';
436
+ runCommand(`npx create-next-app@latest ${projectName} ${flags}`);
437
+ }
438
+ function createProjectCommand(program) {
439
+ program.command("create-project [name]").description("Create a new Next.js project with recommended setup").action(async (projectNameArg)=>{
440
+ try {
441
+ checkEnvironment();
442
+ const { projectName, packageJsonExists } = await checkExistingProject(projectNameArg);
443
+ if (!packageJsonExists) {
444
+ console.log(`\n๐Ÿš€ Starting project creation for ${projectName}...\n`);
445
+ createNextProject(projectName);
446
+ process.chdir(projectName);
447
+ console.log(`๐Ÿ“‚ Moved to ${projectName}`);
448
+ }
449
+ updateLayoutFile(process.cwd());
450
+ updatePostcssConfig(process.cwd());
451
+ installDependencies();
452
+ cleanupPackages();
453
+ createConfigFiles(process.cwd());
454
+ updatePackageJson(process.cwd());
455
+ console.log(`\n๐Ÿ”„ Activating git hooks...`);
456
+ runCommand("pnpm simple-git-hooks");
457
+ console.log(`\n๐Ÿ“ Formatting files with Prettier...`);
458
+ runCommand("pnpm format");
459
+ console.log(`\nโœ… Project ${packageJsonExists ? "configured" : "created"} successfully!`);
460
+ console.log(`- Project: ${projectName}`);
461
+ console.log("- Next.js with TypeScript");
462
+ console.log("- TailwindCSS and @codefast/ui");
463
+ console.log("- ESLint, Prettier, Commitlint, and Git Hooks");
464
+ console.log("- Lint-staged for pre-commit checks");
465
+ console.log(`\n๐Ÿ“ Project directory: ${process.cwd()}`);
466
+ console.log(`\n๐Ÿš€ To start development:`);
467
+ console.log(`cd ${projectName} && pnpm dev`);
468
+ } catch (error) {
469
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
470
+ console.error(`\nโŒ An error occurred: ${errorMessage}`);
471
+ process.exit(1);
472
+ } finally{
473
+ rl.close();
474
+ }
475
+ });
476
+ }
477
+ const external_glob_namespaceObject = require("glob");
32
478
  const external_ts_morph_namespaceObject = require("ts-morph");
33
479
  function makeRegexPrefixesToRemove(prefixes) {
34
480
  const prefixPattern = prefixes.join("|");
@@ -85,8 +531,6 @@ function analyzeImports(indexFilePath, packageConfig) {
85
531
  };
86
532
  }
87
533
  const external_lodash_es_namespaceObject = require("lodash-es");
88
- const external_node_fs_namespaceObject = require("node:fs");
89
- var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
90
534
  const external_zod_namespaceObject = require("zod");
91
535
  const PackageConfigSchema = external_zod_namespaceObject.z["interface"]({
92
536
  cjsOutputPattern: external_zod_namespaceObject.z.string(),
@@ -280,122 +724,92 @@ async function findAllPackages(config) {
280
724
  ignore: DEFAULT_IGNORE_PATTERN
281
725
  });
282
726
  }
283
- function processPackage(packageJsonPath, options, logger) {
727
+ function processPackage(packageJsonPath, options) {
284
728
  const packageDir = external_node_path_default().dirname(packageJsonPath);
285
729
  const packageJson = readPackageJson(packageJsonPath);
286
730
  if (!packageJson) {
287
- logger.error(`Failed to read ${packageJsonPath}`);
731
+ console.error(`Failed to read ${packageJsonPath}`);
288
732
  return false;
289
733
  }
290
734
  const packageName = packageJson.name;
291
735
  if (options.packageFilter && packageName !== options.packageFilter) {
292
- logger.debug(`Skipping ${packageName} (does not match filter)`);
736
+ console.debug(`Skipping ${packageName} (does not match filter)`);
293
737
  return false;
294
738
  }
295
- logger.info(`\n๐Ÿ“ฆ Processing package: ${packageName}`);
739
+ console.info(`Processing package: ${packageName}`);
296
740
  const config = getConfig(options.configPath);
297
741
  const packageConfig = getPackageConfig(packageName, config);
298
742
  const srcIndexPath = external_node_path_default().join(packageDir, packageConfig.srcIndexPath);
299
743
  if (!fileExists(srcIndexPath)) {
300
- logger.error(`Source file not found at ${srcIndexPath}`);
744
+ console.error(`Source file not found at ${srcIndexPath}`);
301
745
  return false;
302
746
  }
303
- logger.info(`๐Ÿ” Analyzing imports from ${srcIndexPath}...`);
747
+ console.info(`Analyzing imports from ${srcIndexPath}...`);
304
748
  const { imports } = analyzeImports(srcIndexPath, packageConfig);
305
749
  if (0 === imports.length) {
306
- logger.warn(`No imports found to analyze in ${packageName}`);
750
+ console.warn(`No imports found to analyze in ${packageName}`);
307
751
  return false;
308
752
  }
309
- logger.success(`Analysis complete. Found ${imports.length} subpath exports.`);
753
+ console.log(`Analysis complete. Found ${imports.length} subpath exports.`);
310
754
  saveExportsAnalysis(packageDir, {
311
755
  imports
312
756
  });
313
757
  const newExports = generateExports(packageName, imports, packageJson.exports, config);
314
758
  const currentExportsCount = packageJson.exports ? Object.keys(packageJson.exports).length : 0;
315
759
  const newExportsCount = Object.keys(newExports).length;
316
- logger.info(`๐Ÿ“Š Exports: ${currentExportsCount} -> ${newExportsCount}`);
760
+ console.info(`Exports: ${currentExportsCount} -> ${newExportsCount}`);
317
761
  if (options.dryRun) {
318
762
  saveExportsPreview(packageDir, newExports);
319
- logger.warn(`๐Ÿงช ๐Ÿ“„ Saved exports preview to .exports-analysis`);
320
- logger.warn(`๐Ÿงช ๐Ÿšซ Dry run: no changes saved for ${packageName}`);
763
+ console.warn("Saved exports preview to .exports-analysis");
764
+ console.warn(`Dry run: no changes saved for ${packageName}`);
321
765
  return true;
322
766
  }
323
- if (backupPackageJson(packageJsonPath)) logger.success(`Backed up ${packageJsonPath}`);
767
+ if (backupPackageJson(packageJsonPath)) console.log(`Backed up ${packageJsonPath}`);
324
768
  const updatedPackageJson = {
325
769
  ...packageJson,
326
770
  exports: newExports
327
771
  };
328
772
  if (savePackageJson(packageJsonPath, updatedPackageJson)) {
329
- logger.success(`Updated exports for ${packageName}`);
773
+ console.log(`Updated exports for ${packageName}`);
330
774
  return true;
331
775
  }
332
- logger.error(`Failed to update ${packageJsonPath}`);
776
+ console.error(`Failed to update ${packageJsonPath}`);
333
777
  return false;
334
778
  }
335
- async function processAllPackages(options, logger) {
779
+ async function processAllPackages(options) {
336
780
  try {
337
- logger.info("๐Ÿ” Searching for packages...");
781
+ console.info("Searching for packages...");
338
782
  const config = getConfig(options.configPath);
339
783
  const packageJsonPaths = await findAllPackages(config);
340
- if (0 === packageJsonPaths.length) return void logger.warn("โš ๏ธ No packages found.");
341
- logger.success(`โœ… Found ${packageJsonPaths.length} packages.`);
784
+ if (0 === packageJsonPaths.length) return void console.warn("No packages found.");
785
+ console.log(`Found ${packageJsonPaths.length} packages.`);
342
786
  let successCount = 0;
343
787
  let skipCount = 0;
344
788
  let errorCount = 0;
345
789
  for (const packageJsonPath of packageJsonPaths){
346
- const result = processPackage(packageJsonPath, options, logger);
790
+ const result = processPackage(packageJsonPath, options);
347
791
  if (result) successCount++;
348
792
  else if (options.packageFilter) skipCount++;
349
793
  else errorCount++;
350
794
  }
351
- logger.success("\nโœ… Completed exports update.");
352
- logger.info(`๐Ÿ“Š Stats: ${successCount} succeeded, ${skipCount} skipped, ${errorCount} failed`);
795
+ console.log("Completed exports update.");
796
+ console.info(`Stats: ${successCount} succeeded, ${skipCount} skipped, ${errorCount} failed`);
353
797
  } catch (error) {
354
- logger.error("โŒ Error processing packages:", error);
798
+ console.error("Error processing packages:", error);
355
799
  throw error;
356
800
  }
357
801
  }
358
- const external_chalk_namespaceObject = require("chalk");
359
- var external_chalk_default = /*#__PURE__*/ __webpack_require__.n(external_chalk_namespaceObject);
360
- class Logger {
361
- verbose;
362
- constructor(options = {}){
363
- this.verbose = options.verbose ?? false;
364
- }
365
- info(message, ...args) {
366
- console.log(external_chalk_default().blue(message), ...args);
367
- }
368
- success(message, ...args) {
369
- console.log(external_chalk_default().green(message), ...args);
370
- }
371
- warn(message, ...args) {
372
- console.log(external_chalk_default().yellow(message), ...args);
373
- }
374
- error(message, ...args) {
375
- console.error(external_chalk_default().red(message), ...args);
376
- }
377
- debug(message, ...args) {
378
- if (this.verbose) console.log(external_chalk_default().gray(message), ...args);
379
- }
380
- table(data) {
381
- console.table(data);
382
- }
383
- }
384
802
  function createUpdateExportsCommand(program) {
385
- 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("-v, --verbose", "Show detailed output").option("-c, --config <path>", "Path to configuration file").action(async (options)=>{
803
+ 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)=>{
386
804
  const processorOptions = {
387
805
  packageFilter: options.package,
388
806
  dryRun: Boolean(options.dryRun),
389
- verbose: Boolean(options.verbose),
390
807
  configPath: options.config
391
808
  };
392
- const logger = new Logger({
393
- verbose: processorOptions.verbose
394
- });
395
809
  try {
396
- await processAllPackages(processorOptions, logger);
810
+ await processAllPackages(processorOptions);
397
811
  } catch (error) {
398
- logger.error("Error processing packages:", error);
812
+ console.error("Error processing packages:", error);
399
813
  process.exit(1);
400
814
  }
401
815
  });
@@ -414,7 +828,9 @@ function main() {
414
828
  const program = new external_commander_namespaceObject.Command();
415
829
  program.name("codefast").description("CodeFast CLI - A development toolkit for CodeFast.").version(getPackageVersion(), "-v, --version", "display CLI version");
416
830
  createUpdateExportsCommand(program);
831
+ createProjectCommand(program);
417
832
  program.action(()=>{
833
+ console.log('Use "codefast create-project" to create a new Next.js project.');
418
834
  console.log('Use "codefast update-exports" to update exports.');
419
835
  console.log('Run "codefast --help" to see all available commands.');
420
836
  program.help();