@eggjs/core 7.0.0-beta.35 → 7.0.0-beta.36
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/dist/base_context_class.d.ts +19 -14
- package/dist/base_context_class.js +39 -36
- package/dist/egg.d.ts +279 -277
- package/dist/egg.js +394 -426
- package/dist/index.d.ts +12 -12
- package/dist/index.js +12 -12
- package/dist/lifecycle.d.ts +79 -75
- package/dist/lifecycle.js +280 -306
- package/dist/loader/context_loader.d.ts +34 -30
- package/dist/loader/context_loader.js +76 -99
- package/dist/loader/egg_loader.d.ts +370 -366
- package/dist/loader/egg_loader.js +1169 -1567
- package/dist/loader/file_loader.d.ts +99 -95
- package/dist/loader/file_loader.js +190 -241
- package/dist/singleton.d.ts +31 -27
- package/dist/singleton.js +107 -117
- package/dist/types.d.ts +54 -51
- package/dist/utils/index.d.ts +16 -14
- package/dist/utils/index.js +96 -105
- package/dist/utils/sequencify.d.ts +13 -10
- package/dist/utils/sequencify.js +44 -58
- package/dist/utils/timing.d.ts +22 -19
- package/dist/utils/timing.js +85 -92
- package/package.json +35 -40
- package/dist/types.js +0 -2
|
@@ -1,249 +1,198 @@
|
|
|
1
|
-
import
|
|
2
|
-
import fs from
|
|
3
|
-
import path from
|
|
4
|
-
import { debuglog } from
|
|
5
|
-
import { isSupportTypeScript } from
|
|
6
|
-
import
|
|
7
|
-
import { isClass, isGeneratorFunction,
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import utils_default from "../utils/index.js";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { debuglog } from "node:util";
|
|
5
|
+
import { isSupportTypeScript } from "@eggjs/utils";
|
|
6
|
+
import assert from "node:assert";
|
|
7
|
+
import { isAsyncFunction, isClass, isGeneratorFunction, isPrimitive } from "is-type-of";
|
|
8
|
+
import globby from "globby";
|
|
9
|
+
|
|
10
|
+
//#region src/loader/file_loader.ts
|
|
11
|
+
const debug = debuglog("egg/core/file_loader");
|
|
12
|
+
const FULLPATH = Symbol("EGG_LOADER_ITEM_FULLPATH");
|
|
13
|
+
const EXPORTS = Symbol("EGG_LOADER_ITEM_EXPORTS");
|
|
14
|
+
const CaseStyle = {
|
|
15
|
+
camel: "camel",
|
|
16
|
+
lower: "lower",
|
|
17
|
+
upper: "upper"
|
|
16
18
|
};
|
|
17
19
|
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const properties = getProperties(filepath, this.options.caseStyle);
|
|
160
|
-
// app/service/foo/bar.js => service.foo.bar
|
|
161
|
-
const pathName = directory.split(/[/\\]/).slice(-1) + '.' + properties.join('.');
|
|
162
|
-
// get exports from the file
|
|
163
|
-
const exports = await getExports(fullpath, this.options, pathName);
|
|
164
|
-
// ignore exports when it's null or false returned by filter function
|
|
165
|
-
if (exports === null || exports === undefined || (filter && filter(exports) === false)) {
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
// set properties of class
|
|
169
|
-
if (isClass(exports)) {
|
|
170
|
-
exports.prototype.pathName = pathName;
|
|
171
|
-
exports.prototype.fullPath = fullpath;
|
|
172
|
-
}
|
|
173
|
-
items.push({ fullpath, properties, exports });
|
|
174
|
-
debug('[parse] parse %s, properties %j, exports %o', fullpath, properties, exports);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return items;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
// convert file path to an array of properties
|
|
181
|
-
// a/b/c.js => ['a', 'b', 'c']
|
|
20
|
+
* Load files from directory to target object.
|
|
21
|
+
* @since 1.0.0
|
|
22
|
+
*/
|
|
23
|
+
var FileLoader = class {
|
|
24
|
+
static get FULLPATH() {
|
|
25
|
+
return FULLPATH;
|
|
26
|
+
}
|
|
27
|
+
static get EXPORTS() {
|
|
28
|
+
return EXPORTS;
|
|
29
|
+
}
|
|
30
|
+
options;
|
|
31
|
+
/**
|
|
32
|
+
* @class
|
|
33
|
+
* @param {Object} options - options
|
|
34
|
+
* @param {String|Array} options.directory - directories to be loaded
|
|
35
|
+
* @param {Object} options.target - attach the target object from loaded files
|
|
36
|
+
* @param {String} options.match - match the files when load, support glob, default to all js files
|
|
37
|
+
* @param {String} options.ignore - ignore the files when load, support glob
|
|
38
|
+
* @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`
|
|
39
|
+
* @param {Boolean} options.call - determine whether invoke when exports is function
|
|
40
|
+
* @param {Boolean} options.override - determine whether override the property when get the same name
|
|
41
|
+
* @param {Object} options.inject - an object that be the argument when invoke the function
|
|
42
|
+
* @param {Function} options.filter - a function that filter the exports which can be loaded
|
|
43
|
+
* @param {String|Function} options.caseStyle - set property's case when converting a filepath to property list.
|
|
44
|
+
*/
|
|
45
|
+
constructor(options) {
|
|
46
|
+
assert(options.directory, "options.directory is required");
|
|
47
|
+
assert(options.target, "options.target is required");
|
|
48
|
+
this.options = {
|
|
49
|
+
caseStyle: CaseStyle.camel,
|
|
50
|
+
call: true,
|
|
51
|
+
override: false,
|
|
52
|
+
...options
|
|
53
|
+
};
|
|
54
|
+
if (this.options.lowercaseFirst === true) {
|
|
55
|
+
utils_default.deprecated("lowercaseFirst is deprecated, use caseStyle instead");
|
|
56
|
+
this.options.caseStyle = CaseStyle.lower;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* attach items to target object. Mapping the directory to properties.
|
|
61
|
+
* `app/controller/group/repository.js` => `target.group.repository`
|
|
62
|
+
* @returns {Object} target
|
|
63
|
+
* @since 1.0.0
|
|
64
|
+
*/
|
|
65
|
+
async load() {
|
|
66
|
+
const items = await this.parse();
|
|
67
|
+
const target = this.options.target;
|
|
68
|
+
for (const item of items) {
|
|
69
|
+
debug("[load] loading item: fullpath: %s, properties: %o", item.fullpath, item.properties);
|
|
70
|
+
item.properties.reduce((target$1, property, index) => {
|
|
71
|
+
let obj;
|
|
72
|
+
const properties = item.properties.slice(0, index + 1).join(".");
|
|
73
|
+
if (index === item.properties.length - 1) {
|
|
74
|
+
if (property in target$1 && !this.options.override) throw new Error(`can't overwrite property '${properties}' from ${target$1[property][FULLPATH]} by ${item.fullpath}`);
|
|
75
|
+
obj = item.exports;
|
|
76
|
+
if (obj && !isPrimitive(obj)) {
|
|
77
|
+
Reflect.set(obj, FULLPATH, item.fullpath);
|
|
78
|
+
Reflect.set(obj, EXPORTS, true);
|
|
79
|
+
}
|
|
80
|
+
} else obj = target$1[property] || {};
|
|
81
|
+
target$1[property] = obj;
|
|
82
|
+
if (debug.enabled) debug("[load] loaded item properties: %o => keys: %j, index: %d", properties, Object.keys(obj), index);
|
|
83
|
+
return obj;
|
|
84
|
+
}, target);
|
|
85
|
+
}
|
|
86
|
+
return target;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Parse files from given directories, then return an items list, each item contains properties and exports.
|
|
90
|
+
*
|
|
91
|
+
* For example, parse `app/controller/group/repository.js`
|
|
92
|
+
*
|
|
93
|
+
* ```
|
|
94
|
+
* module.exports = app => {
|
|
95
|
+
* return class RepositoryController extends app.Controller {};
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* It returns a item
|
|
100
|
+
*
|
|
101
|
+
* ```
|
|
102
|
+
* {
|
|
103
|
+
* properties: [ 'group', 'repository' ],
|
|
104
|
+
* exports: app => { ... },
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* `Properties` is an array that contains the directory of a filepath.
|
|
109
|
+
*
|
|
110
|
+
* `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.
|
|
111
|
+
* @returns {Array} items
|
|
112
|
+
* @since 1.0.0
|
|
113
|
+
*/
|
|
114
|
+
async parse() {
|
|
115
|
+
let files = this.options.match;
|
|
116
|
+
if (files) files = Array.isArray(files) ? files : [files];
|
|
117
|
+
else files = isSupportTypeScript() ? ["**/*.(js|ts)", "!**/*.d.ts"] : ["**/*.js"];
|
|
118
|
+
let ignore = this.options.ignore;
|
|
119
|
+
if (ignore) {
|
|
120
|
+
ignore = Array.isArray(ignore) ? ignore : [ignore];
|
|
121
|
+
ignore = ignore.filter((f) => !!f).map((f) => "!" + f);
|
|
122
|
+
files = files.concat(ignore);
|
|
123
|
+
}
|
|
124
|
+
let directories = this.options.directory;
|
|
125
|
+
if (!Array.isArray(directories)) directories = [directories];
|
|
126
|
+
const filter = typeof this.options.filter === "function" ? this.options.filter : null;
|
|
127
|
+
const items = [];
|
|
128
|
+
debug("[parse] parsing directories: %j", directories);
|
|
129
|
+
for (const directory of directories) {
|
|
130
|
+
const filepaths = globby.sync(files, { cwd: directory });
|
|
131
|
+
debug("[parse] globby files: %o, cwd: %o => %o", files, directory, filepaths);
|
|
132
|
+
for (const filepath of filepaths) {
|
|
133
|
+
const fullpath = path.join(directory, filepath);
|
|
134
|
+
if (!fs.statSync(fullpath).isFile()) continue;
|
|
135
|
+
if (filepath.endsWith(".js")) {
|
|
136
|
+
const filepathTs = filepath.replace(/\.js$/, ".ts");
|
|
137
|
+
if (filepaths.includes(filepathTs)) {
|
|
138
|
+
debug("[parse] ignore %s, because %s exists", fullpath, filepathTs);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const properties = getProperties(filepath, this.options.caseStyle);
|
|
143
|
+
const pathName = directory.split(/[/\\]/).slice(-1) + "." + properties.join(".");
|
|
144
|
+
const exports = await getExports(fullpath, this.options, pathName);
|
|
145
|
+
if (exports === null || exports === void 0 || filter && filter(exports) === false) continue;
|
|
146
|
+
if (isClass(exports)) {
|
|
147
|
+
exports.prototype.pathName = pathName;
|
|
148
|
+
exports.prototype.fullPath = fullpath;
|
|
149
|
+
}
|
|
150
|
+
items.push({
|
|
151
|
+
fullpath,
|
|
152
|
+
properties,
|
|
153
|
+
exports
|
|
154
|
+
});
|
|
155
|
+
debug("[parse] parse %s, properties %j, exports %o", fullpath, properties, exports);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return items;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
182
161
|
function getProperties(filepath, caseStyle) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
// use default camelize
|
|
190
|
-
return defaultCamelize(filepath, caseStyle);
|
|
162
|
+
if (typeof caseStyle === "function") {
|
|
163
|
+
const result = caseStyle(filepath);
|
|
164
|
+
assert(Array.isArray(result), `caseStyle expect an array, but got ${JSON.stringify(result)}`);
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
return defaultCamelize(filepath, caseStyle);
|
|
191
168
|
}
|
|
192
|
-
// Get exports from filepath
|
|
193
|
-
// If exports is null/undefined, it will be ignored
|
|
194
169
|
async function getExports(fullpath, options, pathName) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
return exports;
|
|
211
|
-
}
|
|
212
|
-
// return exports after call when it's a function
|
|
213
|
-
//
|
|
214
|
-
// module.exports = function(app) {
|
|
215
|
-
// return {};
|
|
216
|
-
// }
|
|
217
|
-
if (options.call && typeof exports === 'function') {
|
|
218
|
-
exports = exports(options.inject);
|
|
219
|
-
if (exports !== null && exports !== undefined) {
|
|
220
|
-
return exports;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
// return exports what is
|
|
224
|
-
return exports;
|
|
170
|
+
let exports = await utils_default.loadFile(fullpath);
|
|
171
|
+
if (options.initializer) {
|
|
172
|
+
exports = options.initializer(exports, {
|
|
173
|
+
path: fullpath,
|
|
174
|
+
pathName
|
|
175
|
+
});
|
|
176
|
+
debug("[getExports] after initializer => %o", exports);
|
|
177
|
+
}
|
|
178
|
+
if (isGeneratorFunction(exports)) throw new TypeError(`Support for generators was removed, fullpath: ${fullpath}`);
|
|
179
|
+
if (isClass(exports) || isAsyncFunction(exports)) return exports;
|
|
180
|
+
if (options.call && typeof exports === "function") {
|
|
181
|
+
exports = exports(options.inject);
|
|
182
|
+
if (exports !== null && exports !== void 0) return exports;
|
|
183
|
+
}
|
|
184
|
+
return exports;
|
|
225
185
|
}
|
|
226
186
|
function defaultCamelize(filepath, caseStyle) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
// FooBar.js > FooBar
|
|
236
|
-
// FooBar.js > FooBar
|
|
237
|
-
// FooBar.js > fooBar (if lowercaseFirst is true)
|
|
238
|
-
property = property.replaceAll(/[_-][a-z]/gi, (s) => s.slice(1).toUpperCase());
|
|
239
|
-
let first = property[0];
|
|
240
|
-
if (caseStyle === CaseStyle.lower) {
|
|
241
|
-
first = first.toLowerCase();
|
|
242
|
-
}
|
|
243
|
-
else if (caseStyle === CaseStyle.upper) {
|
|
244
|
-
first = first.toUpperCase();
|
|
245
|
-
}
|
|
246
|
-
return first + property.slice(1);
|
|
247
|
-
});
|
|
187
|
+
return filepath.slice(0, filepath.lastIndexOf(".")).split("/").map((property) => {
|
|
188
|
+
if (!/^[a-z][a-z0-9_-]*$/i.test(property)) throw new Error(`${property} is not match 'a-z0-9_-' in ${filepath}`);
|
|
189
|
+
property = property.replaceAll(/[_-][a-z]/gi, (s) => s.slice(1).toUpperCase());
|
|
190
|
+
let first = property[0];
|
|
191
|
+
if (caseStyle === CaseStyle.lower) first = first.toLowerCase();
|
|
192
|
+
else if (caseStyle === CaseStyle.upper) first = first.toUpperCase();
|
|
193
|
+
return first + property.slice(1);
|
|
194
|
+
});
|
|
248
195
|
}
|
|
249
|
-
|
|
196
|
+
|
|
197
|
+
//#endregion
|
|
198
|
+
export { CaseStyle, EXPORTS, FULLPATH, FileLoader };
|
package/dist/singleton.d.ts
CHANGED
|
@@ -1,29 +1,33 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { EggCore } from "./egg.js";
|
|
2
|
+
|
|
3
|
+
//#region src/singleton.d.ts
|
|
4
|
+
type SingletonCreateMethod = (config: Record<string, any>, app: any, clientName: string) => unknown | Promise<unknown>;
|
|
5
|
+
interface SingletonOptions {
|
|
6
|
+
name: string;
|
|
7
|
+
app: EggCore;
|
|
8
|
+
create: SingletonCreateMethod;
|
|
7
9
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
10
|
+
declare class Singleton<T = any> {
|
|
11
|
+
#private;
|
|
12
|
+
readonly clients: Map<string, T>;
|
|
13
|
+
readonly app: EggCore;
|
|
14
|
+
readonly create: SingletonCreateMethod;
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly options: Record<string, any>;
|
|
17
|
+
constructor(options: SingletonOptions);
|
|
18
|
+
init(): void | Promise<void>;
|
|
19
|
+
initSync(): void;
|
|
20
|
+
initAsync(): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* @deprecated please use `getSingletonInstance(id)` instead
|
|
23
|
+
*/
|
|
24
|
+
get(id: string): T;
|
|
25
|
+
/**
|
|
26
|
+
* Get singleton instance by id
|
|
27
|
+
*/
|
|
28
|
+
getSingletonInstance(id: string): T;
|
|
29
|
+
createInstance(config: Record<string, any>, clientName: string): T;
|
|
30
|
+
createInstanceAsync(config: Record<string, any>, clientName: string): Promise<T>;
|
|
29
31
|
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { Singleton, SingletonCreateMethod, SingletonOptions };
|