create-next-pro-cli 0.1.14 → 0.1.17
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/README.md +3 -2
- package/create-next-pro-completion.sh +9 -1
- package/dist/{bin.js → bin.bun.js} +128 -9
- package/dist/bin.node.js +682 -0
- package/dist/bin.node.js.map +1 -0
- package/dist/create-next-pro +10 -0
- package/package.json +24 -8
- package/templates/Projects/default/README.md +36 -0
- package/templates/Projects/default/src/app/[locale]/(public)/Login/page.tsx +6 -0
- package/templates/Projects/default/src/app/[locale]/(public)/Register/page.tsx +6 -0
- package/templates/Projects/default/src/app/[locale]/(public)/_home/loading.tsx +5 -0
- package/templates/Projects/default/src/app/[locale]/(public)/_home/page.tsx +6 -0
- package/templates/Projects/default/src/app/[locale]/(public)/layout.tsx +9 -0
- package/templates/Projects/default/src/app/[locale]/(user)/Dashboard/error.tsx +38 -0
- package/templates/Projects/default/src/app/[locale]/(user)/Dashboard/loading.tsx +10 -0
- package/templates/Projects/default/src/app/[locale]/(user)/Dashboard/page.tsx +5 -0
- package/templates/Projects/default/src/app/[locale]/(user)/Settings/loading.tsx +17 -0
- package/templates/Projects/default/src/app/[locale]/(user)/Settings/page.tsx +6 -0
- package/templates/Projects/default/src/app/[locale]/(user)/UserInfo/loading.tsx +17 -0
- package/templates/Projects/default/src/app/[locale]/(user)/UserInfo/page.tsx +6 -0
- package/templates/Projects/default/src/app/[locale]/(user)/layout.tsx +9 -0
- package/templates/Projects/default/src/app/[locale]/layout.tsx +31 -0
- package/templates/Projects/default/src/app/[locale]/loading.tsx +14 -0
- package/templates/Projects/default/src/app/[locale]/not-found.tsx +22 -0
- package/templates/Projects/default/src/app/[locale]/page.tsx +6 -0
- package/templates/Projects/default/src/app/api/auth/[...nextauth]/route.ts +62 -0
- package/templates/Projects/default/src/app/api/auth/post-login/route.ts +26 -0
- package/templates/Projects/default/src/app/favicon.ico +0 -0
- package/templates/Projects/default/src/app/layout.tsx +11 -0
- package/templates/Projects/default/src/app/not-found.tsx +17 -0
- package/templates/Projects/default/src/app/page.tsx +6 -0
- package/templates/Projects/default/src/app/sitemap.ts +27 -0
- package/templates/Projects/default/src/app/styles/globals.css +305 -0
- package/templates/Projects/default/src/auth.config.ts +0 -0
- package/templates/Projects/default/src/config.ts +4 -0
- package/templates/Projects/default/src/lib/auth/disconnect.ts +11 -0
- package/templates/Projects/default/src/lib/auth/isConnected.ts +18 -0
- package/templates/Projects/default/src/lib/i18n/navigation.ts +19 -0
- package/templates/Projects/default/src/lib/i18n/request.ts +31 -0
- package/templates/Projects/default/src/lib/i18n/routing.ts +20 -0
- package/templates/Projects/default/src/lib/utils.ts +6 -0
- package/templates/Projects/default/src/ui/Dashboard/LogoutButton.tsx +27 -0
- package/templates/Projects/default/src/ui/Dashboard/StatsCard.tsx +14 -0
- package/templates/Projects/default/src/ui/Dashboard/WelcomeCard.tsx +10 -0
- package/templates/Projects/default/src/ui/Dashboard/page-ui.tsx +23 -0
- package/templates/Projects/default/src/ui/Login/page-ui.tsx +22 -0
- package/templates/Projects/default/src/ui/Register/page-ui.tsx +26 -0
- package/templates/Projects/default/src/ui/Settings/page-ui.tsx +17 -0
- package/templates/Projects/default/src/ui/UserInfo/page-ui.tsx +17 -0
- package/templates/Projects/default/src/ui/_global/BackButton.tsx +17 -0
- package/templates/Projects/default/src/ui/_global/Button.tsx +75 -0
- package/templates/Projects/default/src/ui/_global/GlobalHeader.tsx +55 -0
- package/templates/Projects/default/src/ui/_global/GlobalMain.tsx +15 -0
- package/templates/Projects/default/src/ui/_global/Loading.tsx +13 -0
- package/templates/Projects/default/src/ui/_global/LocaleSwitcher.tsx +38 -0
- package/templates/Projects/default/src/ui/_global/PublicNav.tsx +91 -0
- package/templates/Projects/default/src/ui/_global/ThemeToggle.tsx +53 -0
- package/templates/Projects/default/src/ui/_global/UserNav.tsx +35 -0
- package/templates/Projects/default/src/ui/_home/page-ui.tsx +27 -0
- package/.github/workflows/ci.yml +0 -38
- package/bin.ts +0 -3
- package/commitlint.config.cjs +0 -12
- package/install.sh +0 -74
- package/tsconfig.json +0 -27
package/dist/bin.node.js
ADDED
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import os from "os";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import prompts5 from "prompts";
|
|
8
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9
|
+
import { dirname, resolve } from "path";
|
|
10
|
+
|
|
11
|
+
// src/lib/addComponent.ts
|
|
12
|
+
import { join as join2 } from "path";
|
|
13
|
+
import { mkdir, readFile as readFile2, writeFile, readdir } from "fs/promises";
|
|
14
|
+
import prompts from "prompts";
|
|
15
|
+
|
|
16
|
+
// src/lib/utils.ts
|
|
17
|
+
import { readFile } from "fs/promises";
|
|
18
|
+
import { existsSync } from "fs";
|
|
19
|
+
import { join } from "path";
|
|
20
|
+
function capitalize(str) {
|
|
21
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
22
|
+
}
|
|
23
|
+
async function loadConfig() {
|
|
24
|
+
const configPath = join(process.cwd(), "cnp.config.json");
|
|
25
|
+
if (!existsSync(configPath)) return null;
|
|
26
|
+
try {
|
|
27
|
+
const raw = await readFile(configPath, "utf-8");
|
|
28
|
+
return JSON.parse(raw);
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function toFileName(key) {
|
|
34
|
+
switch (key) {
|
|
35
|
+
case "layout":
|
|
36
|
+
return "layout.tsx";
|
|
37
|
+
case "page":
|
|
38
|
+
return "page.tsx";
|
|
39
|
+
case "loading":
|
|
40
|
+
return "loading.tsx";
|
|
41
|
+
case "not-found":
|
|
42
|
+
return "not-found.tsx";
|
|
43
|
+
case "error":
|
|
44
|
+
return "error.tsx";
|
|
45
|
+
case "global-error":
|
|
46
|
+
return "global-error.tsx";
|
|
47
|
+
case "route":
|
|
48
|
+
return "route.ts";
|
|
49
|
+
case "template":
|
|
50
|
+
return "template.tsx";
|
|
51
|
+
case "default":
|
|
52
|
+
return "default.tsx";
|
|
53
|
+
default:
|
|
54
|
+
return `${key}.tsx`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/lib/addComponent.ts
|
|
59
|
+
import { existsSync as existsSync2, statSync } from "fs";
|
|
60
|
+
async function addComponent(args) {
|
|
61
|
+
let componentName = args[1];
|
|
62
|
+
let pageScope = null;
|
|
63
|
+
let pageIndex = args.findIndex((arg) => arg === "-P" || arg === "--page");
|
|
64
|
+
if (pageIndex !== -1 && args[pageIndex + 1]) {
|
|
65
|
+
pageScope = args[pageIndex + 1];
|
|
66
|
+
}
|
|
67
|
+
let nestedPath = null;
|
|
68
|
+
if (pageScope && pageScope.includes(".")) {
|
|
69
|
+
nestedPath = join2(...pageScope.split("."));
|
|
70
|
+
}
|
|
71
|
+
if (!componentName || componentName.startsWith("-")) {
|
|
72
|
+
const response = await prompts.prompt({
|
|
73
|
+
type: "text",
|
|
74
|
+
name: "componentName",
|
|
75
|
+
message: "\u{1F9E9} Component name to add:",
|
|
76
|
+
validate: (name) => name ? true : "Component name is required"
|
|
77
|
+
});
|
|
78
|
+
componentName = response.componentName;
|
|
79
|
+
}
|
|
80
|
+
const config = await loadConfig();
|
|
81
|
+
if (!config) {
|
|
82
|
+
console.error(
|
|
83
|
+
"\u274C Configuration file cnp.config.json not found. Run this command from the project root."
|
|
84
|
+
);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const useI18n = !!config.useI18n;
|
|
88
|
+
const componentNameUpper = capitalize(componentName);
|
|
89
|
+
const templatePath = join2(
|
|
90
|
+
import.meta.dir,
|
|
91
|
+
"..",
|
|
92
|
+
"..",
|
|
93
|
+
"templates",
|
|
94
|
+
"Component"
|
|
95
|
+
);
|
|
96
|
+
let messagesPath = null;
|
|
97
|
+
if (useI18n) {
|
|
98
|
+
messagesPath = join2(process.cwd(), "messages");
|
|
99
|
+
if (!existsSync2(messagesPath)) {
|
|
100
|
+
console.error("\u274C Messages directory missing. Ensure i18n was configured.");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
let componentTargetPath;
|
|
105
|
+
let translationKey;
|
|
106
|
+
if (pageScope) {
|
|
107
|
+
if (nestedPath) {
|
|
108
|
+
componentTargetPath = join2(process.cwd(), "src", "ui", nestedPath);
|
|
109
|
+
translationKey = pageScope;
|
|
110
|
+
} else {
|
|
111
|
+
componentTargetPath = join2(process.cwd(), "src", "ui", pageScope);
|
|
112
|
+
translationKey = pageScope;
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
componentTargetPath = join2(process.cwd(), "src", "ui", "_global");
|
|
116
|
+
translationKey = "_global_ui";
|
|
117
|
+
}
|
|
118
|
+
if (!existsSync2(componentTargetPath)) {
|
|
119
|
+
await mkdir(componentTargetPath, { recursive: true });
|
|
120
|
+
}
|
|
121
|
+
const componentFile = join2(componentTargetPath, `${componentNameUpper}.tsx`);
|
|
122
|
+
const templateComponentPath = join2(templatePath, "Component.tsx");
|
|
123
|
+
if (existsSync2(templateComponentPath)) {
|
|
124
|
+
let content = await readFile2(templateComponentPath, "utf-8");
|
|
125
|
+
content = content.replace(/Component/g, componentNameUpper).replace(/componentPage/g, translationKey);
|
|
126
|
+
await writeFile(componentFile, content);
|
|
127
|
+
console.log(`\u{1F4C4} File created: ${componentFile}`);
|
|
128
|
+
} else {
|
|
129
|
+
console.error(
|
|
130
|
+
"\u274C Template Component.tsx introuvable :",
|
|
131
|
+
templateComponentPath
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
if (useI18n && messagesPath) {
|
|
135
|
+
const entries = await readdir(messagesPath, { withFileTypes: true });
|
|
136
|
+
const langDirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
137
|
+
const jsonTemplate = join2(templatePath, "component.json");
|
|
138
|
+
if (!existsSync2(jsonTemplate)) {
|
|
139
|
+
console.error("\u274C Template component.json not found:", jsonTemplate);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const jsonContent = await readFile2(jsonTemplate, "utf-8");
|
|
143
|
+
const parsed = JSON.parse(jsonContent);
|
|
144
|
+
for (const locale of langDirs) {
|
|
145
|
+
const localeDir = join2(messagesPath, locale);
|
|
146
|
+
if (!existsSync2(localeDir) || !statSync(localeDir).isDirectory())
|
|
147
|
+
continue;
|
|
148
|
+
let jsonTarget;
|
|
149
|
+
if (pageScope) {
|
|
150
|
+
jsonTarget = join2(messagesPath, locale, `${pageScope}.json`);
|
|
151
|
+
} else {
|
|
152
|
+
jsonTarget = join2(messagesPath, locale, `_global_ui.json`);
|
|
153
|
+
}
|
|
154
|
+
let current = {};
|
|
155
|
+
if (existsSync2(jsonTarget)) {
|
|
156
|
+
const jsonFile = await readFile2(jsonTarget, "utf-8");
|
|
157
|
+
current = JSON.parse(jsonFile);
|
|
158
|
+
}
|
|
159
|
+
current[componentNameUpper] = parsed;
|
|
160
|
+
await writeFile(jsonTarget, JSON.stringify(current, null, 2));
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
console.log("\u2139\uFE0F Skipping translation entries; next-intl not enabled.");
|
|
164
|
+
}
|
|
165
|
+
console.log(
|
|
166
|
+
`\u2705 Component "${componentNameUpper}" added ${pageScope ? `to page ${pageScope}` : "globally"}${useI18n ? " with localized messages" : ""}.`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/lib/addPage.ts
|
|
171
|
+
import { join as join3 } from "path";
|
|
172
|
+
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2, readdir as readdir2 } from "fs/promises";
|
|
173
|
+
import prompts2 from "prompts";
|
|
174
|
+
import { existsSync as existsSync3, statSync as statSync2 } from "fs";
|
|
175
|
+
async function addPage(args) {
|
|
176
|
+
let pageName = args[1];
|
|
177
|
+
if (!pageName || pageName.startsWith("-")) {
|
|
178
|
+
const response = await prompts2.prompt({
|
|
179
|
+
type: "text",
|
|
180
|
+
name: "pageName",
|
|
181
|
+
message: "\u{1F4DD} Page name to add:",
|
|
182
|
+
validate: (name) => name ? true : "Page name is required"
|
|
183
|
+
});
|
|
184
|
+
pageName = response.pageName;
|
|
185
|
+
}
|
|
186
|
+
let parentName = null;
|
|
187
|
+
let childName = null;
|
|
188
|
+
if (pageName.includes(".")) {
|
|
189
|
+
[parentName, childName] = pageName.split(".");
|
|
190
|
+
}
|
|
191
|
+
let shortFlags = args.find((arg) => /^-[A-Za-z]+$/.test(arg));
|
|
192
|
+
let longFlags = new Set(args.filter((a) => a.startsWith("--")));
|
|
193
|
+
const flags = /* @__PURE__ */ new Set();
|
|
194
|
+
if (!shortFlags && Array.from(longFlags).length === 0) {
|
|
195
|
+
shortFlags = "-LPl";
|
|
196
|
+
}
|
|
197
|
+
if (shortFlags) {
|
|
198
|
+
for (const char of shortFlags.slice(1)) {
|
|
199
|
+
switch (char) {
|
|
200
|
+
case "L":
|
|
201
|
+
flags.add("layout");
|
|
202
|
+
break;
|
|
203
|
+
case "P":
|
|
204
|
+
flags.add("page");
|
|
205
|
+
break;
|
|
206
|
+
case "l":
|
|
207
|
+
flags.add("loading");
|
|
208
|
+
break;
|
|
209
|
+
case "n":
|
|
210
|
+
flags.add("not-found");
|
|
211
|
+
break;
|
|
212
|
+
case "e":
|
|
213
|
+
flags.add("error");
|
|
214
|
+
break;
|
|
215
|
+
case "g":
|
|
216
|
+
flags.add("global-error");
|
|
217
|
+
break;
|
|
218
|
+
case "r":
|
|
219
|
+
flags.add("route");
|
|
220
|
+
break;
|
|
221
|
+
case "t":
|
|
222
|
+
flags.add("template");
|
|
223
|
+
break;
|
|
224
|
+
case "d":
|
|
225
|
+
flags.add("default");
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
for (const flag of [
|
|
231
|
+
"layout",
|
|
232
|
+
"page",
|
|
233
|
+
"loading",
|
|
234
|
+
"not-found",
|
|
235
|
+
"error",
|
|
236
|
+
"global-error",
|
|
237
|
+
"route",
|
|
238
|
+
"template",
|
|
239
|
+
"default"
|
|
240
|
+
]) {
|
|
241
|
+
if (longFlags.has("--" + flag)) flags.add(flag);
|
|
242
|
+
}
|
|
243
|
+
const config = await loadConfig();
|
|
244
|
+
if (!config) {
|
|
245
|
+
console.error("\u274C Configuration file cnp.config.json not found. Run this command from the project root.");
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const useI18n = !!config.useI18n;
|
|
249
|
+
const srcSegments = ["src", "app"];
|
|
250
|
+
if (useI18n) srcSegments.push("[locale]");
|
|
251
|
+
const srcPath = join3(process.cwd(), ...srcSegments);
|
|
252
|
+
if (!existsSync3(srcPath)) {
|
|
253
|
+
console.error(`\u274C Expected directory not found: ${srcPath}`);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
let messagesPath = null;
|
|
257
|
+
let locales = [];
|
|
258
|
+
if (useI18n) {
|
|
259
|
+
messagesPath = join3(process.cwd(), "messages");
|
|
260
|
+
if (!existsSync3(messagesPath)) {
|
|
261
|
+
console.error("\u274C Messages directory missing. Ensure i18n was configured.");
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const entries = await readdir2(messagesPath, { withFileTypes: true });
|
|
265
|
+
locales = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
266
|
+
}
|
|
267
|
+
const templatePath = join3(import.meta.dir, "..", "..", "templates", "Page");
|
|
268
|
+
let uiPageDir, localePagePath, jsonFileName;
|
|
269
|
+
if (parentName && childName) {
|
|
270
|
+
uiPageDir = join3(process.cwd(), "src", "ui", parentName, childName);
|
|
271
|
+
localePagePath = join3(srcPath, parentName, childName);
|
|
272
|
+
jsonFileName = parentName;
|
|
273
|
+
} else {
|
|
274
|
+
uiPageDir = join3(process.cwd(), "src", "ui", pageName);
|
|
275
|
+
localePagePath = join3(srcPath, pageName);
|
|
276
|
+
jsonFileName = pageName;
|
|
277
|
+
}
|
|
278
|
+
if (!existsSync3(uiPageDir)) {
|
|
279
|
+
await mkdir2(uiPageDir, { recursive: true });
|
|
280
|
+
}
|
|
281
|
+
const uiPageFile = join3(uiPageDir, "page-ui.tsx");
|
|
282
|
+
const uiPageTemplate = join3(templatePath, "page-ui.tsx");
|
|
283
|
+
if (existsSync3(uiPageTemplate)) {
|
|
284
|
+
let uiContent = await readFile3(uiPageTemplate, "utf-8");
|
|
285
|
+
uiContent = uiContent.replace(/template/g, childName || pageName).replace(/Template/g, capitalize(childName || pageName));
|
|
286
|
+
await writeFile2(uiPageFile, uiContent);
|
|
287
|
+
console.log(`\u{1F4C4} File created: ${uiPageFile}`);
|
|
288
|
+
} else {
|
|
289
|
+
console.warn("\u26A0\uFE0F Template page-ui.tsx manquant.");
|
|
290
|
+
}
|
|
291
|
+
if (!existsSync3(localePagePath)) {
|
|
292
|
+
await mkdir2(localePagePath, { recursive: true });
|
|
293
|
+
}
|
|
294
|
+
for (const flag of flags) {
|
|
295
|
+
const filename = toFileName(flag);
|
|
296
|
+
const src = join3(templatePath, filename);
|
|
297
|
+
const dst = join3(localePagePath, filename);
|
|
298
|
+
if (!existsSync3(src)) {
|
|
299
|
+
console.warn(`\u26A0\uFE0F Missing template file: ${filename}`);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
const content = await readFile3(src, "utf-8");
|
|
303
|
+
const replaced = content.replace(/template/g, childName || pageName).replace(/Template/g, capitalize(childName || pageName));
|
|
304
|
+
await writeFile2(dst, replaced);
|
|
305
|
+
console.log(`\u{1F4C4} File created: ${dst}`);
|
|
306
|
+
}
|
|
307
|
+
if (useI18n && messagesPath) {
|
|
308
|
+
const jsonTemplate = join3(templatePath, "page.json");
|
|
309
|
+
if (!existsSync3(jsonTemplate)) {
|
|
310
|
+
console.warn("\u26A0\uFE0F Missing template page.json.");
|
|
311
|
+
} else {
|
|
312
|
+
const content = await readFile3(jsonTemplate, "utf-8");
|
|
313
|
+
const replaced = content.replace(/template/g, childName || pageName).replace(/Template/g, capitalize(childName || pageName));
|
|
314
|
+
for (const locale of locales) {
|
|
315
|
+
const localeDir = join3(messagesPath, locale);
|
|
316
|
+
if (!existsSync3(localeDir) || !statSync2(localeDir).isDirectory())
|
|
317
|
+
continue;
|
|
318
|
+
const jsonTarget = join3(messagesPath, locale, `${jsonFileName}.json`);
|
|
319
|
+
let current = {};
|
|
320
|
+
if (existsSync3(jsonTarget)) {
|
|
321
|
+
const jsonFile = await readFile3(jsonTarget, "utf-8");
|
|
322
|
+
try {
|
|
323
|
+
current = JSON.parse(jsonFile);
|
|
324
|
+
} catch {
|
|
325
|
+
current = {};
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (parentName && childName) {
|
|
329
|
+
current[childName] = JSON.parse(replaced);
|
|
330
|
+
} else {
|
|
331
|
+
current = JSON.parse(replaced);
|
|
332
|
+
}
|
|
333
|
+
await writeFile2(jsonTarget, JSON.stringify(current, null, 2));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
} else {
|
|
337
|
+
console.log("\u2139\uFE0F Skipping translation templates; next-intl not enabled.");
|
|
338
|
+
}
|
|
339
|
+
console.log(
|
|
340
|
+
`\u2705 Page "${pageName}" with templates added${useI18n ? " for each locale" : ""}.`
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// src/lib/rmPage.ts
|
|
345
|
+
import { join as join4 } from "path";
|
|
346
|
+
import { writeFile as writeFile3, readdir as readdir3 } from "fs/promises";
|
|
347
|
+
import prompts3 from "prompts";
|
|
348
|
+
import { existsSync as existsSync4 } from "fs";
|
|
349
|
+
async function rmPage(args) {
|
|
350
|
+
let pageName = args[1];
|
|
351
|
+
if (!pageName || pageName.startsWith("-")) {
|
|
352
|
+
const response = await prompts3.prompt({
|
|
353
|
+
type: "text",
|
|
354
|
+
name: "pageName",
|
|
355
|
+
message: "\u{1F5D1}\uFE0F Page name to remove:",
|
|
356
|
+
validate: (name) => name ? true : "Page name is required"
|
|
357
|
+
});
|
|
358
|
+
pageName = response.pageName;
|
|
359
|
+
}
|
|
360
|
+
const messagesPath = join4(process.cwd(), "messages");
|
|
361
|
+
const entries = await readdir3(messagesPath, { withFileTypes: true });
|
|
362
|
+
const langDirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
363
|
+
for (const locale of langDirs) {
|
|
364
|
+
const jsonTarget = join4(messagesPath, locale, `${pageName}.json`);
|
|
365
|
+
if (existsSync4(jsonTarget)) {
|
|
366
|
+
await writeFile3(jsonTarget, "");
|
|
367
|
+
await import("child_process").then(
|
|
368
|
+
(cp2) => cp2.execSync(`rm -f '${jsonTarget}'`)
|
|
369
|
+
);
|
|
370
|
+
console.log(`\u{1F5D1}\uFE0F Deleted: ${jsonTarget}`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
const uiPageDir = join4(process.cwd(), "src", "ui", pageName);
|
|
374
|
+
if (existsSync4(uiPageDir)) {
|
|
375
|
+
await import("child_process").then(
|
|
376
|
+
(cp2) => cp2.execSync(`rm -rf '${uiPageDir}'`)
|
|
377
|
+
);
|
|
378
|
+
console.log(`\u{1F5D1}\uFE0F Deleted: ${uiPageDir}`);
|
|
379
|
+
}
|
|
380
|
+
const appLocaleDir = join4(process.cwd(), "src", "app", "[locale]", pageName);
|
|
381
|
+
if (existsSync4(appLocaleDir)) {
|
|
382
|
+
await import("child_process").then(
|
|
383
|
+
(cp2) => cp2.execSync(`rm -rf '${appLocaleDir}'`)
|
|
384
|
+
);
|
|
385
|
+
console.log(`\u{1F5D1}\uFE0F Deleted: ${appLocaleDir}`);
|
|
386
|
+
}
|
|
387
|
+
console.log(`\u2705 Page "${pageName}" deleted.`);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// src/scaffold.ts
|
|
391
|
+
import { cp, mkdir as mkdir3, rm, writeFile as writeFile4, readFile as readFile4 } from "fs/promises";
|
|
392
|
+
import { join as join5 } from "path";
|
|
393
|
+
import { existsSync as existsSync5 } from "fs";
|
|
394
|
+
import { fileURLToPath } from "url";
|
|
395
|
+
async function scaffoldProject(options) {
|
|
396
|
+
const targetPath = join5(process.cwd(), options.projectName);
|
|
397
|
+
const __dirname2 = new URL(".", import.meta.url);
|
|
398
|
+
const templatePath = join5(
|
|
399
|
+
fileURLToPath(__dirname2),
|
|
400
|
+
"..",
|
|
401
|
+
"templates",
|
|
402
|
+
"Projects",
|
|
403
|
+
"default"
|
|
404
|
+
);
|
|
405
|
+
if (existsSync5(targetPath)) {
|
|
406
|
+
if (options.force) {
|
|
407
|
+
console.warn("\u26A0\uFE0F Target directory already exists, removing...");
|
|
408
|
+
await rm(targetPath, { recursive: true, force: true });
|
|
409
|
+
} else {
|
|
410
|
+
console.error(
|
|
411
|
+
"\u274C Target directory already exists. Use --force to overwrite."
|
|
412
|
+
);
|
|
413
|
+
process.exit(1);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
console.log("\u{1F4C1} Creating project directory...");
|
|
418
|
+
await mkdir3(targetPath, { recursive: true });
|
|
419
|
+
console.log("\u{1F4E6} Copying files from template...");
|
|
420
|
+
await cp(templatePath, targetPath, { recursive: true });
|
|
421
|
+
const pkgPath = join5(targetPath, "package.json");
|
|
422
|
+
if (existsSync5(pkgPath)) {
|
|
423
|
+
const pkg = JSON.parse(await readFile4(pkgPath, "utf-8"));
|
|
424
|
+
pkg.dependencies = pkg.dependencies || {};
|
|
425
|
+
if (options.useI18n) {
|
|
426
|
+
pkg.dependencies["next-intl"] = pkg.dependencies["next-intl"] || "^4.3.5";
|
|
427
|
+
}
|
|
428
|
+
await writeFile4(pkgPath, JSON.stringify(pkg, null, 2));
|
|
429
|
+
}
|
|
430
|
+
await writeFile4(
|
|
431
|
+
join5(targetPath, "cnp.config.json"),
|
|
432
|
+
JSON.stringify(options, null, 2)
|
|
433
|
+
);
|
|
434
|
+
console.log("\u2705 Project scaffolded successfully!");
|
|
435
|
+
console.log(`\u27A1\uFE0F cd ${options.projectName} && bun install && bun dev`);
|
|
436
|
+
} catch (err) {
|
|
437
|
+
console.error("\u274C Error during scaffolding:", err);
|
|
438
|
+
process.exit(1);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// src/lib/createProject.ts
|
|
443
|
+
async function createProject(nameArg, force) {
|
|
444
|
+
const response = {
|
|
445
|
+
projectName: nameArg,
|
|
446
|
+
useTypescript: true,
|
|
447
|
+
useEslint: true,
|
|
448
|
+
useTailwind: true,
|
|
449
|
+
useSrcDir: true,
|
|
450
|
+
useTurbopack: true,
|
|
451
|
+
useI18n: true,
|
|
452
|
+
customAlias: true,
|
|
453
|
+
importAlias: "@/*",
|
|
454
|
+
force
|
|
455
|
+
};
|
|
456
|
+
console.log(`\u{1F4E6} Creating project "${response.projectName}"...`);
|
|
457
|
+
await scaffoldProject(response);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// src/lib/createProjectWithPrompt.ts
|
|
461
|
+
import prompts4 from "prompts";
|
|
462
|
+
async function createProjectWithPrompt() {
|
|
463
|
+
const response = await prompts4.prompt([
|
|
464
|
+
{
|
|
465
|
+
type: "text",
|
|
466
|
+
name: "projectName",
|
|
467
|
+
message: "\u{1F9F1} Project name:",
|
|
468
|
+
initial: "my-next-app"
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
type: "toggle",
|
|
472
|
+
name: "useTypescript",
|
|
473
|
+
message: "\u2714 Use TypeScript?",
|
|
474
|
+
initial: true,
|
|
475
|
+
active: "Yes",
|
|
476
|
+
inactive: "No"
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
type: "toggle",
|
|
480
|
+
name: "useEslint",
|
|
481
|
+
message: "\u2714 Use ESLint?",
|
|
482
|
+
initial: true,
|
|
483
|
+
active: "Yes",
|
|
484
|
+
inactive: "No"
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
type: "toggle",
|
|
488
|
+
name: "useTailwind",
|
|
489
|
+
message: "\u2714 Use Tailwind CSS?",
|
|
490
|
+
initial: true,
|
|
491
|
+
active: "Yes",
|
|
492
|
+
inactive: "No"
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
type: "toggle",
|
|
496
|
+
name: "useSrcDir",
|
|
497
|
+
message: "\u2714 Use `src/` directory?",
|
|
498
|
+
initial: true,
|
|
499
|
+
active: "Yes",
|
|
500
|
+
inactive: "No"
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
type: "toggle",
|
|
504
|
+
name: "useTurbopack",
|
|
505
|
+
message: "\u2714 Use Turbopack for `next dev`?",
|
|
506
|
+
initial: true,
|
|
507
|
+
active: "Yes",
|
|
508
|
+
inactive: "No"
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
type: "toggle",
|
|
512
|
+
name: "useI18n",
|
|
513
|
+
message: "\u2714 Use i18n with next-intl for translations?",
|
|
514
|
+
initial: true,
|
|
515
|
+
active: "Yes",
|
|
516
|
+
inactive: "No"
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
type: "toggle",
|
|
520
|
+
name: "customAlias",
|
|
521
|
+
message: "\u2714 Customize import alias (`@/*` by default)?",
|
|
522
|
+
initial: true,
|
|
523
|
+
active: "Yes",
|
|
524
|
+
inactive: "No"
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
type: (prev) => prev ? "text" : null,
|
|
528
|
+
name: "importAlias",
|
|
529
|
+
message: "\u2714 What import alias would you like?",
|
|
530
|
+
initial: "@core/*"
|
|
531
|
+
}
|
|
532
|
+
]);
|
|
533
|
+
console.log("\n\u2705 Your choices:");
|
|
534
|
+
console.log(response);
|
|
535
|
+
await scaffoldProject(response);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// src/index.ts
|
|
539
|
+
var CONFIG_DIR = process.env.XDG_CONFIG_HOME ? path.join(process.env.XDG_CONFIG_HOME, "create-next-pro") : path.join(os.homedir(), ".config", "create-next-pro");
|
|
540
|
+
var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
541
|
+
function readCfg() {
|
|
542
|
+
try {
|
|
543
|
+
return JSON.parse(fs.readFileSync(CONFIG_FILE, "utf8"));
|
|
544
|
+
} catch {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
function writeCfg(cfg) {
|
|
549
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
550
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2));
|
|
551
|
+
}
|
|
552
|
+
function rcFile(shell) {
|
|
553
|
+
return path.join(os.homedir(), shell === "zsh" ? ".zshrc" : ".bashrc");
|
|
554
|
+
}
|
|
555
|
+
function ensureLineInRc(file, line) {
|
|
556
|
+
try {
|
|
557
|
+
const cur = fs.existsSync(file) ? fs.readFileSync(file, "utf8") : "";
|
|
558
|
+
if (!cur.includes(line)) fs.appendFileSync(file, `
|
|
559
|
+
${line}
|
|
560
|
+
`);
|
|
561
|
+
} catch {
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
async function installCompletion(shell) {
|
|
565
|
+
const __dirname2 = path.dirname(fileURLToPath2(import.meta.url));
|
|
566
|
+
const completionSrc = path.resolve(
|
|
567
|
+
__dirname2,
|
|
568
|
+
"../create-next-pro-completion.sh"
|
|
569
|
+
);
|
|
570
|
+
const completionDst = path.join(CONFIG_DIR, "completion.sh");
|
|
571
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
572
|
+
fs.copyFileSync(completionSrc, completionDst);
|
|
573
|
+
ensureLineInRc(rcFile(shell), `source "${completionDst}"`);
|
|
574
|
+
}
|
|
575
|
+
var __filename = fileURLToPath2(import.meta.url);
|
|
576
|
+
var __dirname = dirname(__filename);
|
|
577
|
+
var packageJsonPath = resolve(__dirname, "../package.json");
|
|
578
|
+
var packageJson = fs.readFileSync(packageJsonPath, "utf8");
|
|
579
|
+
async function onboarding() {
|
|
580
|
+
const pkg = JSON.parse(packageJson);
|
|
581
|
+
console.log(`\u{1F680} Welcome to create-next-pro v${pkg.version}
|
|
582
|
+
`);
|
|
583
|
+
const res = await prompts5(
|
|
584
|
+
[
|
|
585
|
+
{
|
|
586
|
+
type: "select",
|
|
587
|
+
name: "shell",
|
|
588
|
+
message: "Which shell do you use?",
|
|
589
|
+
choices: [
|
|
590
|
+
{ title: "zsh", value: "zsh" },
|
|
591
|
+
{ title: "bash", value: "bash" }
|
|
592
|
+
],
|
|
593
|
+
initial: (os.userInfo().shell || "").includes("zsh") ? 0 : 1
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
type: "toggle",
|
|
597
|
+
name: "completion",
|
|
598
|
+
message: "Install autocompletion?",
|
|
599
|
+
initial: true,
|
|
600
|
+
active: "Yes",
|
|
601
|
+
inactive: "No"
|
|
602
|
+
}
|
|
603
|
+
],
|
|
604
|
+
{ onCancel: () => process.exit(1) }
|
|
605
|
+
);
|
|
606
|
+
const cfg = {
|
|
607
|
+
version: 1,
|
|
608
|
+
shell: res.shell,
|
|
609
|
+
completionInstalled: !!res.completion,
|
|
610
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
611
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
612
|
+
};
|
|
613
|
+
if (cfg.completionInstalled) await installCompletion(cfg.shell);
|
|
614
|
+
writeCfg(cfg);
|
|
615
|
+
console.log("\n\u2705 Configuration saved.");
|
|
616
|
+
console.log("you can now use the CLI ! ex : create-next-pro <project-name>");
|
|
617
|
+
console.log(
|
|
618
|
+
"For more information, visit: https://github.com/Rising-Corporation/create-next-pro-cli"
|
|
619
|
+
);
|
|
620
|
+
console.log("Happy coding! \u{1F389}");
|
|
621
|
+
return cfg;
|
|
622
|
+
}
|
|
623
|
+
function showHelp() {
|
|
624
|
+
console.log(`create-next-pro
|
|
625
|
+
|
|
626
|
+
Usage:
|
|
627
|
+
create-next-pro <project-name> [--force]
|
|
628
|
+
create-next-pro addpage [options]
|
|
629
|
+
create-next-pro addcomponent [options]
|
|
630
|
+
create-next-pro rmpage [options]
|
|
631
|
+
|
|
632
|
+
Options:
|
|
633
|
+
--help Show this help message
|
|
634
|
+
--reconfigure Run the configuration assistant again
|
|
635
|
+
`);
|
|
636
|
+
}
|
|
637
|
+
function showVersion() {
|
|
638
|
+
const pkg = JSON.parse(packageJson);
|
|
639
|
+
console.log(`v${pkg.version}`);
|
|
640
|
+
}
|
|
641
|
+
async function main() {
|
|
642
|
+
let args;
|
|
643
|
+
if (typeof Bun !== "undefined") {
|
|
644
|
+
args = Bun.argv.slice(2);
|
|
645
|
+
} else if (typeof process !== "undefined" && process.argv) {
|
|
646
|
+
args = process.argv.slice(2);
|
|
647
|
+
} else {
|
|
648
|
+
args = [];
|
|
649
|
+
}
|
|
650
|
+
if (args.includes("--help")) return showHelp();
|
|
651
|
+
if (args.includes("--version") || args.includes("-v")) return showVersion();
|
|
652
|
+
if (args.includes("--reconfigure") || !readCfg()) {
|
|
653
|
+
await onboarding();
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
const force = args.includes("--force");
|
|
657
|
+
if (args[0] === "addpage" && args.length === 1) {
|
|
658
|
+
args.push("-LPl");
|
|
659
|
+
}
|
|
660
|
+
if (args[0] === "addcomponent") {
|
|
661
|
+
addComponent(args);
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
if (args[0] === "addpage") {
|
|
665
|
+
addPage(args);
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
if (args[0] === "rmpage") {
|
|
669
|
+
rmPage(args);
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
const nameArg = args.find((arg) => !arg.startsWith("--"));
|
|
673
|
+
if (nameArg) {
|
|
674
|
+
createProject(nameArg, force);
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
await createProjectWithPrompt();
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// bin.node.ts
|
|
681
|
+
main();
|
|
682
|
+
//# sourceMappingURL=bin.node.js.map
|