@eggjs/bin 7.0.0-beta.4 → 7.0.1
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 +5 -10
- package/bin/dev.js +6 -4
- package/bin/run.js +2 -2
- package/dist/commonjs/baseCommand.d.ts +49 -0
- package/dist/commonjs/baseCommand.js +370 -0
- package/dist/commonjs/commands/cov.d.ts +22 -0
- package/dist/commonjs/commands/cov.js +97 -0
- package/dist/commonjs/commands/dev.d.ts +21 -0
- package/dist/commonjs/commands/dev.js +95 -0
- package/dist/commonjs/commands/test.d.ts +23 -0
- package/dist/commonjs/commands/test.js +208 -0
- package/dist/commonjs/index.d.ts +7 -0
- package/dist/commonjs/index.js +30 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/commonjs/types.d.ts +9 -0
- package/dist/commonjs/types.js +3 -0
- package/dist/commonjs/utils.d.ts +4 -0
- package/dist/commonjs/utils.js +45 -0
- package/dist/esm/baseCommand.d.ts +33 -6
- package/dist/esm/baseCommand.js +246 -40
- package/dist/esm/commands/cov.d.ts +17 -8
- package/dist/esm/commands/cov.js +83 -17
- package/dist/esm/commands/dev.d.ts +15 -7
- package/dist/esm/commands/dev.js +83 -16
- package/dist/esm/commands/test.d.ts +11 -5
- package/dist/esm/commands/test.js +103 -61
- package/dist/esm/index.d.ts +7 -5
- package/dist/esm/index.js +8 -6
- package/dist/esm/types.d.ts +9 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/utils.d.ts +0 -1
- package/dist/esm/utils.js +1 -11
- package/dist/package.json +1 -1
- package/dist/scripts/start-cluster.cjs +15 -0
- package/package.json +15 -31
- package/scripts/start-cluster.cjs +15 -0
- package/src/baseCommand.ts +254 -43
- package/src/commands/cov.ts +87 -17
- package/src/commands/dev.ts +84 -15
- package/src/commands/test.ts +106 -61
- package/src/index.ts +9 -5
- package/src/types.ts +9 -0
- package/src/utils.ts +0 -10
- package/dist/esm/bin/cli.d.ts +0 -2
- package/dist/esm/bin/cli.js +0 -34
- package/dist/esm/cmd/base.d.ts +0 -12
- package/dist/esm/cmd/base.js +0 -135
- package/dist/esm/cmd/cov.d.ts +0 -8
- package/dist/esm/cmd/cov.js +0 -103
- package/dist/esm/cmd/debug.d.ts +0 -5
- package/dist/esm/cmd/debug.js +0 -28
- package/dist/esm/cmd/dev.d.ts +0 -17
- package/dist/esm/cmd/dev.js +0 -118
- package/dist/esm/cmd/test.d.ts +0 -15
- package/dist/esm/cmd/test.js +0 -237
- package/dist/esm/commands/debug.d.ts +0 -13
- package/dist/esm/commands/debug.js +0 -25
- package/dist/esm/config/framework.d.ts +0 -4
- package/dist/esm/config/framework.js +0 -4
- package/dist/esm/config/plugin.d.ts +0 -11
- package/dist/esm/config/plugin.js +0 -11
- package/dist/esm/hooks/init/options.d.ts +0 -3
- package/dist/esm/hooks/init/options.js +0 -5
- package/dist/esm/middleware/global_options.d.ts +0 -5
- package/dist/esm/middleware/global_options.js +0 -182
- package/dist/esm/middleware/handle_error.d.ts +0 -5
- package/dist/esm/middleware/handle_error.js +0 -47
- package/dist/esm/middleware/inspect.d.ts +0 -5
- package/dist/esm/middleware/inspect.js +0 -69
- package/src/bin/cli.ts +0 -37
- package/src/cmd/base.ts +0 -133
- package/src/cmd/cov.ts +0 -89
- package/src/cmd/debug.ts +0 -14
- package/src/cmd/dev.ts +0 -102
- package/src/cmd/test.ts +0 -219
- package/src/commands/debug.ts +0 -30
- package/src/config/framework.ts +0 -3
- package/src/config/plugin.ts +0 -10
- package/src/hooks/init/options.ts +0 -7
- package/src/middleware/global_options.ts +0 -169
- package/src/middleware/handle_error.ts +0 -30
- package/src/middleware/inspect.ts +0 -54
package/src/cmd/dev.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { debuglog } from 'node:util';
|
|
2
|
-
import { DefineCommand, Option } from '@artus-cli/artus-cli';
|
|
3
|
-
import utils from '@eggjs/utils';
|
|
4
|
-
import detect from 'detect-port';
|
|
5
|
-
import { BaseCommand } from './base.js';
|
|
6
|
-
import { getSourceFilename } from '../utils.js';
|
|
7
|
-
|
|
8
|
-
const debug = debuglog('egg-bin:dev');
|
|
9
|
-
|
|
10
|
-
@DefineCommand({
|
|
11
|
-
command: 'dev',
|
|
12
|
-
description: 'Start server at local dev mode',
|
|
13
|
-
alias: [ 'd' ],
|
|
14
|
-
})
|
|
15
|
-
export class DevCommand extends BaseCommand {
|
|
16
|
-
@Option({
|
|
17
|
-
description: 'listening port, default to 7001',
|
|
18
|
-
alias: 'p',
|
|
19
|
-
})
|
|
20
|
-
port: number;
|
|
21
|
-
|
|
22
|
-
@Option({
|
|
23
|
-
description: 'numbers of app workers, default to 1 at local mode',
|
|
24
|
-
alias: [ 'c', 'cluster' ],
|
|
25
|
-
default: 1,
|
|
26
|
-
})
|
|
27
|
-
workers: number;
|
|
28
|
-
|
|
29
|
-
@Option({
|
|
30
|
-
description: 'specify framework that can be absolute path or npm package, default is egg',
|
|
31
|
-
})
|
|
32
|
-
framework: string;
|
|
33
|
-
|
|
34
|
-
@Option({
|
|
35
|
-
description: 'start a sticky cluster server, default to false',
|
|
36
|
-
type: 'boolean',
|
|
37
|
-
default: false,
|
|
38
|
-
})
|
|
39
|
-
sticky: boolean;
|
|
40
|
-
|
|
41
|
-
async run() {
|
|
42
|
-
debug('run dev: %o', this.ctx.args);
|
|
43
|
-
this.ctx.env.NODE_ENV = this.ctx.env.NODE_ENV ?? 'development';
|
|
44
|
-
this.ctx.env.EGG_MASTER_CLOSE_TIMEOUT = '1000';
|
|
45
|
-
const serverBin = getSourceFilename('../scripts/start-cluster.mjs');
|
|
46
|
-
const eggStartOptions = await this.formatEggStartOptions();
|
|
47
|
-
const args = [ JSON.stringify(eggStartOptions) ];
|
|
48
|
-
const requires = await this.formatRequires();
|
|
49
|
-
const execArgv: string[] = [];
|
|
50
|
-
for (const r of requires) {
|
|
51
|
-
execArgv.push('--require');
|
|
52
|
-
execArgv.push(r);
|
|
53
|
-
}
|
|
54
|
-
await this.forkNode(serverBin, args, { execArgv });
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
protected async formatEggStartOptions() {
|
|
58
|
-
this.framework = utils.getFrameworkPath({
|
|
59
|
-
framework: this.framework,
|
|
60
|
-
baseDir: this.base,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
if (!this.port) {
|
|
64
|
-
let configuredPort: number | undefined;
|
|
65
|
-
try {
|
|
66
|
-
const configuration = await utils.getConfig({
|
|
67
|
-
framework: this.framework,
|
|
68
|
-
baseDir: this.base,
|
|
69
|
-
env: 'local',
|
|
70
|
-
});
|
|
71
|
-
configuredPort = configuration?.cluster?.listen?.port;
|
|
72
|
-
} catch (err) {
|
|
73
|
-
/** skip when failing to read the configuration */
|
|
74
|
-
debug('getConfig error: %s, framework: %o, baseDir: %o, env: local',
|
|
75
|
-
err, this.framework, this.base);
|
|
76
|
-
}
|
|
77
|
-
if (configuredPort) {
|
|
78
|
-
this.port = configuredPort;
|
|
79
|
-
debug(`use port ${this.port} from configuration file`);
|
|
80
|
-
} else {
|
|
81
|
-
const defaultPort = process.env.EGG_BIN_DEFAULT_PORT ?? 7001;
|
|
82
|
-
debug('detect available port');
|
|
83
|
-
this.port = await detect(defaultPort);
|
|
84
|
-
if (this.port !== defaultPort) {
|
|
85
|
-
console.warn('[egg-bin] server port %s is in use, now using port %o',
|
|
86
|
-
defaultPort, this.port);
|
|
87
|
-
}
|
|
88
|
-
debug(`use available port ${this.port}`);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
baseDir: this.base,
|
|
94
|
-
workers: this.workers,
|
|
95
|
-
port: this.port,
|
|
96
|
-
framework: this.framework,
|
|
97
|
-
typescript: this.ctx.args.typescript,
|
|
98
|
-
tscompiler: this.ctx.args.tscompiler,
|
|
99
|
-
sticky: this.sticky,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
}
|
package/src/cmd/test.ts
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { debuglog } from 'node:util';
|
|
2
|
-
import os from 'node:os';
|
|
3
|
-
import fs from 'node:fs/promises';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import {
|
|
6
|
-
DefineCommand, Option,
|
|
7
|
-
} from '@artus-cli/artus-cli';
|
|
8
|
-
import globby from 'globby';
|
|
9
|
-
import { importResolve } from '@eggjs/utils';
|
|
10
|
-
import { getChangedFilesForRoots } from 'jest-changed-files';
|
|
11
|
-
import { BaseCommand } from './base.js';
|
|
12
|
-
|
|
13
|
-
const debug = debuglog('egg-bin:test');
|
|
14
|
-
|
|
15
|
-
@DefineCommand({
|
|
16
|
-
command: 'test [files...]',
|
|
17
|
-
description: 'Run the test',
|
|
18
|
-
alias: [ 't' ],
|
|
19
|
-
})
|
|
20
|
-
export class TestCommand extends BaseCommand {
|
|
21
|
-
@Option({
|
|
22
|
-
default: [],
|
|
23
|
-
array: true,
|
|
24
|
-
type: 'string',
|
|
25
|
-
})
|
|
26
|
-
files: string[];
|
|
27
|
-
|
|
28
|
-
@Option({
|
|
29
|
-
description: 'set test-case timeout in milliseconds, default is 60000',
|
|
30
|
-
alias: 't',
|
|
31
|
-
default: process.env.TEST_TIMEOUT ?? 60000,
|
|
32
|
-
})
|
|
33
|
-
timeout: number | boolean;
|
|
34
|
-
|
|
35
|
-
@Option({
|
|
36
|
-
description: 'only run tests matching <pattern>',
|
|
37
|
-
alias: 'g',
|
|
38
|
-
type: 'string',
|
|
39
|
-
array: true,
|
|
40
|
-
default: [],
|
|
41
|
-
})
|
|
42
|
-
grep: string[];
|
|
43
|
-
|
|
44
|
-
@Option({
|
|
45
|
-
description: 'only test with changed files and match test/**/*.test.(js|ts), default is false',
|
|
46
|
-
alias: 'c',
|
|
47
|
-
type: 'boolean',
|
|
48
|
-
default: false,
|
|
49
|
-
})
|
|
50
|
-
changed: boolean;
|
|
51
|
-
|
|
52
|
-
@Option({
|
|
53
|
-
description: 'mocha parallel mode, default is false',
|
|
54
|
-
alias: 'p',
|
|
55
|
-
type: 'boolean',
|
|
56
|
-
default: false,
|
|
57
|
-
})
|
|
58
|
-
parallel: boolean;
|
|
59
|
-
|
|
60
|
-
@Option({
|
|
61
|
-
description: 'number of jobs to run in parallel',
|
|
62
|
-
type: 'number',
|
|
63
|
-
default: os.cpus().length - 1,
|
|
64
|
-
})
|
|
65
|
-
jobs: number;
|
|
66
|
-
|
|
67
|
-
@Option({
|
|
68
|
-
description: 'auto bootstrap agent in mocha master process, default is true',
|
|
69
|
-
type: 'boolean',
|
|
70
|
-
default: true,
|
|
71
|
-
})
|
|
72
|
-
autoAgent: boolean;
|
|
73
|
-
|
|
74
|
-
@Option({
|
|
75
|
-
description: 'enable mochawesome reporter, default is true',
|
|
76
|
-
type: 'boolean',
|
|
77
|
-
default: true,
|
|
78
|
-
})
|
|
79
|
-
mochawesome: boolean;
|
|
80
|
-
|
|
81
|
-
@Option({
|
|
82
|
-
description: 'bbort ("bail") after first test failure',
|
|
83
|
-
alias: 'b',
|
|
84
|
-
type: 'boolean',
|
|
85
|
-
default: false,
|
|
86
|
-
})
|
|
87
|
-
bail: boolean;
|
|
88
|
-
|
|
89
|
-
async run() {
|
|
90
|
-
try {
|
|
91
|
-
await fs.access(this.base);
|
|
92
|
-
} catch (err) {
|
|
93
|
-
console.error('baseDir: %o not exists', this.base);
|
|
94
|
-
throw err;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const mochaFile = process.env.MOCHA_FILE || importResolve('mocha/bin/_mocha');
|
|
98
|
-
if (this.parallel) {
|
|
99
|
-
this.ctx.env.ENABLE_MOCHA_PARALLEL = 'true';
|
|
100
|
-
if (this.autoAgent) {
|
|
101
|
-
this.ctx.env.AUTO_AGENT = 'true';
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
// set NODE_ENV=test, let egg application load unittest logic
|
|
105
|
-
// https://eggjs.org/basics/env#difference-from-node_env
|
|
106
|
-
this.ctx.env.NODE_ENV = 'test';
|
|
107
|
-
debug('run test: %s %o', mochaFile, this.ctx.args);
|
|
108
|
-
|
|
109
|
-
const mochaArgs = await this.formatMochaArgs();
|
|
110
|
-
if (!mochaArgs) return;
|
|
111
|
-
await this.forkNode(mochaFile, mochaArgs, {
|
|
112
|
-
execArgv: [
|
|
113
|
-
...process.execArgv,
|
|
114
|
-
// https://github.com/mochajs/mocha/issues/2640#issuecomment-1663388547
|
|
115
|
-
'--unhandled-rejections=strict',
|
|
116
|
-
],
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
protected async formatMochaArgs() {
|
|
121
|
-
// collect require
|
|
122
|
-
const requires = await this.formatRequires();
|
|
123
|
-
try {
|
|
124
|
-
const eggMockRegister = importResolve('@eggjs/mock/register', { paths: [ this.base ] });
|
|
125
|
-
requires.push(eggMockRegister);
|
|
126
|
-
debug('auto register @eggjs/mock/register: %o', eggMockRegister);
|
|
127
|
-
} catch (err) {
|
|
128
|
-
// ignore @eggjs/mock not exists
|
|
129
|
-
debug('auto register @eggjs/mock fail, can not require @eggjs/mock on %o, error: %s',
|
|
130
|
-
this.base, (err as Error).message);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// handle mochawesome enable
|
|
134
|
-
let reporter = this.ctx.env.TEST_REPORTER;
|
|
135
|
-
let reporterOptions = '';
|
|
136
|
-
if (!reporter && this.mochawesome) {
|
|
137
|
-
// use https://github.com/node-modules/mochawesome/pull/1 instead
|
|
138
|
-
reporter = importResolve('mochawesome-with-mocha');
|
|
139
|
-
reporterOptions = 'reportDir=node_modules/.mochawesome-reports';
|
|
140
|
-
if (this.parallel) {
|
|
141
|
-
// https://github.com/adamgruber/mochawesome#parallel-mode
|
|
142
|
-
requires.push(importResolve('mochawesome-with-mocha/register'));
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const ext = this.ctx.args.typescript ? 'ts' : 'js';
|
|
147
|
-
let pattern = this.files;
|
|
148
|
-
// changed
|
|
149
|
-
if (this.changed) {
|
|
150
|
-
pattern = await this.getChangedTestFiles(this.base, ext);
|
|
151
|
-
if (!pattern.length) {
|
|
152
|
-
console.log('No changed test files');
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
debug('changed files: %o', pattern);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (!pattern.length && process.env.TESTS) {
|
|
159
|
-
pattern = process.env.TESTS.split(',');
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// collect test files when nothing is changed
|
|
163
|
-
if (!pattern.length) {
|
|
164
|
-
pattern = [ `test/**/*.test.${ext}` ];
|
|
165
|
-
}
|
|
166
|
-
pattern = pattern.concat([ '!test/fixtures', '!test/node_modules' ]);
|
|
167
|
-
|
|
168
|
-
// expand glob and skip node_modules and fixtures
|
|
169
|
-
const files = globby.sync(pattern, { cwd: this.base });
|
|
170
|
-
files.sort();
|
|
171
|
-
|
|
172
|
-
if (files.length === 0) {
|
|
173
|
-
console.log(`No test files found with ${pattern}`);
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// auto add setup file as the first test file
|
|
178
|
-
const setupFile = path.join(this.base, `test/.setup.${ext}`);
|
|
179
|
-
try {
|
|
180
|
-
await fs.access(setupFile);
|
|
181
|
-
files.unshift(setupFile);
|
|
182
|
-
} catch {
|
|
183
|
-
// ignore
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return [
|
|
187
|
-
this.dryRun ? '--dry-run' : '',
|
|
188
|
-
// force exit
|
|
189
|
-
'--exit',
|
|
190
|
-
this.bail ? '--bail' : '',
|
|
191
|
-
this.grep.map(pattern => `--grep='${pattern}'`).join(' '),
|
|
192
|
-
this.timeout === false ? '--no-timeout' : `--timeout=${this.timeout}`,
|
|
193
|
-
this.parallel ? '--parallel' : '',
|
|
194
|
-
this.parallel && this.jobs ? `--jobs=${this.jobs}` : '',
|
|
195
|
-
reporter ? `--reporter=${reporter}` : '',
|
|
196
|
-
reporterOptions ? `--reporter-options=${reporterOptions}` : '',
|
|
197
|
-
...requires.map(r => `--require=${r}`),
|
|
198
|
-
...files,
|
|
199
|
-
].filter(a => a.trim());
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
protected async getChangedTestFiles(dir: string, ext: string) {
|
|
203
|
-
const res = await getChangedFilesForRoots([ path.join(dir, 'test') ], {});
|
|
204
|
-
const changedFiles = res.changedFiles;
|
|
205
|
-
const files: string[] = [];
|
|
206
|
-
for (let cf of changedFiles) {
|
|
207
|
-
// only find test/**/*.test.(js|ts)
|
|
208
|
-
if (cf.endsWith(`.test.${ext}`)) {
|
|
209
|
-
// Patterns MUST use forward slashes (not backslashes)
|
|
210
|
-
// This should be converted on Windows
|
|
211
|
-
if (process.platform === 'win32') {
|
|
212
|
-
cf = cf.replace(/\\/g, '/');
|
|
213
|
-
}
|
|
214
|
-
files.push(cf);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return files;
|
|
218
|
-
}
|
|
219
|
-
}
|
package/src/commands/debug.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
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
|
-
}
|
package/src/config/framework.ts
DELETED
package/src/config/plugin.ts
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { debuglog } from 'node:util';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import {
|
|
5
|
-
Inject, ApplicationLifecycle, LifecycleHook, LifecycleHookUnit,
|
|
6
|
-
Program, CommandContext,
|
|
7
|
-
} from '@artus-cli/artus-cli';
|
|
8
|
-
import { importResolve } from '@eggjs/utils';
|
|
9
|
-
import { runScript } from 'runscript';
|
|
10
|
-
import {
|
|
11
|
-
addNodeOptionsToEnv,
|
|
12
|
-
getSourceDirname,
|
|
13
|
-
readPackageJSON, hasTsConfig, getSourceFilename,
|
|
14
|
-
} from '../utils.js';
|
|
15
|
-
|
|
16
|
-
const debug = debuglog('@eggjs/bin/middleware/global_options');
|
|
17
|
-
|
|
18
|
-
@LifecycleHookUnit()
|
|
19
|
-
export default class GlobalOptions implements ApplicationLifecycle {
|
|
20
|
-
@Inject()
|
|
21
|
-
private readonly program: Program;
|
|
22
|
-
|
|
23
|
-
@LifecycleHook()
|
|
24
|
-
async configDidLoad() {
|
|
25
|
-
// add global options
|
|
26
|
-
this.program.option({
|
|
27
|
-
base: {
|
|
28
|
-
description: 'directory of application, default to `process.cwd()`',
|
|
29
|
-
type: 'string',
|
|
30
|
-
alias: 'baseDir',
|
|
31
|
-
},
|
|
32
|
-
declarations: {
|
|
33
|
-
description: 'whether create typings, will add `--require egg-ts-helper/register`',
|
|
34
|
-
type: 'boolean',
|
|
35
|
-
alias: 'dts',
|
|
36
|
-
},
|
|
37
|
-
typescript: {
|
|
38
|
-
description: 'whether enable typescript support',
|
|
39
|
-
type: 'boolean',
|
|
40
|
-
alias: 'ts',
|
|
41
|
-
},
|
|
42
|
-
tscompiler: {
|
|
43
|
-
description: 'ts compiler, like ts-node/register, ts-node/register/transpile-only, @swc-node/register, esbuild-register etc',
|
|
44
|
-
type: 'string',
|
|
45
|
-
alias: 'tsc',
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
this.program.use(async (ctx: CommandContext, next) => {
|
|
50
|
-
debug('before next');
|
|
51
|
-
if (!ctx.args.base) {
|
|
52
|
-
ctx.args.base = ctx.cwd;
|
|
53
|
-
debug('ctx.args.base not set, auto set it to cwd: %o', ctx.cwd);
|
|
54
|
-
}
|
|
55
|
-
if (!path.isAbsolute(ctx.args.base)) {
|
|
56
|
-
ctx.args.base = path.join(ctx.cwd, ctx.args.base);
|
|
57
|
-
}
|
|
58
|
-
debug('matched cmd: %o, ctx.args.base: %o', ctx.matched?.cmd, ctx.args.base);
|
|
59
|
-
const pkg = await readPackageJSON(ctx.args.base);
|
|
60
|
-
ctx.args.pkgEgg = pkg.egg ?? {};
|
|
61
|
-
const tscompiler = ctx.args.tscompiler ?? ctx.env.TS_COMPILER ?? ctx.args.pkgEgg.tscompiler;
|
|
62
|
-
if (ctx.args.typescript === undefined) {
|
|
63
|
-
// try to ready EGG_TYPESCRIPT env first, only accept 'true' or 'false' string
|
|
64
|
-
if (ctx.env.EGG_TYPESCRIPT === 'false') {
|
|
65
|
-
ctx.args.typescript = false;
|
|
66
|
-
debug('detect typescript=%o from EGG_TYPESCRIPT=%o', false, ctx.env.EGG_TYPESCRIPT);
|
|
67
|
-
} else if (ctx.env.EGG_TYPESCRIPT === 'true') {
|
|
68
|
-
ctx.args.typescript = true;
|
|
69
|
-
debug('detect typescript=%o from EGG_TYPESCRIPT=%o', true, ctx.env.EGG_TYPESCRIPT);
|
|
70
|
-
} else if (typeof ctx.args.pkgEgg.typescript === 'boolean') {
|
|
71
|
-
// read `egg.typescript` from package.json if not pass argv
|
|
72
|
-
ctx.args.typescript = ctx.args.pkgEgg.typescript;
|
|
73
|
-
debug('detect typescript=%o from pkg.egg.typescript=%o', true, ctx.args.pkgEgg.typescript);
|
|
74
|
-
} else if (pkg.dependencies?.typescript) {
|
|
75
|
-
// auto detect pkg.dependencies.typescript or pkg.devDependencies.typescript
|
|
76
|
-
ctx.args.typescript = true;
|
|
77
|
-
debug('detect typescript=%o from pkg.dependencies.typescript=%o', true, pkg.dependencies.typescript);
|
|
78
|
-
} else if (pkg.devDependencies?.typescript) {
|
|
79
|
-
ctx.args.typescript = true;
|
|
80
|
-
debug('detect typescript=%o from pkg.devDependencies.typescript=%o', true, pkg.devDependencies.typescript);
|
|
81
|
-
} else if (await hasTsConfig(ctx.args.base)) {
|
|
82
|
-
// tsconfig.json exists
|
|
83
|
-
ctx.args.typescript = true;
|
|
84
|
-
debug('detect typescript=%o cause tsconfig.json exists', true);
|
|
85
|
-
} else if (tscompiler) {
|
|
86
|
-
ctx.args.typescript = true;
|
|
87
|
-
debug('detect typescript=%o from --tscompiler=%o', true, tscompiler);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const isESM = pkg.type === 'module';
|
|
92
|
-
if (ctx.args.typescript) {
|
|
93
|
-
const findPaths = [ getSourceFilename('middleware') ];
|
|
94
|
-
if (tscompiler) {
|
|
95
|
-
// try app baseDir first on custom tscompiler
|
|
96
|
-
findPaths.unshift(ctx.args.base);
|
|
97
|
-
}
|
|
98
|
-
ctx.args.tscompiler = tscompiler ?? 'ts-node/register';
|
|
99
|
-
let tsNodeRegister = importResolve(ctx.args.tscompiler, {
|
|
100
|
-
paths: findPaths,
|
|
101
|
-
});
|
|
102
|
-
// should require tsNodeRegister on current process, let it can require *.ts files
|
|
103
|
-
// e.g.: dev command will execute egg loader to find configs and plugins
|
|
104
|
-
// await importModule(tsNodeRegister);
|
|
105
|
-
// let child process auto require ts-node too
|
|
106
|
-
if (isESM) {
|
|
107
|
-
tsNodeRegister = pathToFileURL(tsNodeRegister).href;
|
|
108
|
-
addNodeOptionsToEnv(`--import ${tsNodeRegister}`, ctx.env);
|
|
109
|
-
} else {
|
|
110
|
-
addNodeOptionsToEnv(`--require ${tsNodeRegister}`, ctx.env);
|
|
111
|
-
}
|
|
112
|
-
// addNodeOptionsToEnv(`--require ${tsNodeRegister}`, ctx.env);
|
|
113
|
-
// tell egg loader to load ts file
|
|
114
|
-
// see https://github.com/eggjs/egg-core/blob/master/lib/loader/egg_loader.js#L443
|
|
115
|
-
ctx.env.EGG_TYPESCRIPT = 'true';
|
|
116
|
-
// set current process.env.EGG_TYPESCRIPT too
|
|
117
|
-
process.env.EGG_TYPESCRIPT = 'true';
|
|
118
|
-
// load files from tsconfig on startup
|
|
119
|
-
ctx.env.TS_NODE_FILES = process.env.TS_NODE_FILES ?? 'true';
|
|
120
|
-
// keep same logic with egg-core, test cmd load files need it
|
|
121
|
-
// see https://github.com/eggjs/egg-core/blob/master/lib/loader/egg_loader.js#L49
|
|
122
|
-
// addNodeOptionsToEnv(`--require ${importResolve('tsconfig-paths/register', {
|
|
123
|
-
// paths: [ getSourceDirname() ],
|
|
124
|
-
// })}`, ctx.env);
|
|
125
|
-
}
|
|
126
|
-
if (isESM) {
|
|
127
|
-
// use ts-node/esm loader on esm
|
|
128
|
-
let esmLoader = importResolve('ts-node/esm', {
|
|
129
|
-
paths: [ getSourceDirname() ],
|
|
130
|
-
});
|
|
131
|
-
// ES Module loading with absolute path fails on windows
|
|
132
|
-
// https://github.com/nodejs/node/issues/31710#issuecomment-583916239
|
|
133
|
-
// https://nodejs.org/api/url.html#url_url_pathtofileurl_path
|
|
134
|
-
// 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:'
|
|
135
|
-
esmLoader = pathToFileURL(esmLoader).href;
|
|
136
|
-
// wait for https://github.com/nodejs/node/issues/40940
|
|
137
|
-
addNodeOptionsToEnv('--no-warnings', ctx.env);
|
|
138
|
-
addNodeOptionsToEnv(`--loader ${esmLoader}`, ctx.env);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (ctx.args.declarations === undefined) {
|
|
142
|
-
if (typeof ctx.args.pkgEgg.declarations === 'boolean') {
|
|
143
|
-
// read `egg.declarations` from package.json if not pass argv
|
|
144
|
-
ctx.args.declarations = ctx.args.pkgEgg.declarations;
|
|
145
|
-
debug('detect declarations from pkg.egg.declarations=%o', ctx.args.pkgEgg.declarations);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
if (ctx.args.declarations) {
|
|
149
|
-
const etsBin = importResolve('egg-ts-helper/dist/bin');
|
|
150
|
-
debug('run ets first: %o', etsBin);
|
|
151
|
-
await runScript(`node ${etsBin}`);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (ctx.args.pkgEgg.revert) {
|
|
155
|
-
ctx.args.execArgv = ctx.args.execArgv || [];
|
|
156
|
-
const reverts = Array.isArray(ctx.args.pkgEgg.revert) ? ctx.args.pkgEgg.revert : [ ctx.args.pkgEgg.revert ];
|
|
157
|
-
for (const revert of reverts) {
|
|
158
|
-
ctx.args.execArgv.push(`--security-revert=${revert}`);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
debug('set NODE_OPTIONS: %o', ctx.env.NODE_OPTIONS);
|
|
163
|
-
debug('ctx.args: %o', ctx.args);
|
|
164
|
-
debug('enter next');
|
|
165
|
-
await next();
|
|
166
|
-
debug('after next');
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { debuglog } from 'node:util';
|
|
2
|
-
import {
|
|
3
|
-
Inject, ApplicationLifecycle, LifecycleHook, LifecycleHookUnit, Program,
|
|
4
|
-
ArtusCliError,
|
|
5
|
-
} from '@artus-cli/artus-cli';
|
|
6
|
-
|
|
7
|
-
const debug = debuglog('@eggjs/bin/middleware/handle_error');
|
|
8
|
-
|
|
9
|
-
@LifecycleHookUnit()
|
|
10
|
-
export default class implements ApplicationLifecycle {
|
|
11
|
-
@Inject()
|
|
12
|
-
private readonly program: Program;
|
|
13
|
-
|
|
14
|
-
@LifecycleHook()
|
|
15
|
-
async configDidLoad() {
|
|
16
|
-
this.program.use(async (_, next) => {
|
|
17
|
-
debug('enter next');
|
|
18
|
-
try {
|
|
19
|
-
await next();
|
|
20
|
-
debug('after next');
|
|
21
|
-
} catch (err: any) {
|
|
22
|
-
debug('next error: %o', err);
|
|
23
|
-
// let artus cli to handle it
|
|
24
|
-
if (err instanceof ArtusCliError) throw err;
|
|
25
|
-
console.error(err);
|
|
26
|
-
process.exit(typeof err.code === 'number' ? err.code : 1);
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { debuglog } from 'node:util';
|
|
2
|
-
import {
|
|
3
|
-
Inject, ApplicationLifecycle, LifecycleHook, LifecycleHookUnit,
|
|
4
|
-
Program, CommandContext,
|
|
5
|
-
} from '@artus-cli/artus-cli';
|
|
6
|
-
import { addNodeOptionsToEnv } from '../utils.js';
|
|
7
|
-
|
|
8
|
-
const debug = debuglog('@eggjs/bin/middleware/inspect');
|
|
9
|
-
|
|
10
|
-
@LifecycleHookUnit()
|
|
11
|
-
export default class implements ApplicationLifecycle {
|
|
12
|
-
@Inject()
|
|
13
|
-
private readonly program: Program;
|
|
14
|
-
|
|
15
|
-
@LifecycleHook()
|
|
16
|
-
async configDidLoad() {
|
|
17
|
-
// add global options
|
|
18
|
-
// https://nodejs.org/dist/latest-v18.x/docs/api/cli.html#--inspect-brkhostport
|
|
19
|
-
this.program.option({
|
|
20
|
-
'inspect-brk': {
|
|
21
|
-
description: 'Activate inspector and break at start of user script',
|
|
22
|
-
type: 'boolean',
|
|
23
|
-
},
|
|
24
|
-
inspect: {
|
|
25
|
-
description: 'Activate inspector',
|
|
26
|
-
type: 'boolean',
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
this.program.use(async (ctx: CommandContext, next) => {
|
|
31
|
-
debug('before next');
|
|
32
|
-
let hasInspectOption = false;
|
|
33
|
-
if (ctx.args.inspect === true) {
|
|
34
|
-
addNodeOptionsToEnv('--inspect', ctx.env);
|
|
35
|
-
hasInspectOption = true;
|
|
36
|
-
}
|
|
37
|
-
if (ctx.args['inspect-brk'] === true) {
|
|
38
|
-
addNodeOptionsToEnv('--inspect-brk', ctx.env);
|
|
39
|
-
hasInspectOption = true;
|
|
40
|
-
}
|
|
41
|
-
if (hasInspectOption) {
|
|
42
|
-
ctx.args.timeout = false;
|
|
43
|
-
debug('set timeout = false when inspect enable, set env.NODE_OPTIONS=%o', ctx.env.NODE_OPTIONS);
|
|
44
|
-
} else if (process.env.JB_DEBUG_FILE) {
|
|
45
|
-
// others like WebStorm 2019 will pass NODE_OPTIONS, and egg-bin itself will be debug, so could detect `process.env.JB_DEBUG_FILE`.
|
|
46
|
-
ctx.args.timeout = false;
|
|
47
|
-
debug('set timeout = false when process.env.JB_DEBUG_FILE=%o', process.env.JB_DEBUG_FILE);
|
|
48
|
-
}
|
|
49
|
-
debug('enter next');
|
|
50
|
-
await next();
|
|
51
|
-
debug('after next');
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|