egg 3.29.0 → 4.0.0-beta.2

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 (202) 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 +2 -0
  6. package/dist/commonjs/app/extend/context.js +263 -0
  7. package/dist/commonjs/app/middleware/body_parser.d.ts +2 -0
  8. package/dist/commonjs/app/middleware/body_parser.js +8 -0
  9. package/dist/commonjs/app/middleware/meta.d.ts +11 -0
  10. package/dist/commonjs/app/middleware/meta.js +22 -0
  11. package/dist/commonjs/app/middleware/notfound.d.ts +8 -0
  12. package/dist/commonjs/app/middleware/notfound.js +31 -0
  13. package/dist/commonjs/app/middleware/override_method.d.ts +2 -0
  14. package/dist/commonjs/app/middleware/override_method.js +8 -0
  15. package/dist/commonjs/app/middleware/site_file.d.ts +7 -0
  16. package/dist/commonjs/app/middleware/site_file.js +59 -0
  17. package/dist/commonjs/config/config.default.d.ts +9 -0
  18. package/dist/commonjs/config/config.default.js +378 -0
  19. package/dist/commonjs/config/config.local.d.ts +8 -0
  20. package/dist/commonjs/config/config.local.js +12 -0
  21. package/dist/commonjs/config/config.unittest.d.ts +7 -0
  22. package/dist/commonjs/config/config.unittest.js +11 -0
  23. package/dist/commonjs/config/plugin.d.ts +122 -0
  24. package/dist/commonjs/config/plugin.js +125 -0
  25. package/dist/commonjs/index.d.ts +61 -0
  26. package/dist/commonjs/index.js +89 -0
  27. package/dist/commonjs/lib/agent.d.ts +19 -0
  28. package/dist/commonjs/lib/agent.js +58 -0
  29. package/dist/commonjs/lib/application.d.ts +66 -0
  30. package/dist/commonjs/lib/application.js +281 -0
  31. package/dist/commonjs/lib/core/base_context_class.d.ts +14 -0
  32. package/dist/commonjs/lib/core/base_context_class.js +22 -0
  33. package/dist/commonjs/lib/core/base_context_logger.d.ts +36 -0
  34. package/dist/commonjs/lib/core/base_context_logger.js +64 -0
  35. package/dist/commonjs/lib/core/base_hook_class.d.ts +11 -0
  36. package/dist/commonjs/lib/core/base_hook_class.js +30 -0
  37. package/dist/commonjs/lib/core/context_httpclient.d.ts +16 -0
  38. package/dist/commonjs/lib/core/context_httpclient.js +30 -0
  39. package/dist/commonjs/lib/core/httpclient.d.ts +14 -0
  40. package/dist/commonjs/lib/core/httpclient.js +40 -0
  41. package/dist/commonjs/lib/core/logger.d.ts +3 -0
  42. package/dist/commonjs/lib/core/logger.js +40 -0
  43. package/dist/commonjs/lib/core/messenger/IMessenger.d.ts +50 -0
  44. package/dist/commonjs/lib/core/messenger/IMessenger.js +3 -0
  45. package/dist/commonjs/lib/core/messenger/index.d.ts +7 -0
  46. package/dist/commonjs/lib/core/messenger/index.js +14 -0
  47. package/dist/commonjs/lib/core/messenger/ipc.d.ts +57 -0
  48. package/dist/commonjs/lib/core/messenger/ipc.js +126 -0
  49. package/dist/commonjs/lib/core/messenger/local.d.ts +61 -0
  50. package/dist/commonjs/lib/core/messenger/local.js +134 -0
  51. package/dist/commonjs/lib/core/singleton.d.ts +23 -0
  52. package/dist/commonjs/lib/core/singleton.js +120 -0
  53. package/dist/commonjs/lib/core/utils.d.ts +2 -0
  54. package/dist/commonjs/lib/core/utils.js +77 -0
  55. package/dist/commonjs/lib/egg.d.ts +271 -0
  56. package/dist/commonjs/lib/egg.js +613 -0
  57. package/dist/commonjs/lib/loader/AgentWorkerLoader.d.ts +12 -0
  58. package/dist/commonjs/lib/loader/AgentWorkerLoader.js +24 -0
  59. package/dist/commonjs/lib/loader/AppWorkerLoader.d.ts +17 -0
  60. package/dist/commonjs/lib/loader/AppWorkerLoader.js +43 -0
  61. package/dist/commonjs/lib/loader/EggApplicationLoader.d.ts +4 -0
  62. package/dist/commonjs/lib/loader/EggApplicationLoader.js +8 -0
  63. package/dist/commonjs/lib/loader/index.d.ts +3 -0
  64. package/dist/commonjs/lib/loader/index.js +22 -0
  65. package/dist/commonjs/lib/start.d.ts +15 -0
  66. package/dist/commonjs/lib/start.js +49 -0
  67. package/dist/commonjs/lib/type.d.ts +296 -0
  68. package/dist/commonjs/lib/type.js +3 -0
  69. package/dist/commonjs/package.json +3 -0
  70. package/dist/esm/agent.d.ts +4 -0
  71. package/dist/esm/agent.js +7 -0
  72. package/dist/esm/app/extend/context.d.ts +2 -0
  73. package/dist/esm/app/extend/context.js +258 -0
  74. package/dist/esm/app/middleware/body_parser.d.ts +2 -0
  75. package/dist/esm/app/middleware/body_parser.js +3 -0
  76. package/dist/esm/app/middleware/meta.d.ts +11 -0
  77. package/dist/esm/app/middleware/meta.js +20 -0
  78. package/dist/esm/app/middleware/notfound.d.ts +8 -0
  79. package/dist/esm/app/middleware/notfound.js +29 -0
  80. package/dist/esm/app/middleware/override_method.d.ts +2 -0
  81. package/dist/esm/app/middleware/override_method.js +3 -0
  82. package/dist/esm/app/middleware/site_file.d.ts +7 -0
  83. package/dist/esm/app/middleware/site_file.js +54 -0
  84. package/dist/esm/config/config.default.d.ts +9 -0
  85. package/dist/esm/config/config.default.js +373 -0
  86. package/dist/esm/config/config.local.d.ts +8 -0
  87. package/dist/esm/config/config.local.js +10 -0
  88. package/dist/esm/config/config.unittest.d.ts +7 -0
  89. package/dist/esm/config/config.unittest.js +9 -0
  90. package/dist/esm/config/favicon.png +0 -0
  91. package/dist/esm/config/plugin.d.ts +122 -0
  92. package/dist/esm/config/plugin.js +123 -0
  93. package/dist/esm/index.d.ts +61 -0
  94. package/dist/esm/index.js +65 -0
  95. package/dist/esm/lib/agent.d.ts +19 -0
  96. package/dist/esm/lib/agent.js +54 -0
  97. package/dist/esm/lib/application.d.ts +66 -0
  98. package/dist/esm/lib/application.js +274 -0
  99. package/dist/esm/lib/core/base_context_class.d.ts +14 -0
  100. package/dist/esm/lib/core/base_context_class.js +18 -0
  101. package/dist/esm/lib/core/base_context_logger.d.ts +36 -0
  102. package/dist/esm/lib/core/base_context_logger.js +60 -0
  103. package/dist/esm/lib/core/base_hook_class.d.ts +11 -0
  104. package/dist/esm/lib/core/base_hook_class.js +23 -0
  105. package/dist/esm/lib/core/context_httpclient.d.ts +16 -0
  106. package/dist/esm/lib/core/context_httpclient.js +26 -0
  107. package/dist/esm/lib/core/httpclient.d.ts +14 -0
  108. package/dist/esm/lib/core/httpclient.js +33 -0
  109. package/dist/esm/lib/core/logger.d.ts +3 -0
  110. package/dist/esm/lib/core/logger.js +37 -0
  111. package/dist/esm/lib/core/messenger/IMessenger.d.ts +50 -0
  112. package/dist/esm/lib/core/messenger/IMessenger.js +2 -0
  113. package/dist/esm/lib/core/messenger/index.d.ts +7 -0
  114. package/dist/esm/lib/core/messenger/index.js +11 -0
  115. package/dist/esm/lib/core/messenger/ipc.d.ts +57 -0
  116. package/dist/esm/lib/core/messenger/ipc.js +119 -0
  117. package/dist/esm/lib/core/messenger/local.d.ts +61 -0
  118. package/dist/esm/lib/core/messenger/local.js +127 -0
  119. package/dist/esm/lib/core/singleton.d.ts +23 -0
  120. package/dist/esm/lib/core/singleton.js +113 -0
  121. package/dist/esm/lib/core/utils.d.ts +2 -0
  122. package/dist/esm/lib/core/utils.js +70 -0
  123. package/dist/esm/lib/egg.d.ts +271 -0
  124. package/dist/esm/lib/egg.js +573 -0
  125. package/dist/esm/lib/loader/AgentWorkerLoader.d.ts +12 -0
  126. package/dist/esm/lib/loader/AgentWorkerLoader.js +20 -0
  127. package/dist/esm/lib/loader/AppWorkerLoader.d.ts +17 -0
  128. package/dist/esm/lib/loader/AppWorkerLoader.js +39 -0
  129. package/dist/esm/lib/loader/EggApplicationLoader.d.ts +4 -0
  130. package/dist/esm/lib/loader/EggApplicationLoader.js +4 -0
  131. package/dist/esm/lib/loader/index.d.ts +3 -0
  132. package/dist/esm/lib/loader/index.js +4 -0
  133. package/dist/esm/lib/start.d.ts +15 -0
  134. package/dist/esm/lib/start.js +43 -0
  135. package/dist/esm/lib/type.d.ts +296 -0
  136. package/dist/esm/lib/type.js +2 -0
  137. package/dist/esm/package.json +3 -0
  138. package/dist/package.json +4 -0
  139. package/package.json +87 -72
  140. package/src/agent.ts +7 -0
  141. package/{app/extend/context.js → src/app/extend/context.ts} +19 -23
  142. package/src/app/middleware/body_parser.ts +3 -0
  143. package/{app/middleware/meta.js → src/app/middleware/meta.ts} +12 -4
  144. package/{app/middleware/notfound.js → src/app/middleware/notfound.ts} +9 -3
  145. package/src/app/middleware/override_method.ts +3 -0
  146. package/src/app/middleware/site_file.ts +70 -0
  147. package/{config/config.default.js → src/config/config.default.ts} +24 -45
  148. package/src/config/config.local.ts +11 -0
  149. package/src/config/config.unittest.ts +10 -0
  150. package/src/config/favicon.png +0 -0
  151. package/{config/plugin.js → src/config/plugin.ts} +1 -3
  152. package/src/index.ts +78 -0
  153. package/src/lib/agent.ts +66 -0
  154. package/{lib/application.js → src/lib/application.ts} +79 -120
  155. package/src/lib/core/base_context_class.ts +21 -0
  156. package/src/lib/core/base_context_logger.ts +67 -0
  157. package/src/lib/core/base_hook_class.ts +30 -0
  158. package/src/lib/core/context_httpclient.ts +33 -0
  159. package/src/lib/core/httpclient.ts +52 -0
  160. package/src/lib/core/logger.ts +42 -0
  161. package/src/lib/core/messenger/IMessenger.ts +58 -0
  162. package/src/lib/core/messenger/index.ts +15 -0
  163. package/{lib/core/messenger/ipc.js → src/lib/core/messenger/ipc.ts} +24 -29
  164. package/{lib/core/messenger/local.js → src/lib/core/messenger/local.ts} +27 -21
  165. package/{lib/core/singleton.js → src/lib/core/singleton.ts} +56 -33
  166. package/src/lib/core/utils.ts +77 -0
  167. package/{lib/egg.js → src/lib/egg.ts} +262 -219
  168. package/src/lib/loader/AgentWorkerLoader.ts +21 -0
  169. package/src/lib/loader/AppWorkerLoader.ts +42 -0
  170. package/src/lib/loader/EggApplicationLoader.ts +5 -0
  171. package/src/lib/loader/index.ts +3 -0
  172. package/src/lib/start.ts +56 -0
  173. package/src/lib/type.ts +336 -0
  174. package/CHANGELOG.md +0 -2395
  175. package/History.md +0 -52
  176. package/agent.js +0 -11
  177. package/app/middleware/body_parser.js +0 -3
  178. package/app/middleware/override_method.js +0 -3
  179. package/app/middleware/site_file.js +0 -31
  180. package/config/config.local.js +0 -7
  181. package/config/config.unittest.js +0 -8
  182. package/index.d.ts +0 -1288
  183. package/index.js +0 -68
  184. package/lib/agent.js +0 -95
  185. package/lib/core/base_context_class.js +0 -20
  186. package/lib/core/base_context_logger.js +0 -64
  187. package/lib/core/base_hook_class.js +0 -31
  188. package/lib/core/context_httpclient.js +0 -26
  189. package/lib/core/dnscache_httpclient.js +0 -93
  190. package/lib/core/httpclient.js +0 -119
  191. package/lib/core/httpclient_next.js +0 -80
  192. package/lib/core/logger.js +0 -35
  193. package/lib/core/messenger/index.js +0 -14
  194. package/lib/core/utils.js +0 -73
  195. package/lib/loader/agent_worker_loader.js +0 -27
  196. package/lib/loader/app_worker_loader.js +0 -48
  197. package/lib/loader/index.js +0 -5
  198. package/lib/start.js +0 -39
  199. /package/{config → dist/commonjs/config}/favicon.png +0 -0
  200. /package/{app → src/app}/extend/helper.js +0 -0
  201. /package/{app → src/app}/extend/request.js +0 -0
  202. /package/{app → src/app}/extend/response.js +0 -0
@@ -1,15 +1,17 @@
1
- 'use strict';
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';
2
6
 
3
- const debug = require('util').debuglog('egg:util:messenger:ipc');
4
- const is = require('is-type-of');
5
- const workerThreads = require('worker_threads');
6
- const sendmessage = require('sendmessage');
7
- const EventEmitter = require('events');
7
+ const debug = debuglog('egg:lib:core:messenger:ipc');
8
8
 
9
9
  /**
10
10
  * Communication between app worker and agent worker by IPC channel
11
11
  */
12
- class Messenger extends EventEmitter {
12
+ export class Messenger extends EventEmitter implements IMessenger {
13
+ readonly pid: string;
14
+ opids: string[] = [];
13
15
 
14
16
  constructor() {
15
17
  super();
@@ -17,14 +19,13 @@ class Messenger extends EventEmitter {
17
19
  // pids of agent or app managed by master
18
20
  // - retrieve app worker pids when it's an agent worker
19
21
  // - retrieve agent worker pids when it's an app worker
20
- this.opids = [];
21
22
  this.on('egg-pids', pids => {
22
23
  this.opids = pids;
23
24
  });
24
- this._onMessage = this._onMessage.bind(this);
25
- process.on('message', this._onMessage);
25
+ this.onMessage = this.onMessage.bind(this);
26
+ process.on('message', this.onMessage);
26
27
  if (!workerThreads.isMainThread) {
27
- workerThreads.parentPort.on('message', this._onMessage);
28
+ workerThreads.parentPort!.on('message', this.onMessage);
28
29
  }
29
30
  }
30
31
 
@@ -34,7 +35,7 @@ class Messenger extends EventEmitter {
34
35
  * @param {Object} data - message value
35
36
  * @return {Messenger} this
36
37
  */
37
- broadcast(action, data) {
38
+ broadcast(action: string, data?: unknown): Messenger {
38
39
  debug('[%s] broadcast %s with %j', this.pid, action, data);
39
40
  this.send(action, data, 'app');
40
41
  this.send(action, data, 'agent');
@@ -48,7 +49,7 @@ class Messenger extends EventEmitter {
48
49
  * @param {Object} data - message value
49
50
  * @return {Messenger} this
50
51
  */
51
- sendTo(pid, action, data) {
52
+ sendTo(pid: string, action: string, data?: unknown): Messenger {
52
53
  debug('[%s] send %s with %j to %s', this.pid, action, data, pid);
53
54
  sendmessage(process, {
54
55
  action,
@@ -66,10 +67,11 @@ class Messenger extends EventEmitter {
66
67
  * @param {Object} data - message value
67
68
  * @return {Messenger} this
68
69
  */
69
- sendRandom(action, data) {
70
+ sendRandom(action: string, data?: unknown): Messenger {
70
71
  /* istanbul ignore if */
71
- if (!this.opids.length) return this;
72
- const pid = random(this.opids);
72
+ if (this.opids.length === 0) return this;
73
+ const index = Math.floor(Math.random() * this.opids.length);
74
+ const pid = this.opids[index];
73
75
  this.sendTo(String(pid), action, data);
74
76
  return this;
75
77
  }
@@ -80,7 +82,7 @@ class Messenger extends EventEmitter {
80
82
  * @param {Object} data - message value
81
83
  * @return {Messenger} this
82
84
  */
83
- sendToApp(action, data) {
85
+ sendToApp(action: string, data?: unknown): Messenger {
84
86
  debug('[%s] send %s with %j to all app', this.pid, action, data);
85
87
  this.send(action, data, 'app');
86
88
  return this;
@@ -92,7 +94,7 @@ class Messenger extends EventEmitter {
92
94
  * @param {Object} data - message value
93
95
  * @return {Messenger} this
94
96
  */
95
- sendToAgent(action, data) {
97
+ sendToAgent(action: string, data?: unknown): Messenger {
96
98
  debug('[%s] send %s with %j to all agent', this.pid, action, data);
97
99
  this.send(action, data, 'agent');
98
100
  return this;
@@ -104,7 +106,7 @@ class Messenger extends EventEmitter {
104
106
  * @param {String} to - let master know how to send message
105
107
  * @return {Messenger} this
106
108
  */
107
- send(action, data, to) {
109
+ send(action: string, data: unknown | undefined, to?: string): Messenger {
108
110
  sendmessage(process, {
109
111
  action,
110
112
  data,
@@ -113,8 +115,8 @@ class Messenger extends EventEmitter {
113
115
  return this;
114
116
  }
115
117
 
116
- _onMessage(message) {
117
- if (message && is.string(message.action)) {
118
+ onMessage(message: any) {
119
+ if (typeof message?.action === 'string') {
118
120
  debug('[%s] got message %s with %j, receiverPid: %s',
119
121
  this.pid, message.action, message.data, message.receiverPid);
120
122
  this.emit(message.action, message.data);
@@ -122,7 +124,7 @@ class Messenger extends EventEmitter {
122
124
  }
123
125
 
124
126
  close() {
125
- process.removeListener('message', this._onMessage);
127
+ process.removeListener('message', this.onMessage);
126
128
  this.removeAllListeners();
127
129
  }
128
130
 
@@ -132,10 +134,3 @@ class Messenger extends EventEmitter {
132
134
  * @param {Object} data - message value
133
135
  */
134
136
  }
135
-
136
- module.exports = Messenger;
137
-
138
- function random(arr) {
139
- const index = Math.floor(Math.random() * arr.length);
140
- return arr[index];
141
- }
@@ -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,7 +24,7 @@ class Messenger extends EventEmitter {
20
24
  * @param {Object} data - message value
21
25
  * @return {Messenger} this
22
26
  */
23
- broadcast(action, data) {
27
+ broadcast(action: string, data?: unknown): Messenger {
24
28
  debug('[%s] broadcast %s with %j', this.pid, action, data);
25
29
  this.send(action, data, 'both');
26
30
  return this;
@@ -35,9 +39,11 @@ class Messenger extends EventEmitter {
35
39
  * @param {Object} data - message value
36
40
  * @return {Messenger} this
37
41
  */
38
- sendTo(pid, action, data) {
42
+ sendTo(pid: string, action: string, data?: unknown): Messenger {
39
43
  debug('[%s] send %s with %j to %s', this.pid, action, data, pid);
40
- if (pid !== process.pid) return this;
44
+ if (String(pid) !== this.pid) {
45
+ return this;
46
+ }
41
47
  this.send(action, data, 'both');
42
48
  return this;
43
49
  }
@@ -51,7 +57,7 @@ class Messenger extends EventEmitter {
51
57
  * @param {Object} data - message value
52
58
  * @return {Messenger} this
53
59
  */
54
- sendRandom(action, data) {
60
+ sendRandom(action: string, data?: unknown): Messenger {
55
61
  debug('[%s] send %s with %j to opposite', this.pid, action, data);
56
62
  this.send(action, data, 'opposite');
57
63
  return this;
@@ -63,7 +69,7 @@ class Messenger extends EventEmitter {
63
69
  * @param {Object} data - message value
64
70
  * @return {Messenger} this
65
71
  */
66
- sendToApp(action, data) {
72
+ sendToApp(action: string, data?: unknown): Messenger {
67
73
  debug('[%s] send %s with %j to all app', this.pid, action, data);
68
74
  this.send(action, data, 'application');
69
75
  return this;
@@ -75,7 +81,7 @@ class Messenger extends EventEmitter {
75
81
  * @param {Object} data - message value
76
82
  * @return {Messenger} this
77
83
  */
78
- sendToAgent(action, data) {
84
+ sendToAgent(action: string, data?: unknown): Messenger {
79
85
  debug('[%s] send %s with %j to all agent', this.pid, action, data);
80
86
  this.send(action, data, 'agent');
81
87
  return this;
@@ -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,24 +110,26 @@ 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)) {
131
+ onMessage(message: any) {
132
+ if (typeof message?.action === 'string') {
125
133
  debug('[%s] got message %s with %j', this.pid, message.action, message.data);
126
134
  this.emit(message.action, message.data);
127
135
  }
@@ -137,5 +145,3 @@ class Messenger extends EventEmitter {
137
145
  * @param {Object} data - message value
138
146
  */
139
147
  }
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;
@@ -0,0 +1,77 @@
1
+ import util from 'node:util';
2
+ import {
3
+ isSymbol, isRegExp, isPrimitive,
4
+ isClass, isFunction, isGeneratorFunction, isAsyncFunction,
5
+ } from 'is-type-of';
6
+
7
+ export function convertObject(obj: any, ignore: string | RegExp | (string | RegExp)[]) {
8
+ if (!Array.isArray(ignore)) {
9
+ ignore = [ ignore ];
10
+ }
11
+ for (const key of Object.keys(obj)) {
12
+ obj[key] = convertValue(key, obj[key], ignore);
13
+ }
14
+ return obj;
15
+ }
16
+
17
+ function convertValue(key: string, value: any, ignore: (string | RegExp)[]) {
18
+ if (value === null || value === undefined) {
19
+ return value;
20
+ }
21
+
22
+ let hit = false;
23
+ for (const matchKey of ignore) {
24
+ if (typeof matchKey === 'string' && matchKey === key) {
25
+ hit = true;
26
+ break;
27
+ } else if (isRegExp(matchKey) && matchKey.test(key)) {
28
+ hit = true;
29
+ break;
30
+ }
31
+ }
32
+ if (!hit) {
33
+ if (isSymbol(value) || isRegExp(value)) {
34
+ return value.toString();
35
+ }
36
+ if (isPrimitive(value) || Array.isArray(value)) {
37
+ return value;
38
+ }
39
+ }
40
+
41
+ // only convert recursively when it's a plain object,
42
+ // o = {}
43
+ if (Object.getPrototypeOf(value) === Object.prototype) {
44
+ return convertObject(value, ignore);
45
+ }
46
+
47
+ // support class
48
+ const name = value.name || 'anonymous';
49
+ if (isClass(value)) {
50
+ return `<Class ${name}>`;
51
+ }
52
+
53
+ // support generator function
54
+ if (isFunction(value)) {
55
+ if (isGeneratorFunction(value)) return `<GeneratorFunction ${name}>`;
56
+ if (isAsyncFunction(value)) return `<AsyncFunction ${name}>`;
57
+ return `<Function ${name}>`;
58
+ }
59
+
60
+ const typeName = value.constructor.name;
61
+ if (typeName) {
62
+ if (Buffer.isBuffer(value) || typeof value === 'string') {
63
+ return `<${typeName} len: ${value.length}>`;
64
+ }
65
+ return `<${typeName}>`;
66
+ }
67
+
68
+ return util.format(value);
69
+ }
70
+
71
+ export function safeParseURL(url: string) {
72
+ try {
73
+ return new URL(url);
74
+ } catch {
75
+ return null;
76
+ }
77
+ }