@eggjs/bin 7.0.0-beta.3 → 7.0.0-beta.4
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/bin/dev.cmd +3 -0
- package/bin/dev.js +6 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +5 -0
- package/dist/esm/baseCommand.d.ts +22 -0
- package/dist/esm/baseCommand.js +156 -0
- package/dist/esm/bin/cli.js +0 -0
- package/dist/esm/commands/cov.d.ts +13 -0
- package/dist/esm/commands/cov.js +25 -0
- package/dist/esm/commands/debug.d.ts +13 -0
- package/dist/esm/commands/debug.js +25 -0
- package/dist/esm/commands/dev.d.ts +13 -0
- package/dist/esm/commands/dev.js +25 -0
- package/dist/esm/commands/test.d.ts +17 -0
- package/dist/esm/commands/test.js +160 -0
- package/dist/esm/hooks/init/options.d.ts +3 -0
- package/dist/esm/hooks/init/options.js +5 -0
- package/dist/package.json +1 -1
- package/package.json +16 -4
- package/src/baseCommand.ts +181 -0
- package/src/commands/cov.ts +30 -0
- package/src/commands/debug.ts +30 -0
- package/src/commands/dev.ts +30 -0
- package/src/commands/test.ts +175 -0
- package/src/hooks/init/options.ts +7 -0
package/bin/dev.cmd
ADDED
package/bin/dev.js
ADDED
package/bin/run.cmd
ADDED
package/bin/run.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ForkOptions } from 'node:child_process';
|
|
2
|
+
import { Command, Interfaces } from '@oclif/core';
|
|
3
|
+
export type Flags<T extends typeof Command> = Interfaces.InferredFlags<typeof BaseCommand['baseFlags'] & T['flags']>;
|
|
4
|
+
export type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
|
|
5
|
+
export declare abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
6
|
+
static enableJsonFlag: boolean;
|
|
7
|
+
static baseFlags: {
|
|
8
|
+
dryRun: Interfaces.BooleanFlag<boolean>;
|
|
9
|
+
require: Interfaces.OptionFlag<string[] | undefined, Interfaces.CustomOptions>;
|
|
10
|
+
base: Interfaces.OptionFlag<string, Interfaces.CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
protected flags: Flags<T>;
|
|
13
|
+
protected args: Args<T>;
|
|
14
|
+
protected env: NodeJS.ProcessEnv;
|
|
15
|
+
init(): Promise<void>;
|
|
16
|
+
protected catch(err: Error & {
|
|
17
|
+
exitCode?: number;
|
|
18
|
+
}): Promise<any>;
|
|
19
|
+
protected finally(_: Error | undefined): Promise<any>;
|
|
20
|
+
protected formatRequires(): Promise<string[]>;
|
|
21
|
+
protected forkNode(modulePath: string, forkArgs: string[], options?: ForkOptions): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { debuglog } from 'node:util';
|
|
2
|
+
// import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { fork } from 'node:child_process';
|
|
5
|
+
import { Command, Flags } from '@oclif/core';
|
|
6
|
+
import { importResolve } from '@eggjs/utils';
|
|
7
|
+
import { addNodeOptionsToEnv, getSourceDirname,
|
|
8
|
+
// readPackageJSON, hasTsConfig, getSourceFilename,
|
|
9
|
+
} from './utils.js';
|
|
10
|
+
const debug = debuglog('@eggjs/bin/baseCommand');
|
|
11
|
+
// only hook once and only when ever start any child.
|
|
12
|
+
const children = new Set();
|
|
13
|
+
let hadHook = false;
|
|
14
|
+
function graceful(proc) {
|
|
15
|
+
// save child ref
|
|
16
|
+
children.add(proc);
|
|
17
|
+
// only hook once
|
|
18
|
+
/* c8 ignore else */
|
|
19
|
+
if (!hadHook) {
|
|
20
|
+
hadHook = true;
|
|
21
|
+
let signal;
|
|
22
|
+
['SIGINT', 'SIGQUIT', 'SIGTERM'].forEach(event => {
|
|
23
|
+
process.once(event, () => {
|
|
24
|
+
signal = event;
|
|
25
|
+
process.exit(0);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
process.once('exit', (code) => {
|
|
29
|
+
for (const child of children) {
|
|
30
|
+
debug('process exit code: %o, kill child %o with %o', code, child.pid, signal);
|
|
31
|
+
child.kill(signal);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
class ForkError extends Error {
|
|
37
|
+
code;
|
|
38
|
+
constructor(message, code) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.code = code;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export class BaseCommand extends Command {
|
|
44
|
+
// add the --json flag
|
|
45
|
+
static enableJsonFlag = false;
|
|
46
|
+
// define flags that can be inherited by any command that extends BaseCommand
|
|
47
|
+
static baseFlags = {
|
|
48
|
+
// 'log-level': Flags.option({
|
|
49
|
+
// default: 'info',
|
|
50
|
+
// helpGroup: 'GLOBAL',
|
|
51
|
+
// options: ['debug', 'warn', 'error', 'info', 'trace'] as const,
|
|
52
|
+
// summary: 'Specify level for logging.',
|
|
53
|
+
// })(),
|
|
54
|
+
dryRun: Flags.boolean({
|
|
55
|
+
default: false,
|
|
56
|
+
helpGroup: 'GLOBAL',
|
|
57
|
+
summary: 'whether show full command script only',
|
|
58
|
+
char: 'd',
|
|
59
|
+
}),
|
|
60
|
+
require: Flags.string({
|
|
61
|
+
helpGroup: 'GLOBAL',
|
|
62
|
+
summary: 'require the given module',
|
|
63
|
+
char: 'r',
|
|
64
|
+
multiple: true,
|
|
65
|
+
}),
|
|
66
|
+
base: Flags.string({
|
|
67
|
+
helpGroup: 'GLOBAL',
|
|
68
|
+
summary: 'directory of application, default to `process.cwd()`',
|
|
69
|
+
aliases: ['baseDir'],
|
|
70
|
+
default: process.cwd(),
|
|
71
|
+
}),
|
|
72
|
+
};
|
|
73
|
+
flags;
|
|
74
|
+
args;
|
|
75
|
+
env = process.env;
|
|
76
|
+
async init() {
|
|
77
|
+
await super.init();
|
|
78
|
+
const { args, flags } = await this.parse({
|
|
79
|
+
flags: this.ctor.flags,
|
|
80
|
+
baseFlags: super.ctor.baseFlags,
|
|
81
|
+
enableJsonFlag: this.ctor.enableJsonFlag,
|
|
82
|
+
args: this.ctor.args,
|
|
83
|
+
strict: this.ctor.strict,
|
|
84
|
+
});
|
|
85
|
+
this.flags = flags;
|
|
86
|
+
this.args = args;
|
|
87
|
+
// use ts-node/esm loader on esm
|
|
88
|
+
let esmLoader = importResolve('ts-node/esm', {
|
|
89
|
+
paths: [getSourceDirname()],
|
|
90
|
+
});
|
|
91
|
+
// ES Module loading with absolute path fails on windows
|
|
92
|
+
// https://github.com/nodejs/node/issues/31710#issuecomment-583916239
|
|
93
|
+
// https://nodejs.org/api/url.html#url_url_pathtofileurl_path
|
|
94
|
+
// Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'd:'
|
|
95
|
+
esmLoader = pathToFileURL(esmLoader).href;
|
|
96
|
+
// wait for https://github.com/nodejs/node/issues/40940
|
|
97
|
+
addNodeOptionsToEnv('--no-warnings', this.env);
|
|
98
|
+
addNodeOptionsToEnv(`--loader ${esmLoader}`, this.env);
|
|
99
|
+
}
|
|
100
|
+
async catch(err) {
|
|
101
|
+
// add any custom logic to handle errors from the command
|
|
102
|
+
// or simply return the parent class error handling
|
|
103
|
+
return super.catch(err);
|
|
104
|
+
}
|
|
105
|
+
async finally(_) {
|
|
106
|
+
// called after run and catch regardless of whether or not the command errored
|
|
107
|
+
return super.finally(_);
|
|
108
|
+
}
|
|
109
|
+
async formatRequires() {
|
|
110
|
+
const requires = this.args.require ?? [];
|
|
111
|
+
// const eggRequire = this.args.pkgEgg.require;
|
|
112
|
+
// if (Array.isArray(eggRequire)) {
|
|
113
|
+
// for (const r of eggRequire) {
|
|
114
|
+
// requires.push(r);
|
|
115
|
+
// }
|
|
116
|
+
// } else if (typeof eggRequire === 'string' && eggRequire) {
|
|
117
|
+
// requires.push(eggRequire);
|
|
118
|
+
// }
|
|
119
|
+
return requires;
|
|
120
|
+
}
|
|
121
|
+
async forkNode(modulePath, forkArgs, options = {}) {
|
|
122
|
+
const { args } = this;
|
|
123
|
+
if (args.dryRun) {
|
|
124
|
+
console.log('dry run: $ %o', `${process.execPath} ${modulePath} ${args.join(' ')}`);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const forkExecArgv = [
|
|
128
|
+
// ...this.ctx.args.execArgv || [],
|
|
129
|
+
...options.execArgv || [],
|
|
130
|
+
];
|
|
131
|
+
options = {
|
|
132
|
+
stdio: 'inherit',
|
|
133
|
+
env: this.env,
|
|
134
|
+
cwd: args.base,
|
|
135
|
+
...options,
|
|
136
|
+
execArgv: forkExecArgv,
|
|
137
|
+
};
|
|
138
|
+
const proc = fork(modulePath, forkArgs, options);
|
|
139
|
+
debug('Run fork pid: %o\n\n$ %s%s %s %s\n\n', proc.pid, options.env?.NODE_OPTIONS ? `NODE_OPTIONS='${options.env.NODE_OPTIONS}' ` : '', process.execPath, modulePath, forkArgs.map(a => `'${a}'`).join(' '));
|
|
140
|
+
graceful(proc);
|
|
141
|
+
return new Promise((resolve, reject) => {
|
|
142
|
+
proc.once('exit', code => {
|
|
143
|
+
debug('fork pid: %o exit code %o', proc.pid, code);
|
|
144
|
+
children.delete(proc);
|
|
145
|
+
if (code !== 0) {
|
|
146
|
+
const err = new ForkError(modulePath + ' ' + forkArgs.join(' ') + ' exit with code ' + code, code);
|
|
147
|
+
reject(err);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
resolve();
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZUNvbW1hbmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYmFzZUNvbW1hbmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNyQyxnQ0FBZ0M7QUFDaEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsSUFBSSxFQUE2QixNQUFNLG9CQUFvQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFjLE1BQU0sYUFBYSxDQUFDO0FBQ3pELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDN0MsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixnQkFBZ0I7QUFDaEIsbURBQW1EO0VBQ3BELE1BQU0sWUFBWSxDQUFDO0FBRXBCLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0FBRWpELHFEQUFxRDtBQUNyRCxNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBZ0IsQ0FBQztBQUN6QyxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7QUFDcEIsU0FBUyxRQUFRLENBQUMsSUFBa0I7SUFDbEMsaUJBQWlCO0lBQ2pCLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFbkIsaUJBQWlCO0lBQ2pCLG9CQUFvQjtJQUNwQixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQ2YsSUFBSSxNQUFzQixDQUFDO1FBQzNCLENBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDakQsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFO2dCQUN2QixNQUFNLEdBQUcsS0FBdUIsQ0FBQztnQkFDakMsT0FBTyxDQUFDLElBQUks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
|
package/dist/esm/bin/cli.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Cov extends Command {
|
|
3
|
+
static args: {
|
|
4
|
+
file: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
export default class Cov extends Command {
|
|
3
|
+
static args = {
|
|
4
|
+
file: Args.string({ description: 'file to read' }),
|
|
5
|
+
};
|
|
6
|
+
static description = 'describe the command here';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> <%= command.id %>',
|
|
9
|
+
];
|
|
10
|
+
static flags = {
|
|
11
|
+
// flag with no value (-f, --force)
|
|
12
|
+
force: Flags.boolean({ char: 'f' }),
|
|
13
|
+
// flag with a value (-n, --name=VALUE)
|
|
14
|
+
name: Flags.string({ char: 'n', description: 'name to print' }),
|
|
15
|
+
};
|
|
16
|
+
async run() {
|
|
17
|
+
const { args, flags } = await this.parse(Cov);
|
|
18
|
+
const name = flags.name ?? 'world';
|
|
19
|
+
this.log(`hello ${name} from /Users/fengmk2/git/github.com/eggjs/bin/src/commands/cov.ts`);
|
|
20
|
+
if (args.file && flags.force) {
|
|
21
|
+
this.log(`you input --force and --file: ${args.file}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY292LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2Nvdi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFbkQsTUFBTSxDQUFDLE9BQU8sT0FBTyxHQUFJLFNBQVEsT0FBTztJQUN0QyxNQUFNLENBQVUsSUFBSSxHQUFHO1FBQ3JCLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxDQUFDO0tBQ25ELENBQUM7SUFFRixNQUFNLENBQVUsV0FBVyxHQUFHLDJCQUEyQixDQUFDO0lBRTFELE1BQU0sQ0FBVSxRQUFRLEdBQUc7UUFDekIscUNBQXFDO0tBQ3RDLENBQUM7SUFFRixNQUFNLENBQVUsS0FBSyxHQUFHO1FBQ3RCLG1DQUFtQztRQUNuQyxLQUFLLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUNuQyx1Q0FBdUM7UUFDdkMsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsQ0FBQztLQUNoRSxDQUFDO0lBRUssS0FBSyxDQUFDLEdBQUc7UUFDZCxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUU5QyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQztRQUNuQyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsSUFBSSxtRUFBbUUsQ0FBQyxDQUFDO1FBQzNGLElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDN0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxpQ0FBaUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDekQsQ0FBQztJQUNILENBQUMifQ==
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Debug extends Command {
|
|
3
|
+
static args: {
|
|
4
|
+
file: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
export default class Debug extends Command {
|
|
3
|
+
static args = {
|
|
4
|
+
file: Args.string({ description: 'file to read' }),
|
|
5
|
+
};
|
|
6
|
+
static description = 'describe the command here';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> <%= command.id %>',
|
|
9
|
+
];
|
|
10
|
+
static flags = {
|
|
11
|
+
// flag with no value (-f, --force)
|
|
12
|
+
force: Flags.boolean({ char: 'f' }),
|
|
13
|
+
// flag with a value (-n, --name=VALUE)
|
|
14
|
+
name: Flags.string({ char: 'n', description: 'name to print' }),
|
|
15
|
+
};
|
|
16
|
+
async run() {
|
|
17
|
+
const { args, flags } = await this.parse(Debug);
|
|
18
|
+
const name = flags.name ?? 'world';
|
|
19
|
+
this.log(`hello ${name} from /Users/fengmk2/git/github.com/eggjs/bin/src/commands/debug.ts`);
|
|
20
|
+
if (args.file && flags.force) {
|
|
21
|
+
this.log(`you input --force and --file: ${args.file}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVidWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29tbWFuZHMvZGVidWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRW5ELE1BQU0sQ0FBQyxPQUFPLE9BQU8sS0FBTSxTQUFRLE9BQU87SUFDeEMsTUFBTSxDQUFVLElBQUksR0FBRztRQUNyQixJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLFdBQVcsRUFBRSxjQUFjLEVBQUUsQ0FBQztLQUNuRCxDQUFDO0lBRUYsTUFBTSxDQUFVLFdBQVcsR0FBRywyQkFBMkIsQ0FBQztJQUUxRCxNQUFNLENBQVUsUUFBUSxHQUFHO1FBQ3pCLHFDQUFxQztLQUN0QyxDQUFDO0lBRUYsTUFBTSxDQUFVLEtBQUssR0FBRztRQUN0QixtQ0FBbUM7UUFDbkMsS0FBSyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUM7UUFDbkMsdUNBQXVDO1FBQ3ZDLElBQUksRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsZUFBZSxFQUFFLENBQUM7S0FDaEUsQ0FBQztJQUVLLEtBQUssQ0FBQyxHQUFHO1FBQ2QsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFaEQsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksSUFBSSxPQUFPLENBQUM7UUFDbkMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUkscUVBQXFFLENBQUMsQ0FBQztRQUM3RixJQUFJLElBQUksQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxHQUFHLENBQUMsaUNBQWlDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3pELENBQUM7SUFDSCxDQUFDIn0=
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Dev extends Command {
|
|
3
|
+
static args: {
|
|
4
|
+
file: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
export default class Dev extends Command {
|
|
3
|
+
static args = {
|
|
4
|
+
file: Args.string({ description: 'file to read' }),
|
|
5
|
+
};
|
|
6
|
+
static description = 'describe the command here';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> <%= command.id %>',
|
|
9
|
+
];
|
|
10
|
+
static flags = {
|
|
11
|
+
// flag with no value (-f, --force)
|
|
12
|
+
force: Flags.boolean({ char: 'f' }),
|
|
13
|
+
// flag with a value (-n, --name=VALUE)
|
|
14
|
+
name: Flags.string({ char: 'n', description: 'name to print' }),
|
|
15
|
+
};
|
|
16
|
+
async run() {
|
|
17
|
+
const { args, flags } = await this.parse(Dev);
|
|
18
|
+
const name = flags.name ?? 'world';
|
|
19
|
+
this.log(`hello ${name} from /Users/fengmk2/git/github.com/eggjs/bin/src/commands/dev.ts`);
|
|
20
|
+
if (args.file && flags.force) {
|
|
21
|
+
this.log(`you input --force and --file: ${args.file}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV2LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2Rldi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFbkQsTUFBTSxDQUFDLE9BQU8sT0FBTyxHQUFJLFNBQVEsT0FBTztJQUN0QyxNQUFNLENBQVUsSUFBSSxHQUFHO1FBQ3JCLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxDQUFDO0tBQ25ELENBQUM7SUFFRixNQUFNLENBQVUsV0FBVyxHQUFHLDJCQUEyQixDQUFDO0lBRTFELE1BQU0sQ0FBVSxRQUFRLEdBQUc7UUFDekIscUNBQXFDO0tBQ3RDLENBQUM7SUFFRixNQUFNLENBQVUsS0FBSyxHQUFHO1FBQ3RCLG1DQUFtQztRQUNuQyxLQUFLLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUNuQyx1Q0FBdUM7UUFDdkMsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsQ0FBQztLQUNoRSxDQUFDO0lBRUssS0FBSyxDQUFDLEdBQUc7UUFDZCxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUU5QyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQztRQUNuQyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsSUFBSSxtRUFBbUUsQ0FBQyxDQUFDO1FBQzNGLElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDN0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxpQ0FBaUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDekQsQ0FBQztJQUNILENBQUMifQ==
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseCommand } from '../baseCommand.js';
|
|
2
|
+
export default class Test extends BaseCommand<typeof Test> {
|
|
3
|
+
static args: {
|
|
4
|
+
file: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
typescript: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
javascript: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
bail: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
timeout: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
grep: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<void>;
|
|
16
|
+
protected formatMochaArgs(): Promise<string[] | undefined>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { debuglog } from 'node:util';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import { Args, Flags } from '@oclif/core';
|
|
5
|
+
import globby from 'globby';
|
|
6
|
+
import { importResolve } from '@eggjs/utils';
|
|
7
|
+
import { BaseCommand } from '../baseCommand.js';
|
|
8
|
+
const debug = debuglog('@eggjs/bin/commands/test');
|
|
9
|
+
export default class Test extends BaseCommand {
|
|
10
|
+
static args = {
|
|
11
|
+
file: Args.string({
|
|
12
|
+
description: 'file(s) to test',
|
|
13
|
+
default: 'test/**/*.test.ts',
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
static description = 'Run the test';
|
|
17
|
+
static examples = [
|
|
18
|
+
'<%= config.bin %> <%= command.id %>',
|
|
19
|
+
'<%= config.bin %> <%= command.id %> test/index.test.ts',
|
|
20
|
+
'<%= config.bin %> <%= command.id %> --json',
|
|
21
|
+
'<%= config.bin %> <%= command.id %> --log-level debug',
|
|
22
|
+
];
|
|
23
|
+
static flags = {
|
|
24
|
+
// flag with no value (--ts, --typescript)
|
|
25
|
+
typescript: Flags.boolean({
|
|
26
|
+
description: '[default: true] use TypeScript to run the test',
|
|
27
|
+
default: true,
|
|
28
|
+
aliases: ['ts'],
|
|
29
|
+
allowNo: true,
|
|
30
|
+
}),
|
|
31
|
+
javascript: Flags.boolean({
|
|
32
|
+
description: 'use JavaScript to run the test',
|
|
33
|
+
default: false,
|
|
34
|
+
aliases: ['js'],
|
|
35
|
+
}),
|
|
36
|
+
bail: Flags.boolean({
|
|
37
|
+
description: 'bbort ("bail") after first test failure',
|
|
38
|
+
default: false,
|
|
39
|
+
char: 'b',
|
|
40
|
+
}),
|
|
41
|
+
// flag with a value (-n, --name=VALUE)
|
|
42
|
+
timeout: Flags.string({
|
|
43
|
+
char: 't',
|
|
44
|
+
description: 'set test-case timeout in milliseconds',
|
|
45
|
+
default: process.env.TEST_TIMEOUT ?? '60000',
|
|
46
|
+
}),
|
|
47
|
+
grep: Flags.string({
|
|
48
|
+
char: 'g',
|
|
49
|
+
description: 'only run tests matching <pattern>',
|
|
50
|
+
}),
|
|
51
|
+
};
|
|
52
|
+
async run() {
|
|
53
|
+
const { flags } = this;
|
|
54
|
+
try {
|
|
55
|
+
await fs.access(flags.base);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
console.error('baseDir: %o not exists', flags.base);
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
61
|
+
const mochaFile = process.env.MOCHA_FILE || importResolve('mocha/bin/_mocha');
|
|
62
|
+
// if (this.parallel) {
|
|
63
|
+
// this.ctx.env.ENABLE_MOCHA_PARALLEL = 'true';
|
|
64
|
+
// if (this.autoAgent) {
|
|
65
|
+
// this.ctx.env.AUTO_AGENT = 'true';
|
|
66
|
+
// }
|
|
67
|
+
// }
|
|
68
|
+
// set NODE_ENV=test, let egg application load unittest logic
|
|
69
|
+
// https://eggjs.org/basics/env#difference-from-node_env
|
|
70
|
+
// this.ctx.env.NODE_ENV = 'test';
|
|
71
|
+
debug('run test: %s %o', mochaFile, this.args);
|
|
72
|
+
const mochaArgs = await this.formatMochaArgs();
|
|
73
|
+
if (!mochaArgs)
|
|
74
|
+
return;
|
|
75
|
+
await this.forkNode(mochaFile, mochaArgs, {
|
|
76
|
+
execArgv: [
|
|
77
|
+
...process.execArgv,
|
|
78
|
+
// https://github.com/mochajs/mocha/issues/2640#issuecomment-1663388547
|
|
79
|
+
'--unhandled-rejections=strict',
|
|
80
|
+
],
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
async formatMochaArgs() {
|
|
84
|
+
const { args, flags } = this;
|
|
85
|
+
// collect require
|
|
86
|
+
const requires = await this.formatRequires();
|
|
87
|
+
// try {
|
|
88
|
+
// const eggMockRegister = importResolve('@eggjs/mock/register', { paths: [ this.base ] });
|
|
89
|
+
// requires.push(eggMockRegister);
|
|
90
|
+
// debug('auto register @eggjs/mock/register: %o', eggMockRegister);
|
|
91
|
+
// } catch (err) {
|
|
92
|
+
// // ignore @eggjs/mock not exists
|
|
93
|
+
// debug('auto register @eggjs/mock fail, can not require @eggjs/mock on %o, error: %s',
|
|
94
|
+
// this.base, (err as Error).message);
|
|
95
|
+
// }
|
|
96
|
+
// handle mochawesome enable
|
|
97
|
+
// let reporter = this.ctx.env.TEST_REPORTER;
|
|
98
|
+
// let reporterOptions = '';
|
|
99
|
+
// if (!reporter && this.mochawesome) {
|
|
100
|
+
// // use https://github.com/node-modules/mochawesome/pull/1 instead
|
|
101
|
+
// reporter = importResolve('mochawesome-with-mocha');
|
|
102
|
+
// reporterOptions = 'reportDir=node_modules/.mochawesome-reports';
|
|
103
|
+
// if (this.parallel) {
|
|
104
|
+
// // https://github.com/adamgruber/mochawesome#parallel-mode
|
|
105
|
+
// requires.push(importResolve('mochawesome-with-mocha/register'));
|
|
106
|
+
// }
|
|
107
|
+
// }
|
|
108
|
+
const ext = flags.typescript ? 'ts' : 'js';
|
|
109
|
+
let pattern = args.file ? args.file.split(',') : [];
|
|
110
|
+
// // changed
|
|
111
|
+
// if (this.changed) {
|
|
112
|
+
// pattern = await this.getChangedTestFiles(this.base, ext);
|
|
113
|
+
// if (!pattern.length) {
|
|
114
|
+
// console.log('No changed test files');
|
|
115
|
+
// return;
|
|
116
|
+
// }
|
|
117
|
+
// debug('changed files: %o', pattern);
|
|
118
|
+
// }
|
|
119
|
+
if (!pattern.length && process.env.TESTS) {
|
|
120
|
+
pattern = process.env.TESTS.split(',');
|
|
121
|
+
}
|
|
122
|
+
// collect test files when nothing is changed
|
|
123
|
+
if (!pattern.length) {
|
|
124
|
+
pattern = [`test/**/*.test.${ext}`];
|
|
125
|
+
}
|
|
126
|
+
pattern = pattern.concat(['!test/fixtures', '!test/node_modules']);
|
|
127
|
+
// expand glob and skip node_modules and fixtures
|
|
128
|
+
const files = globby.sync(pattern, { cwd: flags.base });
|
|
129
|
+
files.sort();
|
|
130
|
+
if (files.length === 0) {
|
|
131
|
+
console.log(`No test files found with ${pattern}`);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// auto add setup file as the first test file
|
|
135
|
+
const setupFile = path.join(flags.base, `test/.setup.${ext}`);
|
|
136
|
+
try {
|
|
137
|
+
await fs.access(setupFile);
|
|
138
|
+
files.unshift(setupFile);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// ignore
|
|
142
|
+
}
|
|
143
|
+
const grep = flags.grep ? flags.grep.split(',') : [];
|
|
144
|
+
return [
|
|
145
|
+
flags.dryRun ? '--dry-run' : '',
|
|
146
|
+
// force exit
|
|
147
|
+
'--exit',
|
|
148
|
+
flags.bail ? '--bail' : '',
|
|
149
|
+
grep.map(pattern => `--grep='${pattern}'`).join(' '),
|
|
150
|
+
flags.timeout ? `--timeout=${flags.timeout}` : '--no-timeout',
|
|
151
|
+
// this.parallel ? '--parallel' : '',
|
|
152
|
+
// this.parallel && this.jobs ? `--jobs=${this.jobs}` : '',
|
|
153
|
+
// reporter ? `--reporter=${reporter}` : '',
|
|
154
|
+
// reporterOptions ? `--reporter-options=${reporterOptions}` : '',
|
|
155
|
+
...requires.map(r => `--require=${r}`),
|
|
156
|
+
...files,
|
|
157
|
+
].filter(a => a.trim());
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDckMsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2xDLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzFDLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUVoRCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsMEJBQTBCLENBQUMsQ0FBQztBQUVuRCxNQUFNLENBQUMsT0FBTyxPQUFPLElBQUssU0FBUSxXQUF3QjtJQUN4RCxNQUFNLENBQVUsSUFBSSxHQUFHO1FBQ3JCLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQ2hCLFdBQVcsRUFBRSxpQkFBaUI7WUFDOUIsT0FBTyxFQUFFLG1CQUFtQjtTQUM3QixDQUFDO0tBQ0gsQ0FBQztJQUVGLE1BQU0sQ0FBVSxXQUFXLEdBQUcsY0FBYyxDQUFDO0lBRTdDLE1BQU0sQ0FBVSxRQUFRLEdBQUc7UUFDekIscUNBQXFDO1FBQ3JDLHdEQUF3RDtRQUN4RCw0Q0FBNEM7UUFDNUMsdURBQXVEO0tBQ3hELENBQUM7SUFFRixNQUFNLENBQVUsS0FBSyxHQUFHO1FBQ3RCLDBDQUEwQztRQUMxQyxVQUFVLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQztZQUN4QixXQUFXLEVBQUUsZ0RBQWdEO1lBQzdELE9BQU8sRUFBRSxJQUFJO1lBQ2IsT0FBTyxFQUFFLENBQUUsSUFBSSxDQUFFO1lBQ2pCLE9BQU8sRUFBRSxJQUFJO1NBQ2Qs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
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const hook = async function (opts) {
|
|
2
|
+
process.stdout.write(`example hook running ${opts.id}\n`);
|
|
3
|
+
};
|
|
4
|
+
export default hook;
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9ob29rcy9pbml0L29wdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTSxJQUFJLEdBQWlCLEtBQUssV0FBVSxJQUFJO0lBQzVDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHdCQUF3QixJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUM1RCxDQUFDLENBQUM7QUFFRixlQUFlLElBQUksQ0FBQyJ9
|
package/dist/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eggjs/bin",
|
|
3
|
-
"version": "7.0.0-beta.
|
|
3
|
+
"version": "7.0.0-beta.4",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"@artus-cli/plugin-autocomplete": "^0.1.1",
|
|
38
38
|
"@artus-cli/plugin-version": "^1.0.2",
|
|
39
39
|
"@eggjs/utils": "^4.1.2",
|
|
40
|
+
"@oclif/core": "^4.2.0",
|
|
40
41
|
"c8": "^10.0.0",
|
|
41
42
|
"detect-port": "^2.0.0",
|
|
42
43
|
"egg-ts-helper": "^2.1.0",
|
|
@@ -69,6 +70,7 @@
|
|
|
69
70
|
"coffee": "^5.5.1",
|
|
70
71
|
"cpy": "^8.1.2",
|
|
71
72
|
"cpy-cli": "^5.0.0",
|
|
73
|
+
"cross-env": "^7.0.3",
|
|
72
74
|
"egg": "beta",
|
|
73
75
|
"esbuild": "^0.17.7",
|
|
74
76
|
"esbuild-register": "^3.4.2",
|
|
@@ -84,7 +86,7 @@
|
|
|
84
86
|
"lint": "eslint --cache src test --ext .ts",
|
|
85
87
|
"pretest": "npm run clean && npm run lint -- --fix && npm run prepublishOnly",
|
|
86
88
|
"test": "npm run test-local",
|
|
87
|
-
"test-local": "node
|
|
89
|
+
"test-local": "cross-env NODE_DEBUG=* node bin/dev.js test",
|
|
88
90
|
"preci": "npm run clean && npm run lint && npm run prepublishOnly",
|
|
89
91
|
"cov": "c8 -r lcov -r text-summary -x 'test/**' npm run test-local -- --timeout 120000",
|
|
90
92
|
"ci": "npm run cov",
|
|
@@ -113,14 +115,24 @@
|
|
|
113
115
|
"./package.json": "./package.json"
|
|
114
116
|
},
|
|
115
117
|
"files": [
|
|
118
|
+
"bin",
|
|
116
119
|
"dist",
|
|
117
120
|
"src",
|
|
118
121
|
"scripts"
|
|
119
122
|
],
|
|
120
123
|
"bin": {
|
|
121
|
-
"egg-bin": "./
|
|
124
|
+
"egg-bin": "./bin/run.js"
|
|
122
125
|
},
|
|
123
126
|
"types": "./dist/commonjs/index.d.ts",
|
|
124
127
|
"main": "./dist/commonjs/index.js",
|
|
125
|
-
"module": "./dist/esm/index.js"
|
|
128
|
+
"module": "./dist/esm/index.js",
|
|
129
|
+
"oclif": {
|
|
130
|
+
"bin": "egg-bin",
|
|
131
|
+
"commands": "./dist/esm/commands",
|
|
132
|
+
"dirname": "egg-bin",
|
|
133
|
+
"topicSeparator": " ",
|
|
134
|
+
"hooks": {
|
|
135
|
+
"init": "./dist/esm/hooks/init/options"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
126
138
|
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { debuglog } from 'node:util';
|
|
2
|
+
// import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { fork, ForkOptions, ChildProcess } from 'node:child_process';
|
|
5
|
+
import { Command, Flags, Interfaces } from '@oclif/core';
|
|
6
|
+
import { importResolve } from '@eggjs/utils';
|
|
7
|
+
import {
|
|
8
|
+
addNodeOptionsToEnv,
|
|
9
|
+
getSourceDirname,
|
|
10
|
+
// readPackageJSON, hasTsConfig, getSourceFilename,
|
|
11
|
+
} from './utils.js';
|
|
12
|
+
|
|
13
|
+
const debug = debuglog('@eggjs/bin/baseCommand');
|
|
14
|
+
|
|
15
|
+
// only hook once and only when ever start any child.
|
|
16
|
+
const children = new Set<ChildProcess>();
|
|
17
|
+
let hadHook = false;
|
|
18
|
+
function graceful(proc: ChildProcess) {
|
|
19
|
+
// save child ref
|
|
20
|
+
children.add(proc);
|
|
21
|
+
|
|
22
|
+
// only hook once
|
|
23
|
+
/* c8 ignore else */
|
|
24
|
+
if (!hadHook) {
|
|
25
|
+
hadHook = true;
|
|
26
|
+
let signal: NodeJS.Signals;
|
|
27
|
+
[ 'SIGINT', 'SIGQUIT', 'SIGTERM' ].forEach(event => {
|
|
28
|
+
process.once(event, () => {
|
|
29
|
+
signal = event as NodeJS.Signals;
|
|
30
|
+
process.exit(0);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
process.once('exit', (code: number) => {
|
|
35
|
+
for (const child of children) {
|
|
36
|
+
debug('process exit code: %o, kill child %o with %o', code, child.pid, signal);
|
|
37
|
+
child.kill(signal);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class ForkError extends Error {
|
|
44
|
+
code: number | null;
|
|
45
|
+
constructor(message: string, code: number | null) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.code = code;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type Flags<T extends typeof Command> = Interfaces.InferredFlags<typeof BaseCommand['baseFlags'] & T['flags']>;
|
|
52
|
+
export type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
|
|
53
|
+
|
|
54
|
+
export abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
55
|
+
// add the --json flag
|
|
56
|
+
static enableJsonFlag = false;
|
|
57
|
+
|
|
58
|
+
// define flags that can be inherited by any command that extends BaseCommand
|
|
59
|
+
static baseFlags = {
|
|
60
|
+
// 'log-level': Flags.option({
|
|
61
|
+
// default: 'info',
|
|
62
|
+
// helpGroup: 'GLOBAL',
|
|
63
|
+
// options: ['debug', 'warn', 'error', 'info', 'trace'] as const,
|
|
64
|
+
// summary: 'Specify level for logging.',
|
|
65
|
+
// })(),
|
|
66
|
+
dryRun: Flags.boolean({
|
|
67
|
+
default: false,
|
|
68
|
+
helpGroup: 'GLOBAL',
|
|
69
|
+
summary: 'whether show full command script only',
|
|
70
|
+
char: 'd',
|
|
71
|
+
}),
|
|
72
|
+
require: Flags.string({
|
|
73
|
+
helpGroup: 'GLOBAL',
|
|
74
|
+
summary: 'require the given module',
|
|
75
|
+
char: 'r',
|
|
76
|
+
multiple: true,
|
|
77
|
+
}),
|
|
78
|
+
base: Flags.string({
|
|
79
|
+
helpGroup: 'GLOBAL',
|
|
80
|
+
summary: 'directory of application, default to `process.cwd()`',
|
|
81
|
+
aliases: [ 'baseDir' ],
|
|
82
|
+
default: process.cwd(),
|
|
83
|
+
}),
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
protected flags!: Flags<T>;
|
|
87
|
+
protected args!: Args<T>;
|
|
88
|
+
|
|
89
|
+
protected env = process.env;
|
|
90
|
+
|
|
91
|
+
public async init(): Promise<void> {
|
|
92
|
+
await super.init();
|
|
93
|
+
const { args, flags } = await this.parse({
|
|
94
|
+
flags: this.ctor.flags,
|
|
95
|
+
baseFlags: (super.ctor as typeof BaseCommand).baseFlags,
|
|
96
|
+
enableJsonFlag: this.ctor.enableJsonFlag,
|
|
97
|
+
args: this.ctor.args,
|
|
98
|
+
strict: this.ctor.strict,
|
|
99
|
+
});
|
|
100
|
+
this.flags = flags as Flags<T>;
|
|
101
|
+
this.args = args as Args<T>;
|
|
102
|
+
|
|
103
|
+
// use ts-node/esm loader on esm
|
|
104
|
+
let esmLoader = importResolve('ts-node/esm', {
|
|
105
|
+
paths: [ getSourceDirname() ],
|
|
106
|
+
});
|
|
107
|
+
// ES Module loading with absolute path fails on windows
|
|
108
|
+
// https://github.com/nodejs/node/issues/31710#issuecomment-583916239
|
|
109
|
+
// https://nodejs.org/api/url.html#url_url_pathtofileurl_path
|
|
110
|
+
// Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'd:'
|
|
111
|
+
esmLoader = pathToFileURL(esmLoader).href;
|
|
112
|
+
// wait for https://github.com/nodejs/node/issues/40940
|
|
113
|
+
addNodeOptionsToEnv('--no-warnings', this.env);
|
|
114
|
+
addNodeOptionsToEnv(`--loader ${esmLoader}`, this.env);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
protected async catch(err: Error & {exitCode?: number}): Promise<any> {
|
|
118
|
+
// add any custom logic to handle errors from the command
|
|
119
|
+
// or simply return the parent class error handling
|
|
120
|
+
return super.catch(err);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
protected async finally(_: Error | undefined): Promise<any> {
|
|
124
|
+
// called after run and catch regardless of whether or not the command errored
|
|
125
|
+
return super.finally(_);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
protected async formatRequires(): Promise<string[]> {
|
|
129
|
+
const requires = this.args.require ?? [];
|
|
130
|
+
// const eggRequire = this.args.pkgEgg.require;
|
|
131
|
+
// if (Array.isArray(eggRequire)) {
|
|
132
|
+
// for (const r of eggRequire) {
|
|
133
|
+
// requires.push(r);
|
|
134
|
+
// }
|
|
135
|
+
// } else if (typeof eggRequire === 'string' && eggRequire) {
|
|
136
|
+
// requires.push(eggRequire);
|
|
137
|
+
// }
|
|
138
|
+
return requires;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
protected async forkNode(modulePath: string, forkArgs: string[], options: ForkOptions = {}) {
|
|
142
|
+
const { args } = this;
|
|
143
|
+
if (args.dryRun) {
|
|
144
|
+
console.log('dry run: $ %o', `${process.execPath} ${modulePath} ${args.join(' ')}`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const forkExecArgv = [
|
|
148
|
+
// ...this.ctx.args.execArgv || [],
|
|
149
|
+
...options.execArgv || [],
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
options = {
|
|
153
|
+
stdio: 'inherit',
|
|
154
|
+
env: this.env,
|
|
155
|
+
cwd: args.base,
|
|
156
|
+
...options,
|
|
157
|
+
execArgv: forkExecArgv,
|
|
158
|
+
};
|
|
159
|
+
const proc = fork(modulePath, forkArgs, options);
|
|
160
|
+
debug('Run fork pid: %o\n\n$ %s%s %s %s\n\n',
|
|
161
|
+
proc.pid,
|
|
162
|
+
options.env?.NODE_OPTIONS ? `NODE_OPTIONS='${options.env.NODE_OPTIONS}' ` : '',
|
|
163
|
+
process.execPath,
|
|
164
|
+
modulePath, forkArgs.map(a => `'${a}'`).join(' '));
|
|
165
|
+
graceful(proc);
|
|
166
|
+
|
|
167
|
+
return new Promise<void>((resolve, reject) => {
|
|
168
|
+
proc.once('exit', code => {
|
|
169
|
+
debug('fork pid: %o exit code %o', proc.pid, code);
|
|
170
|
+
children.delete(proc);
|
|
171
|
+
if (code !== 0) {
|
|
172
|
+
const err = new ForkError(modulePath + ' ' + forkArgs.join(' ') + ' exit with code ' + code, code);
|
|
173
|
+
reject(err);
|
|
174
|
+
} else {
|
|
175
|
+
resolve();
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
|
|
3
|
+
export default class Cov extends Command {
|
|
4
|
+
static override args = {
|
|
5
|
+
file: Args.string({ description: 'file to read' }),
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
static override description = 'describe the command here';
|
|
9
|
+
|
|
10
|
+
static override examples = [
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
static override flags = {
|
|
15
|
+
// flag with no value (-f, --force)
|
|
16
|
+
force: Flags.boolean({ char: 'f' }),
|
|
17
|
+
// flag with a value (-n, --name=VALUE)
|
|
18
|
+
name: Flags.string({ char: 'n', description: 'name to print' }),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
public async run(): Promise<void> {
|
|
22
|
+
const { args, flags } = await this.parse(Cov);
|
|
23
|
+
|
|
24
|
+
const name = flags.name ?? 'world';
|
|
25
|
+
this.log(`hello ${name} from /Users/fengmk2/git/github.com/eggjs/bin/src/commands/cov.ts`);
|
|
26
|
+
if (args.file && flags.force) {
|
|
27
|
+
this.log(`you input --force and --file: ${args.file}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
|
|
3
|
+
export default class Debug extends Command {
|
|
4
|
+
static override args = {
|
|
5
|
+
file: Args.string({ description: 'file to read' }),
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
static override description = 'describe the command here';
|
|
9
|
+
|
|
10
|
+
static override examples = [
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
static override flags = {
|
|
15
|
+
// flag with no value (-f, --force)
|
|
16
|
+
force: Flags.boolean({ char: 'f' }),
|
|
17
|
+
// flag with a value (-n, --name=VALUE)
|
|
18
|
+
name: Flags.string({ char: 'n', description: 'name to print' }),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
public async run(): Promise<void> {
|
|
22
|
+
const { args, flags } = await this.parse(Debug);
|
|
23
|
+
|
|
24
|
+
const name = flags.name ?? 'world';
|
|
25
|
+
this.log(`hello ${name} from /Users/fengmk2/git/github.com/eggjs/bin/src/commands/debug.ts`);
|
|
26
|
+
if (args.file && flags.force) {
|
|
27
|
+
this.log(`you input --force and --file: ${args.file}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
|
|
3
|
+
export default class Dev extends Command {
|
|
4
|
+
static override args = {
|
|
5
|
+
file: Args.string({ description: 'file to read' }),
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
static override description = 'describe the command here';
|
|
9
|
+
|
|
10
|
+
static override examples = [
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
static override flags = {
|
|
15
|
+
// flag with no value (-f, --force)
|
|
16
|
+
force: Flags.boolean({ char: 'f' }),
|
|
17
|
+
// flag with a value (-n, --name=VALUE)
|
|
18
|
+
name: Flags.string({ char: 'n', description: 'name to print' }),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
public async run(): Promise<void> {
|
|
22
|
+
const { args, flags } = await this.parse(Dev);
|
|
23
|
+
|
|
24
|
+
const name = flags.name ?? 'world';
|
|
25
|
+
this.log(`hello ${name} from /Users/fengmk2/git/github.com/eggjs/bin/src/commands/dev.ts`);
|
|
26
|
+
if (args.file && flags.force) {
|
|
27
|
+
this.log(`you input --force and --file: ${args.file}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { debuglog } from 'node:util';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import { Args, Flags } from '@oclif/core';
|
|
5
|
+
import globby from 'globby';
|
|
6
|
+
import { importResolve } from '@eggjs/utils';
|
|
7
|
+
import { BaseCommand } from '../baseCommand.js';
|
|
8
|
+
|
|
9
|
+
const debug = debuglog('@eggjs/bin/commands/test');
|
|
10
|
+
|
|
11
|
+
export default class Test extends BaseCommand<typeof Test> {
|
|
12
|
+
static override args = {
|
|
13
|
+
file: Args.string({
|
|
14
|
+
description: 'file(s) to test',
|
|
15
|
+
default: 'test/**/*.test.ts',
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
static override description = 'Run the test';
|
|
20
|
+
|
|
21
|
+
static override examples = [
|
|
22
|
+
'<%= config.bin %> <%= command.id %>',
|
|
23
|
+
'<%= config.bin %> <%= command.id %> test/index.test.ts',
|
|
24
|
+
'<%= config.bin %> <%= command.id %> --json',
|
|
25
|
+
'<%= config.bin %> <%= command.id %> --log-level debug',
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
static override flags = {
|
|
29
|
+
// flag with no value (--ts, --typescript)
|
|
30
|
+
typescript: Flags.boolean({
|
|
31
|
+
description: '[default: true] use TypeScript to run the test',
|
|
32
|
+
default: true,
|
|
33
|
+
aliases: [ 'ts' ],
|
|
34
|
+
allowNo: true,
|
|
35
|
+
}),
|
|
36
|
+
javascript: Flags.boolean({
|
|
37
|
+
description: 'use JavaScript to run the test',
|
|
38
|
+
default: false,
|
|
39
|
+
aliases: [ 'js' ],
|
|
40
|
+
}),
|
|
41
|
+
bail: Flags.boolean({
|
|
42
|
+
description: 'bbort ("bail") after first test failure',
|
|
43
|
+
default: false,
|
|
44
|
+
char: 'b',
|
|
45
|
+
}),
|
|
46
|
+
// flag with a value (-n, --name=VALUE)
|
|
47
|
+
timeout: Flags.string({
|
|
48
|
+
char: 't',
|
|
49
|
+
description: 'set test-case timeout in milliseconds',
|
|
50
|
+
default: process.env.TEST_TIMEOUT ?? '60000',
|
|
51
|
+
}),
|
|
52
|
+
grep: Flags.string({
|
|
53
|
+
char: 'g',
|
|
54
|
+
description: 'only run tests matching <pattern>',
|
|
55
|
+
}),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
public async run(): Promise<void> {
|
|
59
|
+
const { flags } = this;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
await fs.access(flags.base);
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.error('baseDir: %o not exists', flags.base);
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const mochaFile = process.env.MOCHA_FILE || importResolve('mocha/bin/_mocha');
|
|
69
|
+
// if (this.parallel) {
|
|
70
|
+
// this.ctx.env.ENABLE_MOCHA_PARALLEL = 'true';
|
|
71
|
+
// if (this.autoAgent) {
|
|
72
|
+
// this.ctx.env.AUTO_AGENT = 'true';
|
|
73
|
+
// }
|
|
74
|
+
// }
|
|
75
|
+
// set NODE_ENV=test, let egg application load unittest logic
|
|
76
|
+
// https://eggjs.org/basics/env#difference-from-node_env
|
|
77
|
+
// this.ctx.env.NODE_ENV = 'test';
|
|
78
|
+
debug('run test: %s %o', mochaFile, this.args);
|
|
79
|
+
|
|
80
|
+
const mochaArgs = await this.formatMochaArgs();
|
|
81
|
+
if (!mochaArgs) return;
|
|
82
|
+
await this.forkNode(mochaFile, mochaArgs, {
|
|
83
|
+
execArgv: [
|
|
84
|
+
...process.execArgv,
|
|
85
|
+
// https://github.com/mochajs/mocha/issues/2640#issuecomment-1663388547
|
|
86
|
+
'--unhandled-rejections=strict',
|
|
87
|
+
],
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
protected async formatMochaArgs() {
|
|
92
|
+
const { args, flags } = this;
|
|
93
|
+
// collect require
|
|
94
|
+
const requires = await this.formatRequires();
|
|
95
|
+
// try {
|
|
96
|
+
// const eggMockRegister = importResolve('@eggjs/mock/register', { paths: [ this.base ] });
|
|
97
|
+
// requires.push(eggMockRegister);
|
|
98
|
+
// debug('auto register @eggjs/mock/register: %o', eggMockRegister);
|
|
99
|
+
// } catch (err) {
|
|
100
|
+
// // ignore @eggjs/mock not exists
|
|
101
|
+
// debug('auto register @eggjs/mock fail, can not require @eggjs/mock on %o, error: %s',
|
|
102
|
+
// this.base, (err as Error).message);
|
|
103
|
+
// }
|
|
104
|
+
|
|
105
|
+
// handle mochawesome enable
|
|
106
|
+
// let reporter = this.ctx.env.TEST_REPORTER;
|
|
107
|
+
// let reporterOptions = '';
|
|
108
|
+
// if (!reporter && this.mochawesome) {
|
|
109
|
+
// // use https://github.com/node-modules/mochawesome/pull/1 instead
|
|
110
|
+
// reporter = importResolve('mochawesome-with-mocha');
|
|
111
|
+
// reporterOptions = 'reportDir=node_modules/.mochawesome-reports';
|
|
112
|
+
// if (this.parallel) {
|
|
113
|
+
// // https://github.com/adamgruber/mochawesome#parallel-mode
|
|
114
|
+
// requires.push(importResolve('mochawesome-with-mocha/register'));
|
|
115
|
+
// }
|
|
116
|
+
// }
|
|
117
|
+
|
|
118
|
+
const ext = flags.typescript ? 'ts' : 'js';
|
|
119
|
+
let pattern = args.file ? args.file.split(',') : [];
|
|
120
|
+
// // changed
|
|
121
|
+
// if (this.changed) {
|
|
122
|
+
// pattern = await this.getChangedTestFiles(this.base, ext);
|
|
123
|
+
// if (!pattern.length) {
|
|
124
|
+
// console.log('No changed test files');
|
|
125
|
+
// return;
|
|
126
|
+
// }
|
|
127
|
+
// debug('changed files: %o', pattern);
|
|
128
|
+
// }
|
|
129
|
+
|
|
130
|
+
if (!pattern.length && process.env.TESTS) {
|
|
131
|
+
pattern = process.env.TESTS.split(',');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// collect test files when nothing is changed
|
|
135
|
+
if (!pattern.length) {
|
|
136
|
+
pattern = [ `test/**/*.test.${ext}` ];
|
|
137
|
+
}
|
|
138
|
+
pattern = pattern.concat([ '!test/fixtures', '!test/node_modules' ]);
|
|
139
|
+
|
|
140
|
+
// expand glob and skip node_modules and fixtures
|
|
141
|
+
const files = globby.sync(pattern, { cwd: flags.base });
|
|
142
|
+
files.sort();
|
|
143
|
+
|
|
144
|
+
if (files.length === 0) {
|
|
145
|
+
console.log(`No test files found with ${pattern}`);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// auto add setup file as the first test file
|
|
150
|
+
const setupFile = path.join(flags.base, `test/.setup.${ext}`);
|
|
151
|
+
try {
|
|
152
|
+
await fs.access(setupFile);
|
|
153
|
+
files.unshift(setupFile);
|
|
154
|
+
} catch {
|
|
155
|
+
// ignore
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const grep = flags.grep ? flags.grep.split(',') : [];
|
|
159
|
+
|
|
160
|
+
return [
|
|
161
|
+
flags.dryRun ? '--dry-run' : '',
|
|
162
|
+
// force exit
|
|
163
|
+
'--exit',
|
|
164
|
+
flags.bail ? '--bail' : '',
|
|
165
|
+
grep.map(pattern => `--grep='${pattern}'`).join(' '),
|
|
166
|
+
flags.timeout ? `--timeout=${flags.timeout}` : '--no-timeout',
|
|
167
|
+
// this.parallel ? '--parallel' : '',
|
|
168
|
+
// this.parallel && this.jobs ? `--jobs=${this.jobs}` : '',
|
|
169
|
+
// reporter ? `--reporter=${reporter}` : '',
|
|
170
|
+
// reporterOptions ? `--reporter-options=${reporterOptions}` : '',
|
|
171
|
+
...requires.map(r => `--require=${r}`),
|
|
172
|
+
...files,
|
|
173
|
+
].filter(a => a.trim());
|
|
174
|
+
}
|
|
175
|
+
}
|