create-egg 4.1.0-beta.18 → 4.1.0-beta.20
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/dist/cli.js +1 -1
- package/dist/index.js +1 -252
- package/dist/src-CwQ2SU3O.js +254 -0
- package/dist/templates/egg3-simple-js/_.gitignore +1 -0
- package/dist/templates/egg3-simple-ts/_.gitignore +1 -0
- package/dist/templates/egg3-tegg/_.gitignore +1 -0
- package/dist/templates/simple-ts/_.gitignore +1 -0
- package/dist/templates/tegg/_.gitignore +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,254 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import spawn from "cross-spawn";
|
|
4
|
-
import mri from "mri";
|
|
5
|
-
import * as prompts from "@clack/prompts";
|
|
6
|
-
import colors from "picocolors";
|
|
1
|
+
import { init } from "./src-CwQ2SU3O.js";
|
|
7
2
|
|
|
8
|
-
//#region src/index.ts
|
|
9
|
-
const { blue, blueBright, green, greenBright, yellow } = colors;
|
|
10
|
-
const argv = mri(process.argv.slice(2), {
|
|
11
|
-
alias: {
|
|
12
|
-
h: "help",
|
|
13
|
-
t: "template"
|
|
14
|
-
},
|
|
15
|
-
boolean: ["help", "overwrite"],
|
|
16
|
-
string: ["template"]
|
|
17
|
-
});
|
|
18
|
-
const cwd = process.cwd();
|
|
19
|
-
const helpMessage = `\
|
|
20
|
-
Usage: create-egg [OPTION]... [DIRECTORY]
|
|
21
|
-
|
|
22
|
-
Create a new Egg.js project.
|
|
23
|
-
With no arguments, start the CLI in interactive mode.
|
|
24
|
-
|
|
25
|
-
Options:
|
|
26
|
-
-t, --template NAME use a specific template
|
|
27
|
-
|
|
28
|
-
Available templates:
|
|
29
|
-
${green("tegg")} egg@4 with tegg module
|
|
30
|
-
${blue("simple-ts")} egg@4 with vanilla TypeScript
|
|
31
|
-
${green("egg3-tegg")} egg@3 with tegg module
|
|
32
|
-
${blue("egg3-simple-ts")} egg@3 with vanilla TypeScript
|
|
33
|
-
${yellow("egg3-simple-js")} egg@3 with vanilla JavaScript
|
|
34
|
-
`;
|
|
35
|
-
const TEMPLATES = [
|
|
36
|
-
{
|
|
37
|
-
name: "tegg",
|
|
38
|
-
display: "Tegg starter, egg@4 with tegg module",
|
|
39
|
-
color: green
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: "simple-ts",
|
|
43
|
-
display: "Simple starter, egg@4 with vanilla TypeScript",
|
|
44
|
-
color: blue
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: "egg3-tegg",
|
|
48
|
-
display: "Tegg starter, egg@3 with tegg module",
|
|
49
|
-
color: green
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
name: "egg3-simple-ts",
|
|
53
|
-
display: "Simple starter, egg@3 with vanilla TypeScript",
|
|
54
|
-
color: blue
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
name: "egg3-simple-js",
|
|
58
|
-
display: "Simple starter, egg@3 with vanilla JavaScript",
|
|
59
|
-
color: yellow
|
|
60
|
-
}
|
|
61
|
-
];
|
|
62
|
-
const defaultTargetDir = "egg-project";
|
|
63
|
-
async function init() {
|
|
64
|
-
const argTargetDir = argv._[0] ? formatTargetDir(String(argv._[0])) : void 0;
|
|
65
|
-
const argTemplate = argv.template;
|
|
66
|
-
const argOverwrite = argv.overwrite;
|
|
67
|
-
if (argv.help) {
|
|
68
|
-
console.log(helpMessage);
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent);
|
|
72
|
-
const cancel = () => prompts.cancel("Operation cancelled");
|
|
73
|
-
prompts.intro(`${greenBright("Egg.js")} - Born to build better enterprise application and framework`);
|
|
74
|
-
let targetDir = argTargetDir;
|
|
75
|
-
if (!targetDir) {
|
|
76
|
-
const projectName = await prompts.text({
|
|
77
|
-
message: "Project name:",
|
|
78
|
-
defaultValue: defaultTargetDir,
|
|
79
|
-
placeholder: defaultTargetDir,
|
|
80
|
-
validate: (value) => {
|
|
81
|
-
return value.length === 0 || formatTargetDir(value).length > 0 ? void 0 : "Invalid project name";
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
if (prompts.isCancel(projectName)) return cancel();
|
|
85
|
-
targetDir = formatTargetDir(projectName);
|
|
86
|
-
}
|
|
87
|
-
if (fs.existsSync(targetDir) && !isEmpty(targetDir)) {
|
|
88
|
-
const overwrite = argOverwrite ? "yes" : await prompts.select({
|
|
89
|
-
message: (targetDir === "." ? "Current directory" : `Target directory "${targetDir}"`) + ` is not empty. Please choose how to proceed:`,
|
|
90
|
-
options: [
|
|
91
|
-
{
|
|
92
|
-
label: "Cancel operation",
|
|
93
|
-
value: "no"
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
label: "Remove existing files and continue",
|
|
97
|
-
value: "yes"
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
label: "Ignore files and continue",
|
|
101
|
-
value: "ignore"
|
|
102
|
-
}
|
|
103
|
-
]
|
|
104
|
-
});
|
|
105
|
-
if (prompts.isCancel(overwrite)) return cancel();
|
|
106
|
-
switch (overwrite) {
|
|
107
|
-
case "yes":
|
|
108
|
-
emptyDir(targetDir);
|
|
109
|
-
break;
|
|
110
|
-
case "no":
|
|
111
|
-
cancel();
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
let packageName = path.basename(path.resolve(targetDir));
|
|
116
|
-
if (!isValidPackageName(packageName)) {
|
|
117
|
-
const packageNameResult = await prompts.text({
|
|
118
|
-
message: "Package name:",
|
|
119
|
-
defaultValue: toValidPackageName(packageName),
|
|
120
|
-
placeholder: toValidPackageName(packageName),
|
|
121
|
-
validate(dir) {
|
|
122
|
-
if (!isValidPackageName(dir)) return "Invalid package.json name";
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
if (prompts.isCancel(packageNameResult)) return cancel();
|
|
126
|
-
packageName = packageNameResult;
|
|
127
|
-
}
|
|
128
|
-
let template = argTemplate;
|
|
129
|
-
let hasInvalidArgTemplate = false;
|
|
130
|
-
if (argTemplate && !TEMPLATES.some((t) => t.name === argTemplate)) {
|
|
131
|
-
template = void 0;
|
|
132
|
-
hasInvalidArgTemplate = true;
|
|
133
|
-
}
|
|
134
|
-
if (!template) {
|
|
135
|
-
const selectedTemplate = await prompts.select({
|
|
136
|
-
message: hasInvalidArgTemplate ? `"${argTemplate}" isn't a valid template. Please choose from below: ` : "Select a template:",
|
|
137
|
-
options: TEMPLATES.map((template$1) => {
|
|
138
|
-
const templateColor = template$1.color;
|
|
139
|
-
return {
|
|
140
|
-
label: templateColor(template$1.display || template$1.name),
|
|
141
|
-
value: template$1.name
|
|
142
|
-
};
|
|
143
|
-
})
|
|
144
|
-
});
|
|
145
|
-
if (prompts.isCancel(selectedTemplate)) return cancel();
|
|
146
|
-
template = selectedTemplate;
|
|
147
|
-
}
|
|
148
|
-
const root = path.join(cwd, targetDir);
|
|
149
|
-
fs.mkdirSync(root, { recursive: true });
|
|
150
|
-
const pkgManager = pkgInfo ? pkgInfo.name : "npm";
|
|
151
|
-
const { customCommand } = TEMPLATES.find((t) => t.name === template) ?? {};
|
|
152
|
-
if (customCommand) {
|
|
153
|
-
const [command, ...args] = getFullCustomCommand(customCommand, pkgInfo).split(" ");
|
|
154
|
-
const replacedArgs = args.map((arg) => arg.replace("TARGET_DIR", () => targetDir));
|
|
155
|
-
const { status } = spawn.sync(command, replacedArgs, { stdio: "inherit" });
|
|
156
|
-
process.exit(status ?? 0);
|
|
157
|
-
}
|
|
158
|
-
prompts.log.step(`Scaffolding project with ${blueBright(template)} in ${root}...`);
|
|
159
|
-
const templateDir = path.join(import.meta.dirname, `templates/${template}`);
|
|
160
|
-
const write = (file, content) => {
|
|
161
|
-
const targetPath = path.join(root, file.startsWith("_") ? file.slice(1) : file);
|
|
162
|
-
if (content) fs.writeFileSync(targetPath, content);
|
|
163
|
-
else copy(path.join(templateDir, file), targetPath);
|
|
164
|
-
};
|
|
165
|
-
const files = fs.readdirSync(templateDir);
|
|
166
|
-
for (const file of files.filter((f) => f !== "package.json")) write(file);
|
|
167
|
-
let pkgJsonContent = fs.readFileSync(path.join(templateDir, `package.json`), "utf-8");
|
|
168
|
-
pkgJsonContent = pkgJsonContent.replaceAll("{{name}}", packageName);
|
|
169
|
-
const pkg = JSON.parse(pkgJsonContent);
|
|
170
|
-
if (pkgInfo) pkg.packageManager = `${pkgInfo.name}@${pkgInfo.version}`;
|
|
171
|
-
write("package.json", JSON.stringify(pkg, null, 2) + "\n");
|
|
172
|
-
const cdProjectName = path.relative(cwd, root);
|
|
173
|
-
if (await prompts.confirm({
|
|
174
|
-
message: "Initialize git repository?",
|
|
175
|
-
initialValue: true
|
|
176
|
-
})) {
|
|
177
|
-
spawn.sync("git", ["init", cdProjectName], { stdio: "pipe" });
|
|
178
|
-
prompts.log.success("Git repository initialized");
|
|
179
|
-
}
|
|
180
|
-
let doneMessage = "";
|
|
181
|
-
doneMessage += `Done. Now run:\n`;
|
|
182
|
-
if (root !== cwd) doneMessage += `\n cd ${cdProjectName.includes(" ") ? `"${cdProjectName}"` : cdProjectName}`;
|
|
183
|
-
switch (pkgManager) {
|
|
184
|
-
case "yarn":
|
|
185
|
-
doneMessage += "\n yarn";
|
|
186
|
-
doneMessage += "\n yarn dev";
|
|
187
|
-
break;
|
|
188
|
-
default:
|
|
189
|
-
doneMessage += `\n ${pkgManager} install`;
|
|
190
|
-
doneMessage += `\n ${pkgManager} run dev`;
|
|
191
|
-
break;
|
|
192
|
-
}
|
|
193
|
-
prompts.outro(greenBright(doneMessage));
|
|
194
|
-
}
|
|
195
|
-
function formatTargetDir(targetDir) {
|
|
196
|
-
return targetDir.trim().replace(/\/+$/g, "");
|
|
197
|
-
}
|
|
198
|
-
function copy(src, dest) {
|
|
199
|
-
if (fs.statSync(src).isDirectory()) copyDir(src, dest);
|
|
200
|
-
else fs.copyFileSync(src, dest);
|
|
201
|
-
}
|
|
202
|
-
function isValidPackageName(projectName) {
|
|
203
|
-
return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(projectName);
|
|
204
|
-
}
|
|
205
|
-
function toValidPackageName(projectName) {
|
|
206
|
-
return projectName.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z\d\-~]+/g, "-");
|
|
207
|
-
}
|
|
208
|
-
function copyDir(srcDir, destDir) {
|
|
209
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
210
|
-
for (const file of fs.readdirSync(srcDir)) {
|
|
211
|
-
const srcFile = path.resolve(srcDir, file);
|
|
212
|
-
const destFile = path.resolve(destDir, file);
|
|
213
|
-
copy(srcFile, destFile);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
function isEmpty(path$1) {
|
|
217
|
-
const files = fs.readdirSync(path$1);
|
|
218
|
-
return files.length === 0 || files.length === 1 && files[0] === ".git";
|
|
219
|
-
}
|
|
220
|
-
function emptyDir(dir) {
|
|
221
|
-
if (!fs.existsSync(dir)) return;
|
|
222
|
-
for (const file of fs.readdirSync(dir)) {
|
|
223
|
-
if (file === ".git") continue;
|
|
224
|
-
fs.rmSync(path.resolve(dir, file), {
|
|
225
|
-
recursive: true,
|
|
226
|
-
force: true
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
function pkgFromUserAgent(userAgent) {
|
|
231
|
-
if (!userAgent) return void 0;
|
|
232
|
-
const pkgSpecArr = userAgent.split(" ")[0].split("/");
|
|
233
|
-
return {
|
|
234
|
-
name: pkgSpecArr[0],
|
|
235
|
-
version: pkgSpecArr[1]
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
function getFullCustomCommand(customCommand, pkgInfo) {
|
|
239
|
-
const pkgManager = pkgInfo ? pkgInfo.name : "npm";
|
|
240
|
-
const isYarn1 = pkgManager === "yarn" && pkgInfo?.version.startsWith("1.");
|
|
241
|
-
return customCommand.replace(/^npm create (?:-- )?/, () => {
|
|
242
|
-
if (pkgManager === "bun") return "bun x create-";
|
|
243
|
-
if (pkgManager === "pnpm") return "pnpm create ";
|
|
244
|
-
return customCommand.startsWith("npm create -- ") ? `${pkgManager} create -- ` : `${pkgManager} create `;
|
|
245
|
-
}).replace("@latest", () => isYarn1 ? "" : "@latest").replace(/^npm exec/, () => {
|
|
246
|
-
if (pkgManager === "pnpm") return "pnpm dlx";
|
|
247
|
-
if (pkgManager === "yarn" && !isYarn1) return "yarn dlx";
|
|
248
|
-
if (pkgManager === "bun") return "bun x";
|
|
249
|
-
return "npm exec";
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
//#endregion
|
|
254
3
|
export { init };
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import spawn from "cross-spawn";
|
|
4
|
+
import mri from "mri";
|
|
5
|
+
import * as prompts from "@clack/prompts";
|
|
6
|
+
import colors from "picocolors";
|
|
7
|
+
|
|
8
|
+
//#region src/index.ts
|
|
9
|
+
const { blue, blueBright, green, greenBright, yellow } = colors;
|
|
10
|
+
const argv = mri(process.argv.slice(2), {
|
|
11
|
+
alias: {
|
|
12
|
+
h: "help",
|
|
13
|
+
t: "template"
|
|
14
|
+
},
|
|
15
|
+
boolean: ["help", "overwrite"],
|
|
16
|
+
string: ["template"]
|
|
17
|
+
});
|
|
18
|
+
const cwd = process.cwd();
|
|
19
|
+
const helpMessage = `\
|
|
20
|
+
Usage: create-egg [OPTION]... [DIRECTORY]
|
|
21
|
+
|
|
22
|
+
Create a new Egg.js project.
|
|
23
|
+
With no arguments, start the CLI in interactive mode.
|
|
24
|
+
|
|
25
|
+
Options:
|
|
26
|
+
-t, --template NAME use a specific template
|
|
27
|
+
|
|
28
|
+
Available templates:
|
|
29
|
+
${green("tegg")} egg@4 with tegg module
|
|
30
|
+
${blue("simple-ts")} egg@4 with vanilla TypeScript
|
|
31
|
+
${green("egg3-tegg")} egg@3 with tegg module
|
|
32
|
+
${blue("egg3-simple-ts")} egg@3 with vanilla TypeScript
|
|
33
|
+
${yellow("egg3-simple-js")} egg@3 with vanilla JavaScript
|
|
34
|
+
`;
|
|
35
|
+
const TEMPLATES = [
|
|
36
|
+
{
|
|
37
|
+
name: "tegg",
|
|
38
|
+
display: "Tegg starter, egg@4 with tegg module",
|
|
39
|
+
color: green
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "simple-ts",
|
|
43
|
+
display: "Simple starter, egg@4 with vanilla TypeScript",
|
|
44
|
+
color: blue
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "egg3-tegg",
|
|
48
|
+
display: "Tegg starter, egg@3 with tegg module",
|
|
49
|
+
color: green
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "egg3-simple-ts",
|
|
53
|
+
display: "Simple starter, egg@3 with vanilla TypeScript",
|
|
54
|
+
color: blue
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "egg3-simple-js",
|
|
58
|
+
display: "Simple starter, egg@3 with vanilla JavaScript",
|
|
59
|
+
color: yellow
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
const defaultTargetDir = "egg-project";
|
|
63
|
+
async function init() {
|
|
64
|
+
const argTargetDir = argv._[0] ? formatTargetDir(String(argv._[0])) : void 0;
|
|
65
|
+
const argTemplate = argv.template;
|
|
66
|
+
const argOverwrite = argv.overwrite;
|
|
67
|
+
if (argv.help) {
|
|
68
|
+
console.log(helpMessage);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent);
|
|
72
|
+
const cancel = () => prompts.cancel("Operation cancelled");
|
|
73
|
+
prompts.intro(`${greenBright("Egg.js")} - Born to build better enterprise application and framework`);
|
|
74
|
+
let targetDir = argTargetDir;
|
|
75
|
+
if (!targetDir) {
|
|
76
|
+
const projectName = await prompts.text({
|
|
77
|
+
message: "Project name:",
|
|
78
|
+
defaultValue: defaultTargetDir,
|
|
79
|
+
placeholder: defaultTargetDir,
|
|
80
|
+
validate: (value) => {
|
|
81
|
+
return value.length === 0 || formatTargetDir(value).length > 0 ? void 0 : "Invalid project name";
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
if (prompts.isCancel(projectName)) return cancel();
|
|
85
|
+
targetDir = formatTargetDir(projectName);
|
|
86
|
+
}
|
|
87
|
+
if (fs.existsSync(targetDir) && !isEmpty(targetDir)) {
|
|
88
|
+
const overwrite = argOverwrite ? "yes" : await prompts.select({
|
|
89
|
+
message: (targetDir === "." ? "Current directory" : `Target directory "${targetDir}"`) + ` is not empty. Please choose how to proceed:`,
|
|
90
|
+
options: [
|
|
91
|
+
{
|
|
92
|
+
label: "Cancel operation",
|
|
93
|
+
value: "no"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
label: "Remove existing files and continue",
|
|
97
|
+
value: "yes"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
label: "Ignore files and continue",
|
|
101
|
+
value: "ignore"
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
});
|
|
105
|
+
if (prompts.isCancel(overwrite)) return cancel();
|
|
106
|
+
switch (overwrite) {
|
|
107
|
+
case "yes":
|
|
108
|
+
emptyDir(targetDir);
|
|
109
|
+
break;
|
|
110
|
+
case "no":
|
|
111
|
+
cancel();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
let packageName = path.basename(path.resolve(targetDir));
|
|
116
|
+
if (!isValidPackageName(packageName)) {
|
|
117
|
+
const packageNameResult = await prompts.text({
|
|
118
|
+
message: "Package name:",
|
|
119
|
+
defaultValue: toValidPackageName(packageName),
|
|
120
|
+
placeholder: toValidPackageName(packageName),
|
|
121
|
+
validate(dir) {
|
|
122
|
+
if (!isValidPackageName(dir)) return "Invalid package.json name";
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
if (prompts.isCancel(packageNameResult)) return cancel();
|
|
126
|
+
packageName = packageNameResult;
|
|
127
|
+
}
|
|
128
|
+
let template = argTemplate;
|
|
129
|
+
let hasInvalidArgTemplate = false;
|
|
130
|
+
if (argTemplate && !TEMPLATES.some((t) => t.name === argTemplate)) {
|
|
131
|
+
template = void 0;
|
|
132
|
+
hasInvalidArgTemplate = true;
|
|
133
|
+
}
|
|
134
|
+
if (!template) {
|
|
135
|
+
const selectedTemplate = await prompts.select({
|
|
136
|
+
message: hasInvalidArgTemplate ? `"${argTemplate}" isn't a valid template. Please choose from below: ` : "Select a template:",
|
|
137
|
+
options: TEMPLATES.map((template$1) => {
|
|
138
|
+
const templateColor = template$1.color;
|
|
139
|
+
return {
|
|
140
|
+
label: templateColor(template$1.display || template$1.name),
|
|
141
|
+
value: template$1.name
|
|
142
|
+
};
|
|
143
|
+
})
|
|
144
|
+
});
|
|
145
|
+
if (prompts.isCancel(selectedTemplate)) return cancel();
|
|
146
|
+
template = selectedTemplate;
|
|
147
|
+
}
|
|
148
|
+
const root = path.join(cwd, targetDir);
|
|
149
|
+
fs.mkdirSync(root, { recursive: true });
|
|
150
|
+
const pkgManager = pkgInfo ? pkgInfo.name : "npm";
|
|
151
|
+
const { customCommand } = TEMPLATES.find((t) => t.name === template) ?? {};
|
|
152
|
+
if (customCommand) {
|
|
153
|
+
const [command, ...args] = getFullCustomCommand(customCommand, pkgInfo).split(" ");
|
|
154
|
+
const replacedArgs = args.map((arg) => arg.replace("TARGET_DIR", () => targetDir));
|
|
155
|
+
const { status } = spawn.sync(command, replacedArgs, { stdio: "inherit" });
|
|
156
|
+
process.exit(status ?? 0);
|
|
157
|
+
}
|
|
158
|
+
prompts.log.step(`Scaffolding project with ${blueBright(template)} in ${root}...`);
|
|
159
|
+
const templateDir = path.join(import.meta.dirname, `templates/${template}`);
|
|
160
|
+
const write = (file, content) => {
|
|
161
|
+
const targetPath = path.join(root, file.startsWith("_") ? file.slice(1) : file);
|
|
162
|
+
if (content) fs.writeFileSync(targetPath, content);
|
|
163
|
+
else copy(path.join(templateDir, file), targetPath);
|
|
164
|
+
};
|
|
165
|
+
const files = fs.readdirSync(templateDir);
|
|
166
|
+
for (const file of files.filter((f) => f !== "package.json")) write(file);
|
|
167
|
+
let pkgJsonContent = fs.readFileSync(path.join(templateDir, `package.json`), "utf-8");
|
|
168
|
+
pkgJsonContent = pkgJsonContent.replaceAll("{{name}}", packageName);
|
|
169
|
+
const pkg = JSON.parse(pkgJsonContent);
|
|
170
|
+
if (pkgInfo) pkg.packageManager = `${pkgInfo.name}@${pkgInfo.version}`;
|
|
171
|
+
write("package.json", JSON.stringify(pkg, null, 2) + "\n");
|
|
172
|
+
const cdProjectName = path.relative(cwd, root);
|
|
173
|
+
if (await prompts.confirm({
|
|
174
|
+
message: "Initialize git repository?",
|
|
175
|
+
initialValue: true
|
|
176
|
+
})) {
|
|
177
|
+
spawn.sync("git", ["init", cdProjectName], { stdio: "pipe" });
|
|
178
|
+
prompts.log.success("Git repository initialized");
|
|
179
|
+
}
|
|
180
|
+
let doneMessage = "";
|
|
181
|
+
doneMessage += `Done. Now run:\n`;
|
|
182
|
+
if (root !== cwd) doneMessage += `\n cd ${cdProjectName.includes(" ") ? `"${cdProjectName}"` : cdProjectName}`;
|
|
183
|
+
switch (pkgManager) {
|
|
184
|
+
case "yarn":
|
|
185
|
+
doneMessage += "\n yarn";
|
|
186
|
+
doneMessage += "\n yarn dev";
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
doneMessage += `\n ${pkgManager} install`;
|
|
190
|
+
doneMessage += `\n ${pkgManager} run dev`;
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
prompts.outro(greenBright(doneMessage));
|
|
194
|
+
}
|
|
195
|
+
function formatTargetDir(targetDir) {
|
|
196
|
+
return targetDir.trim().replace(/\/+$/g, "");
|
|
197
|
+
}
|
|
198
|
+
function copy(src, dest) {
|
|
199
|
+
if (fs.statSync(src).isDirectory()) copyDir(src, dest);
|
|
200
|
+
else fs.copyFileSync(src, dest);
|
|
201
|
+
}
|
|
202
|
+
function isValidPackageName(projectName) {
|
|
203
|
+
return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(projectName);
|
|
204
|
+
}
|
|
205
|
+
function toValidPackageName(projectName) {
|
|
206
|
+
return projectName.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z\d\-~]+/g, "-");
|
|
207
|
+
}
|
|
208
|
+
function copyDir(srcDir, destDir) {
|
|
209
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
210
|
+
for (const file of fs.readdirSync(srcDir)) {
|
|
211
|
+
const srcFile = path.resolve(srcDir, file);
|
|
212
|
+
const destFile = path.resolve(destDir, file);
|
|
213
|
+
copy(srcFile, destFile);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function isEmpty(path$1) {
|
|
217
|
+
const files = fs.readdirSync(path$1);
|
|
218
|
+
return files.length === 0 || files.length === 1 && files[0] === ".git";
|
|
219
|
+
}
|
|
220
|
+
function emptyDir(dir) {
|
|
221
|
+
if (!fs.existsSync(dir)) return;
|
|
222
|
+
for (const file of fs.readdirSync(dir)) {
|
|
223
|
+
if (file === ".git") continue;
|
|
224
|
+
fs.rmSync(path.resolve(dir, file), {
|
|
225
|
+
recursive: true,
|
|
226
|
+
force: true
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function pkgFromUserAgent(userAgent) {
|
|
231
|
+
if (!userAgent) return void 0;
|
|
232
|
+
const pkgSpecArr = userAgent.split(" ")[0].split("/");
|
|
233
|
+
return {
|
|
234
|
+
name: pkgSpecArr[0],
|
|
235
|
+
version: pkgSpecArr[1]
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function getFullCustomCommand(customCommand, pkgInfo) {
|
|
239
|
+
const pkgManager = pkgInfo ? pkgInfo.name : "npm";
|
|
240
|
+
const isYarn1 = pkgManager === "yarn" && pkgInfo?.version.startsWith("1.");
|
|
241
|
+
return customCommand.replace(/^npm create (?:-- )?/, () => {
|
|
242
|
+
if (pkgManager === "bun") return "bun x create-";
|
|
243
|
+
if (pkgManager === "pnpm") return "pnpm create ";
|
|
244
|
+
return customCommand.startsWith("npm create -- ") ? `${pkgManager} create -- ` : `${pkgManager} create `;
|
|
245
|
+
}).replace("@latest", () => isYarn1 ? "" : "@latest").replace(/^npm exec/, () => {
|
|
246
|
+
if (pkgManager === "pnpm") return "pnpm dlx";
|
|
247
|
+
if (pkgManager === "yarn" && !isYarn1) return "yarn dlx";
|
|
248
|
+
if (pkgManager === "bun") return "bun x";
|
|
249
|
+
return "npm exec";
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
//#endregion
|
|
254
|
+
export { init };
|