@eggjs/core 6.5.0 → 6.6.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +1 -5
  2. package/dist/base_context_class.d.ts +21 -0
  3. package/dist/base_context_class.js +40 -0
  4. package/dist/egg.d.ts +248 -0
  5. package/dist/egg.js +358 -0
  6. package/dist/index.d.ts +12 -0
  7. package/dist/index.js +12 -0
  8. package/dist/lifecycle.d.ts +84 -0
  9. package/dist/lifecycle.js +280 -0
  10. package/dist/loader/context_loader.d.ts +39 -0
  11. package/dist/loader/context_loader.js +79 -0
  12. package/dist/loader/egg_loader.d.ts +374 -0
  13. package/dist/loader/egg_loader.js +1184 -0
  14. package/dist/loader/file_loader.d.ts +105 -0
  15. package/dist/loader/file_loader.js +198 -0
  16. package/dist/singleton.d.ts +33 -0
  17. package/dist/singleton.js +107 -0
  18. package/{src/types.ts → dist/types.d.ts} +7 -7
  19. package/dist/utils/index.d.ts +19 -0
  20. package/dist/utils/index.js +103 -0
  21. package/dist/utils/sequencify.d.ts +16 -0
  22. package/dist/utils/sequencify.js +46 -0
  23. package/dist/utils/timing.d.ts +24 -0
  24. package/dist/utils/timing.js +85 -0
  25. package/package.json +39 -75
  26. package/dist/commonjs/base_context_class.d.ts +0 -16
  27. package/dist/commonjs/base_context_class.js +0 -41
  28. package/dist/commonjs/egg.d.ts +0 -246
  29. package/dist/commonjs/egg.js +0 -401
  30. package/dist/commonjs/index.d.ts +0 -12
  31. package/dist/commonjs/index.js +0 -32
  32. package/dist/commonjs/lifecycle.d.ts +0 -78
  33. package/dist/commonjs/lifecycle.js +0 -315
  34. package/dist/commonjs/loader/context_loader.d.ts +0 -35
  35. package/dist/commonjs/loader/context_loader.js +0 -110
  36. package/dist/commonjs/loader/egg_loader.d.ts +0 -369
  37. package/dist/commonjs/loader/egg_loader.js +0 -1558
  38. package/dist/commonjs/loader/file_loader.d.ts +0 -100
  39. package/dist/commonjs/loader/file_loader.js +0 -260
  40. package/dist/commonjs/package.json +0 -3
  41. package/dist/commonjs/singleton.d.ts +0 -29
  42. package/dist/commonjs/singleton.js +0 -124
  43. package/dist/commonjs/types.d.ts +0 -53
  44. package/dist/commonjs/types.js +0 -3
  45. package/dist/commonjs/utils/index.d.ts +0 -17
  46. package/dist/commonjs/utils/index.js +0 -117
  47. package/dist/commonjs/utils/sequencify.d.ts +0 -13
  48. package/dist/commonjs/utils/sequencify.js +0 -64
  49. package/dist/commonjs/utils/timing.d.ts +0 -21
  50. package/dist/commonjs/utils/timing.js +0 -106
  51. package/dist/esm/base_context_class.d.ts +0 -16
  52. package/dist/esm/base_context_class.js +0 -37
  53. package/dist/esm/egg.d.ts +0 -246
  54. package/dist/esm/egg.js +0 -388
  55. package/dist/esm/index.d.ts +0 -12
  56. package/dist/esm/index.js +0 -12
  57. package/dist/esm/lifecycle.d.ts +0 -78
  58. package/dist/esm/lifecycle.js +0 -308
  59. package/dist/esm/loader/context_loader.d.ts +0 -35
  60. package/dist/esm/loader/context_loader.js +0 -102
  61. package/dist/esm/loader/egg_loader.d.ts +0 -369
  62. package/dist/esm/loader/egg_loader.js +0 -1551
  63. package/dist/esm/loader/file_loader.d.ts +0 -100
  64. package/dist/esm/loader/file_loader.js +0 -253
  65. package/dist/esm/package.json +0 -3
  66. package/dist/esm/singleton.d.ts +0 -29
  67. package/dist/esm/singleton.js +0 -117
  68. package/dist/esm/types.d.ts +0 -53
  69. package/dist/esm/types.js +0 -2
  70. package/dist/esm/utils/index.d.ts +0 -17
  71. package/dist/esm/utils/index.js +0 -112
  72. package/dist/esm/utils/sequencify.d.ts +0 -13
  73. package/dist/esm/utils/sequencify.js +0 -61
  74. package/dist/esm/utils/timing.d.ts +0 -21
  75. package/dist/esm/utils/timing.js +0 -99
  76. package/dist/package.json +0 -4
  77. package/src/base_context_class.ts +0 -39
  78. package/src/egg.ts +0 -617
  79. package/src/index.ts +0 -14
  80. package/src/lifecycle.ts +0 -438
  81. package/src/loader/context_loader.ts +0 -123
  82. package/src/loader/egg_loader.ts +0 -1984
  83. package/src/loader/file_loader.ts +0 -349
  84. package/src/singleton.ts +0 -187
  85. package/src/utils/index.ts +0 -132
  86. package/src/utils/sequencify.ts +0 -105
  87. package/src/utils/timing.ts +0 -128
@@ -1,349 +0,0 @@
1
- import assert from 'node:assert';
2
- import fs from 'node:fs';
3
- import { debuglog } from 'node:util';
4
- import path from 'node:path';
5
-
6
- import globby from 'globby';
7
- import {
8
- isClass,
9
- isGeneratorFunction,
10
- isAsyncFunction,
11
- isPrimitive,
12
- } from 'is-type-of';
13
- import { isSupportTypeScript } from '@eggjs/utils';
14
-
15
- import utils, { type Fun } from '../utils/index.js';
16
-
17
- const debug = debuglog('@eggjs/core/file_loader');
18
-
19
- export const FULLPATH = Symbol('EGG_LOADER_ITEM_FULLPATH');
20
- export const EXPORTS = Symbol('EGG_LOADER_ITEM_EXPORTS');
21
-
22
- export enum CaseStyle {
23
- camel = 'camel',
24
- lower = 'lower',
25
- upper = 'upper',
26
- }
27
-
28
- export type CaseStyleFunction = (filepath: string) => string[];
29
- export type FileLoaderInitializer = (
30
- exports: unknown,
31
- options: { path: string; pathName: string }
32
- ) => unknown;
33
- export type FileLoaderFilter = (exports: unknown) => boolean;
34
-
35
- export interface FileLoaderOptions {
36
- /** directories to be loaded */
37
- directory: string | string[];
38
- /** attach the target object from loaded files */
39
-
40
- target: Record<string, any>;
41
- /** match the files when load, support glob, default to all js files */
42
- match?: string | string[];
43
- /** ignore the files when load, support glob */
44
- ignore?: string | string[];
45
- /** custom file exports, receive two parameters, first is the inject object(if not js file, will be content buffer), second is an `options` object that contain `path` */
46
- initializer?: FileLoaderInitializer;
47
- /** determine whether invoke when exports is function */
48
- call?: boolean;
49
- /** determine whether override the property when get the same name */
50
- override?: boolean;
51
- /** an object that be the argument when invoke the function */
52
-
53
- inject?: Record<string, any>;
54
- /** a function that filter the exports which can be loaded */
55
- filter?: FileLoaderFilter;
56
- /** set property's case when converting a filepath to property list. */
57
- caseStyle?: CaseStyle | CaseStyleFunction;
58
- lowercaseFirst?: boolean;
59
- }
60
-
61
- export interface FileLoaderParseItem {
62
- fullpath: string;
63
- properties: string[];
64
- exports: object | Fun;
65
- }
66
-
67
- /**
68
- * Load files from directory to target object.
69
- * @since 1.0.0
70
- */
71
- export class FileLoader {
72
- static get FULLPATH() {
73
- return FULLPATH;
74
- }
75
-
76
- static get EXPORTS() {
77
- return EXPORTS;
78
- }
79
-
80
- readonly options: FileLoaderOptions &
81
- Required<Pick<FileLoaderOptions, 'caseStyle'>>;
82
-
83
- /**
84
- * @class
85
- * @param {Object} options - options
86
- * @param {String|Array} options.directory - directories to be loaded
87
- * @param {Object} options.target - attach the target object from loaded files
88
- * @param {String} options.match - match the files when load, support glob, default to all js files
89
- * @param {String} options.ignore - ignore the files when load, support glob
90
- * @param {Function} options.initializer - custom file exports, receive two parameters, first is the inject object(if not js file, will be content buffer), second is an `options` object that contain `path`
91
- * @param {Boolean} options.call - determine whether invoke when exports is function
92
- * @param {Boolean} options.override - determine whether override the property when get the same name
93
- * @param {Object} options.inject - an object that be the argument when invoke the function
94
- * @param {Function} options.filter - a function that filter the exports which can be loaded
95
- * @param {String|Function} options.caseStyle - set property's case when converting a filepath to property list.
96
- */
97
- constructor(options: FileLoaderOptions) {
98
- assert(options.directory, 'options.directory is required');
99
- assert(options.target, 'options.target is required');
100
- this.options = {
101
- caseStyle: CaseStyle.camel,
102
- call: true,
103
- override: false,
104
- ...options,
105
- };
106
-
107
- // compatible old options _lowercaseFirst_
108
- if (this.options.lowercaseFirst === true) {
109
- utils.deprecated('lowercaseFirst is deprecated, use caseStyle instead');
110
- this.options.caseStyle = CaseStyle.lower;
111
- }
112
- }
113
-
114
- /**
115
- * attach items to target object. Mapping the directory to properties.
116
- * `app/controller/group/repository.js` => `target.group.repository`
117
- * @returns {Object} target
118
- * @since 1.0.0
119
- */
120
- async load(): Promise<object> {
121
- const items = await this.parse();
122
- const target = this.options.target;
123
- for (const item of items) {
124
- debug('loading item: %o', item);
125
- // item { properties: [ 'a', 'b', 'c'], exports }
126
- // => target.a.b.c = exports
127
- // oxlint-disable-next-line unicorn/no-array-reduce
128
- item.properties.reduce((target, property, index) => {
129
- let obj;
130
- const properties = item.properties.slice(0, index + 1).join('.');
131
- if (index === item.properties.length - 1) {
132
- if (property in target && !this.options.override) {
133
- throw new Error(
134
- `can't overwrite property '${properties}' from ${target[property][FULLPATH]} by ${item.fullpath}`
135
- );
136
- }
137
- obj = item.exports;
138
- if (obj && !isPrimitive(obj)) {
139
- Reflect.set(obj, FULLPATH, item.fullpath);
140
- Reflect.set(obj, EXPORTS, true);
141
- }
142
- } else {
143
- obj = target[property] || {};
144
- }
145
- target[property] = obj;
146
- debug('loaded item properties: %o => %o', properties, obj);
147
- return obj;
148
- }, target);
149
- }
150
- return target;
151
- }
152
-
153
- /**
154
- * Parse files from given directories, then return an items list, each item contains properties and exports.
155
- *
156
- * For example, parse `app/controller/group/repository.js`
157
- *
158
- * ```
159
- * module.exports = app => {
160
- * return class RepositoryController extends app.Controller {};
161
- * }
162
- * ```
163
- *
164
- * It returns a item
165
- *
166
- * ```
167
- * {
168
- * properties: [ 'group', 'repository' ],
169
- * exports: app => { ... },
170
- * }
171
- * ```
172
- *
173
- * `Properties` is an array that contains the directory of a filepath.
174
- *
175
- * `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.
176
- * @returns {Array} items
177
- * @since 1.0.0
178
- */
179
- protected async parse(): Promise<FileLoaderParseItem[]> {
180
- let files = this.options.match;
181
- if (files) {
182
- files = Array.isArray(files) ? files : [files];
183
- } else {
184
- files = isSupportTypeScript()
185
- ? ['**/*.(js|ts)', '!**/*.d.ts']
186
- : ['**/*.js'];
187
- }
188
-
189
- let ignore = this.options.ignore;
190
- if (ignore) {
191
- ignore = Array.isArray(ignore) ? ignore : [ignore];
192
- ignore = ignore.filter(f => !!f).map(f => '!' + f);
193
- files = files.concat(ignore);
194
- }
195
-
196
- let directories = this.options.directory;
197
- if (!Array.isArray(directories)) {
198
- directories = [directories];
199
- }
200
-
201
- const filter =
202
- typeof this.options.filter === 'function' ? this.options.filter : null;
203
- const items: FileLoaderParseItem[] = [];
204
- debug('[parse] parsing directories: %j', directories);
205
- for (const directory of directories) {
206
- const filepaths = globby.sync(files, { cwd: directory });
207
- debug(
208
- '[parse] globby files: %o, cwd: %o => %o',
209
- files,
210
- directory,
211
- filepaths
212
- );
213
- for (const filepath of filepaths) {
214
- const fullpath = path.join(directory, filepath);
215
- if (!fs.statSync(fullpath).isFile()) continue;
216
- if (filepath.endsWith('.js')) {
217
- const filepathTs = filepath.replace(/\.js$/, '.ts');
218
- if (filepaths.includes(filepathTs)) {
219
- debug('[parse] ignore %s, because %s exists', fullpath, filepathTs);
220
- continue;
221
- }
222
- }
223
- // get properties
224
- // app/service/foo/bar.js => [ 'foo', 'bar' ]
225
- const properties = getProperties(filepath, this.options.caseStyle);
226
- // app/service/foo/bar.js => service.foo.bar
227
- const pathName =
228
- directory.split(/[/\\]/).slice(-1) + '.' + properties.join('.');
229
- // get exports from the file
230
- const exports = await getExports(fullpath, this.options, pathName);
231
-
232
- // ignore exports when it's null or false returned by filter function
233
- if (
234
- exports === null ||
235
- exports === undefined ||
236
- (filter && filter(exports) === false)
237
- ) {
238
- continue;
239
- }
240
-
241
- // set properties of class
242
- if (isClass(exports)) {
243
- exports.prototype.pathName = pathName;
244
- exports.prototype.fullPath = fullpath;
245
- }
246
-
247
- items.push({ fullpath, properties, exports });
248
- debug(
249
- '[parse] parse %s, properties %j, exports %o',
250
- fullpath,
251
- properties,
252
- exports
253
- );
254
- }
255
- }
256
-
257
- return items;
258
- }
259
- }
260
-
261
- // convert file path to an array of properties
262
- // a/b/c.js => ['a', 'b', 'c']
263
- function getProperties(
264
- filepath: string,
265
- caseStyle: CaseStyle | CaseStyleFunction
266
- ) {
267
- // if caseStyle is function, return the result of function
268
- if (typeof caseStyle === 'function') {
269
- const result = caseStyle(filepath);
270
- assert(
271
- Array.isArray(result),
272
- `caseStyle expect an array, but got ${JSON.stringify(result)}`
273
- );
274
- return result;
275
- }
276
- // use default camelize
277
- return defaultCamelize(filepath, caseStyle);
278
- }
279
-
280
- // Get exports from filepath
281
- // If exports is null/undefined, it will be ignored
282
- async function getExports(
283
- fullpath: string,
284
- options: FileLoaderOptions,
285
- pathName: string
286
- ) {
287
- let exports = await utils.loadFile(fullpath);
288
- // process exports as you like
289
- if (options.initializer) {
290
- exports = options.initializer(exports, { path: fullpath, pathName });
291
- debug('[getExports] after initializer => %o', exports);
292
- }
293
-
294
- if (isGeneratorFunction(exports)) {
295
- throw new TypeError(
296
- `Support for generators was removed, fullpath: ${fullpath}`
297
- );
298
- }
299
-
300
- // return exports when it's a class or async function
301
- //
302
- // module.exports = class Service {};
303
- // or
304
- // module.exports = async function() {}
305
- if (isClass(exports) || isAsyncFunction(exports)) {
306
- return exports;
307
- }
308
-
309
- // return exports after call when it's a function
310
- //
311
- // module.exports = function(app) {
312
- // return {};
313
- // }
314
- if (options.call && typeof exports === 'function') {
315
- exports = exports(options.inject);
316
- if (exports !== null && exports !== undefined) {
317
- return exports;
318
- }
319
- }
320
-
321
- // return exports what is
322
- return exports;
323
- }
324
-
325
- function defaultCamelize(filepath: string, caseStyle: CaseStyle) {
326
- const properties = filepath.slice(0, filepath.lastIndexOf('.')).split('/');
327
- return properties.map(property => {
328
- if (!/^[a-z][a-z0-9_-]*$/i.test(property)) {
329
- throw new Error(`${property} is not match 'a-z0-9_-' in ${filepath}`);
330
- }
331
-
332
- // use default camelize, will capitalize the first letter
333
- // foo_bar.js > FooBar
334
- // fooBar.js > FooBar
335
- // FooBar.js > FooBar
336
- // FooBar.js > FooBar
337
- // FooBar.js > fooBar (if lowercaseFirst is true)
338
- property = property.replaceAll(/[_-][a-z]/gi, s =>
339
- s.slice(1).toUpperCase()
340
- );
341
- let first = property[0];
342
- if (caseStyle === CaseStyle.lower) {
343
- first = first.toLowerCase();
344
- } else if (caseStyle === CaseStyle.upper) {
345
- first = first.toUpperCase();
346
- }
347
- return first + property.slice(1);
348
- });
349
- }
package/src/singleton.ts DELETED
@@ -1,187 +0,0 @@
1
- import assert from 'node:assert';
2
- import { isAsyncFunction } from 'is-type-of';
3
- import type { EggCore } from './egg.js';
4
-
5
- export type SingletonCreateMethod = (
6
- config: Record<string, any>,
7
- app: EggCore,
8
- clientName: string
9
- ) => unknown | Promise<unknown>;
10
-
11
- export interface SingletonOptions {
12
- name: string;
13
- app: EggCore;
14
- create: SingletonCreateMethod;
15
- }
16
-
17
- export class Singleton<T = any> {
18
- readonly clients = new Map<string, T>();
19
- readonly app: EggCore;
20
- readonly create: SingletonCreateMethod;
21
- readonly name: string;
22
- readonly options: Record<string, any>;
23
-
24
- constructor(options: SingletonOptions) {
25
- assert(
26
- options.name,
27
- '[@eggjs/core/singleton] Singleton#constructor options.name is required'
28
- );
29
- assert(
30
- options.app,
31
- '[@eggjs/core/singleton] Singleton#constructor options.app is required'
32
- );
33
- assert(
34
- options.create,
35
- '[@eggjs/core/singleton] Singleton#constructor options.create is required'
36
- );
37
- assert(
38
- !(options.name in options.app),
39
- `[@eggjs/core/singleton] ${options.name} is already exists in app`
40
- );
41
- this.app = options.app;
42
- this.name = options.name;
43
- this.create = options.create;
44
- this.options = options.app.config[this.name] ?? {};
45
- }
46
-
47
- init() {
48
- return isAsyncFunction(this.create) ? this.initAsync() : this.initSync();
49
- }
50
-
51
- initSync() {
52
- const options = this.options;
53
- assert(
54
- !(options.client && options.clients),
55
- `[@eggjs/core/singleton] ${this.name} can not set options.client and options.clients both`
56
- );
57
-
58
- // alias app[name] as client, but still support createInstance method
59
- if (options.client) {
60
- const client = this.createInstance(options.client, options.name);
61
- this.#setClientToApp(client);
62
- this.#extendDynamicMethods(client);
63
- return;
64
- }
65
-
66
- // multi client, use app[name].getSingletonInstance(id)
67
- if (options.clients) {
68
- for (const id of Object.keys(options.clients)) {
69
- const client = this.createInstance(options.clients[id], id);
70
- this.clients.set(id, client);
71
- }
72
- this.#setClientToApp(this);
73
- return;
74
- }
75
-
76
- // no config.clients and config.client
77
- this.#setClientToApp(this);
78
- }
79
-
80
- async initAsync() {
81
- const options = this.options;
82
- assert(
83
- !(options.client && options.clients),
84
- `[@eggjs/core/singleton] ${this.name} can not set options.client and options.clients both`
85
- );
86
-
87
- // alias app[name] as client, but still support createInstance method
88
- if (options.client) {
89
- const client = await this.createInstanceAsync(
90
- options.client,
91
- options.name
92
- );
93
- this.#setClientToApp(client);
94
- this.#extendDynamicMethods(client);
95
- return;
96
- }
97
-
98
- // multi client, use app[name].getInstance(id)
99
- if (options.clients) {
100
- await Promise.all(
101
- Object.keys(options.clients).map((id: string) => {
102
- return this.createInstanceAsync(options.clients[id], id).then(
103
- client => this.clients.set(id, client)
104
- );
105
- })
106
- );
107
- this.#setClientToApp(this);
108
- return;
109
- }
110
-
111
- // no config.clients and config.client
112
- this.#setClientToApp(this);
113
- }
114
-
115
- #setClientToApp(client: unknown) {
116
- Reflect.set(this.app, this.name, client);
117
- }
118
-
119
- /**
120
- * @deprecated please use `getSingletonInstance(id)` instead
121
- */
122
- get(id: string) {
123
- return this.clients.get(id) as T;
124
- }
125
-
126
- /**
127
- * Get singleton instance by id
128
- */
129
- getSingletonInstance(id: string) {
130
- return this.clients.get(id) as T;
131
- }
132
-
133
- createInstance(config: Record<string, any>, clientName: string) {
134
- // async creator only support createInstanceAsync
135
- assert(
136
- !isAsyncFunction(this.create),
137
- `[@eggjs/core/singleton] ${this.name} only support asynchronous creation, please use createInstanceAsync`
138
- );
139
- // options.default will be merge in to options.clients[id]
140
- config = {
141
- ...this.options.default,
142
- ...config,
143
- };
144
- return (this.create as SingletonCreateMethod)(
145
- config,
146
- this.app,
147
- clientName
148
- ) as T;
149
- }
150
-
151
- async createInstanceAsync(config: Record<string, any>, clientName: string) {
152
- // options.default will be merge in to options.clients[id]
153
- config = {
154
- ...this.options.default,
155
- ...config,
156
- };
157
- return (await this.create(config, this.app, clientName)) as T;
158
- }
159
-
160
- #extendDynamicMethods(client: any) {
161
- assert(
162
- !client.createInstance,
163
- '[@eggjs/core/singleton] singleton instance should not have createInstance method'
164
- );
165
- assert(
166
- !client.createInstanceAsync,
167
- '[@eggjs/core/singleton] singleton instance should not have createInstanceAsync method'
168
- );
169
-
170
- try {
171
- let extendable = client;
172
- // Object.preventExtensions() or Object.freeze()
173
- if (!Object.isExtensible(client) || Object.isFrozen(client)) {
174
- // eslint-disable-next-line no-proto
175
- extendable = client.__proto__ || client;
176
- }
177
- extendable.createInstance = this.createInstance.bind(this);
178
- extendable.createInstanceAsync = this.createInstanceAsync.bind(this);
179
- } catch (err) {
180
- this.app.coreLogger.warn(
181
- '[@eggjs/core/singleton] %s dynamic create is disabled because of client is un-extendable',
182
- this.name
183
- );
184
- this.app.coreLogger.warn(err);
185
- }
186
- }
187
- }
@@ -1,132 +0,0 @@
1
- import { debuglog } from 'node:util';
2
- import path from 'node:path';
3
- import fs from 'node:fs';
4
- import { stat } from 'node:fs/promises';
5
- import BuiltinModule from 'node:module';
6
-
7
- import { importResolve, importModule } from '@eggjs/utils';
8
-
9
- const debug = debuglog('@eggjs/core/utils');
10
-
11
- export type Fun = (...args: unknown[]) => unknown;
12
-
13
- // Guard against poorly mocked module constructors.
14
- const Module =
15
- typeof module !== 'undefined' && module.constructor.length > 1
16
- ? module.constructor
17
- : /* istanbul ignore next */
18
- BuiltinModule;
19
-
20
- const extensions = (Module as any)._extensions;
21
- const extensionNames = Object.keys(extensions).concat(['.cjs', '.mjs']);
22
- debug('Module extensions: %j', extensionNames);
23
-
24
- function getCalleeFromStack(withLine?: boolean, stackIndex?: number) {
25
- stackIndex = stackIndex === undefined ? 2 : stackIndex;
26
- const limit = Error.stackTraceLimit;
27
- const prep = Error.prepareStackTrace;
28
-
29
- Error.prepareStackTrace = prepareObjectStackTrace;
30
- Error.stackTraceLimit = 5;
31
-
32
- // capture the stack
33
-
34
- const obj: any = {};
35
- Error.captureStackTrace(obj);
36
- let callSite = obj.stack[stackIndex];
37
- let fileName = '';
38
- if (callSite) {
39
- // egg-mock will create a proxy
40
- // https://github.com/eggjs/egg-mock/blob/master/lib/app.js#L174
41
- fileName = callSite.getFileName();
42
- /* istanbul ignore if */
43
- if (fileName && fileName.endsWith('egg-mock/lib/app.js')) {
44
- // TODO: add test
45
- callSite = obj.stack[stackIndex + 1];
46
- fileName = callSite.getFileName();
47
- }
48
- }
49
-
50
- Error.prepareStackTrace = prep;
51
- Error.stackTraceLimit = limit;
52
-
53
- if (!callSite || !fileName) return '<anonymous>';
54
- if (!withLine) return fileName;
55
- return `${fileName}:${callSite.getLineNumber()}:${callSite.getColumnNumber()}`;
56
- }
57
-
58
- export default {
59
- deprecated(message: string) {
60
- if (debug.enabled) {
61
- console.trace('[@eggjs/core/deprecated] %s', message);
62
- } else {
63
- console.log('[@eggjs/core/deprecated] %s', message);
64
- console.log(
65
- '[@eggjs/core/deprecated] set NODE_DEBUG=@eggjs/core/utils can show call stack'
66
- );
67
- }
68
- },
69
-
70
- extensions,
71
- extensionNames,
72
-
73
- async existsPath(filepath: string) {
74
- try {
75
- await stat(filepath);
76
- return true;
77
- } catch {
78
- return false;
79
- }
80
- },
81
-
82
- async loadFile(filepath: string) {
83
- try {
84
- // if not js module, just return content buffer
85
- const extname = path.extname(filepath);
86
- if (extname && !extensionNames.includes(extname) && extname !== '.ts') {
87
- return fs.readFileSync(filepath);
88
- }
89
- const obj = await importModule(filepath, { importDefaultOnly: true });
90
- return obj;
91
- } catch (e) {
92
- if (!(e instanceof Error)) {
93
- // ts error: test/fixtures/apps/app-ts/app/extend/context.ts(5,17): error TS2339: Property 'url' does not exist on type 'Context'
94
- console.trace(e);
95
- throw e;
96
- }
97
- const err = new Error(
98
- `[@eggjs/core] load file: ${filepath}, error: ${e.message}`
99
- );
100
- err.cause = e;
101
- debug('[loadFile] handle %s error: %s', filepath, e);
102
- throw err;
103
- }
104
- },
105
-
106
- resolvePath(filepath: string, options?: { paths?: string[] }) {
107
- return importResolve(filepath, options);
108
- },
109
-
110
- methods: ['head', 'options', 'get', 'put', 'patch', 'post', 'delete'],
111
-
112
- async callFn(fn: Fun, args?: unknown[], ctx?: unknown) {
113
- args = args || [];
114
- if (typeof fn !== 'function') return;
115
- return ctx ? fn.call(ctx, ...args) : fn(...args);
116
- },
117
-
118
- getCalleeFromStack,
119
-
120
- getResolvedFilename(filepath: string, baseDir: string) {
121
- const reg = /[/\\]/g;
122
- return filepath.replace(baseDir + path.sep, '').replace(reg, '/');
123
- },
124
- };
125
-
126
- /**
127
- * Capture call site stack from v8.
128
- * https://github.com/v8/v8/wiki/Stack-Trace-API
129
- */
130
- function prepareObjectStackTrace(_obj: unknown, stack: unknown) {
131
- return stack;
132
- }