@eggjs/bin 7.3.1 → 7.4.0-beta.10
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 -21
- package/bin/dev.js +0 -0
- package/dist/baseCommand.d.ts +52 -0
- package/dist/baseCommand.js +288 -0
- package/dist/commands/cov.d.ts +27 -0
- package/dist/commands/cov.js +86 -0
- package/dist/commands/dev.d.ts +26 -0
- package/dist/commands/dev.js +86 -0
- package/dist/commands/test.d.ts +28 -0
- package/dist/commands/test.js +168 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/scripts/postinstall.mjs +9 -6
- package/dist/scripts/start-cluster.cjs +3 -2
- package/dist/scripts/start-cluster.mjs +3 -2
- package/{src/types.ts → dist/types.d.ts} +4 -1
- package/dist/utils.js +34 -0
- package/package.json +54 -73
- package/scripts/postinstall.mjs +9 -6
- package/scripts/start-cluster.cjs +3 -2
- package/scripts/start-cluster.mjs +3 -2
- package/dist/commonjs/baseCommand.d.ts +0 -49
- package/dist/commonjs/baseCommand.js +0 -374
- package/dist/commonjs/commands/cov.d.ts +0 -22
- package/dist/commonjs/commands/cov.js +0 -98
- package/dist/commonjs/commands/dev.d.ts +0 -21
- package/dist/commonjs/commands/dev.js +0 -101
- package/dist/commonjs/commands/test.d.ts +0 -23
- package/dist/commonjs/commands/test.js +0 -222
- package/dist/commonjs/index.d.ts +0 -7
- package/dist/commonjs/index.js +0 -30
- package/dist/commonjs/package.json +0 -3
- package/dist/commonjs/types.d.ts +0 -9
- package/dist/commonjs/types.js +0 -3
- package/dist/commonjs/utils.d.ts +0 -4
- package/dist/commonjs/utils.js +0 -45
- package/dist/esm/baseCommand.d.ts +0 -49
- package/dist/esm/baseCommand.js +0 -366
- package/dist/esm/commands/cov.d.ts +0 -22
- package/dist/esm/commands/cov.js +0 -92
- package/dist/esm/commands/dev.d.ts +0 -21
- package/dist/esm/commands/dev.js +0 -98
- package/dist/esm/commands/test.d.ts +0 -23
- package/dist/esm/commands/test.js +0 -216
- package/dist/esm/index.d.ts +0 -7
- package/dist/esm/index.js +0 -8
- package/dist/esm/package.json +0 -3
- package/dist/esm/types.d.ts +0 -9
- package/dist/esm/types.js +0 -2
- package/dist/esm/utils.d.ts +0 -4
- package/dist/esm/utils.js +0 -36
- package/dist/package.json +0 -4
- package/src/baseCommand.ts +0 -395
- package/src/commands/cov.ts +0 -101
- package/src/commands/dev.ts +0 -106
- package/src/commands/test.ts +0 -236
- package/src/index.ts +0 -9
- package/src/utils.ts +0 -37
package/README.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# @eggjs/bin
|
|
2
2
|
|
|
3
3
|
[![NPM version][npm-image]][npm-url]
|
|
4
|
-
[![build status][ci-image]][ci-url]
|
|
5
|
-
[![Test coverage][codecov-image]][codecov-url]
|
|
6
4
|
[![Known Vulnerabilities][snyk-image]][snyk-url]
|
|
7
5
|
[![npm download][download-image]][download-url]
|
|
8
6
|
[![Node.js Version][node-version-image]][node-version-url]
|
|
@@ -10,10 +8,6 @@
|
|
|
10
8
|
|
|
11
9
|
[npm-image]: https://img.shields.io/npm/v/@eggjs/bin.svg?style=flat-square
|
|
12
10
|
[npm-url]: https://npmjs.org/package/@eggjs/bin
|
|
13
|
-
[ci-image]: https://github.com/eggjs/bin/actions/workflows/nodejs.yml/badge.svg
|
|
14
|
-
[ci-url]: https://github.com/eggjs/bin/actions/workflows/nodejs.yml
|
|
15
|
-
[codecov-image]: https://codecov.io/gh/eggjs/bin/branch/master/graph/badge.svg
|
|
16
|
-
[codecov-url]: https://codecov.io/gh/eggjs/bin
|
|
17
11
|
[snyk-image]: https://snyk.io/test/npm/@eggjs/bin/badge.svg?style=flat-square
|
|
18
12
|
[snyk-url]: https://snyk.io/test/npm/@eggjs/bin
|
|
19
13
|
[download-image]: https://img.shields.io/npm/dm/@eggjs/bin.svg?style=flat-square
|
|
@@ -95,12 +89,7 @@ Create `.vscode/launch.json` file:
|
|
|
95
89
|
"request": "launch",
|
|
96
90
|
"name": "Egg Debug",
|
|
97
91
|
"runtimeExecutable": "npm",
|
|
98
|
-
"runtimeArgs": [
|
|
99
|
-
"run",
|
|
100
|
-
"dev",
|
|
101
|
-
"--",
|
|
102
|
-
"--inspect-brk"
|
|
103
|
-
],
|
|
92
|
+
"runtimeArgs": ["run", "dev", "--", "--inspect-brk"],
|
|
104
93
|
"console": "integratedTerminal",
|
|
105
94
|
"restart": true,
|
|
106
95
|
"autoAttachChildProcesses": true
|
|
@@ -110,12 +99,7 @@ Create `.vscode/launch.json` file:
|
|
|
110
99
|
"request": "launch",
|
|
111
100
|
"name": "Egg Test",
|
|
112
101
|
"runtimeExecutable": "npm",
|
|
113
|
-
"runtimeArgs": [
|
|
114
|
-
"run",
|
|
115
|
-
"test-local",
|
|
116
|
-
"--",
|
|
117
|
-
"--inspect-brk"
|
|
118
|
-
],
|
|
102
|
+
"runtimeArgs": ["run", "test-local", "--", "--inspect-brk"],
|
|
119
103
|
"autoAttachChildProcesses": true
|
|
120
104
|
}
|
|
121
105
|
]
|
|
@@ -190,10 +174,8 @@ You can pass any mocha argv.
|
|
|
190
174
|
- `--prerequire` prerequire files for coverage instrument, you can use this options if load files slowly when call `mm.app` or `mm.cluster`
|
|
191
175
|
- `--typescript` enable typescript support. If `true`, will auto add `.ts` extension and ignore `typings` and `d.ts`.
|
|
192
176
|
- `--c8` c8 instruments passthrough. you can use this to overwrite egg-bin's default c8 instruments and add additional ones.
|
|
193
|
-
>
|
|
194
177
|
> - egg-bin have some default instruments passed to c8 like `-r` and `--temp-directory`
|
|
195
178
|
> - `egg-bin cov --c8="-r teamcity -r text" --c8-report=true`
|
|
196
|
-
>
|
|
197
179
|
- also support all test params above.
|
|
198
180
|
|
|
199
181
|
#### cov environment
|
|
@@ -214,7 +196,7 @@ See <https://oclif.io/docs/configuring_your_cli/>
|
|
|
214
196
|
|
|
215
197
|
## Contributors
|
|
216
198
|
|
|
217
|
-
[](https://github.com/eggjs/egg/graphs/contributors)
|
|
218
200
|
|
|
219
201
|
Made with [contributors-img](https://contrib.rocks).
|
|
220
202
|
|
package/bin/dev.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { PackageEgg } from "./types.js";
|
|
2
|
+
import { Command, Interfaces } from "@oclif/core";
|
|
3
|
+
import { ForkOptions } from "node:child_process";
|
|
4
|
+
|
|
5
|
+
//#region src/baseCommand.d.ts
|
|
6
|
+
declare class ForkError extends Error {
|
|
7
|
+
code: number | null;
|
|
8
|
+
constructor(message: string, code: number | null);
|
|
9
|
+
}
|
|
10
|
+
interface ForkNodeOptions extends ForkOptions {
|
|
11
|
+
dryRun?: boolean;
|
|
12
|
+
}
|
|
13
|
+
type CustomFlags<T extends typeof Command> = Interfaces.InferredFlags<(typeof BaseCommand)['baseFlags'] & T['flags']>;
|
|
14
|
+
type Args$1<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
|
|
15
|
+
declare abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
16
|
+
#private;
|
|
17
|
+
static enableJsonFlag: boolean;
|
|
18
|
+
static baseFlags: {
|
|
19
|
+
'dry-run': Interfaces.BooleanFlag<boolean>;
|
|
20
|
+
require: Interfaces.OptionFlag<string[] | undefined, Interfaces.CustomOptions>;
|
|
21
|
+
import: Interfaces.OptionFlag<string[] | undefined, Interfaces.CustomOptions>;
|
|
22
|
+
base: Interfaces.OptionFlag<string, Interfaces.CustomOptions>;
|
|
23
|
+
tscompiler: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
24
|
+
typescript: Interfaces.BooleanFlag<boolean>;
|
|
25
|
+
ts: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
26
|
+
javascript: Interfaces.BooleanFlag<boolean>;
|
|
27
|
+
declarations: Interfaces.BooleanFlag<boolean>;
|
|
28
|
+
inspect: Interfaces.BooleanFlag<boolean>;
|
|
29
|
+
'inspect-brk': Interfaces.BooleanFlag<boolean>;
|
|
30
|
+
};
|
|
31
|
+
protected flags: CustomFlags<T>;
|
|
32
|
+
protected args: Args$1<T>;
|
|
33
|
+
protected env: {
|
|
34
|
+
[key: string]: string | undefined;
|
|
35
|
+
TZ?: string;
|
|
36
|
+
};
|
|
37
|
+
protected pkg: Record<string, any>;
|
|
38
|
+
protected isESM: boolean;
|
|
39
|
+
protected pkgEgg: PackageEgg;
|
|
40
|
+
protected globalExecArgv: string[];
|
|
41
|
+
init(): Promise<void>;
|
|
42
|
+
protected catch(err: Error & {
|
|
43
|
+
exitCode?: number;
|
|
44
|
+
}): Promise<any>;
|
|
45
|
+
protected finally(_: Error | undefined): Promise<any>;
|
|
46
|
+
protected formatRequires(): Promise<string[]>;
|
|
47
|
+
protected formatImportModule(modulePath: string): string;
|
|
48
|
+
protected addNodeOptions(options: string): void;
|
|
49
|
+
protected forkNode(modulePath: string, forkArgs: string[], options?: ForkNodeOptions): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { BaseCommand, ForkError, ForkNodeOptions };
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { getSourceDirname, hasTsConfig, readPackageJSON } from "./utils.js";
|
|
2
|
+
import { debuglog } from "node:util";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { Command, Flags, Interfaces } from "@oclif/core";
|
|
6
|
+
import { importResolve } from "@eggjs/utils";
|
|
7
|
+
import { pathToFileURL } from "node:url";
|
|
8
|
+
import { fork } from "node:child_process";
|
|
9
|
+
import { runScript } from "runscript";
|
|
10
|
+
|
|
11
|
+
//#region src/baseCommand.ts
|
|
12
|
+
const debug = debuglog("egg-bin/baseCommand");
|
|
13
|
+
const children = /* @__PURE__ */ new Set();
|
|
14
|
+
let hadHook = false;
|
|
15
|
+
function graceful(proc) {
|
|
16
|
+
children.add(proc);
|
|
17
|
+
/* c8 ignore else */
|
|
18
|
+
if (!hadHook) {
|
|
19
|
+
hadHook = true;
|
|
20
|
+
let signal;
|
|
21
|
+
[
|
|
22
|
+
"SIGINT",
|
|
23
|
+
"SIGQUIT",
|
|
24
|
+
"SIGTERM"
|
|
25
|
+
].forEach((event) => {
|
|
26
|
+
process.once(event, () => {
|
|
27
|
+
signal = event;
|
|
28
|
+
process.exit(0);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
process.once("exit", (code) => {
|
|
32
|
+
for (const child of children) {
|
|
33
|
+
debug("process exit code: %o, kill child %o with %o", code, child.pid, signal);
|
|
34
|
+
child.kill(signal);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
var ForkError = class extends Error {
|
|
40
|
+
code;
|
|
41
|
+
constructor(message, code) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.code = code;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var BaseCommand = class extends Command {
|
|
47
|
+
static enableJsonFlag = false;
|
|
48
|
+
static baseFlags = {
|
|
49
|
+
"dry-run": Flags.boolean({
|
|
50
|
+
default: false,
|
|
51
|
+
helpGroup: "GLOBAL",
|
|
52
|
+
summary: "whether show full command script only",
|
|
53
|
+
char: "d"
|
|
54
|
+
}),
|
|
55
|
+
require: Flags.string({
|
|
56
|
+
helpGroup: "GLOBAL",
|
|
57
|
+
summary: "require the given module",
|
|
58
|
+
char: "r",
|
|
59
|
+
multiple: true
|
|
60
|
+
}),
|
|
61
|
+
import: Flags.string({
|
|
62
|
+
helpGroup: "GLOBAL",
|
|
63
|
+
summary: "import the given module, only work on ESM",
|
|
64
|
+
multiple: true
|
|
65
|
+
}),
|
|
66
|
+
base: Flags.string({
|
|
67
|
+
helpGroup: "GLOBAL",
|
|
68
|
+
summary: "directory of application",
|
|
69
|
+
aliases: ["baseDir"],
|
|
70
|
+
default: process.cwd()
|
|
71
|
+
}),
|
|
72
|
+
tscompiler: Flags.string({
|
|
73
|
+
helpGroup: "GLOBAL",
|
|
74
|
+
summary: "TypeScript compiler, like ts-node/register",
|
|
75
|
+
aliases: ["tsc"]
|
|
76
|
+
}),
|
|
77
|
+
typescript: Flags.boolean({
|
|
78
|
+
helpGroup: "GLOBAL",
|
|
79
|
+
description: "[default: true] use TypeScript to run the test",
|
|
80
|
+
allowNo: true
|
|
81
|
+
}),
|
|
82
|
+
ts: Flags.string({
|
|
83
|
+
helpGroup: "GLOBAL",
|
|
84
|
+
description: "shortcut for --typescript, e.g.: --ts=false",
|
|
85
|
+
options: ["true", "false"]
|
|
86
|
+
}),
|
|
87
|
+
javascript: Flags.boolean({
|
|
88
|
+
helpGroup: "GLOBAL",
|
|
89
|
+
description: "use JavaScript to run the test",
|
|
90
|
+
aliases: ["js"]
|
|
91
|
+
}),
|
|
92
|
+
declarations: Flags.boolean({
|
|
93
|
+
helpGroup: "GLOBAL",
|
|
94
|
+
description: "whether create typings, will add `--require egg-ts-helper/register`",
|
|
95
|
+
aliases: ["dts"]
|
|
96
|
+
}),
|
|
97
|
+
inspect: Flags.boolean({
|
|
98
|
+
helpGroup: "GLOBAL",
|
|
99
|
+
description: "Activate inspector"
|
|
100
|
+
}),
|
|
101
|
+
"inspect-brk": Flags.boolean({
|
|
102
|
+
helpGroup: "GLOBAL",
|
|
103
|
+
description: "Activate inspector and break at start of user script"
|
|
104
|
+
})
|
|
105
|
+
};
|
|
106
|
+
flags;
|
|
107
|
+
args;
|
|
108
|
+
env = { ...process.env };
|
|
109
|
+
pkg;
|
|
110
|
+
isESM;
|
|
111
|
+
pkgEgg;
|
|
112
|
+
globalExecArgv = [];
|
|
113
|
+
async init() {
|
|
114
|
+
await super.init();
|
|
115
|
+
debug("[init] raw args: %o, NODE_ENV: %o", this.argv, this.env.NODE_ENV);
|
|
116
|
+
const { args, flags } = await this.parse({
|
|
117
|
+
flags: this.ctor.flags,
|
|
118
|
+
baseFlags: super.ctor.baseFlags,
|
|
119
|
+
enableJsonFlag: this.ctor.enableJsonFlag,
|
|
120
|
+
args: this.ctor.args,
|
|
121
|
+
strict: this.ctor.strict
|
|
122
|
+
});
|
|
123
|
+
this.flags = flags;
|
|
124
|
+
this.args = args;
|
|
125
|
+
await this.#afterInit();
|
|
126
|
+
}
|
|
127
|
+
async #afterInit() {
|
|
128
|
+
const { args, flags } = this;
|
|
129
|
+
debug("before: args: %o, flags: %o", args, flags);
|
|
130
|
+
if (!path.isAbsolute(flags.base)) flags.base = path.join(process.cwd(), flags.base);
|
|
131
|
+
const pkg = await readPackageJSON(flags.base);
|
|
132
|
+
this.pkg = pkg;
|
|
133
|
+
this.pkgEgg = pkg.egg ?? {};
|
|
134
|
+
flags.tscompiler = flags.tscompiler ?? this.env.TS_COMPILER ?? this.pkgEgg.tscompiler;
|
|
135
|
+
let typescript = flags.typescript;
|
|
136
|
+
if (flags.ts === "true") typescript = true;
|
|
137
|
+
else if (flags.ts === "false") typescript = false;
|
|
138
|
+
if (typescript === void 0) {
|
|
139
|
+
if (this.env.EGG_TYPESCRIPT === "false") {
|
|
140
|
+
typescript = false;
|
|
141
|
+
debug("detect typescript=%o from EGG_TYPESCRIPT=%o", false, this.env.EGG_TYPESCRIPT);
|
|
142
|
+
} else if (this.env.EGG_TYPESCRIPT === "true") {
|
|
143
|
+
typescript = true;
|
|
144
|
+
debug("detect typescript=%o from EGG_TYPESCRIPT=%o", true, this.env.EGG_TYPESCRIPT);
|
|
145
|
+
} else if (typeof this.pkgEgg.typescript === "boolean") {
|
|
146
|
+
typescript = this.pkgEgg.typescript;
|
|
147
|
+
debug("detect typescript=%o from pkg.egg.typescript=%o", typescript, this.pkgEgg.typescript);
|
|
148
|
+
} else if (pkg.dependencies?.typescript) {
|
|
149
|
+
typescript = true;
|
|
150
|
+
debug("detect typescript=%o from pkg.dependencies.typescript=%o", true, pkg.dependencies.typescript);
|
|
151
|
+
} else if (pkg.devDependencies?.typescript) {
|
|
152
|
+
typescript = true;
|
|
153
|
+
debug("detect typescript=%o from pkg.devDependencies.typescript=%o", true, pkg.devDependencies.typescript);
|
|
154
|
+
} else if (await hasTsConfig(flags.base)) {
|
|
155
|
+
typescript = true;
|
|
156
|
+
debug("detect typescript=%o cause tsconfig.json exists", true);
|
|
157
|
+
} else if (flags.tscompiler) {
|
|
158
|
+
typescript = true;
|
|
159
|
+
debug("detect typescript=%o from --tscompiler=%o", true, flags.tscompiler);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
flags.typescript = typescript;
|
|
163
|
+
let rootDir = path.dirname(getSourceDirname());
|
|
164
|
+
if (path.basename(rootDir) === "dist") rootDir = path.dirname(rootDir);
|
|
165
|
+
const findPaths = [flags.base, rootDir];
|
|
166
|
+
this.isESM = pkg.type === "module";
|
|
167
|
+
if (typescript) {
|
|
168
|
+
flags.tscompiler = flags.tscompiler ?? "ts-node/register";
|
|
169
|
+
const tsNodeRegister = importResolve(flags.tscompiler, { paths: findPaths });
|
|
170
|
+
flags.tscompiler = tsNodeRegister;
|
|
171
|
+
this.addNodeOptions(this.formatImportModule(tsNodeRegister));
|
|
172
|
+
this.env.EGG_TYPESCRIPT = "true";
|
|
173
|
+
process.env.EGG_TYPESCRIPT = "true";
|
|
174
|
+
this.env.TS_NODE_FILES = process.env.TS_NODE_FILES ?? "true";
|
|
175
|
+
const tsConfigPathsRegister = importResolve("tsconfig-paths/register", { paths: findPaths });
|
|
176
|
+
this.addNodeOptions(this.formatImportModule(tsConfigPathsRegister));
|
|
177
|
+
}
|
|
178
|
+
if (this.isESM) {
|
|
179
|
+
let esmLoader = importResolve("ts-node/esm", { paths: findPaths });
|
|
180
|
+
esmLoader = pathToFileURL(esmLoader).href;
|
|
181
|
+
this.addNodeOptions("--no-warnings");
|
|
182
|
+
this.addNodeOptions(`--loader ${esmLoader}`);
|
|
183
|
+
}
|
|
184
|
+
if (flags.declarations === void 0) {
|
|
185
|
+
if (typeof this.pkgEgg.declarations === "boolean") {
|
|
186
|
+
flags.declarations = this.pkgEgg.declarations;
|
|
187
|
+
debug("detect declarations from pkg.egg.declarations=%o", this.pkgEgg.declarations);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (flags.declarations) {
|
|
191
|
+
const etsBin = importResolve("egg-ts-helper/dist/bin", { paths: findPaths });
|
|
192
|
+
debug("run ets first: %o", etsBin);
|
|
193
|
+
await runScript(`node "${etsBin}"`);
|
|
194
|
+
}
|
|
195
|
+
if (this.pkgEgg.revert) {
|
|
196
|
+
const reverts = Array.isArray(this.pkgEgg.revert) ? this.pkgEgg.revert : [this.pkgEgg.revert];
|
|
197
|
+
for (const revert of reverts) this.globalExecArgv.push(`--security-revert=${revert}`);
|
|
198
|
+
}
|
|
199
|
+
let hasInspectOption = false;
|
|
200
|
+
if (flags.inspect) {
|
|
201
|
+
this.addNodeOptions("--inspect");
|
|
202
|
+
hasInspectOption = true;
|
|
203
|
+
}
|
|
204
|
+
if (flags["inspect-brk"]) {
|
|
205
|
+
this.addNodeOptions("--inspect-brk");
|
|
206
|
+
hasInspectOption = true;
|
|
207
|
+
}
|
|
208
|
+
if (hasInspectOption) {
|
|
209
|
+
Reflect.set(flags, "timeout", 0);
|
|
210
|
+
debug("set timeout = 0 when inspect enable");
|
|
211
|
+
} else if (this.env.JB_DEBUG_FILE) {
|
|
212
|
+
Reflect.set(flags, "timeout", 0);
|
|
213
|
+
debug("set timeout = false when process.env.JB_DEBUG_FILE=%o", this.env.JB_DEBUG_FILE);
|
|
214
|
+
}
|
|
215
|
+
debug("baseDir: %o, isESM: %o", flags.base, this.isESM);
|
|
216
|
+
debug("set NODE_OPTIONS: %o", this.env.NODE_OPTIONS);
|
|
217
|
+
debug("after: args: %o, flags: %o", args, flags);
|
|
218
|
+
debug("enter real command: %o", this.id);
|
|
219
|
+
}
|
|
220
|
+
async catch(err) {
|
|
221
|
+
return super.catch(err);
|
|
222
|
+
}
|
|
223
|
+
async finally(_) {
|
|
224
|
+
return super.finally(_);
|
|
225
|
+
}
|
|
226
|
+
async formatRequires() {
|
|
227
|
+
const requires = this.flags.require ?? [];
|
|
228
|
+
const imports = this.flags.import ?? [];
|
|
229
|
+
let eggRequires = this.pkgEgg.require ?? [];
|
|
230
|
+
if (typeof eggRequires === "string") eggRequires = [eggRequires];
|
|
231
|
+
let eggImports = this.pkgEgg.import ?? [];
|
|
232
|
+
if (typeof eggImports === "string") eggImports = [eggImports];
|
|
233
|
+
return [
|
|
234
|
+
...requires,
|
|
235
|
+
...imports,
|
|
236
|
+
...eggRequires,
|
|
237
|
+
...eggImports
|
|
238
|
+
];
|
|
239
|
+
}
|
|
240
|
+
formatImportModule(modulePath) {
|
|
241
|
+
if (this.isESM) return `--import "${pathToFileURL(modulePath).href}"`;
|
|
242
|
+
if (os.platform() === "win32") return `--require "${path.win32.normalize(modulePath).replace(/\\/g, "\\\\")}"`;
|
|
243
|
+
return `--require "${modulePath}"`;
|
|
244
|
+
}
|
|
245
|
+
addNodeOptions(options) {
|
|
246
|
+
if (this.env.NODE_OPTIONS) {
|
|
247
|
+
if (!this.env.NODE_OPTIONS.includes(options)) this.env.NODE_OPTIONS = `${this.env.NODE_OPTIONS} ${options}`;
|
|
248
|
+
} else this.env.NODE_OPTIONS = options;
|
|
249
|
+
}
|
|
250
|
+
async forkNode(modulePath, forkArgs, options = {}) {
|
|
251
|
+
const env = {
|
|
252
|
+
...this.env,
|
|
253
|
+
...options.env
|
|
254
|
+
};
|
|
255
|
+
const forkExecArgv = [...this.globalExecArgv, ...options.execArgv || []];
|
|
256
|
+
const NODE_OPTIONS = env.NODE_OPTIONS ? `NODE_OPTIONS='${env.NODE_OPTIONS}' ` : "";
|
|
257
|
+
const forkExecArgvString = forkExecArgv.length ? " " + forkExecArgv.join(" ") + " " : " ";
|
|
258
|
+
const forkArgsString = forkArgs.map((a) => `'${a}'`).join(" ");
|
|
259
|
+
const fullCommand = `${NODE_OPTIONS}${process.execPath}${forkExecArgvString}${modulePath} ${forkArgsString}`;
|
|
260
|
+
if (options.dryRun) {
|
|
261
|
+
console.log("dry run: $ %s", fullCommand);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
options = {
|
|
265
|
+
stdio: "inherit",
|
|
266
|
+
env,
|
|
267
|
+
cwd: this.flags.base,
|
|
268
|
+
...options,
|
|
269
|
+
execArgv: forkExecArgv
|
|
270
|
+
};
|
|
271
|
+
const proc = fork(modulePath, forkArgs, options);
|
|
272
|
+
debug("Run fork pid: %o\n\n$ %s\n\n", proc.pid, fullCommand);
|
|
273
|
+
graceful(proc);
|
|
274
|
+
return new Promise((resolve, reject) => {
|
|
275
|
+
proc.once("exit", (code) => {
|
|
276
|
+
debug("fork pid: %o exit code %o", proc.pid, code);
|
|
277
|
+
children.delete(proc);
|
|
278
|
+
if (code !== 0) {
|
|
279
|
+
const err = new ForkError(modulePath + " " + forkArgs.join(" ") + " exit with code " + code, code);
|
|
280
|
+
reject(err);
|
|
281
|
+
} else resolve();
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
//#endregion
|
|
288
|
+
export { BaseCommand, ForkError };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ForkNodeOptions } from "../baseCommand.js";
|
|
2
|
+
import { Test } from "./test.js";
|
|
3
|
+
import * as _oclif_core_interfaces6 from "@oclif/core/interfaces";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/cov.d.ts
|
|
6
|
+
declare class Cov<T extends typeof Cov> extends Test<T> {
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
static flags: {
|
|
10
|
+
prerequire: _oclif_core_interfaces6.BooleanFlag<boolean>;
|
|
11
|
+
exclude: _oclif_core_interfaces6.OptionFlag<string[] | undefined, _oclif_core_interfaces6.CustomOptions>;
|
|
12
|
+
c8: _oclif_core_interfaces6.OptionFlag<string, _oclif_core_interfaces6.CustomOptions>;
|
|
13
|
+
bail: _oclif_core_interfaces6.BooleanFlag<boolean>;
|
|
14
|
+
timeout: _oclif_core_interfaces6.OptionFlag<number, _oclif_core_interfaces6.CustomOptions>;
|
|
15
|
+
'no-timeout': _oclif_core_interfaces6.BooleanFlag<boolean>;
|
|
16
|
+
grep: _oclif_core_interfaces6.OptionFlag<string | undefined, _oclif_core_interfaces6.CustomOptions>;
|
|
17
|
+
changed: _oclif_core_interfaces6.BooleanFlag<boolean>;
|
|
18
|
+
mochawesome: _oclif_core_interfaces6.BooleanFlag<boolean>;
|
|
19
|
+
parallel: _oclif_core_interfaces6.BooleanFlag<boolean>;
|
|
20
|
+
jobs: _oclif_core_interfaces6.OptionFlag<number, _oclif_core_interfaces6.CustomOptions>;
|
|
21
|
+
'auto-agent': _oclif_core_interfaces6.BooleanFlag<boolean>;
|
|
22
|
+
};
|
|
23
|
+
protected get defaultExcludes(): string[];
|
|
24
|
+
protected forkNode(modulePath: string, forkArgs: string[], options?: ForkNodeOptions): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { Cov };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import "../baseCommand.js";
|
|
2
|
+
import Test from "./test.js";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import fs from "node:fs/promises";
|
|
5
|
+
import { Flags } from "@oclif/core";
|
|
6
|
+
import { importResolve } from "@eggjs/utils";
|
|
7
|
+
|
|
8
|
+
//#region src/commands/cov.ts
|
|
9
|
+
var Cov = class extends Test {
|
|
10
|
+
static description = "Run the test with coverage";
|
|
11
|
+
static examples = [
|
|
12
|
+
"<%= config.bin %> <%= command.id %>",
|
|
13
|
+
"<%= config.bin %> <%= command.id %> test/index.test.ts",
|
|
14
|
+
"<%= config.bin %> <%= command.id %> test/index.test.ts,test/user.test.ts,..."
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
...Test.flags,
|
|
18
|
+
prerequire: Flags.boolean({ description: "prerequire files for coverage instrument" }),
|
|
19
|
+
exclude: Flags.string({
|
|
20
|
+
description: "coverage ignore, one or more files patterns`",
|
|
21
|
+
multiple: true,
|
|
22
|
+
char: "x"
|
|
23
|
+
}),
|
|
24
|
+
c8: Flags.string({
|
|
25
|
+
description: "c8 instruments passthrough`",
|
|
26
|
+
default: "--temp-directory node_modules/.c8_output -r text-summary -r json-summary -r json -r lcov -r cobertura"
|
|
27
|
+
})
|
|
28
|
+
};
|
|
29
|
+
get defaultExcludes() {
|
|
30
|
+
return [
|
|
31
|
+
"example/",
|
|
32
|
+
"examples/",
|
|
33
|
+
"mocks**/",
|
|
34
|
+
"docs/",
|
|
35
|
+
"test/**",
|
|
36
|
+
"test{,-*}.js",
|
|
37
|
+
"**/*.test.js",
|
|
38
|
+
"**/__tests__/**",
|
|
39
|
+
"**/node_modules/**",
|
|
40
|
+
"typings",
|
|
41
|
+
"**/*.d.ts"
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
async forkNode(modulePath, forkArgs, options = {}) {
|
|
45
|
+
const { flags } = this;
|
|
46
|
+
if (flags.prerequire) this.env.EGG_BIN_PREREQUIRE = "true";
|
|
47
|
+
const c8Args = flags.c8.split(" ").filter((a) => a.trim());
|
|
48
|
+
if (flags.typescript) {
|
|
49
|
+
this.env.SPAWN_WRAP_SHIM_ROOT = path.join(flags.base, "node_modules");
|
|
50
|
+
c8Args.push("--extension");
|
|
51
|
+
c8Args.push(".ts");
|
|
52
|
+
}
|
|
53
|
+
const excludes = new Set([
|
|
54
|
+
...process.env.COV_EXCLUDES?.split(",") ?? [],
|
|
55
|
+
...this.defaultExcludes,
|
|
56
|
+
...Array.from(flags.exclude ?? [])
|
|
57
|
+
]);
|
|
58
|
+
for (const exclude of excludes) {
|
|
59
|
+
c8Args.push("-x");
|
|
60
|
+
c8Args.push(exclude);
|
|
61
|
+
}
|
|
62
|
+
const c8File = importResolve("c8/bin/c8.js");
|
|
63
|
+
const outputDir = path.join(flags.base, "node_modules/.c8_output");
|
|
64
|
+
await fs.rm(outputDir, {
|
|
65
|
+
force: true,
|
|
66
|
+
recursive: true
|
|
67
|
+
});
|
|
68
|
+
const coverageDir = path.join(flags.base, "coverage");
|
|
69
|
+
await fs.rm(coverageDir, {
|
|
70
|
+
force: true,
|
|
71
|
+
recursive: true
|
|
72
|
+
});
|
|
73
|
+
const execArgv = [...this.globalExecArgv, ...options.execArgv || []];
|
|
74
|
+
this.globalExecArgv = [];
|
|
75
|
+
await super.forkNode(c8File, [
|
|
76
|
+
...c8Args,
|
|
77
|
+
process.execPath,
|
|
78
|
+
...execArgv,
|
|
79
|
+
modulePath,
|
|
80
|
+
...forkArgs
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
export { Cov as default };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BaseCommand } from "../baseCommand.js";
|
|
2
|
+
import * as _oclif_core_interfaces0 from "@oclif/core/interfaces";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/dev.d.ts
|
|
5
|
+
declare class Dev<T extends typeof Dev> extends BaseCommand<T> {
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
port: _oclif_core_interfaces0.OptionFlag<number | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
10
|
+
workers: _oclif_core_interfaces0.OptionFlag<number, _oclif_core_interfaces0.CustomOptions>;
|
|
11
|
+
framework: _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
12
|
+
sticky: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
protected formatEggStartOptions(): Promise<{
|
|
16
|
+
baseDir: string;
|
|
17
|
+
workers: number;
|
|
18
|
+
port: number;
|
|
19
|
+
framework: string;
|
|
20
|
+
typescript: boolean;
|
|
21
|
+
tscompiler: string | undefined;
|
|
22
|
+
sticky: boolean;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { Dev };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { getSourceFilename } from "../utils.js";
|
|
2
|
+
import { BaseCommand } from "../baseCommand.js";
|
|
3
|
+
import { debuglog } from "node:util";
|
|
4
|
+
import { Flags } from "@oclif/core";
|
|
5
|
+
import { getConfig, getFrameworkPath } from "@eggjs/utils";
|
|
6
|
+
import { detect } from "detect-port";
|
|
7
|
+
|
|
8
|
+
//#region src/commands/dev.ts
|
|
9
|
+
const debug = debuglog("egg-bin/commands/dev");
|
|
10
|
+
var Dev = class extends BaseCommand {
|
|
11
|
+
static description = "Start server at local dev mode";
|
|
12
|
+
static examples = ["<%= config.bin %> <%= command.id %>"];
|
|
13
|
+
static flags = {
|
|
14
|
+
port: Flags.integer({
|
|
15
|
+
description: "listening port, default to 7001",
|
|
16
|
+
char: "p"
|
|
17
|
+
}),
|
|
18
|
+
workers: Flags.integer({
|
|
19
|
+
char: "c",
|
|
20
|
+
aliases: ["cluster"],
|
|
21
|
+
description: "numbers of app workers",
|
|
22
|
+
default: 1
|
|
23
|
+
}),
|
|
24
|
+
framework: Flags.string({ description: "specify framework that can be absolute path or npm package, default is \"egg\"" }),
|
|
25
|
+
sticky: Flags.boolean({ description: "start a sticky cluster server" })
|
|
26
|
+
};
|
|
27
|
+
async run() {
|
|
28
|
+
debug("NODE_ENV: %o", this.env);
|
|
29
|
+
this.env.NODE_ENV = this.env.NODE_ENV ?? "development";
|
|
30
|
+
this.env.EGG_MASTER_CLOSE_TIMEOUT = "1000";
|
|
31
|
+
const ext = this.isESM ? "mjs" : "cjs";
|
|
32
|
+
const serverBin = getSourceFilename(`../scripts/start-cluster.${ext}`);
|
|
33
|
+
const eggStartOptions = await this.formatEggStartOptions();
|
|
34
|
+
const args = [JSON.stringify(eggStartOptions)];
|
|
35
|
+
const requires = await this.formatRequires();
|
|
36
|
+
const execArgv = [];
|
|
37
|
+
for (const r of requires) {
|
|
38
|
+
const module = this.formatImportModule(r);
|
|
39
|
+
const splitIndex = module.indexOf(" ");
|
|
40
|
+
if (splitIndex !== -1) execArgv.push(module.slice(0, splitIndex), module.slice(splitIndex + 2, -1));
|
|
41
|
+
}
|
|
42
|
+
await this.forkNode(serverBin, args, { execArgv });
|
|
43
|
+
}
|
|
44
|
+
async formatEggStartOptions() {
|
|
45
|
+
const { flags } = this;
|
|
46
|
+
flags.framework = getFrameworkPath({
|
|
47
|
+
framework: flags.framework,
|
|
48
|
+
baseDir: flags.base
|
|
49
|
+
});
|
|
50
|
+
if (!flags.port) {
|
|
51
|
+
let configuredPort;
|
|
52
|
+
try {
|
|
53
|
+
configuredPort = (await getConfig({
|
|
54
|
+
framework: flags.framework,
|
|
55
|
+
baseDir: flags.base,
|
|
56
|
+
env: "local"
|
|
57
|
+
}))?.cluster?.listen?.port;
|
|
58
|
+
} catch (err) {
|
|
59
|
+
/** skip when failing to read the configuration */
|
|
60
|
+
debug("getConfig error: %s, framework: %o, baseDir: %o, env: local", err, flags.framework, flags.base);
|
|
61
|
+
}
|
|
62
|
+
if (configuredPort) {
|
|
63
|
+
flags.port = configuredPort;
|
|
64
|
+
debug(`use port ${flags.port} from configuration file`);
|
|
65
|
+
} else {
|
|
66
|
+
const defaultPort = parseInt(process.env.EGG_BIN_DEFAULT_PORT ?? "7001");
|
|
67
|
+
debug("detect available port");
|
|
68
|
+
flags.port = await detect(defaultPort);
|
|
69
|
+
if (flags.port !== defaultPort) console.warn("[@eggjs/bin] server port %o is unavailable, now using port %o", defaultPort, flags.port);
|
|
70
|
+
debug(`use available port ${flags.port}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
baseDir: flags.base,
|
|
75
|
+
workers: flags.workers,
|
|
76
|
+
port: flags.port,
|
|
77
|
+
framework: flags.framework,
|
|
78
|
+
typescript: flags.typescript,
|
|
79
|
+
tscompiler: flags.tscompiler,
|
|
80
|
+
sticky: flags.sticky
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
export { Dev as default };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { BaseCommand } from "../baseCommand.js";
|
|
2
|
+
import * as _oclif_core_interfaces23 from "@oclif/core/interfaces";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/test.d.ts
|
|
5
|
+
declare class Test<T extends typeof Test> extends BaseCommand<T> {
|
|
6
|
+
static args: {
|
|
7
|
+
file: _oclif_core_interfaces23.Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static description: string;
|
|
10
|
+
static examples: string[];
|
|
11
|
+
static flags: {
|
|
12
|
+
bail: _oclif_core_interfaces23.BooleanFlag<boolean>;
|
|
13
|
+
timeout: _oclif_core_interfaces23.OptionFlag<number, _oclif_core_interfaces23.CustomOptions>;
|
|
14
|
+
'no-timeout': _oclif_core_interfaces23.BooleanFlag<boolean>;
|
|
15
|
+
grep: _oclif_core_interfaces23.OptionFlag<string | undefined, _oclif_core_interfaces23.CustomOptions>;
|
|
16
|
+
changed: _oclif_core_interfaces23.BooleanFlag<boolean>;
|
|
17
|
+
mochawesome: _oclif_core_interfaces23.BooleanFlag<boolean>;
|
|
18
|
+
parallel: _oclif_core_interfaces23.BooleanFlag<boolean>;
|
|
19
|
+
jobs: _oclif_core_interfaces23.OptionFlag<number, _oclif_core_interfaces23.CustomOptions>;
|
|
20
|
+
'auto-agent': _oclif_core_interfaces23.BooleanFlag<boolean>;
|
|
21
|
+
};
|
|
22
|
+
run(): Promise<void>;
|
|
23
|
+
protected runMocha(mochaFile: string, mochaArgs: string[]): Promise<void>;
|
|
24
|
+
protected formatMochaArgs(): Promise<string[] | undefined>;
|
|
25
|
+
protected getChangedTestFiles(dir: string, ext: string): Promise<string[]>;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { Test };
|