create-egg 4.1.0-beta.34 → 4.1.0-beta.36

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 (29) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/index.js +248 -1
  3. package/dist/templates/egg3-simple-js/package.json +19 -19
  4. package/dist/templates/egg3-simple-ts/package.json +11 -11
  5. package/dist/templates/egg3-simple-ts/test/app/controller/home.test.ts +1 -0
  6. package/dist/templates/egg3-simple-ts/test/app/service/Test.test.ts +1 -0
  7. package/dist/templates/egg3-simple-ts/tsconfig.json +1 -1
  8. package/dist/templates/egg3-tegg/app/module/bar/controller/home.ts +1 -1
  9. package/dist/templates/egg3-tegg/app/module/bar/controller/user.ts +1 -1
  10. package/dist/templates/egg3-tegg/app/module/foo/service/HelloService.ts +1 -1
  11. package/dist/templates/egg3-tegg/package.json +18 -18
  12. package/dist/templates/egg3-tegg/test/app/module/foo/service/HelloService.test.ts +1 -2
  13. package/dist/templates/egg3-tegg/tsconfig.json +2 -3
  14. package/dist/templates/simple-ts/package.json +16 -16
  15. package/dist/templates/simple-ts/test/app/controller/home.test.ts +1 -2
  16. package/dist/templates/simple-ts/test/app/service/Test.test.ts +1 -2
  17. package/dist/templates/simple-ts/tsconfig.json +1 -2
  18. package/dist/templates/tegg/app/module/bar/controller/home.ts +2 -3
  19. package/dist/templates/tegg/app/module/bar/controller/user.ts +2 -1
  20. package/dist/templates/tegg/app/module/bar/package.json +2 -2
  21. package/dist/templates/tegg/app/module/foo/package.json +2 -2
  22. package/dist/templates/tegg/app/module/foo/service/HelloService.ts +2 -3
  23. package/dist/templates/tegg/package.json +17 -17
  24. package/dist/templates/tegg/test/app/module/bar/controller/home.test.ts +1 -1
  25. package/dist/templates/tegg/test/app/module/bar/controller/user.test.ts +1 -1
  26. package/dist/templates/tegg/test/app/module/foo/service/HelloService.test.skip.ts +1 -1
  27. package/dist/templates/tegg/tsconfig.json +1 -2
  28. package/package.json +23 -22
  29. package/dist/src-BgL2uwim.js +0 -250
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as init } from "./src-BgL2uwim.js";
2
+ import { init } from "./index.js";
3
3
 
4
4
  //#region src/cli.ts
5
5
  init().catch((err) => {
package/dist/index.js CHANGED
@@ -1,3 +1,250 @@
1
- import { t as init } from "./src-BgL2uwim.js";
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import * as prompts from "@clack/prompts";
4
+ import spawn from "cross-spawn";
5
+ import mri from "mri";
6
+ import colors from "picocolors";
2
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)) copy(path.resolve(srcDir, file), path.resolve(destDir, file));
211
+ }
212
+ function isEmpty(path$1) {
213
+ const files = fs.readdirSync(path$1);
214
+ return files.length === 0 || files.length === 1 && files[0] === ".git";
215
+ }
216
+ function emptyDir(dir) {
217
+ if (!fs.existsSync(dir)) return;
218
+ for (const file of fs.readdirSync(dir)) {
219
+ if (file === ".git") continue;
220
+ fs.rmSync(path.resolve(dir, file), {
221
+ recursive: true,
222
+ force: true
223
+ });
224
+ }
225
+ }
226
+ function pkgFromUserAgent(userAgent) {
227
+ if (!userAgent) return void 0;
228
+ const pkgSpecArr = userAgent.split(" ")[0].split("/");
229
+ return {
230
+ name: pkgSpecArr[0],
231
+ version: pkgSpecArr[1]
232
+ };
233
+ }
234
+ function getFullCustomCommand(customCommand, pkgInfo) {
235
+ const pkgManager = pkgInfo ? pkgInfo.name : "npm";
236
+ const isYarn1 = pkgManager === "yarn" && pkgInfo?.version.startsWith("1.");
237
+ return customCommand.replace(/^npm create (?:-- )?/, () => {
238
+ if (pkgManager === "bun") return "bun x create-";
239
+ if (pkgManager === "pnpm") return "pnpm create ";
240
+ return customCommand.startsWith("npm create -- ") ? `${pkgManager} create -- ` : `${pkgManager} create `;
241
+ }).replace("@latest", () => isYarn1 ? "" : "@latest").replace(/^npm exec/, () => {
242
+ if (pkgManager === "pnpm") return "pnpm dlx";
243
+ if (pkgManager === "yarn" && !isYarn1) return "yarn dlx";
244
+ if (pkgManager === "bun") return "bun x";
245
+ return "npm exec";
246
+ });
247
+ }
248
+
249
+ //#endregion
3
250
  export { init };
@@ -1,10 +1,23 @@
1
1
  {
2
2
  "name": "{{name}}",
3
3
  "version": "1.0.0",
4
- "description": "hello Egg.js",
5
4
  "private": true,
6
- "egg": {
7
- "declarations": true
5
+ "description": "hello Egg.js",
6
+ "license": "MIT",
7
+ "author": "{{author}}",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": ""
11
+ },
12
+ "scripts": {
13
+ "start": "egg-scripts start --daemon --title=egg-server-{{name}}",
14
+ "stop": "egg-scripts stop --title=egg-server-{{name}}",
15
+ "dev": "egg-bin dev",
16
+ "test": "npm run lint -- --fix && npm run test:local",
17
+ "test:local": "egg-bin test",
18
+ "cov": "egg-bin cov",
19
+ "lint": "eslint .",
20
+ "ci": "npm run lint && npm run cov"
8
21
  },
9
22
  "dependencies": {
10
23
  "egg": "^3.17.5",
@@ -19,20 +32,7 @@
19
32
  "engines": {
20
33
  "node": ">=22.18.0"
21
34
  },
22
- "scripts": {
23
- "start": "egg-scripts start --daemon --title=egg-server-{{name}}",
24
- "stop": "egg-scripts stop --title=egg-server-{{name}}",
25
- "dev": "egg-bin dev",
26
- "test": "npm run lint -- --fix && npm run test:local",
27
- "test:local": "egg-bin test",
28
- "cov": "egg-bin cov",
29
- "lint": "eslint .",
30
- "ci": "npm run lint && npm run cov"
31
- },
32
- "repository": {
33
- "type": "git",
34
- "url": ""
35
- },
36
- "author": "{{author}}",
37
- "license": "MIT"
35
+ "egg": {
36
+ "declarations": true
37
+ }
38
38
  }
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "{{name}}",
3
3
  "version": "1.0.0",
4
- "description": "hello Egg.js",
5
4
  "private": true,
6
- "egg": {
7
- "typescript": true,
8
- "declarations": true
5
+ "description": "hello Egg.js",
6
+ "license": "MIT",
7
+ "author": "Author Name <author.name@mail.com>",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": ""
9
11
  },
10
12
  "scripts": {
11
13
  "start": "egg-scripts start --daemon --title=egg-server-{{name}}",
@@ -24,9 +26,9 @@
24
26
  "egg-scripts": "3"
25
27
  },
26
28
  "devDependencies": {
29
+ "@eggjs/tsconfig": "3",
27
30
  "@types/mocha": "10",
28
31
  "@types/node": "24",
29
- "@eggjs/tsconfig": "3",
30
32
  "egg-bin": "6",
31
33
  "egg-mock": "5",
32
34
  "eslint": "8",
@@ -36,10 +38,8 @@
36
38
  "engines": {
37
39
  "node": ">=22.18.0"
38
40
  },
39
- "repository": {
40
- "type": "git",
41
- "url": ""
42
- },
43
- "author": "Author Name <author.name@mail.com>",
44
- "license": "MIT"
41
+ "egg": {
42
+ "typescript": true,
43
+ "declarations": true
44
+ }
45
45
  }
@@ -1,4 +1,5 @@
1
1
  import assert from 'assert';
2
+
2
3
  import { app } from 'egg-mock/bootstrap';
3
4
 
4
5
  describe('test/app/controller/home.test.ts', () => {
@@ -1,4 +1,5 @@
1
1
  import assert from 'assert';
2
+
2
3
  import { Context } from 'egg';
3
4
  import { app } from 'egg-mock/bootstrap';
4
5
 
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "extends": "@eggjs/tsconfig",
3
- "exclude": ["app/public", "app/views", "node_modules*"]
3
+ "exclude": ["app/public", "app/views", "node_modules"]
4
4
  }
@@ -1,5 +1,5 @@
1
- import { EggLogger } from 'egg';
2
1
  import { Inject, HTTPController, HTTPMethod, HTTPMethodEnum } from '@eggjs/tegg';
2
+ import { EggLogger } from 'egg';
3
3
 
4
4
  @HTTPController({
5
5
  path: '/',
@@ -1,5 +1,5 @@
1
- import { Inject, HTTPController, HTTPMethod, HTTPMethodEnum, HTTPQuery } from '@eggjs/tegg';
2
1
  import { HelloService } from '@/module/foo';
2
+ import { Inject, HTTPController, HTTPMethod, HTTPMethodEnum, HTTPQuery } from '@eggjs/tegg';
3
3
 
4
4
  @HTTPController({
5
5
  path: '/bar',
@@ -1,5 +1,5 @@
1
- import { EggLogger } from 'egg';
2
1
  import { SingletonProto, AccessLevel, Inject } from '@eggjs/tegg';
2
+ import { EggLogger } from 'egg';
3
3
 
4
4
  @SingletonProto({
5
5
  // 如果需要在上层使用,需要把 accessLevel 显示声明为 public
@@ -1,9 +1,16 @@
1
1
  {
2
2
  "name": "{{name}}",
3
- "description": "Hello Egg.js",
4
3
  "private": true,
5
- "egg": {
6
- "typescript": true
4
+ "description": "Hello Egg.js",
5
+ "homepage": "https://github.com/YOUR_USERNAME/YOUR_REPO#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/YOUR_USERNAME/YOUR_REPO/issues"
8
+ },
9
+ "license": "MIT",
10
+ "author": "Author Name <author.name@mail.com>",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/YOUR_USERNAME/YOUR_REPO.git"
7
14
  },
8
15
  "scripts": {
9
16
  "start": "eggctl start --daemon --title=egg-server-{{name}}",
@@ -27,31 +34,24 @@
27
34
  "@eggjs/tegg-eventbus-plugin": "^3.5.2",
28
35
  "@eggjs/tegg-plugin": "^3.5.2",
29
36
  "@eggjs/tegg-schedule-plugin": "^3.5.2",
37
+ "egg": "^3.31.0",
30
38
  "egg-scripts": "^3.0.0",
31
- "egg-tracer": "^2.0.0",
32
- "egg": "^3.31.0"
39
+ "egg-tracer": "^2.0.0"
33
40
  },
34
41
  "devDependencies": {
35
- "egg-bin": "^6.13.0",
36
- "egg-mock": "^5.15.2",
37
42
  "@eggjs/tsconfig": "3",
38
43
  "@types/mocha": "10",
39
44
  "@types/node": "24",
45
+ "egg-bin": "^6.13.0",
46
+ "egg-mock": "^5.15.2",
40
47
  "oxlint": "1",
41
- "oxlint-tsgolint": "^0.3.0",
48
+ "oxlint-tsgolint": "^0.10.0",
42
49
  "typescript": "5"
43
50
  },
44
51
  "engines": {
45
52
  "node": ">=22.18.0"
46
53
  },
47
- "homepage": "https://github.com/YOUR_USERNAME/YOUR_REPO#readme",
48
- "bugs": {
49
- "url": "https://github.com/YOUR_USERNAME/YOUR_REPO/issues"
50
- },
51
- "repository": {
52
- "type": "git",
53
- "url": "git+https://github.com/YOUR_USERNAME/YOUR_REPO.git"
54
- },
55
- "author": "Author Name <author.name@mail.com>",
56
- "license": "MIT"
54
+ "egg": {
55
+ "typescript": true
56
+ }
57
57
  }
@@ -1,8 +1,7 @@
1
1
  import { strict as assert } from 'node:assert';
2
2
 
3
- import { app } from 'egg-mock/bootstrap';
4
-
5
3
  import { HelloService } from '@/module/foo/service/HelloService';
4
+ import { app } from 'egg-mock/bootstrap';
6
5
 
7
6
  describe('test/app/module/foo/service/HelloService.test.ts', () => {
8
7
  it('should hello() work', async () => {
@@ -6,8 +6,7 @@
6
6
  "moduleResolution": "NodeNext",
7
7
  "declaration": false,
8
8
  "paths": {
9
- "@/module/*": ["app/module/*"]
10
- },
11
- "baseUrl": "."
9
+ "@/module/*": ["./app/module/*"]
10
+ }
12
11
  }
13
12
  }
@@ -1,11 +1,18 @@
1
1
  {
2
2
  "name": "{{name}}",
3
- "description": "Hello Egg.js",
4
- "type": "module",
5
3
  "private": true,
6
- "egg": {
7
- "typescript": true
4
+ "description": "Hello Egg.js",
5
+ "homepage": "https://github.com/YOUR_USERNAME/YOUR_REPO#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/YOUR_USERNAME/YOUR_REPO/issues"
8
+ },
9
+ "license": "MIT",
10
+ "author": "Author Name <author.name@mail.com>",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/YOUR_USERNAME/YOUR_REPO.git"
8
14
  },
15
+ "type": "module",
9
16
  "scripts": {
10
17
  "start": "eggctl start --daemon --title=egg-server-{{name}}",
11
18
  "stop": "eggctl stop --title=egg-server-{{name}}",
@@ -17,7 +24,7 @@
17
24
  "ci": "vitest run --coverage",
18
25
  "postci": "npm run prepublishOnly && npm start && sleep 10 && npm stop && npm run clean",
19
26
  "lint": "oxlint --type-aware",
20
- "typecheck": "tsc --noEmit",
27
+ "typecheck": "tsgo --noEmit",
21
28
  "tsc": "tsc",
22
29
  "clean": "tsc -b --clean",
23
30
  "prepublishOnly": "npm run clean && npm run tsc"
@@ -32,21 +39,14 @@
32
39
  "@eggjs/tsconfig": "beta",
33
40
  "@types/node": "24",
34
41
  "oxlint": "1",
35
- "oxlint-tsgolint": "^0.3.0",
42
+ "oxlint-tsgolint": "^0.10.0",
36
43
  "typescript": "5",
37
44
  "vitest": "beta"
38
45
  },
39
46
  "engines": {
40
47
  "node": ">=22.18.0"
41
48
  },
42
- "homepage": "https://github.com/YOUR_USERNAME/YOUR_REPO#readme",
43
- "bugs": {
44
- "url": "https://github.com/YOUR_USERNAME/YOUR_REPO/issues"
45
- },
46
- "repository": {
47
- "type": "git",
48
- "url": "git+https://github.com/YOUR_USERNAME/YOUR_REPO.git"
49
- },
50
- "author": "Author Name <author.name@mail.com>",
51
- "license": "MIT"
49
+ "egg": {
50
+ "typescript": true
51
+ }
52
52
  }
@@ -1,6 +1,5 @@
1
- import { test, expect } from 'vitest';
2
-
3
1
  import { app } from '@eggjs/mock/bootstrap';
2
+ import { test, expect } from 'vitest';
4
3
 
5
4
  test('should GET / status 200', async () => {
6
5
  const res = await app.httpRequest().get('/').expect(200);
@@ -1,6 +1,5 @@
1
- import { test, expect } from 'vitest';
2
-
3
1
  import { app } from '@eggjs/mock/bootstrap';
2
+ import { test, expect } from 'vitest';
4
3
 
5
4
  test('sayHi should return hi, egg', async () => {
6
5
  const ctx = app.mockContext();
@@ -4,7 +4,6 @@
4
4
  "target": "ES2022",
5
5
  "module": "NodeNext",
6
6
  "moduleResolution": "NodeNext",
7
- "declaration": false,
8
- "baseUrl": "."
7
+ "declaration": false
9
8
  }
10
9
  }
@@ -1,12 +1,11 @@
1
- import type { EggLogger } from 'egg';
2
- import { Inject, HTTPController, HTTPMethod, HTTPMethodEnum } from '@eggjs/tegg';
1
+ import { Inject, HTTPController, HTTPMethod, HTTPMethodEnum, type Logger } from 'egg';
3
2
 
4
3
  @HTTPController({
5
4
  path: '/',
6
5
  })
7
6
  export class HomeController {
8
7
  @Inject()
9
- private logger: EggLogger;
8
+ private logger: Logger;
10
9
 
11
10
  @HTTPMethod({
12
11
  method: HTTPMethodEnum.GET,
@@ -1,4 +1,5 @@
1
- import { Inject, HTTPController, HTTPMethod, HTTPMethodEnum, HTTPQuery } from '@eggjs/tegg';
1
+ import { Inject, HTTPController, HTTPMethod, HTTPMethodEnum, HTTPQuery } from 'egg';
2
+
2
3
  import { HelloService } from '../../foo/index.ts';
3
4
 
4
5
  @HTTPController({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bar",
3
+ "type": "module",
3
4
  "eggModule": {
4
5
  "name": "bar"
5
- },
6
- "type": "module"
6
+ }
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "foo",
3
+ "type": "module",
3
4
  "eggModule": {
4
5
  "name": "foo"
5
- },
6
- "type": "module"
6
+ }
7
7
  }
@@ -1,5 +1,4 @@
1
- import type { EggLogger } from 'egg';
2
- import { SingletonProto, AccessLevel, Inject } from '@eggjs/tegg';
1
+ import { SingletonProto, AccessLevel, Inject, type Logger } from 'egg';
3
2
 
4
3
  @SingletonProto({
5
4
  // 如果需要在上层使用,需要把 accessLevel 显示声明为 public
@@ -8,7 +7,7 @@ import { SingletonProto, AccessLevel, Inject } from '@eggjs/tegg';
8
7
  export class HelloService {
9
8
  // 注入一个 logger
10
9
  @Inject()
11
- private logger: EggLogger;
10
+ private logger: Logger;
12
11
 
13
12
  // 封装业务
14
13
  async hello(userId: string): Promise<string> {
@@ -1,7 +1,17 @@
1
1
  {
2
2
  "name": "{{name}}",
3
- "description": "Hello Egg.js",
4
3
  "private": true,
4
+ "description": "Hello Egg.js",
5
+ "homepage": "https://github.com/YOUR_USERNAME/YOUR_REPO#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/YOUR_USERNAME/YOUR_REPO/issues"
8
+ },
9
+ "license": "MIT",
10
+ "author": "Author Name <author.name@mail.com>",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/YOUR_USERNAME/YOUR_REPO.git"
14
+ },
5
15
  "type": "module",
6
16
  "scripts": {
7
17
  "start": "eggctl start --daemon --title=egg-server-{{name}}",
@@ -15,7 +25,7 @@
15
25
  "ci": "npm run test:local -- --coverage",
16
26
  "postci": "npm run prepublishOnly && npm start && sleep 10 && npm stop && npm run clean",
17
27
  "lint": "oxlint --type-aware",
18
- "typecheck": "tsc --noEmit",
28
+ "typecheck": "tsgo --noEmit",
19
29
  "build": "tsc",
20
30
  "clean": "tsc -b --clean",
21
31
  "prepublishOnly": "npm run clean && npm run build"
@@ -29,26 +39,16 @@
29
39
  "@eggjs/bin": "beta",
30
40
  "@eggjs/mock": "beta",
31
41
  "@eggjs/tsconfig": "beta",
32
- "@oxc-node/core": "^0.0.32",
42
+ "@oxc-node/core": "^0.0.35",
33
43
  "@types/node": "24",
44
+ "@vitest/coverage-v8": "4",
34
45
  "cross-env": "10",
35
46
  "oxlint": "1",
36
- "oxlint-tsgolint": "^0.3.0",
47
+ "oxlint-tsgolint": "^0.10.0",
37
48
  "typescript": "5",
38
- "vitest": "4",
39
- "@vitest/coverage-v8": "4"
49
+ "vitest": "4"
40
50
  },
41
51
  "engines": {
42
52
  "node": ">=22.18.0"
43
- },
44
- "homepage": "https://github.com/YOUR_USERNAME/YOUR_REPO#readme",
45
- "bugs": {
46
- "url": "https://github.com/YOUR_USERNAME/YOUR_REPO/issues"
47
- },
48
- "repository": {
49
- "type": "git",
50
- "url": "git+https://github.com/YOUR_USERNAME/YOUR_REPO.git"
51
- },
52
- "author": "Author Name <author.name@mail.com>",
53
- "license": "MIT"
53
+ }
54
54
  }
@@ -1,5 +1,5 @@
1
- import { test, expect } from 'vitest';
2
1
  import { app } from '@eggjs/mock/bootstrap';
2
+ import { test, expect } from 'vitest';
3
3
 
4
4
  test('should GET / status 200', async () => {
5
5
  const res = await app.httpRequest().get('/');
@@ -1,5 +1,5 @@
1
- import { test, expect } from 'vitest';
2
1
  import { app } from '@eggjs/mock/bootstrap';
2
+ import { test, expect } from 'vitest';
3
3
 
4
4
  test('should GET /bar/user status 200', async () => {
5
5
  const res = await app.httpRequest().get('/bar/user').query({ userId: '20170901' });
@@ -1,5 +1,5 @@
1
- import { test, expect } from 'vitest';
2
1
  import { app } from '@eggjs/mock/bootstrap';
2
+ import { test, expect } from 'vitest';
3
3
 
4
4
  import { HelloService } from '../../../../../app/module/foo/index.ts';
5
5
 
@@ -4,7 +4,6 @@
4
4
  "target": "ES2022",
5
5
  "module": "NodeNext",
6
6
  "moduleResolution": "NodeNext",
7
- "declaration": false,
8
- "baseUrl": "."
7
+ "declaration": false
9
8
  }
10
9
  }
package/package.json CHANGED
@@ -1,33 +1,25 @@
1
1
  {
2
2
  "name": "create-egg",
3
- "version": "4.1.0-beta.34",
4
- "publishConfig": {
5
- "access": "public"
6
- },
3
+ "version": "4.1.0-beta.36",
7
4
  "description": "Scaffolding Your First Egg.js Project",
8
- "type": "module",
9
- "devDependencies": {
10
- "@types/cross-spawn": "^6.0.6",
11
- "execa": "^9.6.0",
12
- "tsdown": "0.15.11"
13
- },
14
- "engines": {
15
- "node": ">=20.19.0"
5
+ "homepage": "https://github.com/eggjs/egg/tree/next/tools/create-egg",
6
+ "bugs": {
7
+ "url": "https://github.com/eggjs/egg/issues"
16
8
  },
9
+ "license": "MIT",
10
+ "author": "TZ <atian25@qq.com>",
17
11
  "repository": {
18
12
  "type": "git",
19
- "url": "git://github.com/eggjs/egg.git",
13
+ "url": "git+https://github.com/eggjs/egg.git",
20
14
  "directory": "tools/create-egg"
21
15
  },
22
- "bugs": {
23
- "url": "https://github.com/eggjs/egg/issues"
16
+ "bin": {
17
+ "create-egg": "./dist/cli.js"
24
18
  },
25
- "homepage": "https://github.com/eggjs/egg/tree/next/tools/create-egg",
26
19
  "files": [
27
20
  "dist"
28
21
  ],
29
- "author": "TZ <atian25@qq.com>",
30
- "license": "MIT",
22
+ "type": "module",
31
23
  "main": "./dist/index.js",
32
24
  "module": "./dist/index.js",
33
25
  "types": "./dist/index.d.ts",
@@ -36,8 +28,8 @@
36
28
  "./cli": "./dist/cli.js",
37
29
  "./package.json": "./package.json"
38
30
  },
39
- "bin": {
40
- "create-egg": "./dist/cli.js"
31
+ "publishConfig": {
32
+ "access": "public"
41
33
  },
42
34
  "dependencies": {
43
35
  "@clack/prompts": "^0.11.0",
@@ -45,8 +37,17 @@
45
37
  "mri": "^1.2.0",
46
38
  "picocolors": "^1.1.1"
47
39
  },
40
+ "devDependencies": {
41
+ "@types/cross-spawn": "^6.0.6",
42
+ "execa": "^9.6.0",
43
+ "@eggjs/mock": "7.0.0-beta.36",
44
+ "@eggjs/tracer": "4.0.0-beta.36",
45
+ "egg": "4.1.0-beta.36"
46
+ },
47
+ "engines": {
48
+ "node": ">=20.19.0"
49
+ },
48
50
  "scripts": {
49
- "test": "vitest run",
50
- "build": "tsdown"
51
+ "typecheck": "tsgo --noEmit"
51
52
  }
52
53
  }
@@ -1,250 +0,0 @@
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)) copy(path.resolve(srcDir, file), path.resolve(destDir, file));
211
- }
212
- function isEmpty(path$1) {
213
- const files = fs.readdirSync(path$1);
214
- return files.length === 0 || files.length === 1 && files[0] === ".git";
215
- }
216
- function emptyDir(dir) {
217
- if (!fs.existsSync(dir)) return;
218
- for (const file of fs.readdirSync(dir)) {
219
- if (file === ".git") continue;
220
- fs.rmSync(path.resolve(dir, file), {
221
- recursive: true,
222
- force: true
223
- });
224
- }
225
- }
226
- function pkgFromUserAgent(userAgent) {
227
- if (!userAgent) return void 0;
228
- const pkgSpecArr = userAgent.split(" ")[0].split("/");
229
- return {
230
- name: pkgSpecArr[0],
231
- version: pkgSpecArr[1]
232
- };
233
- }
234
- function getFullCustomCommand(customCommand, pkgInfo) {
235
- const pkgManager = pkgInfo ? pkgInfo.name : "npm";
236
- const isYarn1 = pkgManager === "yarn" && pkgInfo?.version.startsWith("1.");
237
- return customCommand.replace(/^npm create (?:-- )?/, () => {
238
- if (pkgManager === "bun") return "bun x create-";
239
- if (pkgManager === "pnpm") return "pnpm create ";
240
- return customCommand.startsWith("npm create -- ") ? `${pkgManager} create -- ` : `${pkgManager} create `;
241
- }).replace("@latest", () => isYarn1 ? "" : "@latest").replace(/^npm exec/, () => {
242
- if (pkgManager === "pnpm") return "pnpm dlx";
243
- if (pkgManager === "yarn" && !isYarn1) return "yarn dlx";
244
- if (pkgManager === "bun") return "bun x";
245
- return "npm exec";
246
- });
247
- }
248
-
249
- //#endregion
250
- export { init as t };