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,27 +1,17 @@
1
- 'use strict';
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+ import http from 'node:http';
4
+ import { Socket } from 'node:net';
5
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
6
+ // @ts-ignore
7
+ import graceful from 'graceful';
8
+ import { assign } from 'utility';
9
+ import { utils as eggUtils } from '@eggjs/core';
10
+ import { EggApplicationCore, EggContext, EggApplicationCoreOptions } from './egg.js';
11
+ import { AppWorkerLoader } from './loader/index.js';
12
+ import { BaseContextClass } from './core/base_context_class.js';
2
13
 
3
- const path = require('path');
4
- const fs = require('fs');
5
- const ms = require('ms');
6
- const is = require('is-type-of');
7
- const graceful = require('graceful');
8
- const http = require('http');
9
- const cluster = require('cluster-client');
10
- const onFinished = require('on-finished');
11
- const { assign } = require('utility');
12
- const eggUtils = require('egg-core').utils;
13
- const EggApplication = require('./egg');
14
- const AppWorkerLoader = require('./loader').AppWorkerLoader;
15
-
16
- const KEYS = Symbol('Application#keys');
17
- const HELPER = Symbol('Application#Helper');
18
- const LOCALS = Symbol('Application#locals');
19
- const BIND_EVENTS = Symbol('Application#bindEvents');
20
- const WARN_CONFUSED_CONFIG = Symbol('Application#warnConfusedConfig');
21
14
  const EGG_LOADER = Symbol.for('egg#loader');
22
- const EGG_PATH = Symbol.for('egg#eggPath');
23
- const CLUSTER_CLIENTS = Symbol.for('egg#clusterClients');
24
- const RESPONSE_RAW = Symbol('Application#responseRaw');
25
15
 
26
16
  // client error => 400 Bad Request
27
17
  // Refs: https://nodejs.org/dist/latest-v8.x/docs/api/http.html#http_event_clienterror
@@ -38,59 +28,60 @@ const DEFAULT_BAD_REQUEST_RESPONSE =
38
28
  `\r\n\r\n${DEFAULT_BAD_REQUEST_HTML}`;
39
29
 
40
30
  // Refs: https://github.com/nodejs/node/blob/b38c81/lib/_http_outgoing.js#L706-L710
41
- function escapeHeaderValue(value) {
31
+ function escapeHeaderValue(value: string) {
42
32
  // Protect against response splitting. The regex test is there to
43
33
  // minimize the performance impact in the common case.
44
34
  return /[\r\n]/.test(value) ? value.replace(/[\r\n]+[ \t]*/g, '') : value;
45
35
  }
46
36
 
47
- // Refs: https://github.com/nodejs/node/blob/b38c81/lib/_http_outgoing.js#L706-L710
48
37
  /**
49
- * Singleton instance in App Worker, extend {@link EggApplication}
50
- * @augments EggApplication
38
+ * The Helper class which can be used as utility function.
39
+ * We support developers to extend Helper through ${baseDir}/app/extend/helper.js ,
40
+ * then you can use all method on `ctx.helper` that is a instance of Helper.
51
41
  */
52
- class Application extends EggApplication {
42
+ class HelperClass extends BaseContextClass {}
53
43
 
44
+ /**
45
+ * Singleton instance in App Worker, extend {@link EggApplicationCore}
46
+ * @augments EggApplicationCore
47
+ */
48
+ export class Application extends EggApplicationCore {
49
+ // will auto set after 'server' event emit
50
+ server?: http.Server;
51
+ #locals: Record<string, any> = {};
54
52
  /**
55
- * @class
56
- * @param {Object} options - see {@link EggApplication}
53
+ * reference to {@link Helper}
54
+ * @member {Helper} Application#Helper
57
55
  */
58
- constructor(options = {}) {
59
- options.type = 'application';
60
- super(options);
61
-
62
- // will auto set after 'server' event emit
63
- this.server = null;
56
+ Helper = HelperClass;
64
57
 
65
- try {
66
- this.loader.load();
67
- } catch (e) {
68
- // close gracefully
69
- this[CLUSTER_CLIENTS].forEach(cluster.close);
70
- throw e;
71
- }
72
-
73
- // dump config after loaded, ensure all the dynamic modifications will be recorded
74
- const dumpStartTime = Date.now();
75
- this.dumpConfig();
76
- this.coreLogger.info('[egg:core] dump config after load, %s', ms(Date.now() - dumpStartTime));
58
+ /**
59
+ * @class
60
+ * @param {Object} options - see {@link EggApplicationCore}
61
+ */
62
+ constructor(options?: Omit<EggApplicationCoreOptions, 'type'>) {
63
+ super({
64
+ ...options,
65
+ type: 'application',
66
+ });
67
+ }
77
68
 
78
- this[WARN_CONFUSED_CONFIG]();
79
- this[BIND_EVENTS]();
69
+ protected async load() {
70
+ await super.load();
71
+ this.#warnConfusedConfig();
72
+ this.#bindEvents();
80
73
  }
81
74
 
82
75
  get [EGG_LOADER]() {
83
76
  return AppWorkerLoader;
84
77
  }
85
78
 
86
- get [EGG_PATH]() {
87
- return path.join(__dirname, '..');
88
- }
89
-
90
- [RESPONSE_RAW](socket, raw) {
79
+ #responseRaw(socket: Socket, raw?: any) {
91
80
  /* istanbul ignore next */
92
81
  if (!socket.writable) return;
93
- if (!raw) return socket.end(DEFAULT_BAD_REQUEST_RESPONSE);
82
+ if (!raw) {
83
+ return socket.end(DEFAULT_BAD_REQUEST_RESPONSE);
84
+ }
94
85
 
95
86
  const body = (raw.body == null) ? DEFAULT_BAD_REQUEST_HTML : raw.body;
96
87
  const headers = raw.headers || {};
@@ -114,10 +105,10 @@ class Application extends EggApplication {
114
105
  socket.end(`${firstLine}\r\n${responseHeaderLines}\r\n${body.toString()}`);
115
106
  }
116
107
 
117
- onClientError(err, socket) {
108
+ onClientError(err: any, socket: Socket) {
118
109
  // ignore when there is no http body, it almost like an ECONNRESET
119
110
  if (err.rawPacket) {
120
- this.logger.warn('A client (%s:%d) error [%s] occurred: %s',
111
+ this.logger.warn('[egg:application] A client (%s:%d) error [%s] occurred: %s',
121
112
  socket.remoteAddress,
122
113
  socket.remotePort,
123
114
  err.code,
@@ -143,19 +134,19 @@ class Application extends EggApplication {
143
134
  // + headers: {}
144
135
  // + status: 400
145
136
  p.then(ret => {
146
- this[RESPONSE_RAW](socket, ret || {});
137
+ this.#responseRaw(socket, ret || {});
147
138
  }).catch(err => {
148
139
  this.logger.error(err);
149
- this[RESPONSE_RAW](socket);
140
+ this.#responseRaw(socket);
150
141
  });
151
142
  } else {
152
143
  // because it's a raw socket object, we should return the raw HTTP response
153
144
  // packet.
154
- this[RESPONSE_RAW](socket);
145
+ this.#responseRaw(socket);
155
146
  }
156
147
  }
157
148
 
158
- onServer(server) {
149
+ onServer(server: http.Server) {
159
150
  // expose app.server
160
151
  this.server = server;
161
152
  // set ignore code
@@ -164,14 +155,14 @@ class Application extends EggApplication {
164
155
  /* istanbul ignore next */
165
156
  graceful({
166
157
  server: [ server ],
167
- error: (err, throwErrorCount) => {
158
+ error: (err: Error, throwErrorCount: number) => {
168
159
  const originMessage = err.message;
169
160
  if (originMessage) {
170
161
  // shouldjs will override error property but only getter
171
162
  // https://github.com/shouldjs/should.js/blob/889e22ebf19a06bc2747d24cf34b25cc00b37464/lib/assertion-error.js#L26
172
163
  Object.defineProperty(err, 'message', {
173
164
  get() {
174
- return originMessage + ' (uncaughtException throw ' + throwErrorCount + ' times on pid:' + process.pid + ')';
165
+ return `${originMessage} (uncaughtException throw ${throwErrorCount} times on pid: ${process.pid})`;
175
166
  },
176
167
  configurable: true,
177
168
  enumerable: false,
@@ -182,10 +173,12 @@ class Application extends EggApplication {
182
173
  ignoreCode: serverGracefulIgnoreCode,
183
174
  });
184
175
 
185
- server.on('clientError', (err, socket) => this.onClientError(err, socket));
176
+ server.on('clientError', (err, socket) => this.onClientError(err, socket as Socket));
186
177
 
187
178
  // server timeout
188
- if (is.number(this.config.serverTimeout)) server.setTimeout(this.config.serverTimeout);
179
+ if (typeof this.config.serverTimeout === 'number') {
180
+ server.setTimeout(this.config.serverTimeout);
181
+ }
189
182
  }
190
183
 
191
184
  /**
@@ -194,24 +187,11 @@ class Application extends EggApplication {
194
187
  * @see Context#locals
195
188
  */
196
189
  get locals() {
197
- if (!this[LOCALS]) {
198
- this[LOCALS] = {};
199
- }
200
- return this[LOCALS];
190
+ return this.#locals;
201
191
  }
202
192
 
203
- set locals(val) {
204
- if (!this[LOCALS]) {
205
- this[LOCALS] = {};
206
- }
207
-
208
- assign(this[LOCALS], val);
209
- }
210
-
211
- handleRequest(ctx, fnMiddleware) {
212
- this.emit('request', ctx);
213
- onFinished(ctx.res, () => this.emit('response', ctx));
214
- return super.handleRequest(ctx, fnMiddleware);
193
+ set locals(val: Record<string, any>) {
194
+ assign(this.#locals, val);
215
195
  }
216
196
 
217
197
  /**
@@ -234,11 +214,11 @@ class Application extends EggApplication {
234
214
  paramNames: layer.paramNames,
235
215
  path: layer.path,
236
216
  regexp: layer.regexp.toString(),
237
- stack: layer.stack.map(stack => stack[FULLPATH] || stack._name || stack.name || 'anonymous'),
217
+ stack: layer.stack.map((stack: any) => stack[FULLPATH] || stack._name || stack.name || 'anonymous'),
238
218
  });
239
219
  }
240
220
  fs.writeFileSync(dumpRouterFile, JSON.stringify(routers, null, 2));
241
- } catch (err) {
221
+ } catch (err: any) {
242
222
  this.coreLogger.warn(`dumpConfig router.json error: ${err.message}`);
243
223
  }
244
224
  }
@@ -248,9 +228,11 @@ class Application extends EggApplication {
248
228
  * @see Context#runInBackground
249
229
  * @param {Function} scope - the first args is an anonymous ctx
250
230
  */
251
- runInBackground(scope) {
231
+ runInBackground(scope: (ctx: EggContext) => void) {
252
232
  const ctx = this.createAnonymousContext();
253
- if (!scope.name) scope._name = eggUtils.getCalleeFromStack(true);
233
+ if (!scope.name) {
234
+ Reflect.set(scope, '_name', eggUtils.getCalleeFromStack(true));
235
+ }
254
236
  this.ctxStorage.run(ctx, () => {
255
237
  ctx.runInBackground(scope);
256
238
  });
@@ -262,11 +244,13 @@ class Application extends EggApplication {
262
244
  * @param {Function} scope - the first args is an anonymous ctx, scope should be async function
263
245
  * @param {Request} [req] - if you want to mock request like querystring, you can pass an object to this function.
264
246
  */
265
- async runInAnonymousContextScope(scope, req) {
247
+ async runInAnonymousContextScope(scope: (ctx: EggContext) => Promise<void>, req?: unknown) {
266
248
  const ctx = this.createAnonymousContext(req);
267
- if (!scope.name) scope._name = eggUtils.getCalleeFromStack(true);
249
+ if (!scope.name) {
250
+ Reflect.set(scope, '_name', eggUtils.getCalleeFromStack(true));
251
+ }
268
252
  return await this.ctxStorage.run(ctx, async () => {
269
- return await scope(ctx);
253
+ return await scope(ctx as EggContext);
270
254
  });
271
255
  }
272
256
 
@@ -275,7 +259,7 @@ class Application extends EggApplication {
275
259
  * @member {String} Application#keys
276
260
  */
277
261
  get keys() {
278
- if (!this[KEYS]) {
262
+ if (!this._keys) {
279
263
  if (!this.config.keys) {
280
264
  if (this.config.env === 'local' || this.config.env === 'unittest') {
281
265
  const configPath = path.join(this.config.baseDir, 'config/config.default.js');
@@ -284,31 +268,9 @@ class Application extends EggApplication {
284
268
  }
285
269
  throw new Error('Please set config.keys first');
286
270
  }
287
-
288
- this[KEYS] = this.config.keys.split(',').map(s => s.trim());
289
- }
290
- return this[KEYS];
291
- }
292
-
293
- set keys(_) {
294
- // ignore
295
- }
296
-
297
- /**
298
- * reference to {@link Helper}
299
- * @member {Helper} Application#Helper
300
- */
301
- get Helper() {
302
- if (!this[HELPER]) {
303
- /**
304
- * The Helper class which can be used as utility function.
305
- * We support developers to extend Helper through ${baseDir}/app/extend/helper.js ,
306
- * then you can use all method on `ctx.helper` that is a instance of Helper.
307
- */
308
- class Helper extends this.BaseContextClass {}
309
- this[HELPER] = Helper;
271
+ this._keys = this.config.keys.split(',').map(s => s.trim());
310
272
  }
311
- return this[HELPER];
273
+ return this._keys;
312
274
  }
313
275
 
314
276
  /**
@@ -316,17 +278,15 @@ class Application extends EggApplication {
316
278
  *
317
279
  * @private
318
280
  */
319
- [BIND_EVENTS]() {
281
+ #bindEvents() {
320
282
  // Browser Cookie Limits: http://browsercookielimits.squawky.net/
321
283
  this.on('cookieLimitExceed', ({ name, value, ctx }) => {
322
284
  const err = new Error(`cookie ${name}'s length(${value.length}) exceed the limit(4093)`);
323
285
  err.name = 'CookieLimitExceedError';
324
- err.key = name;
325
- err.cookie = value;
326
286
  ctx.coreLogger.error(err);
327
287
  });
328
288
  // expose server to support websocket
329
- this.once('server', server => this.onServer(server));
289
+ this.once('server', (server: http.Server) => this.onServer(server));
330
290
  }
331
291
 
332
292
  /**
@@ -334,15 +294,14 @@ class Application extends EggApplication {
334
294
  *
335
295
  * @private
336
296
  */
337
- [WARN_CONFUSED_CONFIG]() {
297
+ #warnConfusedConfig() {
338
298
  const confusedConfigurations = this.config.confusedConfigurations;
339
299
  Object.keys(confusedConfigurations).forEach(key => {
340
300
  if (this.config[key] !== undefined) {
341
- this.logger.warn('Unexpected config key `%s` exists, Please use `%s` instead.',
301
+ this.logger.warn('[egg:application] Unexpected config key `%o` exists, Please use `%o` instead.',
342
302
  key, confusedConfigurations[key]);
343
303
  }
344
304
  });
345
305
  }
346
306
  }
347
307
 
348
- module.exports = Application;
@@ -0,0 +1,21 @@
1
+ import { BaseContextClass as EggCoreBaseContextClass } from '@eggjs/core';
2
+ import type { EggContext } from '../egg.js';
3
+ import { BaseContextLogger } from './base_context_logger.js';
4
+
5
+ /**
6
+ * BaseContextClass is a base class that can be extended,
7
+ * it's instantiated in context level,
8
+ * {@link Helper}, {@link Service} is extending it.
9
+ */
10
+ export class BaseContextClass extends EggCoreBaseContextClass {
11
+ declare ctx: EggContext;
12
+ protected pathName?: string;
13
+ #logger?: BaseContextLogger;
14
+
15
+ get logger() {
16
+ if (!this.#logger) {
17
+ this.#logger = new BaseContextLogger(this.ctx, this.pathName);
18
+ }
19
+ return this.#logger;
20
+ }
21
+ }
@@ -0,0 +1,67 @@
1
+ import type { EggContext } from '../egg.js';
2
+
3
+ export class BaseContextLogger {
4
+ readonly #ctx: EggContext;
5
+ readonly #pathName?: string;
6
+
7
+ /**
8
+ * @class
9
+ * @param {Context} ctx - context instance
10
+ * @param {String} pathName - class path name
11
+ * @since 1.0.0
12
+ */
13
+ constructor(ctx: EggContext, pathName?: string) {
14
+ /**
15
+ * @member {Context} BaseContextLogger#ctx
16
+ * @since 1.2.0
17
+ */
18
+ this.#ctx = ctx;
19
+ this.#pathName = pathName;
20
+ }
21
+
22
+ protected _log(method: 'info' | 'warn' | 'error' | 'debug', args: any[]) {
23
+ // add `[${pathName}]` in log
24
+ if (this.#pathName && typeof args[0] === 'string') {
25
+ args[0] = `[${this.#pathName}] ${args[0]}`;
26
+ }
27
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
28
+ // @ts-ignore
29
+ this.#ctx.app.logger[method](...args);
30
+ }
31
+
32
+ /**
33
+ * @member {Function} BaseContextLogger#debug
34
+ * @param {...any} args - log msg
35
+ * @since 1.2.0
36
+ */
37
+ debug(...args: any[]) {
38
+ this._log('debug', args);
39
+ }
40
+
41
+ /**
42
+ * @member {Function} BaseContextLogger#info
43
+ * @param {...any} args - log msg
44
+ * @since 1.2.0
45
+ */
46
+ info(...args: any[]) {
47
+ this._log('info', args);
48
+ }
49
+
50
+ /**
51
+ * @member {Function} BaseContextLogger#warn
52
+ * @param {...any} args - log msg
53
+ * @since 1.2.0
54
+ */
55
+ warn(...args: any[]) {
56
+ this._log('warn', args);
57
+ }
58
+
59
+ /**
60
+ * @member {Function} BaseContextLogger#error
61
+ * @param {...any} args - log msg
62
+ * @since 1.2.0
63
+ */
64
+ error(...args: any[]) {
65
+ this._log('error', args);
66
+ }
67
+ }
@@ -0,0 +1,30 @@
1
+ import assert from 'node:assert';
2
+ import type { ILifecycleBoot } from '@eggjs/core';
3
+ import type { Application, Agent } from '../../index.js';
4
+
5
+ export class BaseHookClass implements ILifecycleBoot {
6
+ fullPath?: string;
7
+ #instance: Application | Agent;
8
+
9
+ constructor(instance: Application | Agent) {
10
+ this.#instance = instance;
11
+ }
12
+
13
+ get logger(): any {
14
+ return this.#instance.logger;
15
+ }
16
+
17
+ get config() {
18
+ return this.#instance.config;
19
+ }
20
+
21
+ get app() {
22
+ assert(this.#instance.type === 'application', 'agent boot should not use app instance');
23
+ return this.#instance as Application;
24
+ }
25
+
26
+ get agent() {
27
+ assert(this.#instance.type === 'agent', 'app boot should not use agent instance');
28
+ return this.#instance as Agent;
29
+ }
30
+ }
@@ -0,0 +1,33 @@
1
+ import type { EggContext, EggApplicationCore } from '../egg.js';
2
+ import type {
3
+ HttpClientRequestURL, HttpClientRequestOptions,
4
+ } from './httpclient.js';
5
+
6
+ export class ContextHttpClient {
7
+ ctx: EggContext;
8
+ app: EggApplicationCore;
9
+
10
+ constructor(ctx: EggContext) {
11
+ this.ctx = ctx;
12
+ this.app = ctx.app;
13
+ }
14
+
15
+ /**
16
+ * http request helper base on {@link HttpClient}, it will auto save httpclient log.
17
+ * Keep the same api with {@link Application#curl}.
18
+ *
19
+ * @param {String|Object} url - request url address.
20
+ * @param {Object} [options] - options for request.
21
+ */
22
+ async curl<T = any>(url: HttpClientRequestURL, options?: HttpClientRequestOptions) {
23
+ options = {
24
+ ...options,
25
+ ctx: this.ctx,
26
+ };
27
+ return await this.app.curl<T>(url, options);
28
+ }
29
+
30
+ async request<T = any>(url: HttpClientRequestURL, options?: HttpClientRequestOptions) {
31
+ return await this.curl<T>(url, options);
32
+ }
33
+ }
@@ -0,0 +1,52 @@
1
+ import { EggCoreContext } from '@eggjs/core';
2
+ import {
3
+ HttpClient as RawHttpClient,
4
+ RequestURL as HttpClientRequestURL,
5
+ RequestOptions,
6
+ } from 'urllib';
7
+ import ms from 'ms';
8
+ import type { EggApplicationCore } from '../egg.js';
9
+
10
+ export type {
11
+ HttpClientResponse,
12
+ RequestURL as HttpClientRequestURL,
13
+ } from 'urllib';
14
+
15
+ export interface HttpClientRequestOptions extends RequestOptions {
16
+ ctx?: EggCoreContext;
17
+ tracer?: unknown;
18
+ }
19
+
20
+ export class HttpClient extends RawHttpClient {
21
+ readonly #app: EggApplicationCore & { tracer?: unknown };
22
+
23
+ constructor(app: EggApplicationCore) {
24
+ normalizeConfig(app);
25
+ const config = app.config.httpclient;
26
+ super({
27
+ defaultArgs: config.request,
28
+ });
29
+ this.#app = app;
30
+ }
31
+
32
+ async request<T = any>(url: HttpClientRequestURL, options?: HttpClientRequestOptions) {
33
+ options = options ?? {};
34
+ if (options.ctx?.tracer) {
35
+ options.tracer = options.ctx.tracer;
36
+ } else {
37
+ options.tracer = options.tracer ?? this.#app.tracer;
38
+ }
39
+ return await super.request<T>(url, options);
40
+ }
41
+
42
+ async curl<T = any>(url: HttpClientRequestURL, options?: HttpClientRequestOptions) {
43
+ return await this.request<T>(url, options);
44
+ }
45
+ }
46
+
47
+ function normalizeConfig(app: EggApplicationCore) {
48
+ const config = app.config.httpclient;
49
+ if (typeof config.request?.timeout === 'string') {
50
+ config.request.timeout = ms(config.request.timeout as string);
51
+ }
52
+ }
@@ -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} pid - the process id of the receiver
15
+ * @param {String} action - message key
16
+ * @param {Object} data - message value
17
+ * @return {Messenger} this
18
+ */
19
+ sendTo(pid: 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();
15
+ }