@eggjs/development 4.0.0
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/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/commonjs/agent.d.ts +7 -0
- package/dist/commonjs/agent.js +98 -0
- package/dist/commonjs/app/middleware/egg_loader_trace.d.ts +3 -0
- package/dist/commonjs/app/middleware/egg_loader_trace.js +44 -0
- package/dist/commonjs/app.d.ts +6 -0
- package/dist/commonjs/app.js +17 -0
- package/dist/commonjs/config/config.default.d.ts +15 -0
- package/dist/commonjs/config/config.default.js +24 -0
- package/dist/commonjs/config/loader_trace.html +49 -0
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.js +4 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/commonjs/types.d.ts +35 -0
- package/dist/commonjs/types.js +3 -0
- package/dist/commonjs/utils.d.ts +3 -0
- package/dist/commonjs/utils.js +25 -0
- package/dist/esm/agent.d.ts +7 -0
- package/dist/esm/agent.js +92 -0
- package/dist/esm/app/middleware/egg_loader_trace.d.ts +3 -0
- package/dist/esm/app/middleware/egg_loader_trace.js +39 -0
- package/dist/esm/app.d.ts +6 -0
- package/dist/esm/app.js +14 -0
- package/dist/esm/config/config.default.d.ts +15 -0
- package/dist/esm/config/config.default.js +22 -0
- package/dist/esm/config/loader_trace.html +49 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/types.d.ts +35 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/utils.d.ts +3 -0
- package/dist/esm/utils.js +17 -0
- package/dist/package.json +4 -0
- package/package.json +98 -0
- package/src/agent.ts +106 -0
- package/src/app/middleware/egg_loader_trace.ts +39 -0
- package/src/app.ts +17 -0
- package/src/config/config.default.ts +23 -0
- package/src/config/loader_trace.html +49 -0
- package/src/index.ts +1 -0
- package/src/types.ts +37 -0
- package/src/typings/index.d.ts +4 -0
- package/src/utils.ts +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) Alibaba Group Holding Limited and other contributors.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# @eggjs/development
|
|
2
|
+
|
|
3
|
+
[![NPM version][npm-image]][npm-url]
|
|
4
|
+
[](https://github.com/eggjs/egg-development/actions/workflows/nodejs.yml)
|
|
5
|
+
[![Test coverage][codecov-image]][codecov-url]
|
|
6
|
+
[![Known Vulnerabilities][snyk-image]][snyk-url]
|
|
7
|
+
[![npm download][download-image]][download-url]
|
|
8
|
+
[](https://nodejs.org/en/download/)
|
|
9
|
+
[](https://makeapullrequest.com)
|
|
10
|
+
|
|
11
|
+
[npm-image]: https://img.shields.io/npm/v/egg-development.svg?style=flat-square
|
|
12
|
+
[npm-url]: https://npmjs.org/package/egg-development
|
|
13
|
+
[codecov-image]: https://img.shields.io/codecov/c/github/eggjs/egg-development.svg?style=flat-square
|
|
14
|
+
[codecov-url]: https://codecov.io/github/eggjs/egg-development?branch=master
|
|
15
|
+
[snyk-image]: https://snyk.io/test/npm/egg-development/badge.svg?style=flat-square
|
|
16
|
+
[snyk-url]: https://snyk.io/test/npm/egg-development
|
|
17
|
+
[download-image]: https://img.shields.io/npm/dm/egg-development.svg?style=flat-square
|
|
18
|
+
[download-url]: https://npmjs.org/package/egg-development
|
|
19
|
+
|
|
20
|
+
This is an egg plugin for local development, under development environment enabled by default, and closed under other environment.
|
|
21
|
+
|
|
22
|
+
`@eggjs/development` has been built-in for egg. It is enabled by default.
|
|
23
|
+
|
|
24
|
+
## Requirements
|
|
25
|
+
|
|
26
|
+
- egg >= 4.x
|
|
27
|
+
|
|
28
|
+
## Configuration
|
|
29
|
+
|
|
30
|
+
see [config/config.default.ts](https://github.com/eggjs/egg-development/blob/master/src/config/config.default.ts) for more detail.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- Under development environment, Output request log in STDOUT, statistic and output all key parts time-consuming;
|
|
35
|
+
- Watch file changes, and reload application;
|
|
36
|
+
|
|
37
|
+
### About Reload
|
|
38
|
+
|
|
39
|
+
Under the following directory (including subdirectories) will watch file changes under development environment by default, trigger an Egg development environment server reload:
|
|
40
|
+
|
|
41
|
+
- ${app_root}/app
|
|
42
|
+
- ${app_root}/config
|
|
43
|
+
- ${app_root}/mocks
|
|
44
|
+
- ${app_root}/mocks_proxy
|
|
45
|
+
- ${app_root}/app.js
|
|
46
|
+
|
|
47
|
+
> set `config.development.overrideDefault` to `true` to skip defaults merge.
|
|
48
|
+
|
|
49
|
+
Under the following directory (including subdirectories) will ignore file changes under development environment by default:
|
|
50
|
+
|
|
51
|
+
- ${app_root}/app/view
|
|
52
|
+
- ${app_root}/app/assets
|
|
53
|
+
- ${app_root}/app/public
|
|
54
|
+
- ${app_root}/app/web
|
|
55
|
+
|
|
56
|
+
> set `config.development.overrideIgnore` to `true` to skip defaults merge.
|
|
57
|
+
|
|
58
|
+
Developer can use `config.reloadPattern`([multimatch](https://github.com/sindresorhus/multimatch)) to control whether to reload.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
// config/config.default.ts
|
|
62
|
+
export default = {
|
|
63
|
+
development: {
|
|
64
|
+
// don't reload when css fileChanged
|
|
65
|
+
// https://github.com/sindresorhus/multimatch
|
|
66
|
+
reloadPattern: ['**', '!**/*.css'],
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Loader Trace
|
|
72
|
+
|
|
73
|
+
You can view loader trace for performance issue from `http://127.0.0.1:7001/__loader_trace__`
|
|
74
|
+
|
|
75
|
+
## Questions & Suggestions
|
|
76
|
+
|
|
77
|
+
Please open an issue [here](https://github.com/eggjs/egg/issues).
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
[MIT](LICENSE)
|
|
82
|
+
|
|
83
|
+
## Contributors
|
|
84
|
+
|
|
85
|
+
[](https://github.com/eggjs/development/graphs/contributors)
|
|
86
|
+
|
|
87
|
+
Made with [contributors-img](https://contrib.rocks).
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
7
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
8
|
+
const debounce_1 = __importDefault(require("debounce"));
|
|
9
|
+
const multimatch_1 = __importDefault(require("multimatch"));
|
|
10
|
+
const utility_1 = require("utility");
|
|
11
|
+
const utils_js_1 = require("./utils.js");
|
|
12
|
+
class AgentBoot {
|
|
13
|
+
#agent;
|
|
14
|
+
constructor(agent) {
|
|
15
|
+
this.#agent = agent;
|
|
16
|
+
}
|
|
17
|
+
async didLoad() {
|
|
18
|
+
// clean all timing json
|
|
19
|
+
const rundir = this.#agent.config.rundir;
|
|
20
|
+
const stat = await (0, utility_1.exists)(rundir);
|
|
21
|
+
if (!stat)
|
|
22
|
+
return;
|
|
23
|
+
const files = await promises_1.default.readdir(rundir);
|
|
24
|
+
for (const file of files) {
|
|
25
|
+
if (!(0, utils_js_1.isTimingFile)(file))
|
|
26
|
+
continue;
|
|
27
|
+
await promises_1.default.rm(node_path_1.default.join(rundir, file), { force: true, recursive: true });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async serverDidReady() {
|
|
31
|
+
const agent = this.#agent;
|
|
32
|
+
// single process mode don't watch and reload
|
|
33
|
+
if (agent.options && Reflect.get(agent.options, 'mode') === 'single') {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const logger = agent.logger;
|
|
37
|
+
const baseDir = agent.config.baseDir;
|
|
38
|
+
const config = agent.config.development;
|
|
39
|
+
let watchDirs = config.overrideDefault ? [] : [
|
|
40
|
+
'app',
|
|
41
|
+
'config',
|
|
42
|
+
'mocks',
|
|
43
|
+
'mocks_proxy',
|
|
44
|
+
'app.js',
|
|
45
|
+
];
|
|
46
|
+
watchDirs = watchDirs.concat(config.watchDirs).map(dir => node_path_1.default.resolve(baseDir, dir));
|
|
47
|
+
let ignoreReloadFileDirs = config.overrideIgnore ? [] : [
|
|
48
|
+
'app/views',
|
|
49
|
+
'app/view',
|
|
50
|
+
'app/assets',
|
|
51
|
+
'app/public',
|
|
52
|
+
'app/web',
|
|
53
|
+
];
|
|
54
|
+
ignoreReloadFileDirs = ignoreReloadFileDirs.concat(config.ignoreDirs).map(dir => node_path_1.default.resolve(baseDir, dir));
|
|
55
|
+
const reloadFile = (0, debounce_1.default)(function (info) {
|
|
56
|
+
logger.warn(`[agent:development] reload worker because ${info.path} ${info.event}`);
|
|
57
|
+
process.send({
|
|
58
|
+
to: 'master',
|
|
59
|
+
action: 'reload-worker',
|
|
60
|
+
});
|
|
61
|
+
}, 200);
|
|
62
|
+
// watch dirs to reload worker, will debounce 200ms
|
|
63
|
+
/**
|
|
64
|
+
* reload app worker:
|
|
65
|
+
* [AgentWorker] - on file change
|
|
66
|
+
* |-> emit reload-worker
|
|
67
|
+
* [Master] - receive reload-worker event
|
|
68
|
+
* |-> TODO: Mark worker will die
|
|
69
|
+
* |-> Fork new worker
|
|
70
|
+
* |-> kill old worker
|
|
71
|
+
*
|
|
72
|
+
* @param {Object} info - changed fileInfo
|
|
73
|
+
*/
|
|
74
|
+
agent.watcher.watch(watchDirs, info => {
|
|
75
|
+
if (!config.reloadOnDebug) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (isAssetsDir(info.path) || info.isDirectory) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// don't reload if don't match
|
|
82
|
+
if (config.reloadPattern && (0, multimatch_1.default)(info.path, config.reloadPattern).length === 0) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
reloadFile(info);
|
|
86
|
+
});
|
|
87
|
+
function isAssetsDir(filepath) {
|
|
88
|
+
for (const ignorePath of ignoreReloadFileDirs) {
|
|
89
|
+
if (filepath.startsWith(ignorePath)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.default = AgentBoot;
|
|
98
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWdlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSwwREFBNkI7QUFDN0IsZ0VBQWtDO0FBQ2xDLHdEQUFnQztBQUNoQyw0REFBb0M7QUFDcEMscUNBQWlDO0FBRWpDLHlDQUEwQztBQUUxQyxNQUFxQixTQUFTO0lBQzVCLE1BQU0sQ0FBVTtJQUVoQixZQUFZLEtBQWM7UUFDeEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7SUFDdEIsQ0FBQztJQUVELEtBQUssQ0FBQyxPQUFPO1FBQ1gsd0JBQXdCO1FBQ3hCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUN6QyxNQUFNLElBQUksR0FBRyxNQUFNLElBQUEsZ0JBQU0sRUFBQyxNQUFNLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsSUFBSTtZQUFFLE9BQU87UUFDbEIsTUFBTSxLQUFLLEdBQUcsTUFBTSxrQkFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2QyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxJQUFBLHVCQUFZLEVBQUMsSUFBSSxDQUFDO2dCQUFFLFNBQVM7WUFDbEMsTUFBTSxrQkFBRSxDQUFDLEVBQUUsQ0FBQyxtQkFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3pFLENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLGNBQWM7UUFDbEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMxQiw2Q0FBNkM7UUFDN0MsSUFBSSxLQUFLLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FB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
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
7
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
8
|
+
const utility_1 = require("utility");
|
|
9
|
+
const utils_js_1 = require("../../utils.js");
|
|
10
|
+
exports.default = (_, app) => {
|
|
11
|
+
return async (ctx, next) => {
|
|
12
|
+
if (ctx.path !== '/__loader_trace__') {
|
|
13
|
+
return await next();
|
|
14
|
+
}
|
|
15
|
+
const template = await promises_1.default.readFile((0, utils_js_1.getSourceFile)('config/loader_trace.html'), 'utf8');
|
|
16
|
+
const data = await loadTimingData(app);
|
|
17
|
+
ctx.body = template.replace('{{placeholder}}', JSON.stringify(data));
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
async function loadTimingData(app) {
|
|
21
|
+
const rundir = app.config.rundir;
|
|
22
|
+
const files = await promises_1.default.readdir(rundir);
|
|
23
|
+
const data = [];
|
|
24
|
+
for (const file of files) {
|
|
25
|
+
if (!(0, utils_js_1.isTimingFile)(file))
|
|
26
|
+
continue;
|
|
27
|
+
const json = await (0, utility_1.readJSON)(node_path_1.default.join(rundir, file));
|
|
28
|
+
const isAgent = /^agent/.test(file);
|
|
29
|
+
for (const item of json) {
|
|
30
|
+
if (isAgent) {
|
|
31
|
+
item.type = 'agent';
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
item.type = `app_${item.pid}`;
|
|
35
|
+
}
|
|
36
|
+
item.pid = String(item.pid);
|
|
37
|
+
item.range = [item.start, item.end];
|
|
38
|
+
item.title = `${item.type}(${item.index})`;
|
|
39
|
+
data.push(item);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return data;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWdnX2xvYWRlcl90cmFjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvbWlkZGxld2FyZS9lZ2dfbG9hZGVyX3RyYWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsMERBQTZCO0FBQzdCLGdFQUFrQztBQUNsQyxxQ0FBbUM7QUFFbkMsNkNBQTZEO0FBRTdELGtCQUFlLENBQUMsQ0FBVSxFQUFFLEdBQVksRUFBa0IsRUFBRTtJQUMxRCxPQUFPLEtBQUssRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUU7UUFDekIsSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLG1CQUFtQixFQUFFLENBQUM7WUFDckMsT0FBTyxNQUFNLElBQUksRUFBRSxDQUFDO1FBQ3RCLENBQUM7UUFDRCxNQUFNLFFBQVEsR0FBRyxNQUFNLGtCQUFFLENBQUMsUUFBUSxDQUFDLElBQUEsd0JBQWEsRUFBQywwQkFBMEIsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3RGLE1BQU0sSUFBSSxHQUFHLE1BQU0sY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdkUsQ0FBQyxDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBRUYsS0FBSyxVQUFVLGNBQWMsQ0FBQyxHQUFZO0lBQ3hDLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ2pDLE1BQU0sS0FBSyxHQUFHLE1BQU0sa0JBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdkMsTUFBTSxJQUFJLEdBQVUsRUFBRSxDQUFDO0lBQ3ZCLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLElBQUEsdUJBQVksRUFBQyxJQUFJLENBQUM7WUFBRSxTQUFTO1FBQ2xDLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBQSxrQkFBUSxFQUFDLG1CQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3JELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEMsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUN4QixJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDO1lBQ3RCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ2hDLENBQUM7WUFDRCxJQUFJLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxLQUFLLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQztZQUMzQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2xCLENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDIn0=
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class AppBoot {
|
|
4
|
+
#app;
|
|
5
|
+
constructor(app) {
|
|
6
|
+
this.#app = app;
|
|
7
|
+
// if true, then don't need to wait at local development mode
|
|
8
|
+
if (app.config.development.fastReady) {
|
|
9
|
+
process.nextTick(() => this.#app.ready(true));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
async configWillLoad() {
|
|
13
|
+
this.#app.config.coreMiddleware.push('eggLoaderTrace');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.default = AppBoot;
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLE1BQXFCLE9BQU87SUFDMUIsSUFBSSxDQUFVO0lBRWQsWUFBWSxHQUFZO1FBQ3RCLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDO1FBQ2hCLDZEQUE2RDtRQUM3RCxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3JDLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNoRCxDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxjQUFjO1FBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN6RCxDQUFDO0NBQ0Y7QUFkRCwwQkFjQyJ9
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DevelopmentConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* @member Config#development
|
|
4
|
+
* @property {Array} watchDirs - dirs needed watch, when files under these change, application will reload, use relative path
|
|
5
|
+
* @property {Array} ignoreDirs - dirs don't need watch, including subdirectories, use relative path
|
|
6
|
+
* @property {Boolean} fastReady - don't wait all plugins ready, default is false.
|
|
7
|
+
* @property {Boolean} reloadOnDebug - whether reload on debug, default is true.
|
|
8
|
+
* @property {Boolean} overrideDefault - whether override default watchDirs, default is false.
|
|
9
|
+
* @property {Boolean} overrideIgnore - whether override default ignoreDirs, default is false.
|
|
10
|
+
* @property {Array|String} reloadPattern - whether to reload, use https://github.com/sindresorhus/multimatch
|
|
11
|
+
*/
|
|
12
|
+
declare const _default: {
|
|
13
|
+
development: DevelopmentConfig;
|
|
14
|
+
};
|
|
15
|
+
export default _default;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* @member Config#development
|
|
5
|
+
* @property {Array} watchDirs - dirs needed watch, when files under these change, application will reload, use relative path
|
|
6
|
+
* @property {Array} ignoreDirs - dirs don't need watch, including subdirectories, use relative path
|
|
7
|
+
* @property {Boolean} fastReady - don't wait all plugins ready, default is false.
|
|
8
|
+
* @property {Boolean} reloadOnDebug - whether reload on debug, default is true.
|
|
9
|
+
* @property {Boolean} overrideDefault - whether override default watchDirs, default is false.
|
|
10
|
+
* @property {Boolean} overrideIgnore - whether override default ignoreDirs, default is false.
|
|
11
|
+
* @property {Array|String} reloadPattern - whether to reload, use https://github.com/sindresorhus/multimatch
|
|
12
|
+
*/
|
|
13
|
+
exports.default = {
|
|
14
|
+
development: {
|
|
15
|
+
watchDirs: [],
|
|
16
|
+
ignoreDirs: [],
|
|
17
|
+
fastReady: false,
|
|
18
|
+
reloadOnDebug: true,
|
|
19
|
+
overrideDefault: false,
|
|
20
|
+
overrideIgnore: false,
|
|
21
|
+
reloadPattern: undefined,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmRlZmF1bHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29uZmlnL2NvbmZpZy5kZWZhdWx0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBRUE7Ozs7Ozs7OztHQVNHO0FBQ0gsa0JBQWU7SUFDYixXQUFXLEVBQUU7UUFDWCxTQUFTLEVBQUUsRUFBRTtRQUNiLFVBQVUsRUFBRSxFQUFFO1FBQ2QsU0FBUyxFQUFFLEtBQUs7UUFDaEIsYUFBYSxFQUFFLElBQUk7UUFDbkIsZUFBZSxFQUFFLEtBQUs7UUFDdEIsY0FBYyxFQUFFLEtBQUs7UUFDckIsYUFBYSxFQUFFLFNBQVM7S0FDSjtDQUN2QixDQUFDIn0=
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title></title>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<div id="mountNode"></div>
|
|
8
|
+
<script src="https://gw.alipayobjects.com/os/antv/assets/g2/3.0.9/g2.min.js"></script>
|
|
9
|
+
<script>
|
|
10
|
+
var data = {{placeholder}};
|
|
11
|
+
|
|
12
|
+
const chart = new G2.Chart({
|
|
13
|
+
container: 'mountNode', // 指定图表容器 ID
|
|
14
|
+
height: data.length * 22, // 指定图表高度
|
|
15
|
+
forceFit: true,
|
|
16
|
+
padding: 'auto',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Step 2: 载入数据源
|
|
20
|
+
chart.source(data, {
|
|
21
|
+
range: {
|
|
22
|
+
type: 'time',
|
|
23
|
+
mask: 'HH:mm:ss',
|
|
24
|
+
nice: true,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
chart
|
|
28
|
+
.coord()
|
|
29
|
+
.transpose()
|
|
30
|
+
.scale(1, -1);
|
|
31
|
+
|
|
32
|
+
chart.legend({ position: 'top' });
|
|
33
|
+
|
|
34
|
+
chart.tooltip({
|
|
35
|
+
showTitle: false,
|
|
36
|
+
itemTpl: '<li>{duration}ms: {name} </li>'
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
chart
|
|
40
|
+
.interval()
|
|
41
|
+
.position('title*range')
|
|
42
|
+
.color('type')
|
|
43
|
+
.tooltip('name*duration', (name, duration) => ({ name, duration }))
|
|
44
|
+
.size(5);
|
|
45
|
+
|
|
46
|
+
chart.render();
|
|
47
|
+
</script>
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './types.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
require("./types.js");
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxzQkFBb0IifQ==
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface DevelopmentConfig {
|
|
2
|
+
/**
|
|
3
|
+
* dirs needed watch, when files under these change, application will reload, use relative path
|
|
4
|
+
*/
|
|
5
|
+
watchDirs: string[];
|
|
6
|
+
/**
|
|
7
|
+
* dirs don't need watch, including subdirectories, use relative path
|
|
8
|
+
*/
|
|
9
|
+
ignoreDirs: string[];
|
|
10
|
+
/**
|
|
11
|
+
* don't wait all plugins ready, default is false.
|
|
12
|
+
*/
|
|
13
|
+
fastReady: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* whether reload on debug, default is true.
|
|
16
|
+
*/
|
|
17
|
+
reloadOnDebug: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* whether override default watchDirs, default is false.
|
|
20
|
+
*/
|
|
21
|
+
overrideDefault: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* whether override default ignoreDirs, default is false.
|
|
24
|
+
*/
|
|
25
|
+
overrideIgnore: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* whether to reload, use https://github.com/sindresorhus/multimatch
|
|
28
|
+
*/
|
|
29
|
+
reloadPattern?: string[] | string;
|
|
30
|
+
}
|
|
31
|
+
declare module '@eggjs/core' {
|
|
32
|
+
interface EggAppConfig {
|
|
33
|
+
development: DevelopmentConfig;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getSourceDirname = getSourceDirname;
|
|
7
|
+
exports.getSourceFile = getSourceFile;
|
|
8
|
+
exports.isTimingFile = isTimingFile;
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const node_url_1 = require("node:url");
|
|
11
|
+
function getSourceDirname() {
|
|
12
|
+
if (typeof __dirname !== 'undefined') {
|
|
13
|
+
return node_path_1.default.dirname(__dirname);
|
|
14
|
+
}
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
return node_path_1.default.dirname((0, node_url_1.fileURLToPath)('import_meta_url_placeholder_by_tshy_after'));
|
|
18
|
+
}
|
|
19
|
+
function getSourceFile(filename) {
|
|
20
|
+
return node_path_1.default.join(getSourceDirname(), filename);
|
|
21
|
+
}
|
|
22
|
+
function isTimingFile(file) {
|
|
23
|
+
return /^(agent|application)_timing/.test(file);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFHQSw0Q0FPQztBQUVELHNDQUVDO0FBRUQsb0NBRUM7QUFsQkQsMERBQTZCO0FBQzdCLHVDQUF5QztBQUV6QyxTQUFnQixnQkFBZ0I7SUFDOUIsSUFBSSxPQUFPLFNBQVMsS0FBSyxXQUFXLEVBQUUsQ0FBQztRQUNyQyxPQUFPLG1CQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFDRCw2REFBNkQ7SUFDN0QsYUFBYTtJQUNiLE9BQU8sbUJBQUksQ0FBQyxPQUFPLENBQUMsSUFBQSx3QkFBYSxFQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUN0RCxDQUFDO0FBRUQsU0FBZ0IsYUFBYSxDQUFDLFFBQWdCO0lBQzVDLE9BQU8sbUJBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztBQUNqRCxDQUFDO0FBRUQsU0FBZ0IsWUFBWSxDQUFDLElBQVk7SUFDdkMsT0FBTyw2QkFBNkIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDbEQsQ0FBQyJ9
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import debounce from 'debounce';
|
|
4
|
+
import multimatch from 'multimatch';
|
|
5
|
+
import { exists } from 'utility';
|
|
6
|
+
import { isTimingFile } from './utils.js';
|
|
7
|
+
export default class AgentBoot {
|
|
8
|
+
#agent;
|
|
9
|
+
constructor(agent) {
|
|
10
|
+
this.#agent = agent;
|
|
11
|
+
}
|
|
12
|
+
async didLoad() {
|
|
13
|
+
// clean all timing json
|
|
14
|
+
const rundir = this.#agent.config.rundir;
|
|
15
|
+
const stat = await exists(rundir);
|
|
16
|
+
if (!stat)
|
|
17
|
+
return;
|
|
18
|
+
const files = await fs.readdir(rundir);
|
|
19
|
+
for (const file of files) {
|
|
20
|
+
if (!isTimingFile(file))
|
|
21
|
+
continue;
|
|
22
|
+
await fs.rm(path.join(rundir, file), { force: true, recursive: true });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async serverDidReady() {
|
|
26
|
+
const agent = this.#agent;
|
|
27
|
+
// single process mode don't watch and reload
|
|
28
|
+
if (agent.options && Reflect.get(agent.options, 'mode') === 'single') {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const logger = agent.logger;
|
|
32
|
+
const baseDir = agent.config.baseDir;
|
|
33
|
+
const config = agent.config.development;
|
|
34
|
+
let watchDirs = config.overrideDefault ? [] : [
|
|
35
|
+
'app',
|
|
36
|
+
'config',
|
|
37
|
+
'mocks',
|
|
38
|
+
'mocks_proxy',
|
|
39
|
+
'app.js',
|
|
40
|
+
];
|
|
41
|
+
watchDirs = watchDirs.concat(config.watchDirs).map(dir => path.resolve(baseDir, dir));
|
|
42
|
+
let ignoreReloadFileDirs = config.overrideIgnore ? [] : [
|
|
43
|
+
'app/views',
|
|
44
|
+
'app/view',
|
|
45
|
+
'app/assets',
|
|
46
|
+
'app/public',
|
|
47
|
+
'app/web',
|
|
48
|
+
];
|
|
49
|
+
ignoreReloadFileDirs = ignoreReloadFileDirs.concat(config.ignoreDirs).map(dir => path.resolve(baseDir, dir));
|
|
50
|
+
const reloadFile = debounce(function (info) {
|
|
51
|
+
logger.warn(`[agent:development] reload worker because ${info.path} ${info.event}`);
|
|
52
|
+
process.send({
|
|
53
|
+
to: 'master',
|
|
54
|
+
action: 'reload-worker',
|
|
55
|
+
});
|
|
56
|
+
}, 200);
|
|
57
|
+
// watch dirs to reload worker, will debounce 200ms
|
|
58
|
+
/**
|
|
59
|
+
* reload app worker:
|
|
60
|
+
* [AgentWorker] - on file change
|
|
61
|
+
* |-> emit reload-worker
|
|
62
|
+
* [Master] - receive reload-worker event
|
|
63
|
+
* |-> TODO: Mark worker will die
|
|
64
|
+
* |-> Fork new worker
|
|
65
|
+
* |-> kill old worker
|
|
66
|
+
*
|
|
67
|
+
* @param {Object} info - changed fileInfo
|
|
68
|
+
*/
|
|
69
|
+
agent.watcher.watch(watchDirs, info => {
|
|
70
|
+
if (!config.reloadOnDebug) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (isAssetsDir(info.path) || info.isDirectory) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// don't reload if don't match
|
|
77
|
+
if (config.reloadPattern && multimatch(info.path, config.reloadPattern).length === 0) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
reloadFile(info);
|
|
81
|
+
});
|
|
82
|
+
function isAssetsDir(filepath) {
|
|
83
|
+
for (const ignorePath of ignoreReloadFileDirs) {
|
|
84
|
+
if (filepath.startsWith(ignorePath)) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWdlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2xDLE9BQU8sUUFBUSxNQUFNLFVBQVUsQ0FBQztBQUNoQyxPQUFPLFVBQVUsTUFBTSxZQUFZLENBQUM7QUFDcEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUVqQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRTFDLE1BQU0sQ0FBQyxPQUFPLE9BQU8sU0FBUztJQUM1QixNQUFNLENBQVU7SUFFaEIsWUFBWSxLQUFjO1FBQ3hCLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ3RCLENBQUM7SUFFRCxLQUFLLENBQUMsT0FBTztRQUNYLHdCQUF3QjtRQUN4QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7UUFDekMsTUFBTSxJQUFJLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLElBQUk7WUFBRSxPQUFPO1FBQ2xCLE1BQU0sS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2QyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDO2dCQUFFLFNBQVM7WUFDbEMsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN6RSxDQUFDO0lBQ0gsQ0FBQztJQUVE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
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import { readJSON } from 'utility';
|
|
4
|
+
import { getSourceFile, isTimingFile } from '../../utils.js';
|
|
5
|
+
export default (_, app) => {
|
|
6
|
+
return async (ctx, next) => {
|
|
7
|
+
if (ctx.path !== '/__loader_trace__') {
|
|
8
|
+
return await next();
|
|
9
|
+
}
|
|
10
|
+
const template = await fs.readFile(getSourceFile('config/loader_trace.html'), 'utf8');
|
|
11
|
+
const data = await loadTimingData(app);
|
|
12
|
+
ctx.body = template.replace('{{placeholder}}', JSON.stringify(data));
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
async function loadTimingData(app) {
|
|
16
|
+
const rundir = app.config.rundir;
|
|
17
|
+
const files = await fs.readdir(rundir);
|
|
18
|
+
const data = [];
|
|
19
|
+
for (const file of files) {
|
|
20
|
+
if (!isTimingFile(file))
|
|
21
|
+
continue;
|
|
22
|
+
const json = await readJSON(path.join(rundir, file));
|
|
23
|
+
const isAgent = /^agent/.test(file);
|
|
24
|
+
for (const item of json) {
|
|
25
|
+
if (isAgent) {
|
|
26
|
+
item.type = 'agent';
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
item.type = `app_${item.pid}`;
|
|
30
|
+
}
|
|
31
|
+
item.pid = String(item.pid);
|
|
32
|
+
item.range = [item.start, item.end];
|
|
33
|
+
item.title = `${item.type}(${item.index})`;
|
|
34
|
+
data.push(item);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWdnX2xvYWRlcl90cmFjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvbWlkZGxld2FyZS9lZ2dfbG9hZGVyX3RyYWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUM3QixPQUFPLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNsQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBRW5DLE9BQU8sRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFN0QsZUFBZSxDQUFDLENBQVUsRUFBRSxHQUFZLEVBQWtCLEVBQUU7SUFDMUQsT0FBTyxLQUFLLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFO1FBQ3pCLElBQUksR0FBRyxDQUFDLElBQUksS0FBSyxtQkFBbUIsRUFBRSxDQUFDO1lBQ3JDLE9BQU8sTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUN0QixDQUFDO1FBQ0QsTUFBTSxRQUFRLEdBQUcsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQywwQkFBMEIsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3RGLE1BQU0sSUFBSSxHQUFHLE1BQU0sY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdkUsQ0FBQyxDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBRUYsS0FBSyxVQUFVLGNBQWMsQ0FBQyxHQUFZO0lBQ3hDLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ2pDLE1BQU0sS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2QyxNQUFNLElBQUksR0FBVSxFQUFFLENBQUM7SUFDdkIsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztZQUFFLFNBQVM7UUFDbEMsTUFBTSxJQUFJLEdBQUcsTUFBTSxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNyRCxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BDLEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxFQUFFLENBQUM7WUFDeEIsSUFBSSxPQUFPLEVBQUUsQ0FBQztnQkFDWixJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQztZQUN0QixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxDQUFDLElBQUksR0FBRyxPQUFPLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNoQyxDQUFDO1lBQ0QsSUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzVCLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBRSxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUUsQ0FBQztZQUN0QyxJQUFJLENBQUMsS0FBSyxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUM7WUFDM0MsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsQixDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQyJ9
|
package/dist/esm/app.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default class AppBoot {
|
|
2
|
+
#app;
|
|
3
|
+
constructor(app) {
|
|
4
|
+
this.#app = app;
|
|
5
|
+
// if true, then don't need to wait at local development mode
|
|
6
|
+
if (app.config.development.fastReady) {
|
|
7
|
+
process.nextTick(() => this.#app.ready(true));
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
async configWillLoad() {
|
|
11
|
+
this.#app.config.coreMiddleware.push('eggLoaderTrace');
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxNQUFNLENBQUMsT0FBTyxPQUFPLE9BQU87SUFDMUIsSUFBSSxDQUFVO0lBRWQsWUFBWSxHQUFZO1FBQ3RCLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDO1FBQ2hCLDZEQUE2RDtRQUM3RCxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3JDLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNoRCxDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxjQUFjO1FBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN6RCxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DevelopmentConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* @member Config#development
|
|
4
|
+
* @property {Array} watchDirs - dirs needed watch, when files under these change, application will reload, use relative path
|
|
5
|
+
* @property {Array} ignoreDirs - dirs don't need watch, including subdirectories, use relative path
|
|
6
|
+
* @property {Boolean} fastReady - don't wait all plugins ready, default is false.
|
|
7
|
+
* @property {Boolean} reloadOnDebug - whether reload on debug, default is true.
|
|
8
|
+
* @property {Boolean} overrideDefault - whether override default watchDirs, default is false.
|
|
9
|
+
* @property {Boolean} overrideIgnore - whether override default ignoreDirs, default is false.
|
|
10
|
+
* @property {Array|String} reloadPattern - whether to reload, use https://github.com/sindresorhus/multimatch
|
|
11
|
+
*/
|
|
12
|
+
declare const _default: {
|
|
13
|
+
development: DevelopmentConfig;
|
|
14
|
+
};
|
|
15
|
+
export default _default;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @member Config#development
|
|
3
|
+
* @property {Array} watchDirs - dirs needed watch, when files under these change, application will reload, use relative path
|
|
4
|
+
* @property {Array} ignoreDirs - dirs don't need watch, including subdirectories, use relative path
|
|
5
|
+
* @property {Boolean} fastReady - don't wait all plugins ready, default is false.
|
|
6
|
+
* @property {Boolean} reloadOnDebug - whether reload on debug, default is true.
|
|
7
|
+
* @property {Boolean} overrideDefault - whether override default watchDirs, default is false.
|
|
8
|
+
* @property {Boolean} overrideIgnore - whether override default ignoreDirs, default is false.
|
|
9
|
+
* @property {Array|String} reloadPattern - whether to reload, use https://github.com/sindresorhus/multimatch
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
development: {
|
|
13
|
+
watchDirs: [],
|
|
14
|
+
ignoreDirs: [],
|
|
15
|
+
fastReady: false,
|
|
16
|
+
reloadOnDebug: true,
|
|
17
|
+
overrideDefault: false,
|
|
18
|
+
overrideIgnore: false,
|
|
19
|
+
reloadPattern: undefined,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmRlZmF1bHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29uZmlnL2NvbmZpZy5kZWZhdWx0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBOzs7Ozs7Ozs7R0FTRztBQUNILGVBQWU7SUFDYixXQUFXLEVBQUU7UUFDWCxTQUFTLEVBQUUsRUFBRTtRQUNiLFVBQVUsRUFBRSxFQUFFO1FBQ2QsU0FBUyxFQUFFLEtBQUs7UUFDaEIsYUFBYSxFQUFFLElBQUk7UUFDbkIsZUFBZSxFQUFFLEtBQUs7UUFDdEIsY0FBYyxFQUFFLEtBQUs7UUFDckIsYUFBYSxFQUFFLFNBQVM7S0FDSjtDQUN2QixDQUFDIn0=
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title></title>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<div id="mountNode"></div>
|
|
8
|
+
<script src="https://gw.alipayobjects.com/os/antv/assets/g2/3.0.9/g2.min.js"></script>
|
|
9
|
+
<script>
|
|
10
|
+
var data = {{placeholder}};
|
|
11
|
+
|
|
12
|
+
const chart = new G2.Chart({
|
|
13
|
+
container: 'mountNode', // 指定图表容器 ID
|
|
14
|
+
height: data.length * 22, // 指定图表高度
|
|
15
|
+
forceFit: true,
|
|
16
|
+
padding: 'auto',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Step 2: 载入数据源
|
|
20
|
+
chart.source(data, {
|
|
21
|
+
range: {
|
|
22
|
+
type: 'time',
|
|
23
|
+
mask: 'HH:mm:ss',
|
|
24
|
+
nice: true,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
chart
|
|
28
|
+
.coord()
|
|
29
|
+
.transpose()
|
|
30
|
+
.scale(1, -1);
|
|
31
|
+
|
|
32
|
+
chart.legend({ position: 'top' });
|
|
33
|
+
|
|
34
|
+
chart.tooltip({
|
|
35
|
+
showTitle: false,
|
|
36
|
+
itemTpl: '<li>{duration}ms: {name} </li>'
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
chart
|
|
40
|
+
.interval()
|
|
41
|
+
.position('title*range')
|
|
42
|
+
.color('type')
|
|
43
|
+
.tooltip('name*duration', (name, duration) => ({ name, duration }))
|
|
44
|
+
.size(5);
|
|
45
|
+
|
|
46
|
+
chart.render();
|
|
47
|
+
</script>
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './types.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface DevelopmentConfig {
|
|
2
|
+
/**
|
|
3
|
+
* dirs needed watch, when files under these change, application will reload, use relative path
|
|
4
|
+
*/
|
|
5
|
+
watchDirs: string[];
|
|
6
|
+
/**
|
|
7
|
+
* dirs don't need watch, including subdirectories, use relative path
|
|
8
|
+
*/
|
|
9
|
+
ignoreDirs: string[];
|
|
10
|
+
/**
|
|
11
|
+
* don't wait all plugins ready, default is false.
|
|
12
|
+
*/
|
|
13
|
+
fastReady: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* whether reload on debug, default is true.
|
|
16
|
+
*/
|
|
17
|
+
reloadOnDebug: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* whether override default watchDirs, default is false.
|
|
20
|
+
*/
|
|
21
|
+
overrideDefault: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* whether override default ignoreDirs, default is false.
|
|
24
|
+
*/
|
|
25
|
+
overrideIgnore: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* whether to reload, use https://github.com/sindresorhus/multimatch
|
|
28
|
+
*/
|
|
29
|
+
reloadPattern?: string[] | string;
|
|
30
|
+
}
|
|
31
|
+
declare module '@eggjs/core' {
|
|
32
|
+
interface EggAppConfig {
|
|
33
|
+
development: DevelopmentConfig;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
export function getSourceDirname() {
|
|
4
|
+
if (typeof __dirname !== 'undefined') {
|
|
5
|
+
return path.dirname(__dirname);
|
|
6
|
+
}
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
return path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
}
|
|
11
|
+
export function getSourceFile(filename) {
|
|
12
|
+
return path.join(getSourceDirname(), filename);
|
|
13
|
+
}
|
|
14
|
+
export function isTimingFile(file) {
|
|
15
|
+
return /^(agent|application)_timing/.test(file);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFekMsTUFBTSxVQUFVLGdCQUFnQjtJQUM5QixJQUFJLE9BQU8sU0FBUyxLQUFLLFdBQVcsRUFBRSxDQUFDO1FBQ3JDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBQ0QsNkRBQTZEO0lBQzdELGFBQWE7SUFDYixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUN0RCxDQUFDO0FBRUQsTUFBTSxVQUFVLGFBQWEsQ0FBQyxRQUFnQjtJQUM1QyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztBQUNqRCxDQUFDO0FBRUQsTUFBTSxVQUFVLFlBQVksQ0FBQyxJQUFZO0lBQ3ZDLE9BQU8sNkJBQTZCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2xELENBQUMifQ==
|
package/package.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@eggjs/development",
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "development tool for egg",
|
|
8
|
+
"eggPlugin": {
|
|
9
|
+
"name": "development",
|
|
10
|
+
"env": [
|
|
11
|
+
"local"
|
|
12
|
+
],
|
|
13
|
+
"dependencies": [
|
|
14
|
+
"watcher"
|
|
15
|
+
],
|
|
16
|
+
"exports": {
|
|
17
|
+
"import": "./dist/esm",
|
|
18
|
+
"require": "./dist/commonjs",
|
|
19
|
+
"typescript": "./src"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"egg",
|
|
24
|
+
"plugin",
|
|
25
|
+
"egg-plugin",
|
|
26
|
+
"eggPlugin"
|
|
27
|
+
],
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@eggjs/core": "^6.2.11",
|
|
30
|
+
"debounce": "^2.2.0",
|
|
31
|
+
"multimatch": "^5.0.0",
|
|
32
|
+
"utility": "^2.4.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@arethetypeswrong/cli": "^0.17.2",
|
|
36
|
+
"@eggjs/bin": "7",
|
|
37
|
+
"@eggjs/mock": "6",
|
|
38
|
+
"@eggjs/supertest": "8",
|
|
39
|
+
"@eggjs/tsconfig": "1",
|
|
40
|
+
"@types/mocha": "10",
|
|
41
|
+
"@types/node": "22",
|
|
42
|
+
"egg": "beta",
|
|
43
|
+
"eslint": "8",
|
|
44
|
+
"eslint-config-egg": "14",
|
|
45
|
+
"rimraf": "^6.0.1",
|
|
46
|
+
"tshy": "3",
|
|
47
|
+
"tshy-after": "1",
|
|
48
|
+
"typescript": "5"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=18.19.0"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"lint": "eslint --cache src test --ext .ts",
|
|
55
|
+
"pretest": "npm run clean && npm run lint -- --fix",
|
|
56
|
+
"test": "egg-bin test",
|
|
57
|
+
"preci": "npm run clean && npm run lint",
|
|
58
|
+
"ci": "egg-bin cov",
|
|
59
|
+
"postci": "npm run prepublishOnly && npm run clean",
|
|
60
|
+
"clean": "rimraf dist",
|
|
61
|
+
"prepublishOnly": "tshy && tshy-after && attw --pack"
|
|
62
|
+
},
|
|
63
|
+
"repository": {
|
|
64
|
+
"type": "git",
|
|
65
|
+
"url": "git+https://github.com/eggjs/development.git"
|
|
66
|
+
},
|
|
67
|
+
"bugs": "https://github.com/eggjs/egg/issues",
|
|
68
|
+
"homepage": "https://github.com/eggjs/development#readme",
|
|
69
|
+
"author": "jtyjty99999",
|
|
70
|
+
"license": "MIT",
|
|
71
|
+
"type": "module",
|
|
72
|
+
"tshy": {
|
|
73
|
+
"exports": {
|
|
74
|
+
".": "./src/index.ts",
|
|
75
|
+
"./package.json": "./package.json"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"exports": {
|
|
79
|
+
".": {
|
|
80
|
+
"import": {
|
|
81
|
+
"types": "./dist/esm/index.d.ts",
|
|
82
|
+
"default": "./dist/esm/index.js"
|
|
83
|
+
},
|
|
84
|
+
"require": {
|
|
85
|
+
"types": "./dist/commonjs/index.d.ts",
|
|
86
|
+
"default": "./dist/commonjs/index.js"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"./package.json": "./package.json"
|
|
90
|
+
},
|
|
91
|
+
"files": [
|
|
92
|
+
"dist",
|
|
93
|
+
"src"
|
|
94
|
+
],
|
|
95
|
+
"types": "./dist/commonjs/index.d.ts",
|
|
96
|
+
"main": "./dist/commonjs/index.js",
|
|
97
|
+
"module": "./dist/esm/index.js"
|
|
98
|
+
}
|
package/src/agent.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import debounce from 'debounce';
|
|
4
|
+
import multimatch from 'multimatch';
|
|
5
|
+
import { exists } from 'utility';
|
|
6
|
+
import type { ILifecycleBoot, EggCore } from '@eggjs/core';
|
|
7
|
+
import { isTimingFile } from './utils.js';
|
|
8
|
+
|
|
9
|
+
export default class AgentBoot implements ILifecycleBoot {
|
|
10
|
+
#agent: EggCore;
|
|
11
|
+
|
|
12
|
+
constructor(agent: EggCore) {
|
|
13
|
+
this.#agent = agent;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async didLoad() {
|
|
17
|
+
// clean all timing json
|
|
18
|
+
const rundir = this.#agent.config.rundir;
|
|
19
|
+
const stat = await exists(rundir);
|
|
20
|
+
if (!stat) return;
|
|
21
|
+
const files = await fs.readdir(rundir);
|
|
22
|
+
for (const file of files) {
|
|
23
|
+
if (!isTimingFile(file)) continue;
|
|
24
|
+
await fs.rm(path.join(rundir, file), { force: true, recursive: true });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async serverDidReady() {
|
|
29
|
+
const agent = this.#agent;
|
|
30
|
+
// single process mode don't watch and reload
|
|
31
|
+
if (agent.options && Reflect.get(agent.options, 'mode') === 'single') {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const logger = agent.logger;
|
|
36
|
+
const baseDir = agent.config.baseDir;
|
|
37
|
+
const config = agent.config.development;
|
|
38
|
+
|
|
39
|
+
let watchDirs = config.overrideDefault ? [] : [
|
|
40
|
+
'app',
|
|
41
|
+
'config',
|
|
42
|
+
'mocks',
|
|
43
|
+
'mocks_proxy',
|
|
44
|
+
'app.js',
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
watchDirs = watchDirs.concat(config.watchDirs).map(dir => path.resolve(baseDir, dir));
|
|
48
|
+
|
|
49
|
+
let ignoreReloadFileDirs = config.overrideIgnore ? [] : [
|
|
50
|
+
'app/views',
|
|
51
|
+
'app/view',
|
|
52
|
+
'app/assets',
|
|
53
|
+
'app/public',
|
|
54
|
+
'app/web',
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
ignoreReloadFileDirs = ignoreReloadFileDirs.concat(config.ignoreDirs).map(dir => path.resolve(baseDir, dir));
|
|
58
|
+
|
|
59
|
+
const reloadFile = debounce(function(info) {
|
|
60
|
+
logger.warn(`[agent:development] reload worker because ${info.path} ${info.event}`);
|
|
61
|
+
|
|
62
|
+
process.send!({
|
|
63
|
+
to: 'master',
|
|
64
|
+
action: 'reload-worker',
|
|
65
|
+
});
|
|
66
|
+
}, 200);
|
|
67
|
+
|
|
68
|
+
// watch dirs to reload worker, will debounce 200ms
|
|
69
|
+
/**
|
|
70
|
+
* reload app worker:
|
|
71
|
+
* [AgentWorker] - on file change
|
|
72
|
+
* |-> emit reload-worker
|
|
73
|
+
* [Master] - receive reload-worker event
|
|
74
|
+
* |-> TODO: Mark worker will die
|
|
75
|
+
* |-> Fork new worker
|
|
76
|
+
* |-> kill old worker
|
|
77
|
+
*
|
|
78
|
+
* @param {Object} info - changed fileInfo
|
|
79
|
+
*/
|
|
80
|
+
agent.watcher.watch(watchDirs, info => {
|
|
81
|
+
if (!config.reloadOnDebug) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (isAssetsDir(info.path) || info.isDirectory) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// don't reload if don't match
|
|
90
|
+
if (config.reloadPattern && multimatch(info.path, config.reloadPattern).length === 0) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
reloadFile(info);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
function isAssetsDir(filepath: string) {
|
|
98
|
+
for (const ignorePath of ignoreReloadFileDirs) {
|
|
99
|
+
if (filepath.startsWith(ignorePath)) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import { readJSON } from 'utility';
|
|
4
|
+
import type { EggCore, MiddlewareFunc } from '@eggjs/core';
|
|
5
|
+
import { getSourceFile, isTimingFile } from '../../utils.js';
|
|
6
|
+
|
|
7
|
+
export default (_: unknown, app: EggCore): MiddlewareFunc => {
|
|
8
|
+
return async (ctx, next) => {
|
|
9
|
+
if (ctx.path !== '/__loader_trace__') {
|
|
10
|
+
return await next();
|
|
11
|
+
}
|
|
12
|
+
const template = await fs.readFile(getSourceFile('config/loader_trace.html'), 'utf8');
|
|
13
|
+
const data = await loadTimingData(app);
|
|
14
|
+
ctx.body = template.replace('{{placeholder}}', JSON.stringify(data));
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
async function loadTimingData(app: EggCore) {
|
|
19
|
+
const rundir = app.config.rundir;
|
|
20
|
+
const files = await fs.readdir(rundir);
|
|
21
|
+
const data: any[] = [];
|
|
22
|
+
for (const file of files) {
|
|
23
|
+
if (!isTimingFile(file)) continue;
|
|
24
|
+
const json = await readJSON(path.join(rundir, file));
|
|
25
|
+
const isAgent = /^agent/.test(file);
|
|
26
|
+
for (const item of json) {
|
|
27
|
+
if (isAgent) {
|
|
28
|
+
item.type = 'agent';
|
|
29
|
+
} else {
|
|
30
|
+
item.type = `app_${item.pid}`;
|
|
31
|
+
}
|
|
32
|
+
item.pid = String(item.pid);
|
|
33
|
+
item.range = [ item.start, item.end ];
|
|
34
|
+
item.title = `${item.type}(${item.index})`;
|
|
35
|
+
data.push(item);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return data;
|
|
39
|
+
}
|
package/src/app.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ILifecycleBoot, EggCore } from '@eggjs/core';
|
|
2
|
+
|
|
3
|
+
export default class AppBoot implements ILifecycleBoot {
|
|
4
|
+
#app: EggCore;
|
|
5
|
+
|
|
6
|
+
constructor(app: EggCore) {
|
|
7
|
+
this.#app = app;
|
|
8
|
+
// if true, then don't need to wait at local development mode
|
|
9
|
+
if (app.config.development.fastReady) {
|
|
10
|
+
process.nextTick(() => this.#app.ready(true));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async configWillLoad() {
|
|
15
|
+
this.#app.config.coreMiddleware.push('eggLoaderTrace');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DevelopmentConfig } from '../types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @member Config#development
|
|
5
|
+
* @property {Array} watchDirs - dirs needed watch, when files under these change, application will reload, use relative path
|
|
6
|
+
* @property {Array} ignoreDirs - dirs don't need watch, including subdirectories, use relative path
|
|
7
|
+
* @property {Boolean} fastReady - don't wait all plugins ready, default is false.
|
|
8
|
+
* @property {Boolean} reloadOnDebug - whether reload on debug, default is true.
|
|
9
|
+
* @property {Boolean} overrideDefault - whether override default watchDirs, default is false.
|
|
10
|
+
* @property {Boolean} overrideIgnore - whether override default ignoreDirs, default is false.
|
|
11
|
+
* @property {Array|String} reloadPattern - whether to reload, use https://github.com/sindresorhus/multimatch
|
|
12
|
+
*/
|
|
13
|
+
export default {
|
|
14
|
+
development: {
|
|
15
|
+
watchDirs: [],
|
|
16
|
+
ignoreDirs: [],
|
|
17
|
+
fastReady: false,
|
|
18
|
+
reloadOnDebug: true,
|
|
19
|
+
overrideDefault: false,
|
|
20
|
+
overrideIgnore: false,
|
|
21
|
+
reloadPattern: undefined,
|
|
22
|
+
} as DevelopmentConfig,
|
|
23
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title></title>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<div id="mountNode"></div>
|
|
8
|
+
<script src="https://gw.alipayobjects.com/os/antv/assets/g2/3.0.9/g2.min.js"></script>
|
|
9
|
+
<script>
|
|
10
|
+
var data = {{placeholder}};
|
|
11
|
+
|
|
12
|
+
const chart = new G2.Chart({
|
|
13
|
+
container: 'mountNode', // 指定图表容器 ID
|
|
14
|
+
height: data.length * 22, // 指定图表高度
|
|
15
|
+
forceFit: true,
|
|
16
|
+
padding: 'auto',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Step 2: 载入数据源
|
|
20
|
+
chart.source(data, {
|
|
21
|
+
range: {
|
|
22
|
+
type: 'time',
|
|
23
|
+
mask: 'HH:mm:ss',
|
|
24
|
+
nice: true,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
chart
|
|
28
|
+
.coord()
|
|
29
|
+
.transpose()
|
|
30
|
+
.scale(1, -1);
|
|
31
|
+
|
|
32
|
+
chart.legend({ position: 'top' });
|
|
33
|
+
|
|
34
|
+
chart.tooltip({
|
|
35
|
+
showTitle: false,
|
|
36
|
+
itemTpl: '<li>{duration}ms: {name} </li>'
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
chart
|
|
40
|
+
.interval()
|
|
41
|
+
.position('title*range')
|
|
42
|
+
.color('type')
|
|
43
|
+
.tooltip('name*duration', (name, duration) => ({ name, duration }))
|
|
44
|
+
.size(5);
|
|
45
|
+
|
|
46
|
+
chart.render();
|
|
47
|
+
</script>
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './types.js';
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface DevelopmentConfig {
|
|
2
|
+
/**
|
|
3
|
+
* dirs needed watch, when files under these change, application will reload, use relative path
|
|
4
|
+
*/
|
|
5
|
+
watchDirs: string[];
|
|
6
|
+
/**
|
|
7
|
+
* dirs don't need watch, including subdirectories, use relative path
|
|
8
|
+
*/
|
|
9
|
+
ignoreDirs: string[];
|
|
10
|
+
/**
|
|
11
|
+
* don't wait all plugins ready, default is false.
|
|
12
|
+
*/
|
|
13
|
+
fastReady: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* whether reload on debug, default is true.
|
|
16
|
+
*/
|
|
17
|
+
reloadOnDebug: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* whether override default watchDirs, default is false.
|
|
20
|
+
*/
|
|
21
|
+
overrideDefault: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* whether override default ignoreDirs, default is false.
|
|
24
|
+
*/
|
|
25
|
+
overrideIgnore: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* whether to reload, use https://github.com/sindresorhus/multimatch
|
|
28
|
+
*/
|
|
29
|
+
reloadPattern?: string[] | string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare module '@eggjs/core' {
|
|
33
|
+
// add EggAppConfig overrides types
|
|
34
|
+
interface EggAppConfig {
|
|
35
|
+
development: DevelopmentConfig;
|
|
36
|
+
}
|
|
37
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
|
|
4
|
+
export function getSourceDirname() {
|
|
5
|
+
if (typeof __dirname !== 'undefined') {
|
|
6
|
+
return path.dirname(__dirname);
|
|
7
|
+
}
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
return path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getSourceFile(filename: string) {
|
|
14
|
+
return path.join(getSourceDirname(), filename);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isTimingFile(file: string) {
|
|
18
|
+
return /^(agent|application)_timing/.test(file);
|
|
19
|
+
}
|