ee-core 2.6.0 → 2.7.0-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.
@@ -294,11 +294,6 @@ module.exports = appInfo => {
294
294
  dir: path.join(appInfo.root, 'data'),
295
295
  };
296
296
 
297
- /**
298
- * loading页(废弃)
299
- */
300
- config.loadingPage = false;
301
-
302
297
  /**
303
298
  * addons
304
299
  */
@@ -317,5 +312,19 @@ module.exports = appInfo => {
317
312
  rendererExit: true,
318
313
  };
319
314
 
315
+ /**
316
+ * Cross-language service
317
+ * 跨语言服务
318
+ * 例如:执行go的二进制程序
319
+ */
320
+ config.cross = {};
321
+
322
+ /**
323
+ * jobs
324
+ */
325
+ config.jobs = {
326
+ messageLog: true
327
+ };
328
+
320
329
  return config;
321
330
  };
package/cross/index.js ADDED
@@ -0,0 +1,134 @@
1
+ const fs = require('fs');
2
+ const crossSpawn = require('cross-spawn');
3
+ const path = require('path');
4
+ const is = require('is-type-of');
5
+ const Conf = require('../config');
6
+ const UtilsHelper = require('../utils/helper');
7
+ const UtilsIs = require('../utils/is');
8
+ const UtilsPargv = require('../utils/pargv');
9
+ const Ps = require('../ps');
10
+ const Log = require('../log');
11
+ const GetPort = require('../utils/get-port');
12
+ const CoreElectronApp = require('../electron/app');
13
+
14
+ /**
15
+ * Cross-language service
16
+ * 跨语言服务
17
+ */
18
+ const CrossLanguageService = {
19
+
20
+ execProcess: {},
21
+
22
+ /**
23
+ * create
24
+ */
25
+ async create() {
26
+ if (!Ps.isProd()) {
27
+ return
28
+ }
29
+
30
+ // init dir
31
+ this._initPath();
32
+
33
+ // boot services
34
+ const servicesCfg = Conf.getValue('cross');
35
+ //await UtilsHelper.sleep(5 * 1000);
36
+
37
+ for (let key of Object.keys(servicesCfg)) {
38
+ let cfg = servicesCfg[key];
39
+ if (cfg.enable == true) {
40
+ this.run(cfg)
41
+ }
42
+ }
43
+ },
44
+
45
+ /**
46
+ * run
47
+ */
48
+ async run(conf = {}) {
49
+ const cmdName = conf.name;
50
+ const cmdPath = this._getCmdPath(cmdName);
51
+ let cmdArgs = is.string(conf.args) ? [conf.args] : conf.args;
52
+
53
+ // 动态生成port
54
+ // if (Ps.isProd() || this.workspaces.length > 0) {
55
+ let confPort = this.getArgs(cmdArgs, 'port');
56
+ if (!confPort) {
57
+ throw new Error(`[ee-core] [cross/run] --port parameter does not exist!`);
58
+ }
59
+ confPort = await GetPort({ port: confPort });
60
+ // 替换port
61
+ cmdArgs = this.replaceValue(cmdArgs, "--port=", confPort)
62
+
63
+ Log.coreLogger.info(`[ee-core] [cross/run] cmd: ${cmdPath}, args: ${cmdArgs}`);
64
+
65
+ // Launch executable program
66
+ const coreProcess = crossSpawn(cmdPath, cmdArgs, { stdio: 'inherit', detached: false });
67
+ coreProcess.on('close', (code, signal) => {
68
+ Log.coreLogger.info(`[ee-core] [cross/run] [pid=${coreProcess.pid}, port=${port}] exited with code: ${code}, signal: ${signal}`);
69
+ if (0 !== code) {
70
+ // 弹错误窗口
71
+ }
72
+
73
+ CoreElectronApp.quit();
74
+ });
75
+ this.execProcess[cmdName] = coreProcess;
76
+ },
77
+
78
+ getArgs(argv, key) {
79
+ // parse args
80
+ let value = UtilsPargv(argv);
81
+ if (key) {
82
+ value = value[key];
83
+ }
84
+
85
+ return value;
86
+ },
87
+
88
+ replaceValue(arr, key, value) {
89
+ arr = arr.map(item => {
90
+ if (item.startsWith(key)) {
91
+ let newItem = key + value;
92
+ return newItem;
93
+ } else {
94
+ return item;
95
+ }
96
+ });
97
+ return arr;
98
+ },
99
+
100
+ getUrl(argv) {
101
+ const args = this.getArgs(argv);
102
+ let protocol = 'http://';
103
+ if (args.hasOwnProperty('ssl') && (args.ssl == 'true' || args.ssl == '1')) {
104
+ protocol = 'https://';
105
+ }
106
+ const hostname = args.hostname ? args.hostname : '127.0.0.1';
107
+ const url = protocol + hostname + ":" + args.port;
108
+
109
+ return url;
110
+ },
111
+
112
+ _getCmdPath(name) {
113
+ const coreName = UtilsIs.windows() ? name + ".exe" : name;
114
+ const p = path.join(Ps.getExtraResourcesDir(), coreName);
115
+ return p;
116
+ },
117
+
118
+ /**
119
+ * init path
120
+ */
121
+ _initPath() {
122
+ try {
123
+ const pathname = Ps.getUserHomeConfigDir();
124
+ if (!fs.existsSync(pathname)) {
125
+ UtilsHelper.mkdir(pathname, {mode: 0o755});
126
+ }
127
+ } catch (e) {
128
+ Log.coreLogger.error(e);
129
+ throw new Error(`[ee-core] [cross] mkdir ${pathname} failed !`);
130
+ }
131
+ }
132
+ }
133
+
134
+ module.exports = CrossLanguageService;
package/ee/application.js CHANGED
@@ -57,7 +57,7 @@ class Appliaction extends EeApp {
57
57
  }
58
58
 
59
59
  // normalize env
60
- //env.NODE_ENV = options.env;
60
+ env.EE_APP_NAME = options.appName;
61
61
  env.EE_HOME = options.homeDir;
62
62
  env.EE_BASE_DIR = options.baseDir;
63
63
  env.EE_SERVER_ENV = options.env;
@@ -89,6 +89,8 @@ class Appliaction extends EeApp {
89
89
 
90
90
  await this.startSocket();
91
91
 
92
+ await this.crossService();
93
+
92
94
  await this.ready();
93
95
 
94
96
  await this.createElectronApp();
package/ee/eeApp.js CHANGED
@@ -16,6 +16,7 @@ const Socket = require('../socket');
16
16
  const GetPort = require('../utils/get-port');
17
17
  const UtilsHelper = require('../utils/helper');
18
18
  const HttpClient = require('../httpclient');
19
+ const Cross = require('../cross');
19
20
 
20
21
  class EeApp extends BaseApp {
21
22
  constructor(options = {}) {
@@ -59,6 +60,13 @@ class EeApp extends BaseApp {
59
60
  Socket.startAll(this);
60
61
  }
61
62
 
63
+ /**
64
+ * 启动跨语言服务
65
+ */
66
+ async crossService() {
67
+ Cross.create();
68
+ }
69
+
62
70
  /**
63
71
  * 创建electron应用
64
72
  */
@@ -105,6 +113,8 @@ class EeApp extends BaseApp {
105
113
  return;
106
114
  }
107
115
 
116
+ const mainServer = this.config.mainServer;
117
+
108
118
  // 开发环境
109
119
  if (Ps.isDev()) {
110
120
  let modeInfo;
@@ -137,7 +147,7 @@ class EeApp extends BaseApp {
137
147
  let count = 0;
138
148
  let frontendReady = false;
139
149
  const hc = new HttpClient();
140
- while(!frontendReady && count < 30){
150
+ while(!frontendReady && count < 60){
141
151
  await UtilsHelper.sleep(1 * 1000);
142
152
  try {
143
153
  await hc.request(url, {
@@ -165,7 +175,13 @@ class EeApp extends BaseApp {
165
175
  }
166
176
 
167
177
  // 生产环境
168
- const mainServer = this.config.mainServer;
178
+ // cross service takeover web
179
+ if (mainServer.hasOwnProperty('takeover')) {
180
+ await this._crossTakeover(mainServer)
181
+ return
182
+ }
183
+
184
+ // 主进程
169
185
  if (Conf.isFileProtocol(mainServer)) {
170
186
  url = path.join(this.config.homeDir, mainServer.indexPath);
171
187
  this.loadMainUrl('spa', url, 'file');
@@ -174,6 +190,55 @@ class EeApp extends BaseApp {
174
190
  }
175
191
  }
176
192
 
193
+ /**
194
+ * cross service takeover web
195
+ */
196
+ async _crossTakeover(mainCfg = {}) {
197
+ const crossConfig = this.config.cross;
198
+
199
+ // loading page
200
+ this._loadingPage(mainCfg);
201
+
202
+ // cross service url
203
+ if (!crossConfig.hasOwnProperty(mainCfg.takeover)) {
204
+ Log.coreLogger.error(`[ee-core] Please check cross config !`);
205
+ throw new Error(`[ee-core] Please Check the value of mainServer.takeover in the config file !`);
206
+ }
207
+ const servicesCfg = crossConfig[mainCfg.takeover];
208
+ const url = Cross.getUrl(servicesCfg.args);
209
+
210
+ let count = 0;
211
+ let serviceReady = false;
212
+ const hc = new HttpClient();
213
+
214
+ // 循环检查
215
+ const times = Ps.isDev() ? 20 : 100;
216
+ const sleeptime = Ps.isDev() ? 1000 : 100;
217
+ while(!serviceReady && count < times){
218
+ await UtilsHelper.sleep(sleeptime);
219
+ try {
220
+ await hc.request(url, {
221
+ method: 'GET',
222
+ timeout: 100,
223
+ });
224
+ serviceReady = true;
225
+ } catch(err) {
226
+ //console.log('The cross service is starting');
227
+ }
228
+ count++;
229
+ }
230
+ //console.log('count:', count)
231
+ if (serviceReady == false) {
232
+ const bootFailurePage = path.join(__dirname, '..', 'html', 'cross-failure.html');
233
+ this.mainWindow.loadFile(bootFailurePage);
234
+ Log.coreLogger.error(`[ee-core] Please check cross service [${mainCfg.takeover}] ${url} !`);
235
+ return;
236
+ }
237
+
238
+ Log.coreLogger.info(`[ee-core] cross service [${mainCfg.takeover}] is started successfully`);
239
+ this.loadMainUrl('spa', url);
240
+ }
241
+
177
242
  /**
178
243
  * 加载本地前端资源
179
244
  */
@@ -241,6 +306,19 @@ class EeApp extends BaseApp {
241
306
  }
242
307
  }
243
308
 
309
+ /**
310
+ * loading page
311
+ */
312
+ _loadingPage(mainCfg = {}) {
313
+ const p = mainCfg.hasOwnProperty('loadingPage') ? mainCfg.loadingPage : 'unknown';
314
+ const lp = path.join(this.config.homeDir, p);
315
+ if (!fs.existsSync(lp)) {
316
+ return
317
+ }
318
+
319
+ this.mainWindow.loadFile(lp);
320
+ }
321
+
244
322
  /**
245
323
  * electron app退出
246
324
  */
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, maximum-scale=1.0, minimum-scale=1.0" />
7
+ <title>Booting failure</title>
8
+ <style>
9
+ #failure {
10
+ background-color: #dedede;
11
+ font-size: 14px;
12
+ }
13
+ .base {
14
+ position: absolute;
15
+ top: 50%;
16
+ left: 50%;
17
+ transform: translate(-50%, -50%);
18
+ }
19
+ </style>
20
+ </head>
21
+ <body>
22
+ <div id="failure">
23
+ <div class='base'>
24
+ Booting failure, please check cross service is runing !
25
+ </div>
26
+ </div>
27
+ </body>
28
+ </html>
package/html/failure.html CHANGED
@@ -21,7 +21,7 @@
21
21
  <body>
22
22
  <div id="failure">
23
23
  <div class='base'>
24
- Booting failure, please check frontend serve is runing !
24
+ Booting failure, please check frontend service is runing !
25
25
  </div>
26
26
  </div>
27
27
  </body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ee-core",
3
- "version": "2.6.0",
3
+ "version": "2.7.0-beta.1",
4
4
  "description": "ee core",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/ps/index.js CHANGED
@@ -127,6 +127,13 @@ exports.processType = function() {
127
127
  return type;
128
128
  };
129
129
 
130
+ /**
131
+ * app name
132
+ */
133
+ exports.appName = function() {
134
+ return process.env.EE_APP_NAME;
135
+ }
136
+
130
137
  /**
131
138
  * 获取home路径
132
139
  */
@@ -230,10 +237,35 @@ exports.getExecDir = function() {
230
237
  /**
231
238
  * 获取操作系统用户目录
232
239
  */
233
- exports.getUserHomeDir = function () {
240
+ exports.getUserHomeDir = function() {
234
241
  return process.env.EE_USER_HOME;
235
242
  }
236
243
 
244
+ /**
245
+ * 获取用户目录配置数据目录
246
+ */
247
+ exports.getUserHomeConfigDir = function() {
248
+ // const filePath = path.join(this.getHomeDir(), 'package.json');
249
+ // if (!fs.existsSync(filePath)) {
250
+ // throw new Error(filePath + ' is not found');
251
+ // }
252
+ // const pkg = JSON.parse(fs.readFileSync(filePath));
253
+ // if (!pkg.name || pkg.name == "") {
254
+ // throw new Error(`name is required from ${filePath}`);
255
+ // }
256
+ const appname = this.appName();
257
+ const cfgDir = path.join(this.getUserHomeDir(), ".config", appname);
258
+ return cfgDir;
259
+ }
260
+
261
+ /**
262
+ * 获取基础数据路径
263
+ */
264
+ exports.getUserHomeAppFilePath = function() {
265
+ const p = path.join(this.getUserHomeConfigDir(), "app.json");
266
+ return p;
267
+ }
268
+
237
269
  /**
238
270
  * 获取主进程端口
239
271
  */
package/utils/pargv.js ADDED
@@ -0,0 +1,263 @@
1
+ 'use strict';
2
+
3
+ function hasKey(obj, keys) {
4
+ var o = obj;
5
+ keys.slice(0, -1).forEach(function (key) {
6
+ o = o[key] || {};
7
+ });
8
+
9
+ var key = keys[keys.length - 1];
10
+ return key in o;
11
+ }
12
+
13
+ function isNumber(x) {
14
+ if (typeof x === 'number') { return true; }
15
+ if ((/^0x[0-9a-f]+$/i).test(x)) { return true; }
16
+ return (/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/).test(x);
17
+ }
18
+
19
+ function isConstructorOrProto(obj, key) {
20
+ return (key === 'constructor' && typeof obj[key] === 'function') || key === '__proto__';
21
+ }
22
+
23
+ module.exports = function (args, opts) {
24
+ if (!opts) { opts = {}; }
25
+
26
+ var flags = {
27
+ bools: {},
28
+ strings: {},
29
+ unknownFn: null,
30
+ };
31
+
32
+ if (typeof opts.unknown === 'function') {
33
+ flags.unknownFn = opts.unknown;
34
+ }
35
+
36
+ if (typeof opts.boolean === 'boolean' && opts.boolean) {
37
+ flags.allBools = true;
38
+ } else {
39
+ [].concat(opts.boolean).filter(Boolean).forEach(function (key) {
40
+ flags.bools[key] = true;
41
+ });
42
+ }
43
+
44
+ var aliases = {};
45
+
46
+ function aliasIsBoolean(key) {
47
+ return aliases[key].some(function (x) {
48
+ return flags.bools[x];
49
+ });
50
+ }
51
+
52
+ Object.keys(opts.alias || {}).forEach(function (key) {
53
+ aliases[key] = [].concat(opts.alias[key]);
54
+ aliases[key].forEach(function (x) {
55
+ aliases[x] = [key].concat(aliases[key].filter(function (y) {
56
+ return x !== y;
57
+ }));
58
+ });
59
+ });
60
+
61
+ [].concat(opts.string).filter(Boolean).forEach(function (key) {
62
+ flags.strings[key] = true;
63
+ if (aliases[key]) {
64
+ [].concat(aliases[key]).forEach(function (k) {
65
+ flags.strings[k] = true;
66
+ });
67
+ }
68
+ });
69
+
70
+ var defaults = opts.default || {};
71
+
72
+ var argv = { _: [] };
73
+
74
+ function argDefined(key, arg) {
75
+ return (flags.allBools && (/^--[^=]+$/).test(arg))
76
+ || flags.strings[key]
77
+ || flags.bools[key]
78
+ || aliases[key];
79
+ }
80
+
81
+ function setKey(obj, keys, value) {
82
+ var o = obj;
83
+ for (var i = 0; i < keys.length - 1; i++) {
84
+ var key = keys[i];
85
+ if (isConstructorOrProto(o, key)) { return; }
86
+ if (o[key] === undefined) { o[key] = {}; }
87
+ if (
88
+ o[key] === Object.prototype
89
+ || o[key] === Number.prototype
90
+ || o[key] === String.prototype
91
+ ) {
92
+ o[key] = {};
93
+ }
94
+ if (o[key] === Array.prototype) { o[key] = []; }
95
+ o = o[key];
96
+ }
97
+
98
+ var lastKey = keys[keys.length - 1];
99
+ if (isConstructorOrProto(o, lastKey)) { return; }
100
+ if (
101
+ o === Object.prototype
102
+ || o === Number.prototype
103
+ || o === String.prototype
104
+ ) {
105
+ o = {};
106
+ }
107
+ if (o === Array.prototype) { o = []; }
108
+ if (o[lastKey] === undefined || flags.bools[lastKey] || typeof o[lastKey] === 'boolean') {
109
+ o[lastKey] = value;
110
+ } else if (Array.isArray(o[lastKey])) {
111
+ o[lastKey].push(value);
112
+ } else {
113
+ o[lastKey] = [o[lastKey], value];
114
+ }
115
+ }
116
+
117
+ function setArg(key, val, arg) {
118
+ if (arg && flags.unknownFn && !argDefined(key, arg)) {
119
+ if (flags.unknownFn(arg) === false) { return; }
120
+ }
121
+
122
+ var value = !flags.strings[key] && isNumber(val)
123
+ ? Number(val)
124
+ : val;
125
+ setKey(argv, key.split('.'), value);
126
+
127
+ (aliases[key] || []).forEach(function (x) {
128
+ setKey(argv, x.split('.'), value);
129
+ });
130
+ }
131
+
132
+ Object.keys(flags.bools).forEach(function (key) {
133
+ setArg(key, defaults[key] === undefined ? false : defaults[key]);
134
+ });
135
+
136
+ var notFlags = [];
137
+
138
+ if (args.indexOf('--') !== -1) {
139
+ notFlags = args.slice(args.indexOf('--') + 1);
140
+ args = args.slice(0, args.indexOf('--'));
141
+ }
142
+
143
+ for (var i = 0; i < args.length; i++) {
144
+ var arg = args[i];
145
+ var key;
146
+ var next;
147
+
148
+ if ((/^--.+=/).test(arg)) {
149
+ // Using [\s\S] instead of . because js doesn't support the
150
+ // 'dotall' regex modifier. See:
151
+ // http://stackoverflow.com/a/1068308/13216
152
+ var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
153
+ key = m[1];
154
+ var value = m[2];
155
+ if (flags.bools[key]) {
156
+ value = value !== 'false';
157
+ }
158
+ setArg(key, value, arg);
159
+ } else if ((/^--no-.+/).test(arg)) {
160
+ key = arg.match(/^--no-(.+)/)[1];
161
+ setArg(key, false, arg);
162
+ } else if ((/^--.+/).test(arg)) {
163
+ key = arg.match(/^--(.+)/)[1];
164
+ next = args[i + 1];
165
+ if (
166
+ next !== undefined
167
+ && !(/^(-|--)[^-]/).test(next)
168
+ && !flags.bools[key]
169
+ && !flags.allBools
170
+ && (aliases[key] ? !aliasIsBoolean(key) : true)
171
+ ) {
172
+ setArg(key, next, arg);
173
+ i += 1;
174
+ } else if ((/^(true|false)$/).test(next)) {
175
+ setArg(key, next === 'true', arg);
176
+ i += 1;
177
+ } else {
178
+ setArg(key, flags.strings[key] ? '' : true, arg);
179
+ }
180
+ } else if ((/^-[^-]+/).test(arg)) {
181
+ var letters = arg.slice(1, -1).split('');
182
+
183
+ var broken = false;
184
+ for (var j = 0; j < letters.length; j++) {
185
+ next = arg.slice(j + 2);
186
+
187
+ if (next === '-') {
188
+ setArg(letters[j], next, arg);
189
+ continue;
190
+ }
191
+
192
+ if ((/[A-Za-z]/).test(letters[j]) && next[0] === '=') {
193
+ setArg(letters[j], next.slice(1), arg);
194
+ broken = true;
195
+ break;
196
+ }
197
+
198
+ if (
199
+ (/[A-Za-z]/).test(letters[j])
200
+ && (/-?\d+(\.\d*)?(e-?\d+)?$/).test(next)
201
+ ) {
202
+ setArg(letters[j], next, arg);
203
+ broken = true;
204
+ break;
205
+ }
206
+
207
+ if (letters[j + 1] && letters[j + 1].match(/\W/)) {
208
+ setArg(letters[j], arg.slice(j + 2), arg);
209
+ broken = true;
210
+ break;
211
+ } else {
212
+ setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg);
213
+ }
214
+ }
215
+
216
+ key = arg.slice(-1)[0];
217
+ if (!broken && key !== '-') {
218
+ if (
219
+ args[i + 1]
220
+ && !(/^(-|--)[^-]/).test(args[i + 1])
221
+ && !flags.bools[key]
222
+ && (aliases[key] ? !aliasIsBoolean(key) : true)
223
+ ) {
224
+ setArg(key, args[i + 1], arg);
225
+ i += 1;
226
+ } else if (args[i + 1] && (/^(true|false)$/).test(args[i + 1])) {
227
+ setArg(key, args[i + 1] === 'true', arg);
228
+ i += 1;
229
+ } else {
230
+ setArg(key, flags.strings[key] ? '' : true, arg);
231
+ }
232
+ }
233
+ } else {
234
+ if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
235
+ argv._.push(flags.strings._ || !isNumber(arg) ? arg : Number(arg));
236
+ }
237
+ if (opts.stopEarly) {
238
+ argv._.push.apply(argv._, args.slice(i + 1));
239
+ break;
240
+ }
241
+ }
242
+ }
243
+
244
+ Object.keys(defaults).forEach(function (k) {
245
+ if (!hasKey(argv, k.split('.'))) {
246
+ setKey(argv, k.split('.'), defaults[k]);
247
+
248
+ (aliases[k] || []).forEach(function (x) {
249
+ setKey(argv, x.split('.'), defaults[k]);
250
+ });
251
+ }
252
+ });
253
+
254
+ if (opts['--']) {
255
+ argv['--'] = notFlags.slice();
256
+ } else {
257
+ notFlags.forEach(function (k) {
258
+ argv._.push(k);
259
+ });
260
+ }
261
+
262
+ return argv;
263
+ };