egg 3.26.0 → 4.0.0-beta.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/README.md +1 -1
- package/README.zh-CN.md +6 -5
- package/dist/commonjs/agent.d.ts +4 -0
- package/dist/commonjs/agent.js +10 -0
- package/dist/commonjs/app/middleware/body_parser.d.ts +2 -0
- package/dist/commonjs/app/middleware/body_parser.js +8 -0
- package/dist/commonjs/app/middleware/meta.d.ts +11 -0
- package/dist/commonjs/app/middleware/meta.js +22 -0
- package/dist/commonjs/app/middleware/notfound.d.ts +8 -0
- package/dist/commonjs/app/middleware/notfound.js +31 -0
- package/dist/commonjs/app/middleware/override_method.d.ts +2 -0
- package/dist/commonjs/app/middleware/override_method.js +8 -0
- package/dist/commonjs/app/middleware/site_file.d.ts +7 -0
- package/dist/commonjs/app/middleware/site_file.js +40 -0
- package/dist/commonjs/config/config.default.d.ts +9 -0
- package/dist/commonjs/config/config.default.js +378 -0
- package/dist/commonjs/config/config.local.d.ts +8 -0
- package/dist/commonjs/config/config.local.js +12 -0
- package/dist/commonjs/config/config.unittest.d.ts +7 -0
- package/dist/commonjs/config/config.unittest.js +11 -0
- package/dist/commonjs/config/plugin.d.ts +122 -0
- package/dist/commonjs/config/plugin.js +125 -0
- package/dist/commonjs/index.d.ts +61 -0
- package/dist/commonjs/index.js +89 -0
- package/dist/commonjs/lib/agent.d.ts +19 -0
- package/dist/commonjs/lib/agent.js +58 -0
- package/dist/commonjs/lib/application.d.ts +66 -0
- package/dist/commonjs/lib/application.js +281 -0
- package/dist/commonjs/lib/core/base_context_class.d.ts +14 -0
- package/dist/commonjs/lib/core/base_context_class.js +22 -0
- package/dist/commonjs/lib/core/base_context_logger.d.ts +36 -0
- package/dist/commonjs/lib/core/base_context_logger.js +64 -0
- package/dist/commonjs/lib/core/base_hook_class.d.ts +11 -0
- package/dist/commonjs/lib/core/base_hook_class.js +30 -0
- package/dist/commonjs/lib/core/context_httpclient.d.ts +16 -0
- package/dist/commonjs/lib/core/context_httpclient.js +30 -0
- package/dist/commonjs/lib/core/httpclient.d.ts +14 -0
- package/dist/commonjs/lib/core/httpclient.js +40 -0
- package/dist/commonjs/lib/core/logger.d.ts +3 -0
- package/dist/commonjs/lib/core/logger.js +40 -0
- package/dist/commonjs/lib/core/messenger/IMessenger.d.ts +50 -0
- package/dist/commonjs/lib/core/messenger/IMessenger.js +3 -0
- package/dist/commonjs/lib/core/messenger/index.d.ts +7 -0
- package/dist/commonjs/lib/core/messenger/index.js +14 -0
- package/dist/commonjs/lib/core/messenger/ipc.d.ts +57 -0
- package/dist/commonjs/lib/core/messenger/ipc.js +126 -0
- package/dist/commonjs/lib/core/messenger/local.d.ts +61 -0
- package/dist/commonjs/lib/core/messenger/local.js +134 -0
- package/dist/commonjs/lib/core/singleton.d.ts +23 -0
- package/dist/commonjs/lib/core/singleton.js +120 -0
- package/dist/commonjs/lib/core/utils.d.ts +2 -0
- package/dist/commonjs/lib/core/utils.js +77 -0
- package/dist/commonjs/lib/egg.d.ts +267 -0
- package/dist/commonjs/lib/egg.js +595 -0
- package/dist/commonjs/lib/loader/AgentWorkerLoader.d.ts +12 -0
- package/dist/commonjs/lib/loader/AgentWorkerLoader.js +24 -0
- package/dist/commonjs/lib/loader/AppWorkerLoader.d.ts +17 -0
- package/dist/commonjs/lib/loader/AppWorkerLoader.js +43 -0
- package/dist/commonjs/lib/loader/EggApplicationLoader.d.ts +4 -0
- package/dist/commonjs/lib/loader/EggApplicationLoader.js +8 -0
- package/dist/commonjs/lib/loader/index.d.ts +3 -0
- package/dist/commonjs/lib/loader/index.js +22 -0
- package/dist/commonjs/lib/start.d.ts +15 -0
- package/dist/commonjs/lib/start.js +49 -0
- package/dist/commonjs/lib/type.d.ts +295 -0
- package/dist/commonjs/lib/type.js +3 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/esm/agent.d.ts +4 -0
- package/dist/esm/agent.js +7 -0
- package/dist/esm/app/middleware/body_parser.d.ts +2 -0
- package/dist/esm/app/middleware/body_parser.js +3 -0
- package/dist/esm/app/middleware/meta.d.ts +11 -0
- package/dist/esm/app/middleware/meta.js +20 -0
- package/dist/esm/app/middleware/notfound.d.ts +8 -0
- package/dist/esm/app/middleware/notfound.js +29 -0
- package/dist/esm/app/middleware/override_method.d.ts +2 -0
- package/dist/esm/app/middleware/override_method.js +3 -0
- package/dist/esm/app/middleware/site_file.d.ts +7 -0
- package/dist/esm/app/middleware/site_file.js +35 -0
- package/dist/esm/config/config.default.d.ts +9 -0
- package/dist/esm/config/config.default.js +373 -0
- package/dist/esm/config/config.local.d.ts +8 -0
- package/dist/esm/config/config.local.js +10 -0
- package/dist/esm/config/config.unittest.d.ts +7 -0
- package/dist/esm/config/config.unittest.js +9 -0
- package/dist/esm/config/favicon.png +0 -0
- package/dist/esm/config/plugin.d.ts +122 -0
- package/dist/esm/config/plugin.js +123 -0
- package/dist/esm/index.d.ts +61 -0
- package/dist/esm/index.js +65 -0
- package/dist/esm/lib/agent.d.ts +19 -0
- package/dist/esm/lib/agent.js +54 -0
- package/dist/esm/lib/application.d.ts +66 -0
- package/dist/esm/lib/application.js +274 -0
- package/dist/esm/lib/core/base_context_class.d.ts +14 -0
- package/dist/esm/lib/core/base_context_class.js +18 -0
- package/dist/esm/lib/core/base_context_logger.d.ts +36 -0
- package/dist/esm/lib/core/base_context_logger.js +60 -0
- package/dist/esm/lib/core/base_hook_class.d.ts +11 -0
- package/dist/esm/lib/core/base_hook_class.js +23 -0
- package/dist/esm/lib/core/context_httpclient.d.ts +16 -0
- package/dist/esm/lib/core/context_httpclient.js +26 -0
- package/dist/esm/lib/core/httpclient.d.ts +14 -0
- package/dist/esm/lib/core/httpclient.js +33 -0
- package/dist/esm/lib/core/logger.d.ts +3 -0
- package/dist/esm/lib/core/logger.js +37 -0
- package/dist/esm/lib/core/messenger/IMessenger.d.ts +50 -0
- package/dist/esm/lib/core/messenger/IMessenger.js +2 -0
- package/dist/esm/lib/core/messenger/index.d.ts +7 -0
- package/dist/esm/lib/core/messenger/index.js +11 -0
- package/dist/esm/lib/core/messenger/ipc.d.ts +57 -0
- package/dist/esm/lib/core/messenger/ipc.js +119 -0
- package/dist/esm/lib/core/messenger/local.d.ts +61 -0
- package/dist/esm/lib/core/messenger/local.js +127 -0
- package/dist/esm/lib/core/singleton.d.ts +23 -0
- package/dist/esm/lib/core/singleton.js +113 -0
- package/dist/esm/lib/core/utils.d.ts +2 -0
- package/dist/esm/lib/core/utils.js +70 -0
- package/dist/esm/lib/egg.d.ts +267 -0
- package/dist/esm/lib/egg.js +565 -0
- package/dist/esm/lib/loader/AgentWorkerLoader.d.ts +12 -0
- package/dist/esm/lib/loader/AgentWorkerLoader.js +20 -0
- package/dist/esm/lib/loader/AppWorkerLoader.d.ts +17 -0
- package/dist/esm/lib/loader/AppWorkerLoader.js +39 -0
- package/dist/esm/lib/loader/EggApplicationLoader.d.ts +4 -0
- package/dist/esm/lib/loader/EggApplicationLoader.js +4 -0
- package/dist/esm/lib/loader/index.d.ts +3 -0
- package/dist/esm/lib/loader/index.js +4 -0
- package/dist/esm/lib/start.d.ts +15 -0
- package/dist/esm/lib/start.js +43 -0
- package/dist/esm/lib/type.d.ts +295 -0
- package/dist/esm/lib/type.js +2 -0
- package/dist/esm/package.json +3 -0
- package/dist/package.json +4 -0
- package/package.json +83 -70
- package/src/agent.ts +7 -0
- package/src/app/middleware/body_parser.ts +3 -0
- package/{app/middleware/meta.js → src/app/middleware/meta.ts} +12 -4
- package/{app/middleware/notfound.js → src/app/middleware/notfound.ts} +9 -3
- package/src/app/middleware/override_method.ts +3 -0
- package/src/app/middleware/site_file.ts +49 -0
- package/{config/config.default.js → src/config/config.default.ts} +21 -42
- package/src/config/config.local.ts +11 -0
- package/src/config/config.unittest.ts +10 -0
- package/src/config/favicon.png +0 -0
- package/{config/plugin.js → src/config/plugin.ts} +1 -3
- package/src/index.ts +78 -0
- package/src/lib/agent.ts +66 -0
- package/{lib/application.js → src/lib/application.ts} +79 -120
- package/src/lib/core/base_context_class.ts +21 -0
- package/src/lib/core/base_context_logger.ts +67 -0
- package/src/lib/core/base_hook_class.ts +30 -0
- package/src/lib/core/context_httpclient.ts +33 -0
- package/src/lib/core/httpclient.ts +52 -0
- package/src/lib/core/logger.ts +42 -0
- package/src/lib/core/messenger/IMessenger.ts +58 -0
- package/src/lib/core/messenger/index.ts +15 -0
- package/{lib/core/messenger/ipc.js → src/lib/core/messenger/ipc.ts} +25 -29
- package/{lib/core/messenger/local.js → src/lib/core/messenger/local.ts} +27 -21
- package/{lib/core/singleton.js → src/lib/core/singleton.ts} +56 -33
- package/src/lib/core/utils.ts +77 -0
- package/{lib/egg.js → src/lib/egg.ts} +252 -218
- package/src/lib/loader/AgentWorkerLoader.ts +21 -0
- package/src/lib/loader/AppWorkerLoader.ts +42 -0
- package/src/lib/loader/EggApplicationLoader.ts +5 -0
- package/src/lib/loader/index.ts +3 -0
- package/src/lib/start.ts +56 -0
- package/src/lib/type.ts +329 -0
- package/agent.js +0 -11
- package/app/middleware/body_parser.js +0 -3
- package/app/middleware/override_method.js +0 -3
- package/app/middleware/site_file.js +0 -31
- package/config/config.local.js +0 -7
- package/config/config.unittest.js +0 -8
- package/index.d.ts +0 -1285
- package/index.js +0 -68
- package/lib/agent.js +0 -95
- package/lib/core/base_context_class.js +0 -20
- package/lib/core/base_context_logger.js +0 -64
- package/lib/core/base_hook_class.js +0 -31
- package/lib/core/context_httpclient.js +0 -26
- package/lib/core/dnscache_httpclient.js +0 -93
- package/lib/core/httpclient.js +0 -108
- package/lib/core/httpclient_next.js +0 -45
- package/lib/core/logger.js +0 -35
- package/lib/core/messenger/index.js +0 -14
- package/lib/core/utils.js +0 -73
- package/lib/loader/agent_worker_loader.js +0 -27
- package/lib/loader/app_worker_loader.js +0 -48
- package/lib/loader/index.js +0 -5
- package/lib/start.js +0 -39
- /package/{config → dist/commonjs/config}/favicon.png +0 -0
- /package/{app → src/app}/extend/context.js +0 -0
- /package/{app → src/app}/extend/helper.js +0 -0
- /package/{app → src/app}/extend/request.js +0 -0
- /package/{app → src/app}/extend/response.js +0 -0
|
@@ -1,37 +1,120 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
import { performance } from 'node:perf_hooks';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import http, { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
5
|
+
import inspector from 'node:inspector';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { EggCore, type EggCoreContext, type EggCoreOptions } from '@eggjs/core';
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
import createClusterClient, { close as closeClusterClient } from 'cluster-client';
|
|
11
|
+
import extend from 'extend2';
|
|
12
|
+
import { EggContextLogger as ContextLogger, EggLoggers, EggLogger } from 'egg-logger';
|
|
13
|
+
import { Cookies as ContextCookies } from '@eggjs/cookies';
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
import CircularJSON from 'circular-json-for-egg';
|
|
17
|
+
import type { Agent } from './agent.js';
|
|
18
|
+
import type { Application } from './application.js';
|
|
19
|
+
import type { EggAppConfig } from './type.js';
|
|
20
|
+
import { create as createMessenger, IMessenger } from './core/messenger/index.js';
|
|
21
|
+
import { ContextHttpClient } from './core/context_httpclient.js';
|
|
22
|
+
import {
|
|
23
|
+
HttpClient, type HttpClientRequestOptions, type HttpClientRequestURL, type HttpClientResponse,
|
|
24
|
+
} from './core/httpclient.js';
|
|
25
|
+
import { createLoggers } from './core/logger.js';
|
|
26
|
+
import {
|
|
27
|
+
Singleton, type SingletonCreateMethod, type SingletonOptions,
|
|
28
|
+
} from './core/singleton.js';
|
|
29
|
+
import { convertObject } from './core/utils.js';
|
|
30
|
+
import { BaseContextClass } from './core/base_context_class.js';
|
|
31
|
+
import { BaseHookClass } from './core/base_hook_class.js';
|
|
32
|
+
import type { EggApplicationLoader } from './loader/index.js';
|
|
33
|
+
|
|
25
34
|
const EGG_PATH = Symbol.for('egg#eggPath');
|
|
26
|
-
|
|
35
|
+
|
|
36
|
+
export interface EggApplicationCoreOptions extends Omit<EggCoreOptions, 'baseDir'> {
|
|
37
|
+
mode?: 'cluster' | 'single';
|
|
38
|
+
clusterPort?: number;
|
|
39
|
+
baseDir?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface EggContext extends EggCoreContext {
|
|
43
|
+
app: EggApplicationCore;
|
|
44
|
+
/**
|
|
45
|
+
* Request start time
|
|
46
|
+
* @member {Number} Context#starttime
|
|
47
|
+
*/
|
|
48
|
+
starttime: number;
|
|
49
|
+
/**
|
|
50
|
+
* Request start timer using `performance.now()`
|
|
51
|
+
* @member {Number} Context#performanceStarttime
|
|
52
|
+
*/
|
|
53
|
+
performanceStarttime: number;
|
|
54
|
+
}
|
|
27
55
|
|
|
28
56
|
/**
|
|
29
57
|
* Based on koa's Application
|
|
30
58
|
* @see https://github.com/eggjs/egg-core
|
|
31
|
-
* @see
|
|
59
|
+
* @see https://github.com/eggjs/koa/blob/master/src/application.ts
|
|
32
60
|
* @augments EggCore
|
|
33
61
|
*/
|
|
34
|
-
class
|
|
62
|
+
export class EggApplicationCore extends EggCore {
|
|
63
|
+
// export context base classes, let framework can impl sub class and over context extend easily.
|
|
64
|
+
ContextCookies = ContextCookies;
|
|
65
|
+
ContextLogger = ContextLogger;
|
|
66
|
+
ContextHttpClient = ContextHttpClient;
|
|
67
|
+
HttpClient = HttpClient;
|
|
68
|
+
/**
|
|
69
|
+
* Retrieve base context class
|
|
70
|
+
* @member {BaseContextClass} BaseContextClass
|
|
71
|
+
* @since 1.0.0
|
|
72
|
+
*/
|
|
73
|
+
BaseContextClass = BaseContextClass;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Retrieve base controller
|
|
77
|
+
* @member {Controller} Controller
|
|
78
|
+
* @since 1.0.0
|
|
79
|
+
*/
|
|
80
|
+
Controller = BaseContextClass;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Retrieve base service
|
|
84
|
+
* @member {Service} Service
|
|
85
|
+
* @since 1.0.0
|
|
86
|
+
*/
|
|
87
|
+
Service = BaseContextClass;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Retrieve base subscription
|
|
91
|
+
* @member {Subscription} Subscription
|
|
92
|
+
* @since 2.12.0
|
|
93
|
+
*/
|
|
94
|
+
Subscription = BaseContextClass;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Retrieve base context class
|
|
98
|
+
* @member {BaseHookClass} BaseHookClass
|
|
99
|
+
*/
|
|
100
|
+
BaseHookClass = BaseHookClass;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Retrieve base boot
|
|
104
|
+
* @member {Boot}
|
|
105
|
+
*/
|
|
106
|
+
Boot = BaseHookClass;
|
|
107
|
+
|
|
108
|
+
declare options: Required<EggApplicationCoreOptions>;
|
|
109
|
+
|
|
110
|
+
#httpClient?: HttpClient;
|
|
111
|
+
#loggers?: EggLoggers;
|
|
112
|
+
#clusterClients: any[] = [];
|
|
113
|
+
|
|
114
|
+
readonly messenger: IMessenger;
|
|
115
|
+
agent?: Agent;
|
|
116
|
+
application?: Application;
|
|
117
|
+
declare loader: EggApplicationLoader;
|
|
35
118
|
|
|
36
119
|
/**
|
|
37
120
|
* @class
|
|
@@ -41,91 +124,64 @@ class EggApplication extends EggCore {
|
|
|
41
124
|
* - {Object} [plugins] - custom plugin config, use it in unittest
|
|
42
125
|
* - {String} [mode] - process mode, can be cluster / single, default is `cluster`
|
|
43
126
|
*/
|
|
44
|
-
constructor(options
|
|
45
|
-
options
|
|
127
|
+
constructor(options?: EggApplicationCoreOptions) {
|
|
128
|
+
options = {
|
|
129
|
+
mode: 'cluster',
|
|
130
|
+
type: 'application',
|
|
131
|
+
baseDir: process.cwd(),
|
|
132
|
+
...options,
|
|
133
|
+
};
|
|
46
134
|
super(options);
|
|
47
|
-
|
|
48
|
-
// export context base classes, let framework can impl sub class and over context extend easily.
|
|
49
|
-
this.ContextCookies = ContextCookies;
|
|
50
|
-
this.ContextLogger = ContextLogger;
|
|
51
|
-
this.ContextHttpClient = ContextHttpClient;
|
|
52
|
-
this.HttpClient = HttpClient;
|
|
53
|
-
this.HttpClientNext = HttpClientNext;
|
|
54
|
-
|
|
55
|
-
this.loader.loadConfig();
|
|
56
|
-
|
|
57
135
|
/**
|
|
58
136
|
* messenger instance
|
|
59
137
|
* @member {Messenger}
|
|
60
138
|
* @since 1.0.0
|
|
61
139
|
*/
|
|
62
|
-
this.messenger =
|
|
140
|
+
this.messenger = createMessenger(this);
|
|
63
141
|
|
|
64
142
|
// trigger `serverDidReady` hook when all the app workers
|
|
65
143
|
// and agent worker are ready
|
|
66
144
|
this.messenger.once('egg-ready', () => {
|
|
67
145
|
this.lifecycle.triggerServerDidReady();
|
|
68
146
|
});
|
|
147
|
+
this.load();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
protected async loadConfig() {
|
|
151
|
+
await this.loader.loadConfig();
|
|
152
|
+
}
|
|
69
153
|
|
|
154
|
+
protected async load() {
|
|
155
|
+
await this.loadConfig();
|
|
70
156
|
// dump config after ready, ensure all the modifications during start will be recorded
|
|
71
157
|
// make sure dumpConfig is the last ready callback
|
|
72
158
|
this.ready(() => process.nextTick(() => {
|
|
73
159
|
const dumpStartTime = Date.now();
|
|
74
160
|
this.dumpConfig();
|
|
75
161
|
this.dumpTiming();
|
|
76
|
-
this.coreLogger.info('[egg
|
|
162
|
+
this.coreLogger.info('[egg] dump config after ready, %sms', Date.now() - dumpStartTime);
|
|
77
163
|
}));
|
|
78
|
-
this
|
|
164
|
+
this.#setupTimeoutTimer();
|
|
79
165
|
|
|
80
|
-
this.console.info('[egg
|
|
81
|
-
this.console.info('[egg
|
|
82
|
-
this.console.info('[egg
|
|
166
|
+
this.console.info('[egg] App root: %s', this.baseDir);
|
|
167
|
+
this.console.info('[egg] All *.log files save on %j', this.config.logger.dir);
|
|
168
|
+
this.console.info('[egg] Loaded enabled plugin %j', this.loader.orderPlugins);
|
|
83
169
|
|
|
84
170
|
// Listen the error that promise had not catch, then log it in common-error
|
|
85
171
|
this._unhandledRejectionHandler = this._unhandledRejectionHandler.bind(this);
|
|
86
172
|
process.on('unhandledRejection', this._unhandledRejectionHandler);
|
|
87
173
|
|
|
88
|
-
this[CLUSTER_CLIENTS] = [];
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Wrap the Client with Leader/Follower Pattern
|
|
92
|
-
*
|
|
93
|
-
* @description almost the same as Agent.cluster API, the only different is that this method create Follower.
|
|
94
|
-
*
|
|
95
|
-
* @see https://github.com/node-modules/cluster-client
|
|
96
|
-
* @param {Function} clientClass - client class function
|
|
97
|
-
* @param {Object} [options]
|
|
98
|
-
* - {Boolean} [autoGenerate] - whether generate delegate rule automatically, default is true
|
|
99
|
-
* - {Function} [formatKey] - a method to tranform the subscription info into a string,default is JSON.stringify
|
|
100
|
-
* - {Object} [transcode|JSON.stringify/parse]
|
|
101
|
-
* - {Function} encode - custom serialize method
|
|
102
|
-
* - {Function} decode - custom deserialize method
|
|
103
|
-
* - {Boolean} [isBroadcast] - whether broadcast subscrption result to all followers or just one, default is true
|
|
104
|
-
* - {Number} [responseTimeout] - response timeout, default is 3 seconds
|
|
105
|
-
* - {Number} [maxWaitTime|30000] - leader startup max time, default is 30 seconds
|
|
106
|
-
* @return {ClientWrapper} wrapper
|
|
107
|
-
*/
|
|
108
|
-
this.cluster = (clientClass, options) => {
|
|
109
|
-
options = Object.assign({}, this.config.clusterClient, options, {
|
|
110
|
-
singleMode: this.options.mode === 'single',
|
|
111
|
-
// cluster need a port that can't conflict on the environment
|
|
112
|
-
port: this.options.clusterPort,
|
|
113
|
-
// agent worker is leader, app workers are follower
|
|
114
|
-
isLeader: this.type === 'agent',
|
|
115
|
-
logger: this.coreLogger,
|
|
116
|
-
// debug mode does not check heartbeat
|
|
117
|
-
isCheckHeartbeat: this.config.env === 'prod' ? true : require('inspector').url() === undefined,
|
|
118
|
-
});
|
|
119
|
-
const client = cluster(clientClass, options);
|
|
120
|
-
this._patchClusterClient(client);
|
|
121
|
-
return client;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
174
|
// register close function
|
|
125
|
-
this.
|
|
175
|
+
this.lifecycle.registerBeforeClose(async () => {
|
|
176
|
+
// close all cluster clients
|
|
177
|
+
for (const clusterClient of this.#clusterClients) {
|
|
178
|
+
await closeClusterClient(clusterClient);
|
|
179
|
+
}
|
|
180
|
+
this.#clusterClients = [];
|
|
181
|
+
|
|
126
182
|
// single process mode will close agent before app close
|
|
127
183
|
if (this.type === 'application' && this.options.mode === 'single') {
|
|
128
|
-
await this.agent
|
|
184
|
+
await this.agent!.close();
|
|
129
185
|
}
|
|
130
186
|
|
|
131
187
|
for (const logger of this.loggers.values()) {
|
|
@@ -135,45 +191,43 @@ class EggApplication extends EggCore {
|
|
|
135
191
|
process.removeListener('unhandledRejection', this._unhandledRejectionHandler);
|
|
136
192
|
});
|
|
137
193
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
* @member {BaseContextClass} BaseContextClass
|
|
141
|
-
* @since 1.0.0
|
|
142
|
-
*/
|
|
143
|
-
this.BaseContextClass = BaseContextClass;
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Retreive base controller
|
|
147
|
-
* @member {Controller} Controller
|
|
148
|
-
* @since 1.0.0
|
|
149
|
-
*/
|
|
150
|
-
this.Controller = BaseContextClass;
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Retreive base service
|
|
154
|
-
* @member {Service} Service
|
|
155
|
-
* @since 1.0.0
|
|
156
|
-
*/
|
|
157
|
-
this.Service = BaseContextClass;
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Retreive base subscription
|
|
161
|
-
* @member {Subscription} Subscription
|
|
162
|
-
* @since 2.12.0
|
|
163
|
-
*/
|
|
164
|
-
this.Subscription = BaseContextClass;
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Retreive base context class
|
|
168
|
-
* @member {BaseHookClass} BaseHookClass
|
|
169
|
-
*/
|
|
170
|
-
this.BaseHookClass = BaseHookClass;
|
|
194
|
+
await this.loader.load();
|
|
195
|
+
}
|
|
171
196
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
197
|
+
/**
|
|
198
|
+
* Wrap the Client with Leader/Follower Pattern
|
|
199
|
+
*
|
|
200
|
+
* @description almost the same as Agent.cluster API, the only different is that this method create Follower.
|
|
201
|
+
*
|
|
202
|
+
* @see https://github.com/node-modules/cluster-client
|
|
203
|
+
* @param {Function} clientClass - client class function
|
|
204
|
+
* @param {Object} [options]
|
|
205
|
+
* - {Boolean} [autoGenerate] - whether generate delegate rule automatically, default is true
|
|
206
|
+
* - {Function} [formatKey] - a method to transform the subscription info into a string,default is JSON.stringify
|
|
207
|
+
* - {Object} [transcode|JSON.stringify/parse]
|
|
208
|
+
* - {Function} encode - custom serialize method
|
|
209
|
+
* - {Function} decode - custom deserialize method
|
|
210
|
+
* - {Boolean} [isBroadcast] - whether broadcast subscription result to all followers or just one, default is true
|
|
211
|
+
* - {Number} [responseTimeout] - response timeout, default is 3 seconds
|
|
212
|
+
* - {Number} [maxWaitTime|30000] - leader startup max time, default is 30 seconds
|
|
213
|
+
* @return {ClientWrapper} wrapper
|
|
214
|
+
*/
|
|
215
|
+
cluster(clientClass: unknown, options: object) {
|
|
216
|
+
const clientClassOptions = {
|
|
217
|
+
...this.config.clusterClient,
|
|
218
|
+
...options,
|
|
219
|
+
singleMode: this.options.mode === 'single',
|
|
220
|
+
// cluster need a port that can't conflict on the environment
|
|
221
|
+
port: this.options.clusterPort,
|
|
222
|
+
// agent worker is leader, app workers are follower
|
|
223
|
+
isLeader: this.type === 'agent',
|
|
224
|
+
logger: this.coreLogger,
|
|
225
|
+
// debug mode does not check heartbeat
|
|
226
|
+
isCheckHeartbeat: this.config.env === 'prod' ? true : inspector.url() === undefined,
|
|
227
|
+
};
|
|
228
|
+
const client = createClusterClient(clientClass, clientClassOptions);
|
|
229
|
+
this.#patchClusterClient(client);
|
|
230
|
+
return client;
|
|
177
231
|
}
|
|
178
232
|
|
|
179
233
|
/**
|
|
@@ -185,7 +239,7 @@ class EggApplication extends EggCore {
|
|
|
185
239
|
* console.log(app);
|
|
186
240
|
* =>
|
|
187
241
|
* {
|
|
188
|
-
* name: '
|
|
242
|
+
* name: 'mock-app',
|
|
189
243
|
* env: 'test',
|
|
190
244
|
* subdomainOffset: 2,
|
|
191
245
|
* config: '<egg config>',
|
|
@@ -197,23 +251,21 @@ class EggApplication extends EggCore {
|
|
|
197
251
|
* }
|
|
198
252
|
* ```
|
|
199
253
|
*/
|
|
200
|
-
inspect() {
|
|
254
|
+
inspect(): any {
|
|
201
255
|
const res = {
|
|
202
256
|
env: this.config.env,
|
|
203
257
|
};
|
|
204
258
|
|
|
205
|
-
function delegate(res, app, keys) {
|
|
259
|
+
function delegate(res: any, app: any, keys: string[]) {
|
|
206
260
|
for (const key of keys) {
|
|
207
|
-
/* istanbul ignore else */
|
|
208
261
|
if (app[key]) {
|
|
209
262
|
res[key] = app[key];
|
|
210
263
|
}
|
|
211
264
|
}
|
|
212
265
|
}
|
|
213
266
|
|
|
214
|
-
function abbr(res, app, keys) {
|
|
267
|
+
function abbr(res: any, app: any, keys: string[]) {
|
|
215
268
|
for (const key of keys) {
|
|
216
|
-
/* istanbul ignore else */
|
|
217
269
|
if (app[key]) {
|
|
218
270
|
res[key] = `<egg ${key}>`;
|
|
219
271
|
}
|
|
@@ -250,13 +302,13 @@ class EggApplication extends EggCore {
|
|
|
250
302
|
* See https://github.com/node-modules/urllib#api-doc for more details.
|
|
251
303
|
*
|
|
252
304
|
* @param {String} url request url address.
|
|
253
|
-
* @param {Object}
|
|
305
|
+
* @param {Object} options
|
|
254
306
|
* - method {String} - Request method, defaults to GET. Could be GET, POST, DELETE or PUT. Alias 'type'.
|
|
255
307
|
* - data {Object} - Data to be sent. Will be stringify automatically.
|
|
256
308
|
* - dataType {String} - String - Type of response data. Could be `text` or `json`.
|
|
257
|
-
* If it's `text`, the
|
|
309
|
+
* If it's `text`, the callback data would be a String.
|
|
258
310
|
* If it's `json`, the data of callback would be a parsed JSON Object.
|
|
259
|
-
* Default
|
|
311
|
+
* Default callback data would be a Buffer.
|
|
260
312
|
* - headers {Object} - Request headers.
|
|
261
313
|
* - timeout {Number} - Request timeout in milliseconds. Defaults to exports.TIMEOUT.
|
|
262
314
|
* Include remote server connecting timeout and response timeout.
|
|
@@ -266,10 +318,10 @@ class EggApplication extends EggCore {
|
|
|
266
318
|
* - gzip {Boolean} - let you get the res object when request connected, default false. alias customResponse
|
|
267
319
|
* - nestedQuerystring {Boolean} - urllib default use querystring to stringify form data which don't
|
|
268
320
|
* support nested object, will use qs instead of querystring to support nested object by set this option to true.
|
|
269
|
-
* - more options see https://
|
|
321
|
+
* - more options see https://github.com/node-modules/urllib
|
|
270
322
|
* @return {Object}
|
|
271
323
|
* - status {Number} - HTTP response status
|
|
272
|
-
* - headers {Object} - HTTP response
|
|
324
|
+
* - headers {Object} - HTTP response headers
|
|
273
325
|
* - res {Object} - HTTP response meta
|
|
274
326
|
* - data {Object} - HTTP response body
|
|
275
327
|
*
|
|
@@ -282,24 +334,8 @@ class EggApplication extends EggCore {
|
|
|
282
334
|
* console.log(result.status, result.headers, result.data);
|
|
283
335
|
* ```
|
|
284
336
|
*/
|
|
285
|
-
async curl(url,
|
|
286
|
-
return await this.
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Create a new HttpClient instance with custom options
|
|
291
|
-
* @param {Object} [options] HttpClient init options
|
|
292
|
-
*/
|
|
293
|
-
createHttpClient(options) {
|
|
294
|
-
let httpClient;
|
|
295
|
-
if (this.config.httpclient.useHttpClientNext) {
|
|
296
|
-
httpClient = new this.HttpClientNext(this, options);
|
|
297
|
-
} else if (this.config.httpclient.enableDNSCache) {
|
|
298
|
-
httpClient = new DNSCacheHttpClient(this, options);
|
|
299
|
-
} else {
|
|
300
|
-
httpClient = new this.HttpClient(this, options);
|
|
301
|
-
}
|
|
302
|
-
return httpClient;
|
|
337
|
+
async curl<T = any>(url: HttpClientRequestURL, options?: HttpClientRequestOptions): Promise<HttpClientResponse<T>> {
|
|
338
|
+
return await this.httpClient.request<T>(url, options);
|
|
303
339
|
}
|
|
304
340
|
|
|
305
341
|
/**
|
|
@@ -307,31 +343,32 @@ class EggApplication extends EggCore {
|
|
|
307
343
|
* @see https://github.com/node-modules/urllib
|
|
308
344
|
* @member {HttpClient}
|
|
309
345
|
*/
|
|
310
|
-
get
|
|
311
|
-
if (!this
|
|
312
|
-
this
|
|
346
|
+
get httpClient() {
|
|
347
|
+
if (!this.#httpClient) {
|
|
348
|
+
this.#httpClient = new this.HttpClient(this);
|
|
313
349
|
}
|
|
314
|
-
return this
|
|
350
|
+
return this.#httpClient;
|
|
315
351
|
}
|
|
316
352
|
|
|
317
353
|
/**
|
|
318
|
-
* @
|
|
354
|
+
* @deprecated please use httpClient instead
|
|
355
|
+
* @alias httpClient
|
|
319
356
|
* @member {HttpClient}
|
|
320
357
|
*/
|
|
321
|
-
get
|
|
322
|
-
return this.
|
|
358
|
+
get httpclient() {
|
|
359
|
+
return this.httpClient;
|
|
323
360
|
}
|
|
324
361
|
|
|
325
362
|
/**
|
|
326
|
-
*
|
|
363
|
+
* All loggers contain logger, coreLogger and customLogger
|
|
327
364
|
* @member {Object}
|
|
328
365
|
* @since 1.0.0
|
|
329
366
|
*/
|
|
330
367
|
get loggers() {
|
|
331
|
-
if (!this
|
|
332
|
-
this
|
|
368
|
+
if (!this.#loggers) {
|
|
369
|
+
this.#loggers = createLoggers(this);
|
|
333
370
|
}
|
|
334
|
-
return this
|
|
371
|
+
return this.#loggers;
|
|
335
372
|
}
|
|
336
373
|
|
|
337
374
|
/**
|
|
@@ -340,7 +377,7 @@ class EggApplication extends EggCore {
|
|
|
340
377
|
* @param {String} name - logger name
|
|
341
378
|
* @return {Logger} logger
|
|
342
379
|
*/
|
|
343
|
-
getLogger(name) {
|
|
380
|
+
getLogger(name: string): EggLogger {
|
|
344
381
|
return this.loggers[name] || null;
|
|
345
382
|
}
|
|
346
383
|
|
|
@@ -362,7 +399,7 @@ class EggApplication extends EggCore {
|
|
|
362
399
|
return this.getLogger('coreLogger');
|
|
363
400
|
}
|
|
364
401
|
|
|
365
|
-
_unhandledRejectionHandler(err) {
|
|
402
|
+
_unhandledRejectionHandler(err: any) {
|
|
366
403
|
if (!(err instanceof Error)) {
|
|
367
404
|
const newError = new Error(String(err));
|
|
368
405
|
// err maybe an object, try to copy the name, message and stack to the new error instance
|
|
@@ -384,21 +421,23 @@ class EggApplication extends EggCore {
|
|
|
384
421
|
/**
|
|
385
422
|
* dump out the config and meta object
|
|
386
423
|
* @private
|
|
387
|
-
* @return {Object} the result
|
|
388
424
|
*/
|
|
389
425
|
dumpConfigToObject() {
|
|
390
|
-
let ignoreList;
|
|
426
|
+
let ignoreList: (string | RegExp)[];
|
|
391
427
|
try {
|
|
392
428
|
// support array and set
|
|
393
429
|
ignoreList = Array.from(this.config.dump.ignore);
|
|
394
430
|
} catch (_) {
|
|
395
431
|
ignoreList = [];
|
|
396
432
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
433
|
+
const config = extend(true, {}, {
|
|
434
|
+
config: this.config,
|
|
435
|
+
plugins: this.loader.allPlugins,
|
|
436
|
+
appInfo: this.loader.appInfo,
|
|
437
|
+
});
|
|
438
|
+
convertObject(config, ignoreList);
|
|
400
439
|
return {
|
|
401
|
-
config
|
|
440
|
+
config,
|
|
402
441
|
meta: this.loader.configMeta,
|
|
403
442
|
};
|
|
404
443
|
}
|
|
@@ -410,10 +449,11 @@ class EggApplication extends EggCore {
|
|
|
410
449
|
dumpConfig() {
|
|
411
450
|
const rundir = this.config.rundir;
|
|
412
451
|
try {
|
|
413
|
-
|
|
414
|
-
|
|
452
|
+
if (!fs.existsSync(rundir)) {
|
|
453
|
+
fs.mkdirSync(rundir);
|
|
454
|
+
}
|
|
415
455
|
|
|
416
|
-
// get
|
|
456
|
+
// get dumped object
|
|
417
457
|
const { config, meta } = this.dumpConfigToObject();
|
|
418
458
|
|
|
419
459
|
// dump config
|
|
@@ -423,8 +463,8 @@ class EggApplication extends EggCore {
|
|
|
423
463
|
// dump config meta
|
|
424
464
|
const dumpMetaFile = path.join(rundir, `${this.type}_config_meta.json`);
|
|
425
465
|
fs.writeFileSync(dumpMetaFile, CircularJSON.stringify(meta, null, 2));
|
|
426
|
-
} catch (err) {
|
|
427
|
-
this.coreLogger.warn(`dumpConfig error: ${err.message}`);
|
|
466
|
+
} catch (err: any) {
|
|
467
|
+
this.coreLogger.warn(`[egg] dumpConfig error: ${err.message}`);
|
|
428
468
|
}
|
|
429
469
|
}
|
|
430
470
|
|
|
@@ -437,24 +477,29 @@ class EggApplication extends EggCore {
|
|
|
437
477
|
this.coreLogger.info(this.timing.toString());
|
|
438
478
|
// only disable, not clear bootstrap timing data.
|
|
439
479
|
this.timing.disable();
|
|
440
|
-
// show duration >= ${slowBootActionMinDuration}ms action to
|
|
480
|
+
// show duration >= ${slowBootActionMinDuration}ms action to warning log
|
|
441
481
|
for (const item of items) {
|
|
442
482
|
// ignore #0 name: Process Start
|
|
443
|
-
if (item.index > 0 && item.duration >= this.config.dump.timing.slowBootActionMinDuration) {
|
|
444
|
-
this.coreLogger.warn('[egg
|
|
483
|
+
if (item.index > 0 && item.duration && item.duration >= this.config.dump.timing.slowBootActionMinDuration) {
|
|
484
|
+
this.coreLogger.warn('[egg][dumpTiming][slow-boot-action] #%d %dms, name: %s',
|
|
445
485
|
item.index, item.duration, item.name);
|
|
446
486
|
}
|
|
447
487
|
}
|
|
448
|
-
} catch (err) {
|
|
449
|
-
this.coreLogger.warn(`dumpTiming error: ${err.message}`);
|
|
488
|
+
} catch (err: any) {
|
|
489
|
+
this.coreLogger.warn(`[egg] dumpTiming error: ${err.message}`);
|
|
450
490
|
}
|
|
451
491
|
}
|
|
452
492
|
|
|
453
493
|
get [EGG_PATH]() {
|
|
454
|
-
|
|
494
|
+
if (typeof __dirname !== 'undefined') {
|
|
495
|
+
return path.dirname(__dirname);
|
|
496
|
+
}
|
|
497
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
498
|
+
// @ts-ignore
|
|
499
|
+
return path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
|
455
500
|
}
|
|
456
501
|
|
|
457
|
-
|
|
502
|
+
#setupTimeoutTimer() {
|
|
458
503
|
const startTimeoutTimer = setTimeout(() => {
|
|
459
504
|
this.coreLogger.error(this.timing.toString());
|
|
460
505
|
this.coreLogger.error(`${this.type} still doesn't ready after ${this.config.workerStartTimeout} ms.`);
|
|
@@ -464,7 +509,8 @@ class EggApplication extends EggCore {
|
|
|
464
509
|
if (item.end) continue;
|
|
465
510
|
this.coreLogger.error(`unfinished timing item: ${CircularJSON.stringify(item)}`);
|
|
466
511
|
}
|
|
467
|
-
this.coreLogger.error(
|
|
512
|
+
this.coreLogger.error('[egg][setupTimeoutTimer] check run/%s_timing_%s.json for more details.',
|
|
513
|
+
this.type, process.pid);
|
|
468
514
|
this.emit('startTimeout');
|
|
469
515
|
this.dumpConfig();
|
|
470
516
|
this.dumpTiming();
|
|
@@ -472,6 +518,10 @@ class EggApplication extends EggCore {
|
|
|
472
518
|
this.ready(() => clearTimeout(startTimeoutTimer));
|
|
473
519
|
}
|
|
474
520
|
|
|
521
|
+
get config() {
|
|
522
|
+
return super.config as EggAppConfig;
|
|
523
|
+
}
|
|
524
|
+
|
|
475
525
|
/**
|
|
476
526
|
* app.env delegate app.config.env
|
|
477
527
|
* @deprecated
|
|
@@ -499,11 +549,12 @@ class EggApplication extends EggCore {
|
|
|
499
549
|
* @param {String} name - unique name for singleton
|
|
500
550
|
* @param {Function|AsyncFunction} create - method will be invoked when singleton instance create
|
|
501
551
|
*/
|
|
502
|
-
addSingleton(name, create) {
|
|
503
|
-
const options = {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
552
|
+
addSingleton(name: string, create: SingletonCreateMethod) {
|
|
553
|
+
const options: SingletonOptions = {
|
|
554
|
+
name,
|
|
555
|
+
create,
|
|
556
|
+
app: this,
|
|
557
|
+
};
|
|
507
558
|
const singleton = new Singleton(options);
|
|
508
559
|
const initPromise = singleton.init();
|
|
509
560
|
if (initPromise) {
|
|
@@ -513,12 +564,11 @@ class EggApplication extends EggCore {
|
|
|
513
564
|
}
|
|
514
565
|
}
|
|
515
566
|
|
|
516
|
-
|
|
517
|
-
const
|
|
518
|
-
client.create = (...args) => {
|
|
519
|
-
const realClient =
|
|
520
|
-
this
|
|
521
|
-
this.beforeClose(() => cluster.close(realClient));
|
|
567
|
+
#patchClusterClient(client: any) {
|
|
568
|
+
const rawCreate = client.create;
|
|
569
|
+
client.create = (...args: any) => {
|
|
570
|
+
const realClient = rawCreate.apply(client, args);
|
|
571
|
+
this.#clusterClients.push(realClient);
|
|
522
572
|
return realClient;
|
|
523
573
|
};
|
|
524
574
|
}
|
|
@@ -530,8 +580,8 @@ class EggApplication extends EggCore {
|
|
|
530
580
|
* @param {Request} [req] - if you want to mock request like querystring, you can pass an object to this function.
|
|
531
581
|
* @return {Context} context
|
|
532
582
|
*/
|
|
533
|
-
createAnonymousContext(req) {
|
|
534
|
-
const request = {
|
|
583
|
+
createAnonymousContext(req?: any): EggCoreContext {
|
|
584
|
+
const request: any = {
|
|
535
585
|
headers: {
|
|
536
586
|
host: '127.0.0.1',
|
|
537
587
|
'x-forwarded-for': '127.0.0.1',
|
|
@@ -570,36 +620,20 @@ class EggApplication extends EggCore {
|
|
|
570
620
|
* @param {Res} res - node native Response object
|
|
571
621
|
* @return {Context} context object
|
|
572
622
|
*/
|
|
573
|
-
createContext(req, res) {
|
|
574
|
-
const
|
|
575
|
-
const context = Object.create(
|
|
576
|
-
const
|
|
577
|
-
|
|
578
|
-
context.app = request.app = response.app = app;
|
|
623
|
+
createContext(req: IncomingMessage, res: ServerResponse): EggContext {
|
|
624
|
+
const context = Object.create(this.context) as EggContext;
|
|
625
|
+
const request = context.request = Object.create(this.request);
|
|
626
|
+
const response = context.response = Object.create(this.response);
|
|
627
|
+
context.app = request.app = response.app = this;
|
|
579
628
|
context.req = request.req = response.req = req;
|
|
580
629
|
context.res = request.res = response.res = res;
|
|
581
630
|
request.ctx = response.ctx = context;
|
|
582
631
|
request.response = response;
|
|
583
632
|
response.request = request;
|
|
584
633
|
context.onerror = context.onerror.bind(context);
|
|
585
|
-
context.originalUrl = request.originalUrl = req.url;
|
|
586
|
-
|
|
587
|
-
/**
|
|
588
|
-
* Request start time
|
|
589
|
-
* @member {Number} Context#starttime
|
|
590
|
-
*/
|
|
634
|
+
context.originalUrl = request.originalUrl = req.url as string;
|
|
591
635
|
context.starttime = Date.now();
|
|
592
|
-
|
|
593
|
-
if (this.config.logger.enablePerformanceTimer) {
|
|
594
|
-
/**
|
|
595
|
-
* Request start timer using `performance.now()`
|
|
596
|
-
* @member {Number} Context#performanceStarttime
|
|
597
|
-
*/
|
|
598
|
-
context.performanceStarttime = performance.now();
|
|
599
|
-
}
|
|
636
|
+
context.performanceStarttime = performance.now();
|
|
600
637
|
return context;
|
|
601
638
|
}
|
|
602
|
-
|
|
603
639
|
}
|
|
604
|
-
|
|
605
|
-
module.exports = EggApplication;
|