ee-core 1.3.2 → 1.3.4-beta.1

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.
@@ -0,0 +1,92 @@
1
+ const { BrowserWindow } = require('electron');
2
+
3
+ /**
4
+ * 窗口插件
5
+ * @class
6
+ */
7
+ class WinAddon {
8
+
9
+ constructor(app) {
10
+ this.app = app;
11
+ this.windowContentsIdMap = {};
12
+ }
13
+
14
+ /**
15
+ * create window
16
+ *
17
+ * @function
18
+ * @since 1.0.0
19
+ */
20
+ create(name, opt) {
21
+ const options = Object.assign({
22
+ x: 10,
23
+ y: 10,
24
+ width: 980,
25
+ height: 650,
26
+ webPreferences: {
27
+ contextIsolation: false,
28
+ nodeIntegration: true,
29
+ },
30
+ }, opt);
31
+ const win = new BrowserWindow(options)
32
+
33
+ const winContentsId = win.webContents.id;
34
+ win.webContents.on('did-finish-load', () => {
35
+ this.registerWCid(name, winContentsId);
36
+ })
37
+
38
+ win.webContents.on('destroyed', () => {
39
+ this.removeWCid(name);
40
+ })
41
+
42
+ win.webContents.on('render-process-gone', (event, details) => {
43
+ this.removeWCid(name);
44
+ })
45
+
46
+ return win;
47
+ }
48
+
49
+ /**
50
+ * 获取窗口Contents id
51
+ *
52
+ * @function
53
+ * @since 1.0.0
54
+ */
55
+ getWCid(name) {
56
+ const id = this.windowContentsIdMap[name] || null;
57
+ return id;
58
+ }
59
+
60
+ /**
61
+ * 获取主窗口Contents id
62
+ *
63
+ * @function
64
+ * @since 1.0.0
65
+ */
66
+ getMWCid() {
67
+ const id = this.windowContentsIdMap['main'] || null;
68
+ return id;
69
+ }
70
+
71
+ /**
72
+ * 注册窗口Contents id
73
+ *
74
+ * @function
75
+ * @since 1.0.0
76
+ */
77
+ registerWCid (name, id) {
78
+ this.windowContentsIdMap[name] = id;
79
+ }
80
+
81
+ /**
82
+ * 销毁窗口Contents id
83
+ *
84
+ * @function
85
+ * @since 1.0.0
86
+ */
87
+ removeWCid (name) {
88
+ delete this.windowContentsIdMap[name];
89
+ }
90
+ }
91
+
92
+ module.exports = WinAddon;
@@ -222,6 +222,10 @@ module.exports = appInfo => {
222
222
  },
223
223
  body: {
224
224
  multipart: true, // 文件类型
225
+ },
226
+ filterRequest: {
227
+ uris: [],
228
+ returnData: ''
225
229
  }
226
230
  };
227
231
 
@@ -257,7 +261,16 @@ module.exports = appInfo => {
257
261
  /**
258
262
  * loading页(废弃)
259
263
  */
260
- config.loadingPage = false;
264
+ config.loadingPage = false;
265
+
266
+ /**
267
+ * addons
268
+ */
269
+ config.addons = {
270
+ window: {
271
+ enable: true,
272
+ }
273
+ };
261
274
 
262
275
  return config;
263
276
  };
package/core/lib/ee.js CHANGED
@@ -157,6 +157,15 @@ class EeCore extends KoaApplication {
157
157
  return this.loader ? this.loader.config : {};
158
158
  }
159
159
 
160
+ /**
161
+ * The addon of application
162
+ * @member {Addon}
163
+ * @since 1.0.0
164
+ */
165
+ get addon() {
166
+ return this.loader ? this.loader.addon : {};
167
+ }
168
+
160
169
  get [EE_LOADER]() {
161
170
  return require('./loader/ee_loader');
162
171
  }
@@ -373,10 +373,16 @@ class EeLoader {
373
373
  directory,
374
374
  property,
375
375
  inject: this.app,
376
+ loader: this
376
377
  }, opt);
377
378
  const timingKey = `Load "${String(property)}" to Context`;
378
379
  this.timing.start(timingKey);
379
- new ContextLoader(opt).load();
380
+ if (['addon'].includes(property)) {
381
+ new ContextLoader(opt).loadAddons();
382
+ } else {
383
+ new ContextLoader(opt).load();
384
+ }
385
+
380
386
  this.timing.end(timingKey);
381
387
  }
382
388
 
@@ -441,6 +447,7 @@ const loaders = [
441
447
  require('./mixin/config'),
442
448
  require('./mixin/service'),
443
449
  require('./mixin/controller'),
450
+ require('./mixin/addon'),
444
451
  ];
445
452
 
446
453
  for (const loader of loaders) {
@@ -23,6 +23,7 @@ const defaults = {
23
23
  override: false,
24
24
  inject: undefined,
25
25
  filter: null,
26
+ loader: undefined,
26
27
  };
27
28
 
28
29
  /**
@@ -44,6 +45,7 @@ class FileLoader {
44
45
  * @param {Object} options.inject - an object that be the argument when invoke the function
45
46
  * @param {Function} options.filter - a function that filter the exports which can be loaded
46
47
  * @param {String|Function} options.caseStyle - set property's case when converting a filepath to property list.
48
+ * @param {Object} options.loader - an object that be the argument when invoke the function
47
49
  */
48
50
  constructor(options) {
49
51
  assert(options.directory, 'options.directory is required');
@@ -175,6 +177,68 @@ class FileLoader {
175
177
  return items;
176
178
  }
177
179
 
180
+ /**
181
+ * attach items to target object for addons.
182
+ * `app/addon/group/index.js` => `target.group`
183
+ * @return {Object} target
184
+ * @since 1.0.0
185
+ */
186
+ loadAddons() {
187
+ const items = [];
188
+ const files = '*';
189
+ const app = this.options.inject;
190
+ const loader = this.options.loader;
191
+ const target = this.options.target;
192
+ let directories = this.options.directory;
193
+
194
+ if (!Array.isArray(directories)) {
195
+ directories = [ directories ];
196
+ }
197
+
198
+ // check addon
199
+ const config = app.config.addons;
200
+ let filterAddons = [];
201
+ for (let key of Object.keys(config)) {
202
+ if (!config[key].enable) {
203
+ filterAddons.push(key);
204
+ }
205
+ }
206
+
207
+ for (const directory of directories) {
208
+ const addonpaths = globby.sync(files, { cwd: directory, deep: 1, onlyDirectories: true});
209
+ for (const addonName of addonpaths) {
210
+ if (filterAddons.includes(addonName)) continue;
211
+
212
+ let fullpath = path.join(directory, addonName, 'index');
213
+ fullpath = loader.resolveModule(fullpath);
214
+ if (!fs.statSync(fullpath).isFile()) continue;
215
+
216
+ let exports = getExports(fullpath, this.options, addonName);
217
+ if (exports == null) continue;
218
+
219
+ const properties = [addonName];
220
+ if (is.class(exports) || utils.isBytecodeClass(exports)) {
221
+ exports.prototype.pathName = addonName;
222
+ exports.prototype.fullPath = fullpath;
223
+ }
224
+
225
+ items.push({ fullpath, properties, exports });
226
+ }
227
+
228
+ for (const item of items) {
229
+ const property = item.properties[0];
230
+ let obj = item.exports;
231
+ if (obj && !is.primitive(obj)) {
232
+ obj[FULLPATH] = item.fullpath;
233
+ obj[EXPORTS] = true;
234
+ }
235
+
236
+ target[property] = obj;
237
+ }
238
+ }
239
+
240
+ return target;
241
+ }
178
242
  }
179
243
 
180
244
  module.exports = FileLoader;
@@ -0,0 +1,32 @@
1
+ const path = require('path');
2
+
3
+ module.exports = {
4
+
5
+ /**
6
+ * Load app/addon
7
+ * @param {Object} opt - LoaderOptions
8
+ * @function
9
+ * @since 1.0.0
10
+ */
11
+ loadAddon(opt) {
12
+ this.timing.start('Load Addon');
13
+
14
+ // 加载ee-core的插件 和 用户插件
15
+ const directorys = [
16
+ path.join(this.options.framework, 'addon'),
17
+ path.join(this.options.baseDir, 'addon'),
18
+ ]
19
+ opt = Object.assign({
20
+ call: true,
21
+ caseStyle: 'lower',
22
+ directory: directorys
23
+ }, opt);
24
+
25
+ const addonPaths = opt.directory;
26
+ this.loadToContext(addonPaths, 'addon', opt);
27
+
28
+ this.timing.end('Load Addon');
29
+ },
30
+ };
31
+
32
+
@@ -2,7 +2,6 @@
2
2
 
3
3
  const path = require('path');
4
4
 
5
-
6
5
  module.exports = {
7
6
 
8
7
  /**
@@ -104,6 +104,18 @@ module.exports = {
104
104
 
105
105
  return isClass;
106
106
  },
107
+
108
+ /**
109
+ * 文件类型
110
+ */
111
+ filePatterns () {
112
+ const files = (process.env.EE_TYPESCRIPT === 'true' && Module._extensions['.ts'])
113
+ ? [ '**/*.(js|ts)', '!**/*.d.ts' ]
114
+ : [ '**/*.js','**/*.jsc' ];
115
+
116
+ return files;
117
+ }
118
+
107
119
  };
108
120
 
109
121
 
package/lib/appLoader.js CHANGED
@@ -30,6 +30,14 @@ class AppLoader extends EeLoader {
30
30
 
31
31
  }
32
32
 
33
+ /**
34
+ * load addons
35
+ * @since 1.0.0
36
+ */
37
+ loadAddons() {
38
+ this.loadAddon();
39
+ }
40
+
33
41
  /**
34
42
  * load electron modules
35
43
  * @since 1.0.0
package/lib/eeApp.js CHANGED
@@ -16,7 +16,7 @@ class EeApp extends BaseApp {
16
16
  tray: null,
17
17
  extra: {
18
18
  closeWindow: false,
19
- }
19
+ },
20
20
  };
21
21
  }
22
22
 
@@ -115,7 +115,9 @@ class EeApp extends BaseApp {
115
115
 
116
116
  await this.windowReady();
117
117
 
118
- await this.loderPreload();
118
+ await this._loderAddons();
119
+
120
+ await this._loderPreload();
119
121
 
120
122
  this.selectAppType();
121
123
 
@@ -256,10 +258,25 @@ class EeApp extends BaseApp {
256
258
  app.quit();
257
259
  }
258
260
 
261
+ /**
262
+ * 加载插件
263
+ */
264
+ async _loderAddons () {
265
+ this.loader.loadAddons();
266
+
267
+ // 注册主窗口Contents id
268
+ const addonsCfg = this.config.addons;
269
+ if (addonsCfg.window.enable) {
270
+ const win = this.electron.mainWindow;
271
+ const addonWindow = this.addon.window;
272
+ addonWindow.registerWCid('main', win.webContents.id);
273
+ }
274
+ }
275
+
259
276
  /**
260
277
  * 预加载模块
261
278
  */
262
- async loderPreload () {
279
+ async _loderPreload () {
263
280
  let filepath = this.loader.resolveModule(path.join(this.config.baseDir, 'preload', 'index'));
264
281
  if (!filepath) return;
265
282
  const fileObj = this.loader.loadFile(filepath);
@@ -268,7 +285,7 @@ class EeApp extends BaseApp {
268
285
  } else if (is.asyncFunction(fileObj)) {
269
286
  await fileObj();
270
287
  }
271
- }
288
+ }
272
289
 
273
290
  /**
274
291
  * 序列化参数
@@ -8,6 +8,7 @@ const koaBody = require('koa-body');
8
8
  const https = require('https');
9
9
  const fs = require('fs');
10
10
  const path = require('path');
11
+ const _ = require('lodash');
11
12
 
12
13
  /**
13
14
  * http server
@@ -77,6 +78,7 @@ class HttpServer {
77
78
  * 路由分发
78
79
  */
79
80
  async dispatch (ctx, next) {
81
+ const config = ctx.eeApp.config.httpServer;
80
82
  let uriPath = ctx.request.path;
81
83
  const method = ctx.request.method;
82
84
  let params = ctx.request.query;
@@ -96,6 +98,12 @@ class HttpServer {
96
98
  if (uriPath.indexOf('/') == 0) {
97
99
  uriPath = uriPath.substring(1);
98
100
  }
101
+ // 过滤
102
+ if (_.includes(config.filterRequest.uris, uriPath)) {
103
+ ctx.response.body = config.filterRequest.returnData;
104
+ await next();
105
+ return
106
+ }
99
107
  if (uriPath.slice(0, 10) != 'controller') {
100
108
  uriPath = 'controller/' + uriPath;
101
109
  }
@@ -24,9 +24,7 @@ class IpcServer {
24
24
 
25
25
  const self = this;
26
26
  // 遍历方法
27
- const files = (process.env.EE_TYPESCRIPT === 'true' && utils.extensions['.ts'])
28
- ? [ '**/*.(js|ts)', '!**/*.d.ts' ]
29
- : [ '**/*.js','**/*.jsc' ];
27
+ const files = utils.filePatterns();
30
28
  const directory = path.join(this.app.config.baseDir, 'controller');
31
29
  const filepaths = globby.sync(files, { cwd: directory });
32
30
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ee-core",
3
- "version": "1.3.2",
3
+ "version": "1.3.4-beta.1",
4
4
  "description": "ee core",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -37,7 +37,7 @@
37
37
  "path-to-regexp": "^6.2.0",
38
38
  "socket.io": "^4.4.1",
39
39
  "socket.io-client": "^4.4.1",
40
- "uglify-js": "^3.14.5",
40
+ "javascript-obfuscator": "^4.0.0",
41
41
  "urllib": "^2.38.0",
42
42
  "utility": "^1.17.0"
43
43
  },
package/tools/encrypt.js CHANGED
@@ -4,10 +4,10 @@ const path = require('path');
4
4
  const fs = require('fs');
5
5
  const fsPro = require('fs-extra');
6
6
  const is = require('is-type-of');
7
- const UglifyJS = require('uglify-js');
8
7
  const bytenode = require('bytenode');
9
8
  const utility = require('utility');
10
9
  const crypto = require('crypto');
10
+ const JavaScriptObfuscator = require('javascript-obfuscator');
11
11
 
12
12
  class Encrypt {
13
13
  constructor() {
@@ -130,13 +130,33 @@ class Encrypt {
130
130
  generate (curPath) {
131
131
  if (this.type == 'bytecode') {
132
132
  this.generateBytecodeFile(curPath);
133
+ } else if (this.type == 'confuse') {
134
+ this.generateJSConfuseFile(curPath);
133
135
  } else {
134
- this.generateConfuseFile(curPath);
136
+ this.generateJSConfuseFile(curPath);
137
+ this.generateBytecodeFile(curPath);
138
+ }
139
+ }
140
+
141
+ /**
142
+ * 使用 javascript-obfuscator 生成压缩/混淆文件
143
+ */
144
+ generateJSConfuseFile (file) {
145
+ let defaultOpt = {
146
+ compact: true,
147
+ stringArray: true,
148
+ rotateStringArray: true,
149
+ stringArrayEncoding: ['base64'],
150
+ stringArrayThreshold: 1,
151
+ disableConsoleOutput: true,
135
152
  }
153
+ let code = fs.readFileSync(file, "utf8");
154
+ let result = JavaScriptObfuscator.obfuscate(code, defaultOpt);
155
+ fs.writeFileSync(file, result.getObfuscatedCode(), "utf8");
136
156
  }
137
157
 
138
158
  /**
139
- * 生成压缩/混淆文件
159
+ * (废弃) 使用 uglify 生成压缩/混淆文件
140
160
  */
141
161
  generateConfuseFile (file) {
142
162
  let defaultOpt = {
@@ -175,6 +195,9 @@ class Encrypt {
175
195
  output: jscFile,
176
196
  electron: true
177
197
  });
198
+
199
+ //fs.writeFileSync(curPath, 'require("bytenode");module.exports = require("./'+path.basename(jscFile)+'");', 'utf8');
200
+
178
201
  fsPro.removeSync(curPath);
179
202
  }
180
203