create-next-pro-cli 0.1.4 → 0.1.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.
Files changed (77) hide show
  1. package/package.json +5 -1
  2. package/src/index.ts +10 -454
  3. package/src/lib/addComponent.ts +113 -0
  4. package/src/lib/addPage.ts +170 -0
  5. package/src/lib/createProject.ts +18 -0
  6. package/src/lib/createProjectWithPrompt.ts +79 -0
  7. package/src/lib/rmPage.ts +52 -0
  8. package/src/lib/utils.ts +36 -0
  9. package/src/save-index.ts +520 -0
  10. package/templates/Page/loading.tsx +2 -7
  11. package/templates/Page/not-found.tsx +11 -0
  12. package/templates/Page/page-ui.tsx +1 -1
  13. package/templates/Projects/default/messages/en/{dashboard.json → Dashboard.json} +2 -1
  14. package/templates/Projects/default/messages/en/_global_ui.json +4 -0
  15. package/templates/Projects/default/messages/fr/{dashboard.json → Dashboard.json} +2 -1
  16. package/templates/Projects/default/messages/fr/_global_ui.json +4 -0
  17. package/templates/Projects/default/package.json +8 -2
  18. package/templates/Projects/default/src/app/[locale]/(public)/Login/page.tsx +6 -0
  19. package/templates/Projects/default/src/app/[locale]/(public)/Register/page.tsx +6 -0
  20. package/templates/Projects/default/src/app/[locale]/(public)/_home/loading.tsx +5 -1
  21. package/templates/Projects/default/src/app/[locale]/(public)/_home/page.tsx +3 -13
  22. package/templates/Projects/default/src/app/[locale]/(public)/layout.tsx +0 -2
  23. package/templates/Projects/default/src/app/[locale]/(user)/Dashboard/loading.tsx +10 -0
  24. package/templates/Projects/default/src/app/[locale]/(user)/Dashboard/page.tsx +5 -0
  25. package/templates/Projects/default/src/app/[locale]/(user)/Settings/page.tsx +6 -0
  26. package/templates/Projects/default/src/app/[locale]/(user)/UserInfo/page.tsx +6 -0
  27. package/templates/Projects/default/src/app/[locale]/(user)/layout.tsx +0 -3
  28. package/templates/Projects/default/src/app/[locale]/layout.tsx +3 -4
  29. package/templates/Projects/default/src/app/[locale]/loading.tsx +3 -6
  30. package/templates/Projects/default/src/app/[locale]/page.tsx +1 -111
  31. package/templates/Projects/default/src/app/api/auth/[...nextauth]/route.ts +6 -25
  32. package/templates/Projects/default/src/app/api/auth/post-login/route.ts +1 -2
  33. package/templates/Projects/default/src/app/styles/globals.css +295 -16
  34. package/templates/Projects/default/src/lib/auth/disconnect.ts +11 -0
  35. package/templates/Projects/default/src/lib/auth/isConnected.ts +5 -3
  36. package/templates/Projects/default/src/lib/utils.ts +6 -0
  37. package/templates/Projects/default/src/ui/Dashboard/LogoutButton.tsx +27 -0
  38. package/templates/Projects/default/src/ui/{dashboard/page.tsx → Dashboard/page-ui.tsx} +5 -4
  39. package/templates/Projects/default/src/{app/[locale]/(public)/login/page.tsx → ui/Login/page-ui.tsx} +7 -4
  40. package/templates/Projects/default/src/{app/[locale]/(public)/register/page.tsx → ui/Register/page-ui.tsx} +7 -4
  41. package/templates/Projects/default/src/ui/Settings/page-ui.tsx +17 -0
  42. package/templates/Projects/default/src/ui/UserInfo/page-ui.tsx +17 -0
  43. package/templates/Projects/default/src/ui/_global/BackButton.tsx +5 -3
  44. package/templates/Projects/default/src/ui/_global/Button.tsx +75 -0
  45. package/templates/Projects/default/src/ui/_global/GlobalHeader.tsx +42 -21
  46. package/templates/Projects/default/src/ui/_global/GlobalMain.tsx +3 -3
  47. package/templates/Projects/default/src/ui/_global/Loading.tsx +13 -0
  48. package/templates/Projects/default/src/ui/_global/LocaleSwitcher.tsx +1 -1
  49. package/templates/Projects/default/src/ui/_global/PublicNav.tsx +74 -13
  50. package/templates/Projects/default/src/ui/_global/ThemeToggle.tsx +53 -0
  51. package/templates/Projects/default/src/ui/_global/UserNav.tsx +8 -5
  52. package/templates/Projects/default/src/ui/_home/page-ui.tsx +27 -0
  53. package/templates/Projects/default/public/cnp-logo.ico +0 -0
  54. package/templates/Projects/default/public/file.svg +0 -1
  55. package/templates/Projects/default/public/globe.svg +0 -1
  56. package/templates/Projects/default/public/next.svg +0 -1
  57. package/templates/Projects/default/public/vercel.svg +0 -1
  58. package/templates/Projects/default/public/window.svg +0 -1
  59. package/templates/Projects/default/src/app/[locale]/(user)/dashboard/loading.tsx +0 -17
  60. package/templates/Projects/default/src/app/[locale]/(user)/dashboard/page.tsx +0 -12
  61. package/templates/Projects/default/src/app/[locale]/(user)/settings/page.tsx +0 -12
  62. package/templates/Projects/default/src/app/[locale]/(user)/user_info/page.tsx +0 -12
  63. package/templates/Projects/default/src/app/api/auth/[...nextauth].ts +0 -0
  64. package/templates/Projects/default/src/app/api/me/route.ts +0 -15
  65. /package/templates/Projects/default/messages/en/{login.json → Login.json} +0 -0
  66. /package/templates/Projects/default/messages/en/{register.json → Register.json} +0 -0
  67. /package/templates/Projects/default/messages/en/{settings.json → Settings.json} +0 -0
  68. /package/templates/Projects/default/messages/en/{user_info.json → UserInfo.json} +0 -0
  69. /package/templates/Projects/default/messages/fr/{login.json → Login.json} +0 -0
  70. /package/templates/Projects/default/messages/fr/{register.json → Register.json} +0 -0
  71. /package/templates/Projects/default/messages/fr/{settings.json → Settings.json} +0 -0
  72. /package/templates/Projects/default/messages/fr/{user_info.json → UserInfo.json} +0 -0
  73. /package/templates/Projects/default/src/app/[locale]/(user)/{dashboard → Dashboard}/error.tsx +0 -0
  74. /package/templates/Projects/default/src/app/[locale]/(user)/{settings → Settings}/loading.tsx +0 -0
  75. /package/templates/Projects/default/src/app/[locale]/(user)/{user_info → UserInfo}/loading.tsx +0 -0
  76. /package/templates/Projects/default/src/ui/{dashboard → Dashboard}/StatsCard.tsx +0 -0
  77. /package/templates/Projects/default/src/ui/{dashboard → Dashboard}/WelcomeCard.tsx +0 -0
@@ -0,0 +1,170 @@
1
+ import { join } from "node:path";
2
+ import { mkdir, readFile, writeFile, readdir } from "node:fs/promises";
3
+ import prompts from "prompts";
4
+ import { capitalize, toFileName } from "./utils"; // Assuming you have a utility function to capitalize strings
5
+ import { existsSync } from "node:fs";
6
+
7
+ export async function addPage(args: string[]) {
8
+ let pageName = args[1];
9
+ if (!pageName || pageName.startsWith("-")) {
10
+ const response = await prompts.prompt({
11
+ type: "text",
12
+ name: "pageName",
13
+ message: "📝 Page name to add:",
14
+ validate: (name: string) => (name ? true : "Page name is required"),
15
+ });
16
+ pageName = response.pageName;
17
+ }
18
+
19
+ // Handle nested pages
20
+ let parentName = null;
21
+ let childName = null;
22
+ if (pageName.includes(".")) {
23
+ [parentName, childName] = pageName.split(".");
24
+ }
25
+
26
+ let shortFlags = args.find((arg) => /^-[A-Za-z]+$/.test(arg));
27
+ let longFlags = new Set(args.filter((a) => a.startsWith("--")));
28
+ const flags = new Set<string>();
29
+
30
+ if (!shortFlags && Array.from(longFlags).length === 0) {
31
+ shortFlags = "-LPl";
32
+ }
33
+
34
+ if (shortFlags) {
35
+ for (const char of shortFlags.slice(1)) {
36
+ switch (char) {
37
+ case "L":
38
+ flags.add("layout");
39
+ break;
40
+ case "P":
41
+ flags.add("page");
42
+ break;
43
+ case "l":
44
+ flags.add("loading");
45
+ break;
46
+ case "n":
47
+ flags.add("not-found");
48
+ break;
49
+ case "e":
50
+ flags.add("error");
51
+ break;
52
+ case "g":
53
+ flags.add("global-error");
54
+ break;
55
+ case "r":
56
+ flags.add("route");
57
+ break;
58
+ case "t":
59
+ flags.add("template");
60
+ break;
61
+ case "d":
62
+ flags.add("default");
63
+ break;
64
+ }
65
+ }
66
+ }
67
+
68
+ for (const flag of [
69
+ "layout",
70
+ "page",
71
+ "loading",
72
+ "not-found",
73
+ "error",
74
+ "global-error",
75
+ "route",
76
+ "template",
77
+ "default",
78
+ ]) {
79
+ if (longFlags.has("--" + flag)) flags.add(flag);
80
+ }
81
+
82
+ const srcPath = join(process.cwd(), "src", "app", "[locale]");
83
+ const messagesPath = join(process.cwd(), "messages");
84
+ const templatePath = join(import.meta.dir, "..", "templates", "Page");
85
+ const entries = await readdir(messagesPath, { withFileTypes: true });
86
+ const locales = entries.filter((e) => e.isDirectory()).map((e) => e.name);
87
+
88
+ // Create folders/files for nested or simple page
89
+ let uiPageDir, localePagePath, jsonFileName;
90
+ if (parentName && childName) {
91
+ uiPageDir = join(process.cwd(), "src", "ui", parentName, childName);
92
+ localePagePath = join(srcPath, parentName, childName);
93
+ jsonFileName = parentName;
94
+ } else {
95
+ uiPageDir = join(process.cwd(), "src", "ui", pageName);
96
+ localePagePath = join(srcPath, pageName);
97
+ jsonFileName = pageName;
98
+ }
99
+ if (!existsSync(uiPageDir)) {
100
+ await mkdir(uiPageDir, { recursive: true });
101
+ }
102
+ const uiPageFile = join(uiPageDir, "page-ui.tsx");
103
+ const uiPageTemplate = join(templatePath, "page-ui.tsx");
104
+ if (existsSync(uiPageTemplate)) {
105
+ let uiContent = await readFile(uiPageTemplate, "utf-8");
106
+ uiContent = uiContent
107
+ .replace(/template/g, childName || pageName)
108
+ .replace(/Template/g, capitalize(childName || pageName));
109
+ await writeFile(uiPageFile, uiContent);
110
+ console.log(`📄 File created: ${uiPageFile}`);
111
+ } else {
112
+ console.warn("⚠️ Template page-ui.tsx manquant.");
113
+ }
114
+ if (!existsSync(localePagePath)) {
115
+ await mkdir(localePagePath, { recursive: true });
116
+ }
117
+ for (const flag of flags) {
118
+ const filename = toFileName(flag);
119
+ const src = join(templatePath, filename);
120
+ const dst = join(localePagePath, filename);
121
+ if (!existsSync(src)) {
122
+ console.warn(`⚠️ Missing template file: ${filename}`);
123
+ continue;
124
+ }
125
+ const content = await readFile(src, "utf-8");
126
+ const replaced = content
127
+ .replace(/template/g, childName || pageName)
128
+ .replace(/Template/g, capitalize(childName || pageName));
129
+ await writeFile(dst, replaced);
130
+ console.log(`📄 File created: ${dst}`);
131
+ }
132
+
133
+ // Add JSON to parent object if nested, otherwise create a simple file
134
+ const jsonTemplate = join(templatePath, "page.json");
135
+ if (!existsSync(jsonTemplate)) {
136
+ console.warn("⚠️ Missing template page.json.");
137
+ }
138
+ const content = await readFile(jsonTemplate, "utf-8");
139
+ const replaced = content
140
+ .replace(/template/g, childName || pageName)
141
+ .replace(/Template/g, capitalize(childName || pageName));
142
+ for (const locale of locales) {
143
+ // Only process if messages/<locale> is a directory
144
+ const localeDir = join(messagesPath, locale);
145
+ if (
146
+ !existsSync(localeDir) ||
147
+ !require("node:fs").statSync(localeDir).isDirectory()
148
+ )
149
+ continue;
150
+ const jsonTarget = join(messagesPath, locale, `${jsonFileName}.json`);
151
+ let current: Record<string, any> = {};
152
+ if (existsSync(jsonTarget)) {
153
+ const jsonFile = await readFile(jsonTarget, "utf-8");
154
+ try {
155
+ current = JSON.parse(jsonFile) as Record<string, any>;
156
+ } catch {
157
+ current = {};
158
+ }
159
+ }
160
+ if (parentName && childName) {
161
+ current[childName] = JSON.parse(replaced);
162
+ } else {
163
+ // fichier simple
164
+ current = JSON.parse(replaced);
165
+ }
166
+ await writeFile(jsonTarget, JSON.stringify(current, null, 2));
167
+ }
168
+
169
+ console.log(`✅ Page "${pageName}" with templates added for each locale.`);
170
+ }
@@ -0,0 +1,18 @@
1
+ import { scaffoldProject } from "../scaffold";
2
+ export async function createProject(nameArg: string, force: boolean) {
3
+ const response = {
4
+ projectName: nameArg,
5
+ useTypescript: true,
6
+ useEslint: true,
7
+ useTailwind: true,
8
+ useSrcDir: true,
9
+ useTurbopack: true,
10
+ useI18n: true,
11
+ customAlias: false,
12
+ importAlias: "@/*",
13
+ force,
14
+ };
15
+
16
+ console.log(`📦 Creating project "${response.projectName}"...`);
17
+ await scaffoldProject(response);
18
+ }
@@ -0,0 +1,79 @@
1
+ import { scaffoldProject } from "../scaffold";
2
+ import prompts from "prompts";
3
+ export async function createProjectWithPrompt() {
4
+ const response = await prompts.prompt([
5
+ {
6
+ type: "text",
7
+ name: "projectName",
8
+ message: "🧱 Project name:",
9
+ initial: "my-next-app",
10
+ },
11
+ {
12
+ type: "toggle",
13
+ name: "useTypescript",
14
+ message: "✔ Use TypeScript?",
15
+ initial: true,
16
+ active: "Yes",
17
+ inactive: "No",
18
+ },
19
+ {
20
+ type: "toggle",
21
+ name: "useEslint",
22
+ message: "✔ Use ESLint?",
23
+ initial: true,
24
+ active: "Yes",
25
+ inactive: "No",
26
+ },
27
+ {
28
+ type: "toggle",
29
+ name: "useTailwind",
30
+ message: "✔ Use Tailwind CSS?",
31
+ initial: true,
32
+ active: "Yes",
33
+ inactive: "No",
34
+ },
35
+ {
36
+ type: "toggle",
37
+ name: "useSrcDir",
38
+ message: "✔ Use `src/` directory?",
39
+ initial: false,
40
+ active: "Yes",
41
+ inactive: "No",
42
+ },
43
+ {
44
+ type: "toggle",
45
+ name: "useTurbopack",
46
+ message: "✔ Use Turbopack for `next dev`?",
47
+ initial: true,
48
+ active: "Yes",
49
+ inactive: "No",
50
+ },
51
+ {
52
+ type: "toggle",
53
+ name: "useI18n",
54
+ message: "✔ Use i18n with next-intl for translations?",
55
+ initial: true,
56
+ active: "Yes",
57
+ inactive: "No",
58
+ },
59
+ {
60
+ type: "toggle",
61
+ name: "customAlias",
62
+ message: "✔ Customize import alias (`@/*` by default)?",
63
+ initial: false,
64
+ active: "Yes",
65
+ inactive: "No",
66
+ },
67
+ {
68
+ type: (prev: boolean) => (prev ? "text" : null),
69
+ name: "importAlias",
70
+ message: "✔ What import alias would you like?",
71
+ initial: "@core/*",
72
+ },
73
+ ]);
74
+
75
+ console.log("\n✅ Your choices:");
76
+ console.log(response);
77
+
78
+ await scaffoldProject(response);
79
+ }
@@ -0,0 +1,52 @@
1
+ import { join } from "node:path";
2
+ import { writeFile, readdir } from "node:fs/promises";
3
+ import prompts from "prompts";
4
+ import { existsSync } from "node:fs";
5
+
6
+ export async function rmPage(args: string[]) {
7
+ let pageName = args[1];
8
+ if (!pageName || pageName.startsWith("-")) {
9
+ const response = await prompts.prompt({
10
+ type: "text",
11
+ name: "pageName",
12
+ message: "🗑️ Page name to remove:",
13
+ validate: (name: string) => (name ? true : "Page name is required"),
14
+ });
15
+ pageName = response.pageName;
16
+ }
17
+
18
+ // Remove translation files messages/<lang>/<PageName>.json
19
+ const messagesPath = join(process.cwd(), "messages");
20
+ const entries = await readdir(messagesPath, { withFileTypes: true });
21
+ const langDirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
22
+ for (const locale of langDirs) {
23
+ const jsonTarget = join(messagesPath, locale, `${pageName}.json`);
24
+ if (existsSync(jsonTarget)) {
25
+ await writeFile(jsonTarget, "");
26
+ await import("node:child_process").then((cp) =>
27
+ cp.execSync(`rm -f '${jsonTarget}'`)
28
+ );
29
+ console.log(`🗑️ Deleted: ${jsonTarget}`);
30
+ }
31
+ }
32
+
33
+ // Remove folder src/ui/<PageName>
34
+ const uiPageDir = join(process.cwd(), "src", "ui", pageName);
35
+ if (existsSync(uiPageDir)) {
36
+ await import("node:child_process").then((cp) =>
37
+ cp.execSync(`rm -rf '${uiPageDir}'`)
38
+ );
39
+ console.log(`🗑️ Deleted: ${uiPageDir}`);
40
+ }
41
+
42
+ // Remove folder src/app/[locale]/<PageName>
43
+ const appLocaleDir = join(process.cwd(), "src", "app", "[locale]", pageName);
44
+ if (existsSync(appLocaleDir)) {
45
+ await import("node:child_process").then((cp) =>
46
+ cp.execSync(`rm -rf '${appLocaleDir}'`)
47
+ );
48
+ console.log(`🗑️ Deleted: ${appLocaleDir}`);
49
+ }
50
+
51
+ console.log(`✅ Page "${pageName}" deleted.`);
52
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Capitalize the first letter of a string.
3
+ */
4
+ export function capitalize(str: string): string {
5
+ return str.charAt(0).toUpperCase() + str.slice(1);
6
+ }
7
+
8
+ /**
9
+ * Map a key to its corresponding file name for page/component templates.
10
+ * @param key string
11
+ * @returns file name string
12
+ */
13
+ export function toFileName(key: string): string {
14
+ switch (key) {
15
+ case "layout":
16
+ return "layout.tsx";
17
+ case "page":
18
+ return "page.tsx";
19
+ case "loading":
20
+ return "loading.tsx";
21
+ case "not-found":
22
+ return "not-found.tsx";
23
+ case "error":
24
+ return "error.tsx";
25
+ case "global-error":
26
+ return "global-error.tsx";
27
+ case "route":
28
+ return "route.ts";
29
+ case "template":
30
+ return "template.tsx";
31
+ case "default":
32
+ return "default.tsx";
33
+ default:
34
+ return `${key}.tsx`;
35
+ }
36
+ }