ee-core 2.9.2-beta.1 → 2.10.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.
Files changed (103) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +65 -65
  3. package/addon/index.js +34 -34
  4. package/addon/window/index.js +98 -98
  5. package/bin/tools.js +8 -8
  6. package/config/cache.js +41 -38
  7. package/config/config.default.js +331 -330
  8. package/config/index.js +75 -73
  9. package/const/channel.js +17 -17
  10. package/const/index.js +8 -8
  11. package/controller/baseContextClass.js +34 -34
  12. package/controller/index.js +34 -34
  13. package/core/index.js +10 -10
  14. package/core/lib/ee.js +216 -216
  15. package/core/lib/loader/context_loader.js +106 -106
  16. package/core/lib/loader/ee_loader.js +435 -435
  17. package/core/lib/loader/file_loader.js +326 -326
  18. package/core/lib/loader/mixin/addon.js +32 -32
  19. package/core/lib/loader/mixin/config.js +130 -130
  20. package/core/lib/loader/mixin/controller.js +125 -125
  21. package/core/lib/loader/mixin/service.js +28 -28
  22. package/core/lib/utils/base_context_class.js +34 -34
  23. package/core/lib/utils/function.js +30 -30
  24. package/core/lib/utils/index.js +133 -133
  25. package/core/lib/utils/sequencify.js +59 -59
  26. package/core/lib/utils/timing.js +77 -77
  27. package/cross/index.js +183 -183
  28. package/cross/spawnProcess.js +183 -183
  29. package/ee/appLoader.js +48 -48
  30. package/ee/application.js +99 -99
  31. package/ee/baseApp.js +103 -102
  32. package/ee/eeApp.js +408 -408
  33. package/ee/index.js +57 -57
  34. package/electron/app/index.js +64 -58
  35. package/electron/index.js +19 -19
  36. package/electron/window/index.js +73 -73
  37. package/electron/window/winState.js +186 -186
  38. package/exception/index.js +112 -112
  39. package/html/boot.html +98 -98
  40. package/html/cross-failure.html +28 -28
  41. package/html/failure.html +28 -28
  42. package/html/index.js +13 -13
  43. package/httpclient/index.js +161 -161
  44. package/index.js +54 -54
  45. package/jobs/baseJobClass.js +16 -16
  46. package/jobs/child/app.js +65 -65
  47. package/jobs/child/forkProcess.js +145 -145
  48. package/jobs/child/index.js +82 -82
  49. package/jobs/child-pool/index.js +213 -213
  50. package/jobs/index.js +8 -8
  51. package/jobs/load-balancer/algorithm/index.js +11 -11
  52. package/jobs/load-balancer/algorithm/minimumConnection.js +18 -18
  53. package/jobs/load-balancer/algorithm/polling.js +11 -11
  54. package/jobs/load-balancer/algorithm/random.js +9 -9
  55. package/jobs/load-balancer/algorithm/specify.js +14 -14
  56. package/jobs/load-balancer/algorithm/weights.js +21 -21
  57. package/jobs/load-balancer/algorithm/weightsMinimumConnection.js +29 -29
  58. package/jobs/load-balancer/algorithm/weightsPolling.js +22 -22
  59. package/jobs/load-balancer/algorithm/weightsRandom.js +16 -16
  60. package/jobs/load-balancer/consts.js +9 -9
  61. package/jobs/load-balancer/index.js +201 -201
  62. package/jobs/load-balancer/scheduler.js +31 -31
  63. package/jobs/renderer/index.js +141 -141
  64. package/jobs/renderer/loadView.js +40 -40
  65. package/jobs/unification.js +63 -63
  66. package/loader/index.js +172 -172
  67. package/log/index.js +68 -68
  68. package/log/logger.js +86 -80
  69. package/main/index.js +56 -56
  70. package/message/childMessage.js +54 -54
  71. package/message/index.js +18 -18
  72. package/old-utils/index.js +91 -91
  73. package/package.json +38 -38
  74. package/ps/index.js +371 -371
  75. package/services/baseContextClass.js +34 -34
  76. package/services/index.js +40 -40
  77. package/socket/httpServer.js +147 -147
  78. package/socket/index.js +81 -81
  79. package/socket/io.js +27 -27
  80. package/socket/ipcServer.js +112 -112
  81. package/socket/socketServer.js +69 -65
  82. package/storage/index.js +38 -38
  83. package/storage/jsondb/adapters/Base.js +23 -23
  84. package/storage/jsondb/adapters/FileSync.js +64 -52
  85. package/storage/jsondb/main.js +55 -42
  86. package/storage/jsondbStorage.js +195 -195
  87. package/storage/sqliteStorage.js +123 -123
  88. package/utils/co.js +237 -237
  89. package/utils/copyto.js +160 -160
  90. package/utils/depd/index.js +538 -538
  91. package/utils/depd/lib/browser/index.js +77 -77
  92. package/utils/extend.js +73 -73
  93. package/utils/get-port/index.d.ts +64 -64
  94. package/utils/get-port/index.js +148 -148
  95. package/utils/helper.js +220 -220
  96. package/utils/index.js +160 -160
  97. package/utils/ip.js +261 -261
  98. package/utils/is.js +145 -145
  99. package/utils/json.js +72 -72
  100. package/utils/pargv.js +263 -263
  101. package/utils/time/index.js +19 -19
  102. package/utils/time/ms.js +162 -162
  103. package/utils/wrap.js +35 -35
@@ -1,435 +1,435 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const assert = require('assert');
6
- const is = require('is-type-of');
7
- const debug = require('debug')('ee-core:EeLoader');
8
- const FileLoader = require('./file_loader');
9
- const ContextLoader = require('./context_loader');
10
- const Utils = require('../utils');
11
- const Timing = require('../utils/timing');
12
- const Ps = require('../../../ps');
13
-
14
- const REQUIRE_COUNT = Symbol('EeLoader#requireCount');
15
-
16
- class EeLoader {
17
-
18
- /**
19
- * @class
20
- * @param {Object} options - options
21
- * @param {String} options.baseDir - the directory of application
22
- * @param {EeCore} options.app - Application instance
23
- * @param {Logger} options.logger - logger
24
- * @since 1.0.0
25
- */
26
- constructor(options) {
27
- this.options = options;
28
- // assert(fs.existsSync(this.options.baseDir), `${this.options.baseDir} not exists`);
29
- assert(this.options.app, 'options.app is required');
30
- assert(this.options.logger, 'options.logger is required');
31
-
32
- this.app = this.options.app;
33
- this.timing = this.app.timing || new Timing();
34
- this[REQUIRE_COUNT] = 0;
35
-
36
- /**
37
- * @member {Object} EeLoader#pkg
38
- * @see {@link AppInfo#pkg}
39
- * @since 1.0.0
40
- */
41
- this.pkg = this.getPkg();
42
-
43
- /**
44
- * Framework directories
45
- *
46
- * @member {Array} EeLoader#EePaths
47
- * @see EeLoader#getEePaths
48
- * @since 1.0.0
49
- */
50
- this.EePaths = this.getEePaths();
51
- debug('Loaded EePaths %j', this.EePaths);
52
-
53
- /**
54
- * @member {String} EeLoader#serverEnv
55
- * @see AppInfo#env
56
- * @since 1.0.0
57
- */
58
- this.serverEnv = this.getServerEnv();
59
- debug('Loaded serverEnv %j', this.serverEnv);
60
-
61
- /**
62
- * @member {AppInfo} EeLoader#appInfo
63
- * @since 1.0.0
64
- */
65
- this.appInfo = this.getAppInfo();
66
-
67
- /**
68
- * @member {String} EeLoader#serverScope
69
- * @see AppInfo#serverScope
70
- */
71
- this.serverScope = options.serverScope !== undefined
72
- ? options.serverScope
73
- : this.getServerScope();
74
- }
75
-
76
- /**
77
- * Get {@link AppInfo#env}
78
- * @return {String} env
79
- * @see AppInfo#env
80
- * @private
81
- * @since 1.0.0
82
- */
83
- getServerEnv() {
84
- let serverEnv = this.options.env;
85
-
86
- if (!serverEnv) {
87
- throw new Error('[core] [lib] [loader] getServerEnv serverEnv can not be empty!');
88
- }
89
-
90
- return serverEnv;
91
- }
92
-
93
- /**
94
- * Get {@link AppInfo#scope}
95
- * @return {String} serverScope
96
- * @private
97
- */
98
- getServerScope() {
99
- return process.env.EE_SERVER_SCOPE || '';
100
- }
101
-
102
- /**
103
- * Get {@link AppInfo#name}
104
- * @return {String} appname
105
- * @private
106
- * @since 1.0.0
107
- */
108
- getAppname() {
109
- if (this.pkg.name) {
110
- debug('Loaded appname(%s) from package.json', this.pkg.name);
111
- return this.pkg.name;
112
- }
113
-
114
- throw new Error(`name is required from ${pkg}`);
115
- }
116
-
117
- /**
118
- * Get home directory
119
- * @return {String} home directory
120
- * @since 3.4.0
121
- */
122
- getHomedir() {
123
- return this.options.homeDir;
124
- }
125
-
126
- /**
127
- * Get app info
128
- * @return {AppInfo} appInfo
129
- * @since 1.0.0
130
- */
131
- getAppInfo() {
132
- const env = this.serverEnv;
133
-
134
- /**
135
- * Meta information of the application
136
- * @class AppInfo
137
- */
138
- return {
139
- /**
140
- * The name of the application, retrieve from the name property in `package.json`.
141
- * @member {String} AppInfo#name
142
- */
143
- name: this.getAppname(),
144
-
145
- /**
146
- * The current directory, where the application code is.
147
- * @member {String} AppInfo#baseDir
148
- */
149
- baseDir: this.options.baseDir,
150
-
151
- /**
152
- * The environment of the application, **it's not NODE_ENV**
153
- *
154
- * 1. from `$baseDir/config/env`
155
- * 2. from EE_SERVER_ENV
156
- * 3. from NODE_ENV
157
- *
158
- * env | description
159
- * --- | ---
160
- * test | system integration testing
161
- * prod | production
162
- * local | local on your own computer
163
- * unittest | unit test
164
- *
165
- * @member {String} AppInfo#env
166
- * @see https://Eejs.org/zh-cn/basics/env.html
167
- */
168
- env: env,
169
-
170
- /**
171
- * @member {String} AppInfo#scope
172
- */
173
- scope: this.serverScope,
174
-
175
- /**
176
- * The use directory, same as `process.env.HOME`
177
- * @member {String} AppInfo#HOME
178
- */
179
- home: this.getHomedir(),
180
-
181
- /**
182
- * The directory whether is homeDir or appUserData depend on env.
183
- * @member {String} AppInfo#root
184
- */
185
- root: Ps.getRootDir(),
186
-
187
- /**
188
- * electron application data dir
189
- * @member {String} AppInfo#appUserDataDir
190
- */
191
- appUserDataDir: this.options.appUserData,
192
-
193
- /**
194
- * system user home dir
195
- * @member {String} AppInfo#userHome
196
- */
197
- userHome: this.options.userHome,
198
-
199
- /**
200
- * application version
201
- * @member {String} AppInfo#appVersion
202
- */
203
- appVersion: this.options.appVersion,
204
-
205
- /**
206
- * application package status
207
- * @member {boolean} AppInfo#isPackaged
208
- */
209
- isPackaged: this.options.isPackaged,
210
-
211
- /**
212
- * application exec file dir
213
- * @member {String} AppInfo#execDir
214
- */
215
- execDir: this.options.execDir
216
- };
217
- }
218
-
219
- /**
220
- * Get {@link EeLoader#EePaths}
221
- * @return {Array} framework directories
222
- * @see {@link EeLoader#EePaths}
223
- * @private
224
- * @since 1.0.0
225
- */
226
- getEePaths() {
227
- // avoid require recursively
228
- const EePaths = [];
229
- EePaths.push(this.app[Symbol.for('ee#eePath')]);
230
-
231
- return EePaths;
232
- }
233
-
234
- // Low Level API
235
-
236
- /**
237
- * Load single file, will invoke when export is function
238
- *
239
- * @param {String} filepath - fullpath
240
- * @param {Array} inject - pass rest arguments into the function when invoke
241
- * @return {Object} exports
242
- * @example
243
- * ```js
244
- * app.loader.loadFile(path.join(app.options.baseDir, 'config/router.js'));
245
- * ```
246
- * @since 1.0.0
247
- */
248
- loadFile(filepath, ...inject) {
249
- filepath = filepath && this.resolveModule(filepath);
250
- if (!filepath) {
251
- return null;
252
- }
253
-
254
- // function(arg1, args, ...) {}
255
- if (inject.length === 0) inject = [ this.app ];
256
-
257
- let ret = this.requireFile(filepath);
258
- if (is.function(ret) && !is.class(ret) && !Utils.isBytecodeClass(ret)) {
259
- ret = ret(...inject);
260
- }
261
- return ret;
262
- }
263
-
264
- /**
265
- * @param {String} filepath - fullpath
266
- * @return {Object} exports
267
- * @private
268
- */
269
- requireFile(filepath) {
270
- const timingKey = `Require(${this[REQUIRE_COUNT]++}) ${Utils.getResolvedFilename(filepath, this.options.baseDir)}`;
271
- this.timing.start(timingKey);
272
- const ret = Utils.loadFile(filepath);
273
- this.timing.end(timingKey);
274
- return ret;
275
- }
276
-
277
- /**
278
- * Get all loadUnit
279
- *
280
- * loadUnit is a directory that can be loaded by EeLoader, it has the same structure.
281
- * loadUnit has a path and a type(app, framework, plugin).
282
- *
283
- * The order of the loadUnits:
284
- *
285
- * 1. plugin
286
- * 2. framework
287
- * 3. app
288
- *
289
- * @return {Array} loadUnits
290
- * @since 1.0.0
291
- */
292
- getLoadUnits() {
293
- if (this.dirs) {
294
- return this.dirs;
295
- }
296
-
297
- const dirs = this.dirs = [];
298
-
299
- // framework or Ee path
300
- for (const EePath of this.EePaths) {
301
- dirs.push({
302
- path: EePath,
303
- type: 'framework',
304
- });
305
- }
306
-
307
- // application
308
- dirs.push({
309
- path: this.options.baseDir,
310
- type: 'app',
311
- });
312
-
313
- debug('Loaded dirs %j', dirs);
314
- return dirs;
315
- }
316
-
317
- /**
318
- * Load files using {@link FileLoader}, inject to {@link Application}
319
- * @param {String|Array} directory - see {@link FileLoader}
320
- * @param {String} property - see {@link FileLoader}
321
- * @param {Object} opt - see {@link FileLoader}
322
- * @since 1.0.0
323
- */
324
- loadToApp(directory, property, opt) {
325
- const target = this.app[property] = {};
326
- opt = Object.assign({}, {
327
- directory,
328
- target,
329
- inject: this.app,
330
- }, opt);
331
-
332
- const timingKey = `Load "${String(property)}" to Application`;
333
- this.timing.start(timingKey);
334
- new FileLoader(opt).load();
335
- this.timing.end(timingKey);
336
- }
337
-
338
- /**
339
- * Load files using {@link ContextLoader}
340
- * @param {String|Array} directory - see {@link ContextLoader}
341
- * @param {String} property - see {@link ContextLoader}
342
- * @param {Object} opt - see {@link ContextLoader}
343
- * @since 1.0.0
344
- */
345
- loadToContext(directory, property, opt) {
346
- opt = Object.assign({}, {
347
- directory,
348
- property,
349
- inject: this.app,
350
- loader: this
351
- }, opt);
352
- const timingKey = `Load "${String(property)}" to Context`;
353
- this.timing.start(timingKey);
354
- if (['addon'].includes(property)) {
355
- new ContextLoader(opt).loadAddons();
356
- } else {
357
- new ContextLoader(opt).load();
358
- }
359
-
360
- this.timing.end(timingKey);
361
- }
362
-
363
- /**
364
- * @member {FileLoader} EeLoader#FileLoader
365
- * @since 1.0.0
366
- */
367
- get FileLoader() {
368
- return FileLoader;
369
- }
370
-
371
- /**
372
- * @member {ContextLoader} EeLoader#ContextLoader
373
- * @since 1.0.0
374
- */
375
- get ContextLoader() {
376
- return ContextLoader;
377
- }
378
-
379
- getTypeFiles(filename) {
380
- const files = [ `${filename}.default` ];
381
- files.push(`${filename}.${this.serverEnv}`);
382
-
383
- return files;
384
- }
385
-
386
- resolveModule(filepath) {
387
- let fullpath;
388
- try {
389
- fullpath = require.resolve(filepath);
390
- } catch (e) {
391
-
392
- // 特殊后缀处理
393
- if (filepath && (filepath.endsWith('.defalut') || filepath.endsWith('.prod'))) {
394
- fullpath = filepath + '.jsc';
395
- } else if (filepath && filepath.endsWith('.js')) {
396
- fullpath = filepath + 'c';
397
- }
398
-
399
- if (!fs.existsSync(filepath) && !fs.existsSync(fullpath)) {
400
- //this.options.logger.warn(`[ee-core] [core/lib/loader/ee_loader] resolveModule unknow filepath: ${filepath}`)
401
- return undefined;
402
- }
403
- }
404
-
405
- return fullpath;
406
- }
407
-
408
- getPkg() {
409
- const filePath = path.join(this.options.homeDir, 'package.json');
410
- if (!fs.existsSync(filePath)) {
411
- throw new Error(filePath + ' is not found');
412
- }
413
- const json = JSON.parse(fs.readFileSync(filePath));
414
-
415
- return json;
416
- }
417
- }
418
-
419
- /**
420
- * Mixin methods to EeLoader
421
- * // ES6 Multiple Inheritance
422
- * https://medium.com/@leocavalcante/es6-multiple-inheritance-73a3c66d2b6b
423
- */
424
- const loaders = [
425
- require('./mixin/config'),
426
- require('./mixin/service'),
427
- require('./mixin/controller'),
428
- require('./mixin/addon'),
429
- ];
430
-
431
- for (const loader of loaders) {
432
- Object.assign(EeLoader.prototype, loader);
433
- }
434
-
435
- module.exports = EeLoader;
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const assert = require('assert');
6
+ const is = require('is-type-of');
7
+ const debug = require('debug')('ee-core:EeLoader');
8
+ const FileLoader = require('./file_loader');
9
+ const ContextLoader = require('./context_loader');
10
+ const Utils = require('../utils');
11
+ const Timing = require('../utils/timing');
12
+ const Ps = require('../../../ps');
13
+
14
+ const REQUIRE_COUNT = Symbol('EeLoader#requireCount');
15
+
16
+ class EeLoader {
17
+
18
+ /**
19
+ * @class
20
+ * @param {Object} options - options
21
+ * @param {String} options.baseDir - the directory of application
22
+ * @param {EeCore} options.app - Application instance
23
+ * @param {Logger} options.logger - logger
24
+ * @since 1.0.0
25
+ */
26
+ constructor(options) {
27
+ this.options = options;
28
+ // assert(fs.existsSync(this.options.baseDir), `${this.options.baseDir} not exists`);
29
+ assert(this.options.app, 'options.app is required');
30
+ assert(this.options.logger, 'options.logger is required');
31
+
32
+ this.app = this.options.app;
33
+ this.timing = this.app.timing || new Timing();
34
+ this[REQUIRE_COUNT] = 0;
35
+
36
+ /**
37
+ * @member {Object} EeLoader#pkg
38
+ * @see {@link AppInfo#pkg}
39
+ * @since 1.0.0
40
+ */
41
+ this.pkg = this.getPkg();
42
+
43
+ /**
44
+ * Framework directories
45
+ *
46
+ * @member {Array} EeLoader#EePaths
47
+ * @see EeLoader#getEePaths
48
+ * @since 1.0.0
49
+ */
50
+ this.EePaths = this.getEePaths();
51
+ debug('Loaded EePaths %j', this.EePaths);
52
+
53
+ /**
54
+ * @member {String} EeLoader#serverEnv
55
+ * @see AppInfo#env
56
+ * @since 1.0.0
57
+ */
58
+ this.serverEnv = this.getServerEnv();
59
+ debug('Loaded serverEnv %j', this.serverEnv);
60
+
61
+ /**
62
+ * @member {AppInfo} EeLoader#appInfo
63
+ * @since 1.0.0
64
+ */
65
+ this.appInfo = this.getAppInfo();
66
+
67
+ /**
68
+ * @member {String} EeLoader#serverScope
69
+ * @see AppInfo#serverScope
70
+ */
71
+ this.serverScope = options.serverScope !== undefined
72
+ ? options.serverScope
73
+ : this.getServerScope();
74
+ }
75
+
76
+ /**
77
+ * Get {@link AppInfo#env}
78
+ * @return {String} env
79
+ * @see AppInfo#env
80
+ * @private
81
+ * @since 1.0.0
82
+ */
83
+ getServerEnv() {
84
+ let serverEnv = this.options.env;
85
+
86
+ if (!serverEnv) {
87
+ throw new Error('[core] [lib] [loader] getServerEnv serverEnv can not be empty!');
88
+ }
89
+
90
+ return serverEnv;
91
+ }
92
+
93
+ /**
94
+ * Get {@link AppInfo#scope}
95
+ * @return {String} serverScope
96
+ * @private
97
+ */
98
+ getServerScope() {
99
+ return process.env.EE_SERVER_SCOPE || '';
100
+ }
101
+
102
+ /**
103
+ * Get {@link AppInfo#name}
104
+ * @return {String} appname
105
+ * @private
106
+ * @since 1.0.0
107
+ */
108
+ getAppname() {
109
+ if (this.pkg.name) {
110
+ debug('Loaded appname(%s) from package.json', this.pkg.name);
111
+ return this.pkg.name;
112
+ }
113
+
114
+ throw new Error(`name is required from ${pkg}`);
115
+ }
116
+
117
+ /**
118
+ * Get home directory
119
+ * @return {String} home directory
120
+ * @since 3.4.0
121
+ */
122
+ getHomedir() {
123
+ return this.options.homeDir;
124
+ }
125
+
126
+ /**
127
+ * Get app info
128
+ * @return {AppInfo} appInfo
129
+ * @since 1.0.0
130
+ */
131
+ getAppInfo() {
132
+ const env = this.serverEnv;
133
+
134
+ /**
135
+ * Meta information of the application
136
+ * @class AppInfo
137
+ */
138
+ return {
139
+ /**
140
+ * The name of the application, retrieve from the name property in `package.json`.
141
+ * @member {String} AppInfo#name
142
+ */
143
+ name: this.getAppname(),
144
+
145
+ /**
146
+ * The current directory, where the application code is.
147
+ * @member {String} AppInfo#baseDir
148
+ */
149
+ baseDir: this.options.baseDir,
150
+
151
+ /**
152
+ * The environment of the application, **it's not NODE_ENV**
153
+ *
154
+ * 1. from `$baseDir/config/env`
155
+ * 2. from EE_SERVER_ENV
156
+ * 3. from NODE_ENV
157
+ *
158
+ * env | description
159
+ * --- | ---
160
+ * test | system integration testing
161
+ * prod | production
162
+ * local | local on your own computer
163
+ * unittest | unit test
164
+ *
165
+ * @member {String} AppInfo#env
166
+ * @see https://Eejs.org/zh-cn/basics/env.html
167
+ */
168
+ env: env,
169
+
170
+ /**
171
+ * @member {String} AppInfo#scope
172
+ */
173
+ scope: this.serverScope,
174
+
175
+ /**
176
+ * The use directory, same as `process.env.HOME`
177
+ * @member {String} AppInfo#HOME
178
+ */
179
+ home: this.getHomedir(),
180
+
181
+ /**
182
+ * The directory whether is homeDir or appUserData depend on env.
183
+ * @member {String} AppInfo#root
184
+ */
185
+ root: Ps.getRootDir(),
186
+
187
+ /**
188
+ * electron application data dir
189
+ * @member {String} AppInfo#appUserDataDir
190
+ */
191
+ appUserDataDir: this.options.appUserData,
192
+
193
+ /**
194
+ * system user home dir
195
+ * @member {String} AppInfo#userHome
196
+ */
197
+ userHome: this.options.userHome,
198
+
199
+ /**
200
+ * application version
201
+ * @member {String} AppInfo#appVersion
202
+ */
203
+ appVersion: this.options.appVersion,
204
+
205
+ /**
206
+ * application package status
207
+ * @member {boolean} AppInfo#isPackaged
208
+ */
209
+ isPackaged: this.options.isPackaged,
210
+
211
+ /**
212
+ * application exec file dir
213
+ * @member {String} AppInfo#execDir
214
+ */
215
+ execDir: this.options.execDir
216
+ };
217
+ }
218
+
219
+ /**
220
+ * Get {@link EeLoader#EePaths}
221
+ * @return {Array} framework directories
222
+ * @see {@link EeLoader#EePaths}
223
+ * @private
224
+ * @since 1.0.0
225
+ */
226
+ getEePaths() {
227
+ // avoid require recursively
228
+ const EePaths = [];
229
+ EePaths.push(this.app[Symbol.for('ee#eePath')]);
230
+
231
+ return EePaths;
232
+ }
233
+
234
+ // Low Level API
235
+
236
+ /**
237
+ * Load single file, will invoke when export is function
238
+ *
239
+ * @param {String} filepath - fullpath
240
+ * @param {Array} inject - pass rest arguments into the function when invoke
241
+ * @return {Object} exports
242
+ * @example
243
+ * ```js
244
+ * app.loader.loadFile(path.join(app.options.baseDir, 'config/router.js'));
245
+ * ```
246
+ * @since 1.0.0
247
+ */
248
+ loadFile(filepath, ...inject) {
249
+ filepath = filepath && this.resolveModule(filepath);
250
+ if (!filepath) {
251
+ return null;
252
+ }
253
+
254
+ // function(arg1, args, ...) {}
255
+ if (inject.length === 0) inject = [ this.app ];
256
+
257
+ let ret = this.requireFile(filepath);
258
+ if (is.function(ret) && !is.class(ret) && !Utils.isBytecodeClass(ret)) {
259
+ ret = ret(...inject);
260
+ }
261
+ return ret;
262
+ }
263
+
264
+ /**
265
+ * @param {String} filepath - fullpath
266
+ * @return {Object} exports
267
+ * @private
268
+ */
269
+ requireFile(filepath) {
270
+ const timingKey = `Require(${this[REQUIRE_COUNT]++}) ${Utils.getResolvedFilename(filepath, this.options.baseDir)}`;
271
+ this.timing.start(timingKey);
272
+ const ret = Utils.loadFile(filepath);
273
+ this.timing.end(timingKey);
274
+ return ret;
275
+ }
276
+
277
+ /**
278
+ * Get all loadUnit
279
+ *
280
+ * loadUnit is a directory that can be loaded by EeLoader, it has the same structure.
281
+ * loadUnit has a path and a type(app, framework, plugin).
282
+ *
283
+ * The order of the loadUnits:
284
+ *
285
+ * 1. plugin
286
+ * 2. framework
287
+ * 3. app
288
+ *
289
+ * @return {Array} loadUnits
290
+ * @since 1.0.0
291
+ */
292
+ getLoadUnits() {
293
+ if (this.dirs) {
294
+ return this.dirs;
295
+ }
296
+
297
+ const dirs = this.dirs = [];
298
+
299
+ // framework or Ee path
300
+ for (const EePath of this.EePaths) {
301
+ dirs.push({
302
+ path: EePath,
303
+ type: 'framework',
304
+ });
305
+ }
306
+
307
+ // application
308
+ dirs.push({
309
+ path: this.options.baseDir,
310
+ type: 'app',
311
+ });
312
+
313
+ debug('Loaded dirs %j', dirs);
314
+ return dirs;
315
+ }
316
+
317
+ /**
318
+ * Load files using {@link FileLoader}, inject to {@link Application}
319
+ * @param {String|Array} directory - see {@link FileLoader}
320
+ * @param {String} property - see {@link FileLoader}
321
+ * @param {Object} opt - see {@link FileLoader}
322
+ * @since 1.0.0
323
+ */
324
+ loadToApp(directory, property, opt) {
325
+ const target = this.app[property] = {};
326
+ opt = Object.assign({}, {
327
+ directory,
328
+ target,
329
+ inject: this.app,
330
+ }, opt);
331
+
332
+ const timingKey = `Load "${String(property)}" to Application`;
333
+ this.timing.start(timingKey);
334
+ new FileLoader(opt).load();
335
+ this.timing.end(timingKey);
336
+ }
337
+
338
+ /**
339
+ * Load files using {@link ContextLoader}
340
+ * @param {String|Array} directory - see {@link ContextLoader}
341
+ * @param {String} property - see {@link ContextLoader}
342
+ * @param {Object} opt - see {@link ContextLoader}
343
+ * @since 1.0.0
344
+ */
345
+ loadToContext(directory, property, opt) {
346
+ opt = Object.assign({}, {
347
+ directory,
348
+ property,
349
+ inject: this.app,
350
+ loader: this
351
+ }, opt);
352
+ const timingKey = `Load "${String(property)}" to Context`;
353
+ this.timing.start(timingKey);
354
+ if (['addon'].includes(property)) {
355
+ new ContextLoader(opt).loadAddons();
356
+ } else {
357
+ new ContextLoader(opt).load();
358
+ }
359
+
360
+ this.timing.end(timingKey);
361
+ }
362
+
363
+ /**
364
+ * @member {FileLoader} EeLoader#FileLoader
365
+ * @since 1.0.0
366
+ */
367
+ get FileLoader() {
368
+ return FileLoader;
369
+ }
370
+
371
+ /**
372
+ * @member {ContextLoader} EeLoader#ContextLoader
373
+ * @since 1.0.0
374
+ */
375
+ get ContextLoader() {
376
+ return ContextLoader;
377
+ }
378
+
379
+ getTypeFiles(filename) {
380
+ const files = [ `${filename}.default` ];
381
+ files.push(`${filename}.${this.serverEnv}`);
382
+
383
+ return files;
384
+ }
385
+
386
+ resolveModule(filepath) {
387
+ let fullpath;
388
+ try {
389
+ fullpath = require.resolve(filepath);
390
+ } catch (e) {
391
+
392
+ // 特殊后缀处理
393
+ if (filepath && (filepath.endsWith('.defalut') || filepath.endsWith('.prod'))) {
394
+ fullpath = filepath + '.jsc';
395
+ } else if (filepath && filepath.endsWith('.js')) {
396
+ fullpath = filepath + 'c';
397
+ }
398
+
399
+ if (!fs.existsSync(filepath) && !fs.existsSync(fullpath)) {
400
+ //this.options.logger.warn(`[ee-core] [core/lib/loader/ee_loader] resolveModule unknow filepath: ${filepath}`)
401
+ return undefined;
402
+ }
403
+ }
404
+
405
+ return fullpath;
406
+ }
407
+
408
+ getPkg() {
409
+ const filePath = path.join(this.options.homeDir, 'package.json');
410
+ if (!fs.existsSync(filePath)) {
411
+ throw new Error(filePath + ' is not found');
412
+ }
413
+ const json = JSON.parse(fs.readFileSync(filePath));
414
+
415
+ return json;
416
+ }
417
+ }
418
+
419
+ /**
420
+ * Mixin methods to EeLoader
421
+ * // ES6 Multiple Inheritance
422
+ * https://medium.com/@leocavalcante/es6-multiple-inheritance-73a3c66d2b6b
423
+ */
424
+ const loaders = [
425
+ require('./mixin/config'),
426
+ require('./mixin/service'),
427
+ require('./mixin/controller'),
428
+ require('./mixin/addon'),
429
+ ];
430
+
431
+ for (const loader of loaders) {
432
+ Object.assign(EeLoader.prototype, loader);
433
+ }
434
+
435
+ module.exports = EeLoader;