@eggjs/core 6.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +296 -0
- package/dist/commonjs/base_context_class.d.ts +16 -0
- package/dist/commonjs/base_context_class.js +41 -0
- package/dist/commonjs/egg.d.ts +204 -0
- package/dist/commonjs/egg.js +346 -0
- package/dist/commonjs/index.d.ts +5 -0
- package/dist/commonjs/index.js +26 -0
- package/dist/commonjs/lifecycle.d.ts +75 -0
- package/dist/commonjs/lifecycle.js +306 -0
- package/dist/commonjs/loader/context_loader.d.ts +24 -0
- package/dist/commonjs/loader/context_loader.js +109 -0
- package/dist/commonjs/loader/egg_loader.d.ts +405 -0
- package/dist/commonjs/loader/egg_loader.js +1497 -0
- package/dist/commonjs/loader/file_loader.d.ts +96 -0
- package/dist/commonjs/loader/file_loader.js +248 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/commonjs/types.d.ts +1 -0
- package/dist/commonjs/types.js +403 -0
- package/dist/commonjs/utils/index.d.ts +14 -0
- package/dist/commonjs/utils/index.js +146 -0
- package/dist/commonjs/utils/sequencify.d.ts +13 -0
- package/dist/commonjs/utils/sequencify.js +59 -0
- package/dist/commonjs/utils/timing.d.ts +22 -0
- package/dist/commonjs/utils/timing.js +100 -0
- package/dist/esm/base_context_class.d.ts +16 -0
- package/dist/esm/base_context_class.js +37 -0
- package/dist/esm/egg.d.ts +204 -0
- package/dist/esm/egg.js +339 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/lifecycle.d.ts +75 -0
- package/dist/esm/lifecycle.js +276 -0
- package/dist/esm/loader/context_loader.d.ts +24 -0
- package/dist/esm/loader/context_loader.js +102 -0
- package/dist/esm/loader/egg_loader.d.ts +405 -0
- package/dist/esm/loader/egg_loader.js +1490 -0
- package/dist/esm/loader/file_loader.d.ts +96 -0
- package/dist/esm/loader/file_loader.js +241 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/types.d.ts +1 -0
- package/dist/esm/types.js +402 -0
- package/dist/esm/utils/index.d.ts +14 -0
- package/dist/esm/utils/index.js +141 -0
- package/dist/esm/utils/sequencify.d.ts +13 -0
- package/dist/esm/utils/sequencify.js +56 -0
- package/dist/esm/utils/timing.d.ts +22 -0
- package/dist/esm/utils/timing.js +93 -0
- package/package.json +103 -0
- package/src/base_context_class.ts +39 -0
- package/src/egg.ts +430 -0
- package/src/index.ts +6 -0
- package/src/lifecycle.ts +363 -0
- package/src/loader/context_loader.ts +121 -0
- package/src/loader/egg_loader.ts +1703 -0
- package/src/loader/file_loader.ts +295 -0
- package/src/types.ts +447 -0
- package/src/utils/index.ts +154 -0
- package/src/utils/sequencify.ts +70 -0
- package/src/utils/timing.ts +114 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
// import type KoaApplication from '@eggjs/koa';
|
|
2
|
+
// // import type depd = require('depd');
|
|
3
|
+
// import type { Logger } from 'egg-logger';
|
|
4
|
+
|
|
5
|
+
// export type EggType = 'application' | 'agent';
|
|
6
|
+
|
|
7
|
+
// interface PlainObject<T = any> {
|
|
8
|
+
// [key: string]: T;
|
|
9
|
+
// }
|
|
10
|
+
|
|
11
|
+
// export interface EggCoreOptions {
|
|
12
|
+
// /** egg type, application or agent */
|
|
13
|
+
// type?: EggType;
|
|
14
|
+
// /** the directory of application */
|
|
15
|
+
// baseDir?: EggAppInfo['baseDir'];
|
|
16
|
+
// /** server scope */
|
|
17
|
+
// serverScope?: string;
|
|
18
|
+
// /** custom plugins */
|
|
19
|
+
// plugins?: Plugins;
|
|
20
|
+
// }
|
|
21
|
+
|
|
22
|
+
// export interface EggLoaderOptions {
|
|
23
|
+
// /** Application instance */
|
|
24
|
+
// app: EggCore;
|
|
25
|
+
// /** the directory of application */
|
|
26
|
+
// baseDir: EggAppInfo['baseDir'];
|
|
27
|
+
// /** egg logger */
|
|
28
|
+
// logger: Logger;
|
|
29
|
+
// /** server scope */
|
|
30
|
+
// serverScope?: string;
|
|
31
|
+
// /** custom plugins */
|
|
32
|
+
// plugins?: Plugins;
|
|
33
|
+
// }
|
|
34
|
+
|
|
35
|
+
// export interface PluginInfo {
|
|
36
|
+
// /** the plugin name, it can be used in `dep` */
|
|
37
|
+
// name: string;
|
|
38
|
+
// /** the package name of plugin */
|
|
39
|
+
// package: string;
|
|
40
|
+
// /** whether enabled */
|
|
41
|
+
// enable: boolean;
|
|
42
|
+
// /** the directory of the plugin package */
|
|
43
|
+
// path: string;
|
|
44
|
+
// /** the dependent plugins, you can use the plugin name */
|
|
45
|
+
// dependencies: string[];
|
|
46
|
+
// /** the optional dependent plugins. */
|
|
47
|
+
// optionalDependencies: string[];
|
|
48
|
+
// /** specify the serverEnv that only enable the plugin in it */
|
|
49
|
+
// env: string[];
|
|
50
|
+
// /** the file plugin config in. */
|
|
51
|
+
// from: string;
|
|
52
|
+
// }
|
|
53
|
+
|
|
54
|
+
// export interface Plugins extends PlainObject<PluginInfo> { }
|
|
55
|
+
|
|
56
|
+
// export interface EggCoreBase<Config> extends KoaApplication {
|
|
57
|
+
// /**
|
|
58
|
+
// * Whether `application` or `agent`
|
|
59
|
+
// * @member {String}
|
|
60
|
+
// * @since 1.0.0
|
|
61
|
+
// */
|
|
62
|
+
// type: EggType;
|
|
63
|
+
|
|
64
|
+
// /**
|
|
65
|
+
// * The current directory of application
|
|
66
|
+
// * @member {String}
|
|
67
|
+
// * @see {@link EggAppInfo#baseDir}
|
|
68
|
+
// * @since 1.0.0
|
|
69
|
+
// */
|
|
70
|
+
// baseDir: EggAppInfo['baseDir'];
|
|
71
|
+
|
|
72
|
+
// /**
|
|
73
|
+
// * The name of application
|
|
74
|
+
// * @member {String}
|
|
75
|
+
// * @see {@link EggAppInfo#name}
|
|
76
|
+
// * @since 1.0.0
|
|
77
|
+
// */
|
|
78
|
+
// name: EggAppInfo['name'];
|
|
79
|
+
|
|
80
|
+
// /**
|
|
81
|
+
// * Convert a generator function to a promisable one.
|
|
82
|
+
// *
|
|
83
|
+
// * Notice: for other kinds of functions, it directly returns you what it is.
|
|
84
|
+
// *
|
|
85
|
+
// * @param {Function} fn The inputted function.
|
|
86
|
+
// * @return {AsyncFunction} An async promise-based function.
|
|
87
|
+
// * @example
|
|
88
|
+
// * ```javascript
|
|
89
|
+
// * const fn = function* (arg) {
|
|
90
|
+
// return arg;
|
|
91
|
+
// };
|
|
92
|
+
// const wrapped = app.toAsyncFunction(fn);
|
|
93
|
+
// wrapped(true).then((value) => console.log(value));
|
|
94
|
+
// * ```
|
|
95
|
+
// */
|
|
96
|
+
// toAsyncFunction<T = any>(fn: (...args: any[]) => IterableIterator<T>): (...args: any[]) => Promise<T>;
|
|
97
|
+
|
|
98
|
+
// /**
|
|
99
|
+
// * Convert an object with generator functions to a Promisable one.
|
|
100
|
+
// * @param {Mixed} obj The inputted object.
|
|
101
|
+
// * @return {Promise} A Promisable result.
|
|
102
|
+
// * @example
|
|
103
|
+
// * ```javascript
|
|
104
|
+
// * const fn = function* (arg) {
|
|
105
|
+
// return arg;
|
|
106
|
+
// };
|
|
107
|
+
// const arr = [ fn(1), fn(2) ];
|
|
108
|
+
// const promise = app.toPromise(arr);
|
|
109
|
+
// promise.then(res => console.log(res));
|
|
110
|
+
// * ```
|
|
111
|
+
// */
|
|
112
|
+
// toPromise<T = any>(obj: any): Promise<T>;
|
|
113
|
+
|
|
114
|
+
// /**
|
|
115
|
+
// * register an callback function that will be invoked when application is ready.
|
|
116
|
+
// * @see https://github.com/node-modules/ready
|
|
117
|
+
// * @since 1.0.0
|
|
118
|
+
// * @param {boolean|Error|Function} flagOrFunction -
|
|
119
|
+
// * @return {Promise|null} return promise when argument is undefined
|
|
120
|
+
// * @example
|
|
121
|
+
// * const app = new Application(...);
|
|
122
|
+
// * app.ready(err => {
|
|
123
|
+
// * if (err) throw err;
|
|
124
|
+
// * console.log('done');
|
|
125
|
+
// * });
|
|
126
|
+
// */
|
|
127
|
+
// ready(fn?: (err?: Error) => void): any;
|
|
128
|
+
|
|
129
|
+
// /**
|
|
130
|
+
// * Close all, it wil close
|
|
131
|
+
// * - callbacks registered by beforeClose
|
|
132
|
+
// * - emit `close` event
|
|
133
|
+
// * - remove add listeners
|
|
134
|
+
// *
|
|
135
|
+
// * If error is thrown when it's closing, the promise will reject.
|
|
136
|
+
// * It will also reject after following call.
|
|
137
|
+
// * @return {Promise} promise
|
|
138
|
+
// * @since 1.0.0
|
|
139
|
+
// */
|
|
140
|
+
// close(): Promise<any>;
|
|
141
|
+
|
|
142
|
+
// /**
|
|
143
|
+
// * If a client starts asynchronously, you can register `readyCallback`,
|
|
144
|
+
// * then the application will wait for the callback to ready
|
|
145
|
+
// *
|
|
146
|
+
// * It will log when the callback is not invoked after 10s
|
|
147
|
+
// *
|
|
148
|
+
// * Recommend to use {@link EggCore#beforeStart}
|
|
149
|
+
// * @since 1.0.0
|
|
150
|
+
// *
|
|
151
|
+
// * @param {String} name - readyCallback task name
|
|
152
|
+
// * @param {object} opts -
|
|
153
|
+
// * - {Number} [timeout=10000] - emit `ready_timeout` when it doesn't finish but reach the timeout
|
|
154
|
+
// * - {Boolean} [isWeakDep=false] - whether it's a weak dependency
|
|
155
|
+
// * @return {Function} - a callback
|
|
156
|
+
// * @example
|
|
157
|
+
// * const done = app.readyCallback('mysql');
|
|
158
|
+
// * mysql.ready(done);
|
|
159
|
+
// */
|
|
160
|
+
// readyCallback(name: string, opts?: { timeout?: number; isWeakDep?: boolean }): () => void;
|
|
161
|
+
|
|
162
|
+
// /**
|
|
163
|
+
// * The loader instance, the default class is {@link EggLoader}.
|
|
164
|
+
// * If you want define
|
|
165
|
+
// * @member {EggLoader} EggCore#loader
|
|
166
|
+
// * @since 1.0.0
|
|
167
|
+
// */
|
|
168
|
+
// loader: EggLoader<this, Config>;
|
|
169
|
+
|
|
170
|
+
// /**
|
|
171
|
+
// * The configuration of application
|
|
172
|
+
// * @member {Config}
|
|
173
|
+
// * @since 1.0.0
|
|
174
|
+
// */
|
|
175
|
+
// config: Config;
|
|
176
|
+
|
|
177
|
+
// /**
|
|
178
|
+
// * Retrieve enabled plugins
|
|
179
|
+
// * @member {Object}
|
|
180
|
+
// * @since 1.0.0
|
|
181
|
+
// */
|
|
182
|
+
// plugins: Plugins;
|
|
183
|
+
|
|
184
|
+
// /**
|
|
185
|
+
// * Register a function that will be called when app close
|
|
186
|
+
// */
|
|
187
|
+
// beforeClose(fn: () => void): void;
|
|
188
|
+
|
|
189
|
+
// /**
|
|
190
|
+
// * Execute scope after loaded and before app start
|
|
191
|
+
// */
|
|
192
|
+
// beforeStart(scope: () => void): void;
|
|
193
|
+
|
|
194
|
+
// /**
|
|
195
|
+
// * Alias to {@link https://npmjs.com/package/depd}
|
|
196
|
+
// * @member {Function}
|
|
197
|
+
// * @since 1.0.0
|
|
198
|
+
// */
|
|
199
|
+
// deprecate: depd.Deprecate;
|
|
200
|
+
// }
|
|
201
|
+
|
|
202
|
+
// export interface EggCore<Config = PlainObject> extends EggCoreBase<Config> {
|
|
203
|
+
// Controller: typeof BaseContextClass;
|
|
204
|
+
// Service: typeof BaseContextClass;
|
|
205
|
+
// }
|
|
206
|
+
|
|
207
|
+
// export class EggCore {
|
|
208
|
+
// /**
|
|
209
|
+
// * @class
|
|
210
|
+
// * @param {Object} options - options
|
|
211
|
+
// * @param {String} [options.baseDir=process.cwd()] - the directory of application
|
|
212
|
+
// * @param {String} [options.type=application|agent] - whether it's running in app worker or agent worker
|
|
213
|
+
// * @param {Object} [options.plugins] - custom plugins
|
|
214
|
+
// * @since 1.0.0
|
|
215
|
+
// */
|
|
216
|
+
// constructor(options?: EggCoreOptions);
|
|
217
|
+
// }
|
|
218
|
+
|
|
219
|
+
// /**
|
|
220
|
+
// * egg app info
|
|
221
|
+
// * @example
|
|
222
|
+
// * ```js
|
|
223
|
+
// * // config/config.default.ts
|
|
224
|
+
// * import { EggAppInfo } from 'egg';
|
|
225
|
+
// *
|
|
226
|
+
// * export default (appInfo: EggAppInfo) => {
|
|
227
|
+
// * return {
|
|
228
|
+
// * keys: appInfo.name + '123456',
|
|
229
|
+
// * };
|
|
230
|
+
// * }
|
|
231
|
+
// * ```
|
|
232
|
+
// */
|
|
233
|
+
// export interface EggAppInfo {
|
|
234
|
+
// /** package.json */
|
|
235
|
+
// pkg: PlainObject;
|
|
236
|
+
// /** the application name from package.json */
|
|
237
|
+
// name: string;
|
|
238
|
+
// /** current directory of application */
|
|
239
|
+
// baseDir: string;
|
|
240
|
+
// /** equals to serverEnv */
|
|
241
|
+
// env: string;
|
|
242
|
+
// /** home directory of the OS */
|
|
243
|
+
// HOME: string;
|
|
244
|
+
// /** baseDir when local and unittest, HOME when other environment */
|
|
245
|
+
// root: string;
|
|
246
|
+
// }
|
|
247
|
+
|
|
248
|
+
// /**
|
|
249
|
+
// * BaseContextClass is a base class that can be extended,
|
|
250
|
+
// * it's instantiated in context level,
|
|
251
|
+
// * {@link Helper}, {@link Service} is extending it.
|
|
252
|
+
// */
|
|
253
|
+
// export class BaseContextClass<
|
|
254
|
+
// Context = any,
|
|
255
|
+
// Application = any,
|
|
256
|
+
// EggAppConfig = any,
|
|
257
|
+
// Service = any
|
|
258
|
+
// > {
|
|
259
|
+
// constructor(ctx: Context);
|
|
260
|
+
|
|
261
|
+
// /** request context */
|
|
262
|
+
// protected ctx: Context;
|
|
263
|
+
|
|
264
|
+
// /** Application */
|
|
265
|
+
// protected app: Application;
|
|
266
|
+
|
|
267
|
+
// /** Application config object */
|
|
268
|
+
// protected config: EggAppConfig;
|
|
269
|
+
|
|
270
|
+
// /** service */
|
|
271
|
+
// protected service: Service;
|
|
272
|
+
// }
|
|
273
|
+
|
|
274
|
+
// declare interface FileLoaderBase {
|
|
275
|
+
// /**
|
|
276
|
+
// * attach items to target object. Mapping the directory to properties.
|
|
277
|
+
// * `app/controller/group/repository.js` => `target.group.repository`
|
|
278
|
+
// * @return {Object} target
|
|
279
|
+
// * @since 1.0.0
|
|
280
|
+
// */
|
|
281
|
+
// load(): object;
|
|
282
|
+
|
|
283
|
+
// /**
|
|
284
|
+
// * Parse files from given directories, then return an items list, each item contains properties and exports.
|
|
285
|
+
// *
|
|
286
|
+
// * For example, parse `app/controller/group/repository.js`
|
|
287
|
+
// *
|
|
288
|
+
// * ```js
|
|
289
|
+
// * module.exports = app => {
|
|
290
|
+
// * return class RepositoryController extends app.Controller {};
|
|
291
|
+
// * }
|
|
292
|
+
// * ```
|
|
293
|
+
// *
|
|
294
|
+
// * It returns a item
|
|
295
|
+
// *
|
|
296
|
+
// * ```js
|
|
297
|
+
// * {
|
|
298
|
+
// * properties: [ 'group', 'repository' ],
|
|
299
|
+
// * exports: app => { ... },
|
|
300
|
+
// * }
|
|
301
|
+
// * ```
|
|
302
|
+
// *
|
|
303
|
+
// * `Properties` is an array that contains the directory of a filepath.
|
|
304
|
+
// *
|
|
305
|
+
// * `Exports` depends on type, if exports is a function, it will be called. if initializer is specified, it will be called with exports for customizing.
|
|
306
|
+
// * @return {Array} items
|
|
307
|
+
// * @since 1.0.0
|
|
308
|
+
// */
|
|
309
|
+
// parse(): Array<{ fullpath: string; properties: string[]; exports: any; }>;
|
|
310
|
+
// }
|
|
311
|
+
|
|
312
|
+
// declare interface ContextLoaderBase extends FileLoaderBase {}
|
|
313
|
+
|
|
314
|
+
// export interface FileLoader {
|
|
315
|
+
// /**
|
|
316
|
+
// * Load files from directory to target object.
|
|
317
|
+
// * @since 1.0.0
|
|
318
|
+
// */
|
|
319
|
+
// new (options: FileLoaderOption): FileLoaderBase;
|
|
320
|
+
// }
|
|
321
|
+
|
|
322
|
+
// export interface ContextLoader {
|
|
323
|
+
// /**
|
|
324
|
+
// * Same as {@link FileLoader}, but it will attach file to `inject[fieldClass]`. The exports will be lazy loaded, such as `ctx.group.repository`.
|
|
325
|
+
// * @augments FileLoader
|
|
326
|
+
// * @since 1.0.0
|
|
327
|
+
// */
|
|
328
|
+
// new (options: ContextLoaderOption): ContextLoaderBase;
|
|
329
|
+
// }
|
|
330
|
+
|
|
331
|
+
// export class EggLoader<
|
|
332
|
+
// T = EggCore,
|
|
333
|
+
// Config = any,
|
|
334
|
+
// Options extends EggLoaderOptions = EggLoaderOptions
|
|
335
|
+
// > {
|
|
336
|
+
// app: T;
|
|
337
|
+
// eggPaths: string[];
|
|
338
|
+
// pkg: PlainObject;
|
|
339
|
+
// appInfo: EggAppInfo;
|
|
340
|
+
// serverScope: string;
|
|
341
|
+
// plugins: Plugins;
|
|
342
|
+
// config: Config;
|
|
343
|
+
// options: Options;
|
|
344
|
+
|
|
345
|
+
// /**
|
|
346
|
+
// * @class
|
|
347
|
+
// * @param {Object} options - options
|
|
348
|
+
// * @param {String} options.baseDir - the directory of application
|
|
349
|
+
// * @param {EggCore} options.app - Application instance
|
|
350
|
+
// * @param {Logger} options.logger - logger
|
|
351
|
+
// * @param {Object} [options.plugins] - custom plugins
|
|
352
|
+
// * @since 1.0.0
|
|
353
|
+
// */
|
|
354
|
+
// constructor(options: EggLoaderOptions);
|
|
355
|
+
|
|
356
|
+
// /**
|
|
357
|
+
// * Get home directory
|
|
358
|
+
// * @return {String} home directory
|
|
359
|
+
// * @since 3.4.0
|
|
360
|
+
// */
|
|
361
|
+
// getHomedir(): EggAppInfo['HOME'];
|
|
362
|
+
|
|
363
|
+
// /**
|
|
364
|
+
// * Get app info
|
|
365
|
+
// * @return {EggAppInfo} appInfo
|
|
366
|
+
// * @since 1.0.0
|
|
367
|
+
// */
|
|
368
|
+
// getAppInfo(): EggAppInfo;
|
|
369
|
+
|
|
370
|
+
// // Low Level API
|
|
371
|
+
|
|
372
|
+
// /**
|
|
373
|
+
// * Load single file, will invoke when export is function
|
|
374
|
+
// *
|
|
375
|
+
// * @param {String} filepath - fullpath
|
|
376
|
+
// * @param {Array} arguments - pass rest arguments into the function when invoke
|
|
377
|
+
// * @return {Object} exports
|
|
378
|
+
// * @example
|
|
379
|
+
// * ```js
|
|
380
|
+
// * app.loader.loadFile(path.join(app.options.baseDir, 'config/router.js'));
|
|
381
|
+
// * ```
|
|
382
|
+
// * @since 1.0.0
|
|
383
|
+
// */
|
|
384
|
+
// loadFile<T = any>(filepath: string, ...inject: any[]): T;
|
|
385
|
+
|
|
386
|
+
// /**
|
|
387
|
+
// * Get all loadUnit
|
|
388
|
+
// *
|
|
389
|
+
// * loadUnit is a directory that can be loaded by EggLoader, it has the same structure.
|
|
390
|
+
// * loadUnit has a path and a type(app, framework, plugin).
|
|
391
|
+
// *
|
|
392
|
+
// * The order of the loadUnits:
|
|
393
|
+
// *
|
|
394
|
+
// * 1. plugin
|
|
395
|
+
// * 2. framework
|
|
396
|
+
// * 3. app
|
|
397
|
+
// *
|
|
398
|
+
// * @return {Array} loadUnits
|
|
399
|
+
// * @since 1.0.0
|
|
400
|
+
// */
|
|
401
|
+
// getLoadUnits(): Array<{ path: string; type: string; }>;
|
|
402
|
+
|
|
403
|
+
// getEggPaths(): string[];
|
|
404
|
+
|
|
405
|
+
// getServerEnv(): string;
|
|
406
|
+
|
|
407
|
+
// /**
|
|
408
|
+
// * Load files using {@link FileLoader}, inject to {@link Application}
|
|
409
|
+
// * @param {String|Array} directory - see {@link FileLoader}
|
|
410
|
+
// * @param {String} property - see {@link FileLoader}
|
|
411
|
+
// * @param {Object} opt - see {@link FileLoader}
|
|
412
|
+
// * @since 1.0.0
|
|
413
|
+
// */
|
|
414
|
+
// loadToApp(directory: string | string[], property: string, opt?: Partial<FileLoaderOption>): void;
|
|
415
|
+
|
|
416
|
+
// /**
|
|
417
|
+
// * Load files using {@link ContextLoader}
|
|
418
|
+
// * @param {String|Array} directory - see {@link ContextLoader}
|
|
419
|
+
// * @param {String} property - see {@link ContextLoader}
|
|
420
|
+
// * @param {Object} opt - see {@link ContextLoader}
|
|
421
|
+
// * @since 1.0.0
|
|
422
|
+
// */
|
|
423
|
+
// loadToContext(directory: string | string[], property: string, opt?: Partial<ContextLoaderOption>): void;
|
|
424
|
+
|
|
425
|
+
// getTypeFiles(filename: string): string[];
|
|
426
|
+
// resolveModule(filepath: string): string | undefined;
|
|
427
|
+
|
|
428
|
+
// FileLoader: FileLoader;
|
|
429
|
+
// ContextLoader: ContextLoader;
|
|
430
|
+
|
|
431
|
+
// // load methods
|
|
432
|
+
// protected loadConfig(): void;
|
|
433
|
+
// protected loadController(opt?: Partial<FileLoaderOption>): void;
|
|
434
|
+
// protected loadCustomLoader(): void;
|
|
435
|
+
// protected loadCustomApp(): void;
|
|
436
|
+
// protected loadCustomAgent(): void;
|
|
437
|
+
// protected loadAgentExtend(): void;
|
|
438
|
+
// protected loadApplicationExtend(): void;
|
|
439
|
+
// protected loadRequestExtend(): void;
|
|
440
|
+
// protected loadResponseExtend(): void;
|
|
441
|
+
// protected loadContextExtend(): void;
|
|
442
|
+
// protected loadHelperExtend(): void;
|
|
443
|
+
// protected loadMiddleware(opt?: Partial<FileLoaderOption>): void;
|
|
444
|
+
// protected loadPlugin(): void;
|
|
445
|
+
// protected loadRouter(): void;
|
|
446
|
+
// protected loadService(opt?: Partial<ContextLoaderOption>): void;
|
|
447
|
+
// }
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { debuglog } from 'node:util';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import BuiltinModule from 'node:module';
|
|
6
|
+
import { createRequire } from 'node:module';
|
|
7
|
+
|
|
8
|
+
const debug = debuglog('@eggjs/core:utils');
|
|
9
|
+
|
|
10
|
+
export type Fun = (...args: any[]) => any;
|
|
11
|
+
|
|
12
|
+
// Guard against poorly mocked module constructors.
|
|
13
|
+
const Module = typeof module !== 'undefined' && module.constructor.length > 1
|
|
14
|
+
? module.constructor
|
|
15
|
+
/* istanbul ignore next */
|
|
16
|
+
: BuiltinModule;
|
|
17
|
+
|
|
18
|
+
const extensions = (Module as any)._extensions;
|
|
19
|
+
const extensionNames = Object.keys(extensions).concat([ '.cjs', '.mjs' ]);
|
|
20
|
+
debug('Module extensions: %j', extensionNames);
|
|
21
|
+
|
|
22
|
+
let _customRequire: NodeRequire;
|
|
23
|
+
function getCustomRequire() {
|
|
24
|
+
if (!_customRequire && typeof require === 'undefined') {
|
|
25
|
+
_customRequire = createRequire(process.cwd());
|
|
26
|
+
// _customRequire = createRequire(import.meta.url);
|
|
27
|
+
}
|
|
28
|
+
return _customRequire;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
deprecated(message: string) {
|
|
33
|
+
console.warn('[@eggjs/core:deprecated] %s', message);
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
extensions,
|
|
37
|
+
|
|
38
|
+
// async _importOrRequire(filepath: string) {
|
|
39
|
+
// // try import first
|
|
40
|
+
// let obj: any;
|
|
41
|
+
// try {
|
|
42
|
+
// obj = await import(filepath);
|
|
43
|
+
// } catch (err: any) {
|
|
44
|
+
// debug('await import error, use require instead, %s', err);
|
|
45
|
+
// // use custom require
|
|
46
|
+
// obj = getCustomRequire()(filepath);
|
|
47
|
+
// }
|
|
48
|
+
// return obj;
|
|
49
|
+
// },
|
|
50
|
+
|
|
51
|
+
async loadFile(filepath: string) {
|
|
52
|
+
try {
|
|
53
|
+
// if not js module, just return content buffer
|
|
54
|
+
const extname = path.extname(filepath);
|
|
55
|
+
if (extname && !extensionNames.includes(extname)) {
|
|
56
|
+
return fs.readFileSync(filepath);
|
|
57
|
+
}
|
|
58
|
+
let obj: any;
|
|
59
|
+
let isESM = false;
|
|
60
|
+
if (typeof require === 'function') {
|
|
61
|
+
// commonjs
|
|
62
|
+
obj = require(filepath);
|
|
63
|
+
debug('[loadFile] require %s => %o', filepath, obj);
|
|
64
|
+
if (obj && obj.__esModule) {
|
|
65
|
+
isESM = true;
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
// esm
|
|
69
|
+
debug('[loadFile] await import start: %s', filepath);
|
|
70
|
+
const fileUrl = pathToFileURL(filepath).toString();
|
|
71
|
+
obj = await import(fileUrl);
|
|
72
|
+
debug('[loadFile] await import end: %s => %o', filepath, obj);
|
|
73
|
+
isESM = true;
|
|
74
|
+
if (obj && typeof obj === 'object' && 'default' in obj) {
|
|
75
|
+
// default: { default: [Function (anonymous)] }
|
|
76
|
+
obj = obj.default;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!obj) return obj;
|
|
80
|
+
// it's es module, use default export
|
|
81
|
+
if (isESM && typeof obj === 'object') {
|
|
82
|
+
obj = 'default' in obj ? obj.default : obj;
|
|
83
|
+
}
|
|
84
|
+
debug('[loadFile] return %s => %o', filepath, obj);
|
|
85
|
+
return obj;
|
|
86
|
+
} catch (e: any) {
|
|
87
|
+
const err = new Error(`[@eggjs/core] load file: ${filepath}, error: ${e.message}`);
|
|
88
|
+
err.cause = e;
|
|
89
|
+
debug('[loadFile] handle %s error: %s', filepath, e);
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
resolvePath(filepath: string, options?: { paths?: string[] }) {
|
|
95
|
+
if (typeof require !== 'undefined') {
|
|
96
|
+
return require.resolve(filepath, options);
|
|
97
|
+
}
|
|
98
|
+
return getCustomRequire().resolve(filepath, options);
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
methods: [ 'head', 'options', 'get', 'put', 'patch', 'post', 'delete' ],
|
|
102
|
+
|
|
103
|
+
async callFn(fn: Fun, args?: any[], ctx?: any) {
|
|
104
|
+
args = args || [];
|
|
105
|
+
if (typeof fn !== 'function') return;
|
|
106
|
+
return ctx ? fn.call(ctx, ...args) : fn(...args);
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
getCalleeFromStack(withLine?: boolean, stackIndex?: number) {
|
|
110
|
+
stackIndex = stackIndex === undefined ? 2 : stackIndex;
|
|
111
|
+
const limit = Error.stackTraceLimit;
|
|
112
|
+
const prep = Error.prepareStackTrace;
|
|
113
|
+
|
|
114
|
+
Error.prepareStackTrace = prepareObjectStackTrace;
|
|
115
|
+
Error.stackTraceLimit = 5;
|
|
116
|
+
|
|
117
|
+
// capture the stack
|
|
118
|
+
const obj: any = {};
|
|
119
|
+
Error.captureStackTrace(obj);
|
|
120
|
+
let callSite = obj.stack[stackIndex];
|
|
121
|
+
let fileName = '';
|
|
122
|
+
if (callSite) {
|
|
123
|
+
// egg-mock will create a proxy
|
|
124
|
+
// https://github.com/eggjs/egg-mock/blob/master/lib/app.js#L174
|
|
125
|
+
fileName = callSite.getFileName();
|
|
126
|
+
/* istanbul ignore if */
|
|
127
|
+
if (fileName && fileName.endsWith('egg-mock/lib/app.js')) {
|
|
128
|
+
// TODO: add test
|
|
129
|
+
callSite = obj.stack[stackIndex + 1];
|
|
130
|
+
fileName = callSite.getFileName();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
Error.prepareStackTrace = prep;
|
|
135
|
+
Error.stackTraceLimit = limit;
|
|
136
|
+
|
|
137
|
+
if (!callSite || !fileName) return '<anonymous>';
|
|
138
|
+
if (!withLine) return fileName;
|
|
139
|
+
return `${fileName}:${callSite.getLineNumber()}:${callSite.getColumnNumber()}`;
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
getResolvedFilename(filepath: string, baseDir: string) {
|
|
143
|
+
const reg = /[/\\]/g;
|
|
144
|
+
return filepath.replace(baseDir + path.sep, '').replace(reg, '/');
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Capture call site stack from v8.
|
|
150
|
+
* https://github.com/v8/v8/wiki/Stack-Trace-API
|
|
151
|
+
*/
|
|
152
|
+
function prepareObjectStackTrace(_obj: any, stack: any) {
|
|
153
|
+
return stack;
|
|
154
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { debuglog } from 'node:util';
|
|
2
|
+
|
|
3
|
+
const debug = debuglog('@eggjs/core:utils:sequencify');
|
|
4
|
+
|
|
5
|
+
export interface SequencifyResult {
|
|
6
|
+
sequence: string[];
|
|
7
|
+
requires: Record<string, true>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface SequencifyTask {
|
|
11
|
+
dependencies: string[];
|
|
12
|
+
optionalDependencies: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function sequence(tasks: Record<string, SequencifyTask>, names: string[], result: SequencifyResult,
|
|
16
|
+
missing: string[], recursive: string[],
|
|
17
|
+
nest: string[], optional: boolean, parent: string) {
|
|
18
|
+
names.forEach(function(name) {
|
|
19
|
+
if (result.requires[name]) return;
|
|
20
|
+
|
|
21
|
+
const node = tasks[name];
|
|
22
|
+
if (!node) {
|
|
23
|
+
if (optional === true) return;
|
|
24
|
+
missing.push(name);
|
|
25
|
+
} else if (nest.includes(name)) {
|
|
26
|
+
nest.push(name);
|
|
27
|
+
recursive.push(...nest.slice(0));
|
|
28
|
+
nest.pop();
|
|
29
|
+
} else if (node.dependencies.length || node.optionalDependencies.length) {
|
|
30
|
+
nest.push(name);
|
|
31
|
+
if (node.dependencies.length) {
|
|
32
|
+
sequence(tasks, node.dependencies, result, missing, recursive, nest, optional, name);
|
|
33
|
+
}
|
|
34
|
+
if (node.optionalDependencies.length) {
|
|
35
|
+
sequence(tasks, node.optionalDependencies, result, missing, recursive, nest, true, name);
|
|
36
|
+
}
|
|
37
|
+
nest.pop();
|
|
38
|
+
}
|
|
39
|
+
if (!optional) {
|
|
40
|
+
result.requires[name] = true;
|
|
41
|
+
debug('task: %s is enabled by %s', name, parent);
|
|
42
|
+
}
|
|
43
|
+
if (!result.sequence.includes(name)) {
|
|
44
|
+
result.sequence.push(name);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// tasks: object with keys as task names
|
|
50
|
+
// names: array of task names
|
|
51
|
+
export default function sequencify(tasks: Record<string, SequencifyTask>, names: string[]) {
|
|
52
|
+
const result: SequencifyResult = {
|
|
53
|
+
sequence: [],
|
|
54
|
+
requires: {},
|
|
55
|
+
}; // the final sequence
|
|
56
|
+
const missing: string[] = []; // missing tasks
|
|
57
|
+
const recursive: string[] = []; // recursive task dependencies
|
|
58
|
+
|
|
59
|
+
sequence(tasks, names, result, missing, recursive, [], false, 'app');
|
|
60
|
+
|
|
61
|
+
if (missing.length || recursive.length) {
|
|
62
|
+
result.sequence = []; // results are incomplete at best, completely wrong at worst, remove them to avoid confusion
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
sequence: result.sequence.filter(item => result.requires[item]),
|
|
67
|
+
missingTasks: missing,
|
|
68
|
+
recursiveDependencies: recursive,
|
|
69
|
+
};
|
|
70
|
+
}
|