egg 3.29.0 → 4.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/README.md +2 -1
  2. package/README.zh-CN.md +7 -5
  3. package/dist/commonjs/agent.d.ts +4 -0
  4. package/dist/commonjs/agent.js +10 -0
  5. package/dist/commonjs/app/extend/context.d.ts +154 -0
  6. package/dist/commonjs/app/extend/context.js +261 -0
  7. package/dist/commonjs/app/extend/context.types.d.ts +16 -0
  8. package/dist/commonjs/app/extend/context.types.js +3 -0
  9. package/dist/commonjs/app/extend/helper.d.ts +37 -0
  10. package/dist/commonjs/app/extend/helper.js +49 -0
  11. package/dist/commonjs/app/extend/request.d.ts +128 -0
  12. package/dist/commonjs/app/extend/request.js +270 -0
  13. package/dist/commonjs/app/extend/response.d.ts +25 -0
  14. package/dist/commonjs/app/extend/response.js +37 -0
  15. package/dist/commonjs/app/middleware/body_parser.d.ts +2 -0
  16. package/dist/commonjs/app/middleware/body_parser.js +8 -0
  17. package/dist/commonjs/app/middleware/meta.d.ts +10 -0
  18. package/dist/commonjs/app/middleware/meta.js +22 -0
  19. package/dist/commonjs/app/middleware/notfound.d.ts +7 -0
  20. package/dist/commonjs/app/middleware/notfound.js +31 -0
  21. package/dist/commonjs/app/middleware/override_method.d.ts +2 -0
  22. package/dist/commonjs/app/middleware/override_method.js +8 -0
  23. package/dist/commonjs/app/middleware/site_file.d.ts +9 -0
  24. package/dist/commonjs/app/middleware/site_file.js +58 -0
  25. package/dist/commonjs/config/config.default.d.ts +9 -0
  26. package/dist/commonjs/config/config.default.js +379 -0
  27. package/dist/commonjs/config/config.local.d.ts +8 -0
  28. package/dist/commonjs/config/config.local.js +12 -0
  29. package/dist/commonjs/config/config.unittest.d.ts +7 -0
  30. package/dist/commonjs/config/config.unittest.js +11 -0
  31. package/dist/commonjs/config/plugin.d.ts +122 -0
  32. package/dist/commonjs/config/plugin.js +125 -0
  33. package/dist/commonjs/index.d.ts +63 -0
  34. package/dist/commonjs/index.js +91 -0
  35. package/dist/commonjs/lib/agent.d.ts +19 -0
  36. package/dist/commonjs/lib/agent.js +58 -0
  37. package/dist/commonjs/lib/application.d.ts +59 -0
  38. package/dist/commonjs/lib/application.js +270 -0
  39. package/dist/commonjs/lib/core/base_context_class.d.ts +14 -0
  40. package/dist/commonjs/lib/core/base_context_class.js +22 -0
  41. package/dist/commonjs/lib/core/base_context_logger.d.ts +36 -0
  42. package/dist/commonjs/lib/core/base_context_logger.js +64 -0
  43. package/dist/commonjs/lib/core/base_hook_class.d.ts +11 -0
  44. package/dist/commonjs/lib/core/base_hook_class.js +30 -0
  45. package/dist/commonjs/lib/core/context_httpclient.d.ts +16 -0
  46. package/dist/commonjs/lib/core/context_httpclient.js +30 -0
  47. package/dist/commonjs/lib/core/httpclient.d.ts +13 -0
  48. package/dist/commonjs/lib/core/httpclient.js +37 -0
  49. package/dist/commonjs/lib/core/logger.d.ts +3 -0
  50. package/dist/commonjs/lib/core/logger.js +40 -0
  51. package/dist/commonjs/lib/core/messenger/IMessenger.d.ts +50 -0
  52. package/dist/commonjs/lib/core/messenger/IMessenger.js +3 -0
  53. package/dist/commonjs/lib/core/messenger/index.d.ts +7 -0
  54. package/dist/commonjs/lib/core/messenger/index.js +14 -0
  55. package/dist/commonjs/lib/core/messenger/ipc.d.ts +59 -0
  56. package/dist/commonjs/lib/core/messenger/ipc.js +137 -0
  57. package/dist/commonjs/lib/core/messenger/local.d.ts +61 -0
  58. package/dist/commonjs/lib/core/messenger/local.js +137 -0
  59. package/dist/commonjs/lib/core/singleton.d.ts +23 -0
  60. package/dist/commonjs/lib/core/singleton.js +120 -0
  61. package/dist/commonjs/lib/core/utils.d.ts +2 -0
  62. package/dist/commonjs/lib/core/utils.js +77 -0
  63. package/dist/commonjs/lib/egg.d.ts +276 -0
  64. package/dist/commonjs/lib/egg.js +617 -0
  65. package/dist/commonjs/lib/egg.types.d.ts +6 -0
  66. package/dist/commonjs/lib/egg.types.js +3 -0
  67. package/dist/commonjs/lib/loader/AgentWorkerLoader.d.ts +12 -0
  68. package/dist/commonjs/lib/loader/AgentWorkerLoader.js +24 -0
  69. package/dist/commonjs/lib/loader/AppWorkerLoader.d.ts +17 -0
  70. package/dist/commonjs/lib/loader/AppWorkerLoader.js +43 -0
  71. package/dist/commonjs/lib/loader/EggApplicationLoader.d.ts +4 -0
  72. package/dist/commonjs/lib/loader/EggApplicationLoader.js +8 -0
  73. package/dist/commonjs/lib/loader/index.d.ts +3 -0
  74. package/dist/commonjs/lib/loader/index.js +22 -0
  75. package/dist/commonjs/lib/start.d.ts +15 -0
  76. package/dist/commonjs/lib/start.js +49 -0
  77. package/dist/commonjs/lib/type.d.ts +293 -0
  78. package/dist/commonjs/lib/type.js +3 -0
  79. package/dist/commonjs/lib/utils.d.ts +2 -0
  80. package/dist/commonjs/lib/utils.js +21 -0
  81. package/dist/commonjs/package.json +3 -0
  82. package/dist/esm/agent.d.ts +4 -0
  83. package/dist/esm/agent.js +7 -0
  84. package/dist/esm/app/extend/context.d.ts +154 -0
  85. package/dist/esm/app/extend/context.js +255 -0
  86. package/dist/esm/app/extend/context.types.d.ts +16 -0
  87. package/dist/esm/app/extend/context.types.js +2 -0
  88. package/dist/esm/app/extend/helper.d.ts +37 -0
  89. package/dist/esm/app/extend/helper.js +43 -0
  90. package/dist/esm/app/extend/request.d.ts +128 -0
  91. package/dist/esm/app/extend/request.js +264 -0
  92. package/dist/esm/app/extend/response.d.ts +25 -0
  93. package/dist/esm/app/extend/response.js +34 -0
  94. package/dist/esm/app/middleware/body_parser.d.ts +2 -0
  95. package/dist/esm/app/middleware/body_parser.js +3 -0
  96. package/dist/esm/app/middleware/meta.d.ts +10 -0
  97. package/dist/esm/app/middleware/meta.js +20 -0
  98. package/dist/esm/app/middleware/notfound.d.ts +7 -0
  99. package/dist/esm/app/middleware/notfound.js +29 -0
  100. package/dist/esm/app/middleware/override_method.d.ts +2 -0
  101. package/dist/esm/app/middleware/override_method.js +3 -0
  102. package/dist/esm/app/middleware/site_file.d.ts +9 -0
  103. package/dist/esm/app/middleware/site_file.js +53 -0
  104. package/dist/esm/config/config.default.d.ts +9 -0
  105. package/dist/esm/config/config.default.js +374 -0
  106. package/dist/esm/config/config.local.d.ts +8 -0
  107. package/dist/esm/config/config.local.js +10 -0
  108. package/dist/esm/config/config.unittest.d.ts +7 -0
  109. package/dist/esm/config/config.unittest.js +9 -0
  110. package/dist/esm/config/favicon.png +0 -0
  111. package/dist/esm/config/plugin.d.ts +122 -0
  112. package/dist/esm/config/plugin.js +123 -0
  113. package/dist/esm/index.d.ts +63 -0
  114. package/dist/esm/index.js +66 -0
  115. package/dist/esm/lib/agent.d.ts +19 -0
  116. package/dist/esm/lib/agent.js +54 -0
  117. package/dist/esm/lib/application.d.ts +59 -0
  118. package/dist/esm/lib/application.js +263 -0
  119. package/dist/esm/lib/core/base_context_class.d.ts +14 -0
  120. package/dist/esm/lib/core/base_context_class.js +18 -0
  121. package/dist/esm/lib/core/base_context_logger.d.ts +36 -0
  122. package/dist/esm/lib/core/base_context_logger.js +60 -0
  123. package/dist/esm/lib/core/base_hook_class.d.ts +11 -0
  124. package/dist/esm/lib/core/base_hook_class.js +23 -0
  125. package/dist/esm/lib/core/context_httpclient.d.ts +16 -0
  126. package/dist/esm/lib/core/context_httpclient.js +26 -0
  127. package/dist/esm/lib/core/httpclient.d.ts +13 -0
  128. package/dist/esm/lib/core/httpclient.js +33 -0
  129. package/dist/esm/lib/core/logger.d.ts +3 -0
  130. package/dist/esm/lib/core/logger.js +37 -0
  131. package/dist/esm/lib/core/messenger/IMessenger.d.ts +50 -0
  132. package/dist/esm/lib/core/messenger/IMessenger.js +2 -0
  133. package/dist/esm/lib/core/messenger/index.d.ts +7 -0
  134. package/dist/esm/lib/core/messenger/index.js +11 -0
  135. package/dist/esm/lib/core/messenger/ipc.d.ts +59 -0
  136. package/dist/esm/lib/core/messenger/ipc.js +130 -0
  137. package/dist/esm/lib/core/messenger/local.d.ts +61 -0
  138. package/dist/esm/lib/core/messenger/local.js +130 -0
  139. package/dist/esm/lib/core/singleton.d.ts +23 -0
  140. package/dist/esm/lib/core/singleton.js +113 -0
  141. package/dist/esm/lib/core/utils.d.ts +2 -0
  142. package/dist/esm/lib/core/utils.js +70 -0
  143. package/dist/esm/lib/egg.d.ts +276 -0
  144. package/dist/esm/lib/egg.js +574 -0
  145. package/dist/esm/lib/egg.types.d.ts +6 -0
  146. package/dist/esm/lib/egg.types.js +2 -0
  147. package/dist/esm/lib/loader/AgentWorkerLoader.d.ts +12 -0
  148. package/dist/esm/lib/loader/AgentWorkerLoader.js +20 -0
  149. package/dist/esm/lib/loader/AppWorkerLoader.d.ts +17 -0
  150. package/dist/esm/lib/loader/AppWorkerLoader.js +39 -0
  151. package/dist/esm/lib/loader/EggApplicationLoader.d.ts +4 -0
  152. package/dist/esm/lib/loader/EggApplicationLoader.js +4 -0
  153. package/dist/esm/lib/loader/index.d.ts +3 -0
  154. package/dist/esm/lib/loader/index.js +4 -0
  155. package/dist/esm/lib/start.d.ts +15 -0
  156. package/dist/esm/lib/start.js +43 -0
  157. package/dist/esm/lib/type.d.ts +293 -0
  158. package/dist/esm/lib/type.js +2 -0
  159. package/dist/esm/lib/utils.d.ts +2 -0
  160. package/dist/esm/lib/utils.js +14 -0
  161. package/dist/esm/package.json +3 -0
  162. package/dist/package.json +4 -0
  163. package/package.json +97 -79
  164. package/src/agent.ts +7 -0
  165. package/src/app/extend/context.ts +303 -0
  166. package/src/app/extend/context.types.ts +24 -0
  167. package/{app/extend/helper.js → src/app/extend/helper.ts} +14 -13
  168. package/{app/extend/request.js → src/app/extend/request.ts} +81 -79
  169. package/src/app/extend/response.ts +36 -0
  170. package/src/app/middleware/body_parser.ts +3 -0
  171. package/{app/middleware/meta.js → src/app/middleware/meta.ts} +11 -4
  172. package/{app/middleware/notfound.js → src/app/middleware/notfound.ts} +8 -3
  173. package/src/app/middleware/override_method.ts +3 -0
  174. package/src/app/middleware/site_file.ts +68 -0
  175. package/{config/config.default.js → src/config/config.default.ts} +25 -45
  176. package/src/config/config.local.ts +11 -0
  177. package/src/config/config.unittest.ts +10 -0
  178. package/src/config/favicon.png +0 -0
  179. package/{config/plugin.js → src/config/plugin.ts} +3 -5
  180. package/src/index.ts +80 -0
  181. package/src/lib/agent.ts +66 -0
  182. package/{lib/application.js → src/lib/application.ts} +76 -124
  183. package/src/lib/core/base_context_class.ts +21 -0
  184. package/src/lib/core/base_context_logger.ts +67 -0
  185. package/src/lib/core/base_hook_class.ts +30 -0
  186. package/src/lib/core/context_httpclient.ts +33 -0
  187. package/src/lib/core/httpclient.ts +51 -0
  188. package/src/lib/core/logger.ts +42 -0
  189. package/src/lib/core/messenger/IMessenger.ts +58 -0
  190. package/src/lib/core/messenger/index.ts +15 -0
  191. package/src/lib/core/messenger/ipc.ts +148 -0
  192. package/{lib/core/messenger/local.js → src/lib/core/messenger/local.ts} +36 -28
  193. package/{lib/core/singleton.js → src/lib/core/singleton.ts} +56 -33
  194. package/src/lib/core/utils.ts +77 -0
  195. package/{lib/egg.js → src/lib/egg.ts} +287 -221
  196. package/src/lib/egg.types.ts +6 -0
  197. package/src/lib/loader/AgentWorkerLoader.ts +21 -0
  198. package/src/lib/loader/AppWorkerLoader.ts +42 -0
  199. package/src/lib/loader/EggApplicationLoader.ts +5 -0
  200. package/src/lib/loader/index.ts +3 -0
  201. package/src/lib/start.ts +56 -0
  202. package/src/lib/type.ts +329 -0
  203. package/src/lib/utils.ts +16 -0
  204. package/CHANGELOG.md +0 -2395
  205. package/History.md +0 -52
  206. package/agent.js +0 -11
  207. package/app/extend/context.js +0 -285
  208. package/app/extend/response.js +0 -101
  209. package/app/middleware/body_parser.js +0 -3
  210. package/app/middleware/override_method.js +0 -3
  211. package/app/middleware/site_file.js +0 -31
  212. package/config/config.local.js +0 -7
  213. package/config/config.unittest.js +0 -8
  214. package/index.d.ts +0 -1288
  215. package/index.js +0 -68
  216. package/lib/agent.js +0 -95
  217. package/lib/core/base_context_class.js +0 -20
  218. package/lib/core/base_context_logger.js +0 -64
  219. package/lib/core/base_hook_class.js +0 -31
  220. package/lib/core/context_httpclient.js +0 -26
  221. package/lib/core/dnscache_httpclient.js +0 -93
  222. package/lib/core/httpclient.js +0 -119
  223. package/lib/core/httpclient_next.js +0 -80
  224. package/lib/core/logger.js +0 -35
  225. package/lib/core/messenger/index.js +0 -14
  226. package/lib/core/messenger/ipc.js +0 -141
  227. package/lib/core/utils.js +0 -73
  228. package/lib/loader/agent_worker_loader.js +0 -27
  229. package/lib/loader/app_worker_loader.js +0 -48
  230. package/lib/loader/index.js +0 -5
  231. package/lib/start.js +0 -39
  232. /package/{config → dist/commonjs/config}/favicon.png +0 -0
@@ -0,0 +1,51 @@
1
+ import {
2
+ HttpClient as RawHttpClient,
3
+ RequestURL as HttpClientRequestURL,
4
+ RequestOptions,
5
+ } from 'urllib';
6
+ import { ms } from 'humanize-ms';
7
+ import type { EggApplicationCore, ContextDelegation } from '../egg.js';
8
+
9
+ export type {
10
+ HttpClientResponse,
11
+ RequestURL as HttpClientRequestURL,
12
+ } from 'urllib';
13
+
14
+ export interface HttpClientRequestOptions extends RequestOptions {
15
+ ctx?: ContextDelegation;
16
+ tracer?: unknown;
17
+ }
18
+
19
+ export class HttpClient extends RawHttpClient {
20
+ readonly #app: EggApplicationCore & { tracer?: unknown };
21
+
22
+ constructor(app: EggApplicationCore) {
23
+ normalizeConfig(app);
24
+ const config = app.config.httpclient;
25
+ super({
26
+ defaultArgs: config.request,
27
+ });
28
+ this.#app = app;
29
+ }
30
+
31
+ async request<T = any>(url: HttpClientRequestURL, options?: HttpClientRequestOptions) {
32
+ options = options ?? {};
33
+ if (options.ctx?.tracer) {
34
+ options.tracer = options.ctx.tracer;
35
+ } else {
36
+ options.tracer = options.tracer ?? this.#app.tracer;
37
+ }
38
+ return await super.request<T>(url, options);
39
+ }
40
+
41
+ async curl<T = any>(url: HttpClientRequestURL, options?: HttpClientRequestOptions) {
42
+ return await this.request<T>(url, options);
43
+ }
44
+ }
45
+
46
+ function normalizeConfig(app: EggApplicationCore) {
47
+ const config = app.config.httpclient;
48
+ if (typeof config.request?.timeout === 'string') {
49
+ config.request.timeout = ms(config.request.timeout);
50
+ }
51
+ }
@@ -0,0 +1,42 @@
1
+ import { EggLoggers, EggLoggersOptions } from 'egg-logger';
2
+ import { setCustomLogger } from 'onelogger';
3
+ import type { EggApplicationCore } from '../egg.js';
4
+
5
+ export function createLoggers(app: EggApplicationCore) {
6
+ const loggerOptions = {
7
+ ...app.config.logger,
8
+ type: app.type,
9
+ localStorage: app.ctxStorage,
10
+ } as EggLoggersOptions;
11
+
12
+ // set DEBUG level into INFO on prod env
13
+ if (app.config.env === 'prod' && loggerOptions.level === 'DEBUG' && !app.config.logger.allowDebugAtProd) {
14
+ loggerOptions.level = 'INFO';
15
+ }
16
+
17
+ const loggers = new EggLoggers({
18
+ logger: loggerOptions,
19
+ customLogger: app.config.customLogger,
20
+ });
21
+
22
+ // won't print to console after started, except for local and unittest
23
+ app.ready(() => {
24
+ if (app.config.logger.disableConsoleAfterReady) {
25
+ loggers.disableConsole();
26
+ loggers.coreLogger.info('[egg:lib:core:logger] disable console log after app ready');
27
+ }
28
+ });
29
+
30
+ // set global logger
31
+ for (const loggerName of Object.keys(loggers)) {
32
+ setCustomLogger(loggerName, loggers[loggerName]);
33
+ }
34
+ // reset global logger on beforeClose hook
35
+ app.lifecycle.registerBeforeClose(() => {
36
+ for (const loggerName of Object.keys(loggers)) {
37
+ setCustomLogger(loggerName, undefined);
38
+ }
39
+ });
40
+ loggers.coreLogger.info('[egg:lib:core:logger] init all loggers with options: %j', loggerOptions);
41
+ return loggers;
42
+ }
@@ -0,0 +1,58 @@
1
+ import type { EventEmitter } from 'node:events';
2
+
3
+ export interface IMessenger extends EventEmitter {
4
+ /**
5
+ * Send message to all agent and app
6
+ * @param {String} action - message key
7
+ * @param {Object} data - message value
8
+ * @return {Messenger} this
9
+ */
10
+ broadcast(action: string, data?: unknown): IMessenger;
11
+
12
+ /**
13
+ * send message to the specified process
14
+ * @param {String} workerId - the workerId of the receiver
15
+ * @param {String} action - message key
16
+ * @param {Object} data - message value
17
+ * @return {Messenger} this
18
+ */
19
+ sendTo(workerId: string, action: string, data?: unknown): IMessenger;
20
+
21
+ /**
22
+ * send message to one app worker by random
23
+ * - if it's running in agent, it will send to one of app workers
24
+ * - if it's running in app, it will send to agent
25
+ * @param {String} action - message key
26
+ * @param {Object} data - message value
27
+ * @return {Messenger} this
28
+ */
29
+ sendRandom(action: string, data?: unknown): IMessenger;
30
+
31
+ /**
32
+ * send message to app
33
+ * @param {String} action - message key
34
+ * @param {Object} data - message value
35
+ * @return {Messenger} this
36
+ */
37
+ sendToApp(action: string, data?: unknown): IMessenger;
38
+
39
+ /**
40
+ * send message to agent
41
+ * @param {String} action - message key
42
+ * @param {Object} data - message value
43
+ * @return {Messenger} this
44
+ */
45
+ sendToAgent(action: string, data?: unknown): IMessenger;
46
+
47
+ /**
48
+ * @param {String} action - message key
49
+ * @param {Object} data - message value
50
+ * @param {String} to - let master know how to send message
51
+ * @return {Messenger} this
52
+ */
53
+ send(action: string, data: unknown | undefined, to?: string): IMessenger;
54
+
55
+ close(): void;
56
+
57
+ onMessage(message: any): void;
58
+ }
@@ -0,0 +1,15 @@
1
+ import { Messenger as LocalMessenger } from './local.js';
2
+ import { Messenger as IPCMessenger } from './ipc.js';
3
+ import type { IMessenger } from './IMessenger.js';
4
+ import type { EggApplicationCore } from '../../egg.js';
5
+
6
+ export type { IMessenger } from './IMessenger.js';
7
+
8
+ /**
9
+ * @class Messenger
10
+ */
11
+ export function create(egg: EggApplicationCore): IMessenger {
12
+ return egg.options.mode === 'single'
13
+ ? new LocalMessenger(egg)
14
+ : new IPCMessenger(egg);
15
+ }
@@ -0,0 +1,148 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { debuglog } from 'node:util';
3
+ import workerThreads from 'node:worker_threads';
4
+ import { sendmessage } from 'sendmessage';
5
+ import type { IMessenger } from './IMessenger.js';
6
+ import type { EggApplicationCore } from '../../egg.js';
7
+
8
+ const debug = debuglog('egg/lib/core/messenger/ipc');
9
+
10
+ /**
11
+ * Communication between app worker and agent worker by IPC channel
12
+ */
13
+ export class Messenger extends EventEmitter implements IMessenger {
14
+ readonly pid: string;
15
+ readonly egg: EggApplicationCore;
16
+ opids: string[] = [];
17
+
18
+ constructor(egg: EggApplicationCore) {
19
+ super();
20
+ this.pid = String(process.pid);
21
+ this.egg = egg;
22
+ // pids of agent or app managed by master
23
+ // - retrieve app worker pids when it's an agent worker
24
+ // - retrieve agent worker pids when it's an app worker
25
+ this.on('egg-pids', workerIds => {
26
+ debug('[%s:%s] got egg-pids %j', this.egg.type, this.pid, workerIds);
27
+ this.opids = workerIds.map((workerId: number) => String(workerId));
28
+ });
29
+ this.onMessage = this.onMessage.bind(this);
30
+ process.on('message', this.onMessage);
31
+ if (!workerThreads.isMainThread) {
32
+ workerThreads.parentPort!.on('message', this.onMessage);
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Send message to all agent and app
38
+ * @param {String} action - message key
39
+ * @param {Object} data - message value
40
+ * @return {Messenger} this
41
+ */
42
+ broadcast(action: string, data?: unknown): Messenger {
43
+ debug('[%s:%s] broadcast %s with %j', this.egg.type, this.pid, action, data);
44
+ this.send(action, data, 'app');
45
+ this.send(action, data, 'agent');
46
+ return this;
47
+ }
48
+
49
+ /**
50
+ * send message to the specified process
51
+ * @param {String} workerId - the workerId of the receiver
52
+ * @param {String} action - message key
53
+ * @param {Object} data - message value
54
+ * @return {Messenger} this
55
+ */
56
+ sendTo(workerId: string, action: string, data?: unknown): Messenger {
57
+ debug('[%s:%s] send %s with %j to workerId:%s', this.egg.type, this.pid, action, data, workerId);
58
+ sendmessage(process, {
59
+ action,
60
+ data,
61
+ /**
62
+ * @deprecated Keep compatible, please use receiverWorkerId instead
63
+ */
64
+ receiverPid: String(workerId),
65
+ receiverWorkerId: String(workerId),
66
+ });
67
+ return this;
68
+ }
69
+
70
+ /**
71
+ * send message to one app worker by random
72
+ * - if it's running in agent, it will send to one of app workers
73
+ * - if it's running in app, it will send to agent
74
+ * @param {String} action - message key
75
+ * @param {Object} data - message value
76
+ * @return {Messenger} this
77
+ */
78
+ sendRandom(action: string, data?: unknown): Messenger {
79
+ if (this.opids.length === 0) {
80
+ debug('[%s:%s] no pids, ignore sendRandom %s with %j', this.egg.type, this.pid, action, data);
81
+ return this;
82
+ }
83
+ const index = Math.floor(Math.random() * this.opids.length);
84
+ const workerId = this.opids[index];
85
+ this.sendTo(workerId, action, data);
86
+ return this;
87
+ }
88
+
89
+ /**
90
+ * send message to app
91
+ * @param {String} action - message key
92
+ * @param {Object} data - message value
93
+ * @return {Messenger} this
94
+ */
95
+ sendToApp(action: string, data?: unknown): Messenger {
96
+ debug('[%s:%s] send %s with %j to all app', this.egg.type, this.pid, action, data);
97
+ this.send(action, data, 'app');
98
+ return this;
99
+ }
100
+
101
+ /**
102
+ * send message to agent
103
+ * @param {String} action - message key
104
+ * @param {Object} data - message value
105
+ * @return {Messenger} this
106
+ */
107
+ sendToAgent(action: string, data?: unknown): Messenger {
108
+ debug('[%s:%s] send %s with %j to all agent', this.egg.type, this.pid, action, data);
109
+ this.send(action, data, 'agent');
110
+ return this;
111
+ }
112
+
113
+ /**
114
+ * @param {String} action - message key
115
+ * @param {Object} data - message value
116
+ * @param {String} to - let master know how to send message
117
+ * @return {Messenger} this
118
+ */
119
+ send(action: string, data: unknown | undefined, to?: string): Messenger {
120
+ sendmessage(process, {
121
+ action,
122
+ data,
123
+ to,
124
+ });
125
+ return this;
126
+ }
127
+
128
+ onMessage(message: any) {
129
+ if (typeof message?.action === 'string') {
130
+ debug('[%s:%s] got message %s with %j, receiverWorkerId: %s',
131
+ this.egg.type, this.pid, message.action, message.data, message.receiverWorkerId ?? message.receiverPid);
132
+ this.emit(message.action, message.data);
133
+ } else {
134
+ debug('[%s:%s] got an invalid message %j', this.egg.type, this.pid, message);
135
+ }
136
+ }
137
+
138
+ close() {
139
+ process.removeListener('message', this.onMessage);
140
+ this.removeAllListeners();
141
+ }
142
+
143
+ /**
144
+ * @function Messenger#on
145
+ * @param {String} action - message key
146
+ * @param {Object} data - message value
147
+ */
148
+ }
@@ -1,17 +1,21 @@
1
- 'use strict';
1
+ import { debuglog } from 'node:util';
2
+ import EventEmitter from 'node:events';
3
+ import type { IMessenger } from './IMessenger.js';
4
+ import type { EggApplicationCore } from '../../egg.js';
2
5
 
3
- const debug = require('util').debuglog('egg:util:messenger:local');
4
- const is = require('is-type-of');
5
- const EventEmitter = require('events');
6
+ const debug = debuglog('egg/lib/core/messenger/local');
6
7
 
7
8
  /**
8
9
  * Communication between app worker and agent worker with EventEmitter
9
10
  */
10
- class Messenger extends EventEmitter {
11
+ export class Messenger extends EventEmitter implements IMessenger {
12
+ readonly pid: string;
13
+ readonly egg: EggApplicationCore;
11
14
 
12
- constructor(egg) {
15
+ constructor(egg: EggApplicationCore) {
13
16
  super();
14
17
  this.egg = egg;
18
+ this.pid = String(process.pid);
15
19
  }
16
20
 
17
21
  /**
@@ -20,8 +24,8 @@ class Messenger extends EventEmitter {
20
24
  * @param {Object} data - message value
21
25
  * @return {Messenger} this
22
26
  */
23
- broadcast(action, data) {
24
- debug('[%s] broadcast %s with %j', this.pid, action, data);
27
+ broadcast(action: string, data?: unknown): Messenger {
28
+ debug('[%s:%s] broadcast %s with %j', this.egg.type, this.pid, action, data);
25
29
  this.send(action, data, 'both');
26
30
  return this;
27
31
  }
@@ -30,14 +34,16 @@ class Messenger extends EventEmitter {
30
34
  * send message to the specified process
31
35
  * Notice: in single process mode, it only can send to self process,
32
36
  * and it will send to both agent and app's messengers.
33
- * @param {String} pid - the process id of the receiver
37
+ * @param {String} workerId - the workerId of the receiver
34
38
  * @param {String} action - message key
35
39
  * @param {Object} data - message value
36
40
  * @return {Messenger} this
37
41
  */
38
- sendTo(pid, action, data) {
39
- debug('[%s] send %s with %j to %s', this.pid, action, data, pid);
40
- if (pid !== process.pid) return this;
42
+ sendTo(workerId: string, action: string, data?: unknown): Messenger {
43
+ debug('[%s:%s] send %s with %j to %s', this.egg.type, this.pid, action, data, workerId);
44
+ if (String(workerId) !== this.pid) {
45
+ return this;
46
+ }
41
47
  this.send(action, data, 'both');
42
48
  return this;
43
49
  }
@@ -51,8 +57,8 @@ class Messenger extends EventEmitter {
51
57
  * @param {Object} data - message value
52
58
  * @return {Messenger} this
53
59
  */
54
- sendRandom(action, data) {
55
- debug('[%s] send %s with %j to opposite', this.pid, action, data);
60
+ sendRandom(action: string, data?: unknown): Messenger {
61
+ debug('[%s:%s] send %s with %j to opposite', this.egg.type, this.pid, action, data);
56
62
  this.send(action, data, 'opposite');
57
63
  return this;
58
64
  }
@@ -63,8 +69,8 @@ class Messenger extends EventEmitter {
63
69
  * @param {Object} data - message value
64
70
  * @return {Messenger} this
65
71
  */
66
- sendToApp(action, data) {
67
- debug('[%s] send %s with %j to all app', this.pid, action, data);
72
+ sendToApp(action: string, data?: unknown): Messenger {
73
+ debug('[%s:%s] send %s with %j to all app', this.egg.type, this.pid, action, data);
68
74
  this.send(action, data, 'application');
69
75
  return this;
70
76
  }
@@ -75,8 +81,8 @@ class Messenger extends EventEmitter {
75
81
  * @param {Object} data - message value
76
82
  * @return {Messenger} this
77
83
  */
78
- sendToAgent(action, data) {
79
- debug('[%s] send %s with %j to all agent', this.pid, action, data);
84
+ sendToAgent(action: string, data?: unknown): Messenger {
85
+ debug('[%s:%s] send %s with %j to all agent', this.egg.type, this.pid, action, data);
80
86
  this.send(action, data, 'agent');
81
87
  return this;
82
88
  }
@@ -87,7 +93,7 @@ class Messenger extends EventEmitter {
87
93
  * @param {String} to - let master know how to send message
88
94
  * @return {Messenger} this
89
95
  */
90
- send(action, data, to) {
96
+ send(action: string, data: unknown | undefined, to?: string): Messenger {
91
97
  // use nextTick to keep it async as IPC messenger
92
98
  process.nextTick(() => {
93
99
  const { egg } = this;
@@ -104,26 +110,30 @@ class Messenger extends EventEmitter {
104
110
  application = egg.application;
105
111
  opposite = application;
106
112
  }
107
- if (!to) to = egg.type === 'application' ? 'agent' : 'application';
113
+ if (!to) {
114
+ to = egg.type === 'application' ? 'agent' : 'application';
115
+ }
108
116
 
109
117
  if (application && application.messenger && (to === 'application' || to === 'both')) {
110
- application.messenger._onMessage({ action, data });
118
+ application.messenger.onMessage({ action, data });
111
119
  }
112
120
  if (agent && agent.messenger && (to === 'agent' || to === 'both')) {
113
- agent.messenger._onMessage({ action, data });
121
+ agent.messenger.onMessage({ action, data });
114
122
  }
115
123
  if (opposite && opposite.messenger && to === 'opposite') {
116
- opposite.messenger._onMessage({ action, data });
124
+ opposite.messenger.onMessage({ action, data });
117
125
  }
118
126
  });
119
127
 
120
128
  return this;
121
129
  }
122
130
 
123
- _onMessage(message) {
124
- if (message && is.string(message.action)) {
125
- debug('[%s] got message %s with %j', this.pid, message.action, message.data);
131
+ onMessage(message: any) {
132
+ if (typeof message?.action === 'string') {
133
+ debug('[%s:%s] got message %s with %j', this.egg.type, this.pid, message.action, message.data);
126
134
  this.emit(message.action, message.data);
135
+ } else {
136
+ debug('[%s:%s] got an invalid message %j', this.egg.type, this.pid, message);
127
137
  }
128
138
  }
129
139
 
@@ -137,5 +147,3 @@ class Messenger extends EventEmitter {
137
147
  * @param {Object} data - message value
138
148
  */
139
149
  }
140
-
141
- module.exports = Messenger;
@@ -1,36 +1,48 @@
1
- 'use strict';
1
+ import assert from 'node:assert';
2
+ import { isAsyncFunction } from 'is-type-of';
3
+ import type { EggApplicationCore } from '../egg.js';
2
4
 
3
- const assert = require('assert');
4
- const is = require('is-type-of');
5
+ export type SingletonCreateMethod =
6
+ (config: Record<string, any>, app: EggApplicationCore, clientName: string) => unknown | Promise<unknown>;
5
7
 
6
- class Singleton {
7
- constructor(options = {}) {
8
+ export interface SingletonOptions {
9
+ name: string;
10
+ app: EggApplicationCore;
11
+ create: SingletonCreateMethod;
12
+ }
13
+
14
+ export class Singleton {
15
+ readonly clients = new Map<string, any>();
16
+ readonly app: EggApplicationCore;
17
+ readonly create: SingletonCreateMethod;
18
+ readonly name: string;
19
+ readonly options: Record<string, any>;
20
+
21
+ constructor(options: SingletonOptions) {
8
22
  assert(options.name, '[egg:singleton] Singleton#constructor options.name is required');
9
23
  assert(options.app, '[egg:singleton] Singleton#constructor options.app is required');
10
24
  assert(options.create, '[egg:singleton] Singleton#constructor options.create is required');
11
- assert(!options.app[options.name], `${options.name} is already exists in app`);
12
- this.clients = new Map();
25
+ assert(!(options.name in options.app), `[egg:singleton] ${options.name} is already exists in app`);
13
26
  this.app = options.app;
14
27
  this.name = options.name;
15
28
  this.create = options.create;
16
- /* istanbul ignore next */
17
- this.options = options.app.config[this.name] || {};
29
+ this.options = options.app.config[this.name] ?? {};
18
30
  }
19
31
 
20
32
  init() {
21
- return is.asyncFunction(this.create) ? this.initAsync() : this.initSync();
33
+ return isAsyncFunction(this.create) ? this.initAsync() : this.initSync();
22
34
  }
23
35
 
24
36
  initSync() {
25
37
  const options = this.options;
26
38
  assert(!(options.client && options.clients),
27
- `egg:singleton ${this.name} can not set options.client and options.clients both`);
39
+ `[egg:singleton] ${this.name} can not set options.client and options.clients both`);
28
40
 
29
41
  // alias app[name] as client, but still support createInstance method
30
42
  if (options.client) {
31
43
  const client = this.createInstance(options.client, options.name);
32
- this.app[this.name] = client;
33
- this._extendDynamicMethods(client);
44
+ this.#setClientToApp(client);
45
+ this.#extendDynamicMethods(client);
34
46
  return;
35
47
  }
36
48
 
@@ -40,66 +52,76 @@ class Singleton {
40
52
  const client = this.createInstance(options.clients[id], id);
41
53
  this.clients.set(id, client);
42
54
  });
43
- this.app[this.name] = this;
55
+ this.#setClientToApp(this);
44
56
  return;
45
57
  }
46
58
 
47
59
  // no config.clients and config.client
48
- this.app[this.name] = this;
60
+ this.#setClientToApp(this);
49
61
  }
50
62
 
51
63
  async initAsync() {
52
64
  const options = this.options;
53
65
  assert(!(options.client && options.clients),
54
- `egg:singleton ${this.name} can not set options.client and options.clients both`);
66
+ `[egg:singleton] ${this.name} can not set options.client and options.clients both`);
55
67
 
56
68
  // alias app[name] as client, but still support createInstance method
57
69
  if (options.client) {
58
70
  const client = await this.createInstanceAsync(options.client, options.name);
59
- this.app[this.name] = client;
60
- this._extendDynamicMethods(client);
71
+ this.#setClientToApp(client);
72
+ this.#extendDynamicMethods(client);
61
73
  return;
62
74
  }
63
75
 
64
76
  // multi client, use app[name].getInstance(id)
65
77
  if (options.clients) {
66
- await Promise.all(Object.keys(options.clients).map(id => {
78
+ await Promise.all(Object.keys(options.clients).map((id: string) => {
67
79
  return this.createInstanceAsync(options.clients[id], id)
68
80
  .then(client => this.clients.set(id, client));
69
81
  }));
70
- this.app[this.name] = this;
82
+ this.#setClientToApp(this);
71
83
  return;
72
84
  }
73
85
 
74
86
  // no config.clients and config.client
75
- this.app[this.name] = this;
87
+ this.#setClientToApp(this);
76
88
  }
77
89
 
78
- get(id) {
90
+ #setClientToApp(client: unknown) {
91
+ Reflect.set(this.app, this.name, client);
92
+ }
93
+
94
+ get(id: string) {
79
95
  return this.clients.get(id);
80
96
  }
81
97
 
82
98
  // alias to `get(id)`
83
- getSingletonInstance(id) {
99
+ getSingletonInstance(id: string) {
84
100
  return this.clients.get(id);
85
101
  }
86
102
 
87
- createInstance(config, clientName) {
103
+ createInstance(config: Record<string, any>, clientName: string) {
88
104
  // async creator only support createInstanceAsync
89
- assert(!is.asyncFunction(this.create),
105
+ assert(!isAsyncFunction(this.create),
90
106
  `egg:singleton ${this.name} only support create asynchronous, please use createInstanceAsync`);
91
107
  // options.default will be merge in to options.clients[id]
92
- config = Object.assign({}, this.options.default, config);
93
- return this.create(config, this.app, clientName);
108
+ config = {
109
+ ...this.options.default,
110
+ ...config,
111
+ };
112
+ return (this.create as SingletonCreateMethod)(config, this.app, clientName);
94
113
  }
95
114
 
96
- async createInstanceAsync(config, clientName) {
115
+ async createInstanceAsync(config: Record<string, any>, clientName: string) {
97
116
  // options.default will be merge in to options.clients[id]
98
- config = Object.assign({}, this.options.default, config);
117
+ config = {
118
+ ...this.options.default,
119
+ ...config,
120
+ };
99
121
  return await this.create(config, this.app, clientName);
100
122
  }
101
123
 
102
- _extendDynamicMethods(client) {
124
+ #extendDynamicMethods(client: any) {
103
125
  assert(!client.createInstance, 'singleton instance should not have createInstance method');
104
126
  assert(!client.createInstanceAsync, 'singleton instance should not have createInstanceAsync method');
105
127
 
@@ -113,9 +135,10 @@ class Singleton {
113
135
  extendable.createInstance = this.createInstance.bind(this);
114
136
  extendable.createInstanceAsync = this.createInstanceAsync.bind(this);
115
137
  } catch (err) {
116
- this.app.logger.warn('egg:singleton %s dynamic create is disabled because of client is unextensible', this.name);
138
+ this.app.coreLogger.warn(
139
+ '[egg:singleton] %s dynamic create is disabled because of client is un-extendable',
140
+ this.name);
141
+ this.app.coreLogger.warn(err);
117
142
  }
118
143
  }
119
144
  }
120
-
121
- module.exports = Singleton;