ee-core 2.7.1 → 2.8.0-beta.2
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/config/config.default.js +1 -1
- package/cross/index.js +134 -71
- package/cross/spawnProcess.js +125 -0
- package/electron/app/index.js +1 -1
- package/main/index.js +12 -2
- package/package.json +1 -1
- package/ps/index.js +1 -1
package/config/config.default.js
CHANGED
|
@@ -262,7 +262,7 @@ module.exports = appInfo => {
|
|
|
262
262
|
|
|
263
263
|
/* 主进程加载的地址 */
|
|
264
264
|
config.mainServer = {
|
|
265
|
-
protocol: '
|
|
265
|
+
protocol: 'file://', // http:// | https:// | file://
|
|
266
266
|
indexPath: '/public/dist/index.html',
|
|
267
267
|
host: 'localhost',
|
|
268
268
|
port: 7072, // 默认端口(如果端口被使用,则随机获取一个)
|
package/cross/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
-
const
|
|
2
|
+
const EventEmitter = require('events');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const is = require('is-type-of');
|
|
5
5
|
const Conf = require('../config/cache');
|
|
@@ -9,7 +9,8 @@ const UtilsPargv = require('../utils/pargv');
|
|
|
9
9
|
const Ps = require('../ps');
|
|
10
10
|
const Log = require('../log');
|
|
11
11
|
const GetPort = require('../utils/get-port');
|
|
12
|
-
const
|
|
12
|
+
const SpawnProcess = require('./spawnProcess');
|
|
13
|
+
const Channel = require('../const/channel');
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Cross-language service
|
|
@@ -17,18 +18,24 @@ const { app: electronApp } = require('electron');
|
|
|
17
18
|
*/
|
|
18
19
|
const CrossLanguageService = {
|
|
19
20
|
|
|
21
|
+
emitter: undefined,
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* pid唯一
|
|
25
|
+
* {pid:{name,entity}, pid:{name,entity}, ...}
|
|
26
|
+
*/
|
|
20
27
|
children: {},
|
|
21
28
|
|
|
29
|
+
/**
|
|
30
|
+
* name唯一
|
|
31
|
+
* {name:pid, name:pid, ...}
|
|
32
|
+
*/
|
|
33
|
+
childrenMap: {},
|
|
34
|
+
|
|
22
35
|
/**
|
|
23
36
|
* create
|
|
24
37
|
*/
|
|
25
38
|
async create() {
|
|
26
|
-
if (!Ps.isProd()) {
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// init dir
|
|
31
|
-
this._initPath();
|
|
32
39
|
|
|
33
40
|
// boot services
|
|
34
41
|
const servicesCfg = Conf.getValue('cross');
|
|
@@ -37,79 +44,113 @@ const CrossLanguageService = {
|
|
|
37
44
|
for (let key of Object.keys(servicesCfg)) {
|
|
38
45
|
let cfg = servicesCfg[key];
|
|
39
46
|
if (cfg.enable == true) {
|
|
40
|
-
this.run(
|
|
47
|
+
this.run(key)
|
|
41
48
|
}
|
|
42
49
|
}
|
|
43
50
|
},
|
|
44
51
|
|
|
52
|
+
/**
|
|
53
|
+
* _initEventEmitter
|
|
54
|
+
*/
|
|
55
|
+
async _initEventEmitter() {
|
|
56
|
+
if (this.emitter) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
this.emitter = new EventEmitter();
|
|
60
|
+
this.emitter.on(Channel.events.childProcessExit, (data) => {
|
|
61
|
+
console.log("------childProcessExit:", data)
|
|
62
|
+
const child = this.children[data.pid];
|
|
63
|
+
delete this.childrenMap[child.name];
|
|
64
|
+
delete this.children[data.pid];
|
|
65
|
+
});
|
|
66
|
+
this.emitter.on(Channel.events.childProcessError, (data) => {
|
|
67
|
+
console.log("------childProcessError:", data)
|
|
68
|
+
const child = this.children[data.pid];
|
|
69
|
+
delete this.childrenMap[child.name];
|
|
70
|
+
delete this.children[data.pid];
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
|
|
45
74
|
/**
|
|
46
75
|
* run
|
|
47
76
|
*/
|
|
48
|
-
async run(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
77
|
+
async run(service) {
|
|
78
|
+
// init dir
|
|
79
|
+
this._initPath();
|
|
80
|
+
|
|
81
|
+
const allConfig = Conf.all();
|
|
82
|
+
if (!allConfig.cross.hasOwnProperty(service)) {
|
|
83
|
+
throw new Error(`[ee-core] [cross] The service [${service}] config does not exit`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const targetConf = Object.assign({}, allConfig.cross[service]);
|
|
87
|
+
|
|
88
|
+
// eventEmitter
|
|
89
|
+
this._initEventEmitter();
|
|
90
|
+
|
|
91
|
+
let cmdPath = this._getCmdPath(targetConf.name);
|
|
92
|
+
let cmdArgs = is.string(targetConf.args) ? [targetConf.args] : targetConf.args;
|
|
93
|
+
if (targetConf.hasOwnProperty('cmd')) {
|
|
94
|
+
cmdPath = targetConf.cmd;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let confPort = this._getValueFromArgs(cmdArgs, 'port');
|
|
98
|
+
if (UtilsHelper.validValue(confPort)) {
|
|
99
|
+
// 动态生成port
|
|
100
|
+
confPort = await GetPort({ port: confPort });
|
|
101
|
+
// 替换port
|
|
102
|
+
cmdArgs = this._replaceValue(cmdArgs, "--port=", confPort)
|
|
103
|
+
targetConf.args = cmdArgs;
|
|
58
104
|
}
|
|
59
|
-
confPort = await GetPort({ port: confPort });
|
|
60
|
-
// 替换port
|
|
61
|
-
cmdArgs = this.replaceValue(cmdArgs, "--port=", confPort)
|
|
62
105
|
|
|
63
106
|
Log.coreLogger.info(`[ee-core] [cross/run] cmd: ${cmdPath}, args: ${cmdArgs}`);
|
|
64
107
|
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
108
|
+
// 创建进程
|
|
109
|
+
const subProcess = new SpawnProcess(this, { cmdPath, cmdArgs, targetConf });
|
|
110
|
+
let uniqueName = targetConf.name;
|
|
111
|
+
if (this.childrenMap.hasOwnProperty(uniqueName)) {
|
|
112
|
+
uniqueName = uniqueName + "-" + String(subProcess.pid);
|
|
69
113
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
114
|
+
this.childrenMap[uniqueName] = subProcess.pid;
|
|
115
|
+
subProcess.name = uniqueName;
|
|
116
|
+
this.children[subProcess.pid] = {
|
|
117
|
+
name: uniqueName,
|
|
118
|
+
entity: subProcess
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return subProcess;
|
|
122
|
+
},
|
|
77
123
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
electronApp.quit();
|
|
83
|
-
}, 1000)
|
|
84
|
-
}
|
|
124
|
+
killAll() {
|
|
125
|
+
Object.keys(this.children).forEach(pid => {
|
|
126
|
+
console.log("-----killAll: ", pid);
|
|
127
|
+
this.kill(pid)
|
|
85
128
|
});
|
|
86
|
-
this.children[cmdName] = coreProcess;
|
|
87
129
|
},
|
|
88
130
|
|
|
89
|
-
kill() {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
setTimeout(() => {
|
|
95
|
-
if (proc.killed) return;
|
|
96
|
-
proc.kill('SIGKILL');
|
|
97
|
-
}, 500)
|
|
98
|
-
}
|
|
99
|
-
});
|
|
131
|
+
kill(pid) {
|
|
132
|
+
const entity = this.getProc(pid);
|
|
133
|
+
if (entity) {
|
|
134
|
+
entity.kill();
|
|
135
|
+
}
|
|
100
136
|
},
|
|
101
137
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
value = value[key];
|
|
138
|
+
killByName(name) {
|
|
139
|
+
const entity = this.getProcByName(name);
|
|
140
|
+
if (entity) {
|
|
141
|
+
entity.kill();
|
|
107
142
|
}
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
_getValueFromArgs(argv, key) {
|
|
146
|
+
// parse args
|
|
147
|
+
const argsObj = UtilsPargv(argv);
|
|
148
|
+
const value = argsObj[key];
|
|
108
149
|
|
|
109
150
|
return value;
|
|
110
151
|
},
|
|
111
152
|
|
|
112
|
-
|
|
153
|
+
_replaceValue(arr, key, value) {
|
|
113
154
|
arr = arr.map(item => {
|
|
114
155
|
if (item.startsWith(key)) {
|
|
115
156
|
let newItem = key + value;
|
|
@@ -121,11 +162,9 @@ const CrossLanguageService = {
|
|
|
121
162
|
return arr;
|
|
122
163
|
},
|
|
123
164
|
|
|
124
|
-
getUrl(
|
|
125
|
-
const
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
const args = this.getArgs(servicesCfg.args);
|
|
165
|
+
getUrl(name) {
|
|
166
|
+
const entity = this.getProcByName(name);
|
|
167
|
+
const args = entity.getArgsObj();
|
|
129
168
|
let protocol = 'http://';
|
|
130
169
|
if (args.hasOwnProperty('ssl') && (args.ssl == 'true' || args.ssl == '1')) {
|
|
131
170
|
protocol = 'https://';
|
|
@@ -136,6 +175,35 @@ const CrossLanguageService = {
|
|
|
136
175
|
return url;
|
|
137
176
|
},
|
|
138
177
|
|
|
178
|
+
// 获取 proc
|
|
179
|
+
getProcByName(name) {
|
|
180
|
+
const pid = this.childrenMap[name];
|
|
181
|
+
if (!pid) {
|
|
182
|
+
throw new Error(`[ee-core] [cross] The process named [${name}] does not exit`);
|
|
183
|
+
}
|
|
184
|
+
const entity = this.getProc(pid);
|
|
185
|
+
|
|
186
|
+
return entity;
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
// 获取 proc
|
|
190
|
+
getProc(pid) {
|
|
191
|
+
const child = this.children[pid];
|
|
192
|
+
if (!pid) {
|
|
193
|
+
throw new Error(`[ee-core] [cross] The process pid [${pid}] does not exit`);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return child.entity;
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 获取pids
|
|
201
|
+
*/
|
|
202
|
+
getPids() {
|
|
203
|
+
let pids = Object.keys(this.children);
|
|
204
|
+
return pids;
|
|
205
|
+
},
|
|
206
|
+
|
|
139
207
|
_getCmdPath(name) {
|
|
140
208
|
const coreName = UtilsIs.windows() ? name + ".exe" : name;
|
|
141
209
|
const p = path.join(Ps.getExtraResourcesDir(), coreName);
|
|
@@ -146,14 +214,9 @@ const CrossLanguageService = {
|
|
|
146
214
|
* init path
|
|
147
215
|
*/
|
|
148
216
|
_initPath() {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
UtilsHelper.mkdir(pathname, {mode: 0o755});
|
|
153
|
-
}
|
|
154
|
-
} catch (e) {
|
|
155
|
-
Log.coreLogger.error(e);
|
|
156
|
-
throw new Error(`[ee-core] [cross] mkdir ${pathname} failed !`);
|
|
217
|
+
const pathname = Ps.getUserHomeConfigDir();
|
|
218
|
+
if (!fs.existsSync(pathname)) {
|
|
219
|
+
UtilsHelper.mkdir(pathname, {mode: 0o755});
|
|
157
220
|
}
|
|
158
221
|
}
|
|
159
222
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
const EventEmitter = require('events');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const crossSpawn = require('cross-spawn');
|
|
4
|
+
const Log = require('../log');
|
|
5
|
+
const Ps = require('../ps');
|
|
6
|
+
const Channel = require('../const/channel');
|
|
7
|
+
const Helper = require('../utils/helper');
|
|
8
|
+
const UtilsPargv = require('../utils/pargv');
|
|
9
|
+
const EE = require('../ee');
|
|
10
|
+
|
|
11
|
+
class SpawnProcess {
|
|
12
|
+
constructor(host, opt = {}) {
|
|
13
|
+
this.emitter = new EventEmitter();
|
|
14
|
+
this.host = host;
|
|
15
|
+
this.child = undefined;
|
|
16
|
+
this.pid = 0;
|
|
17
|
+
this.name = "";
|
|
18
|
+
this.config = {};
|
|
19
|
+
this._init(opt);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 初始化子进程
|
|
25
|
+
*/
|
|
26
|
+
_init(options = {}) {
|
|
27
|
+
const { cmdPath, cmdArgs, targetConf } = options;
|
|
28
|
+
this.config = targetConf;
|
|
29
|
+
this.name = this.config.name;
|
|
30
|
+
|
|
31
|
+
// Launch executable program
|
|
32
|
+
let standardOutput = ['ignore', 'ignore', 'ignore', 'ipc'];
|
|
33
|
+
if (!Ps.isPackaged()) {
|
|
34
|
+
standardOutput = ['inherit', 'inherit', 'inherit', 'ipc'];
|
|
35
|
+
}
|
|
36
|
+
let execDir = Ps.getExtraResourcesDir();
|
|
37
|
+
if (this.config.hasOwnProperty('directory')) {
|
|
38
|
+
execDir = path.join(process.cwd(), this.config.directory);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const coreProcess = crossSpawn(cmdPath, cmdArgs, {
|
|
42
|
+
stdio: standardOutput,
|
|
43
|
+
detached: false,
|
|
44
|
+
cwd: execDir,
|
|
45
|
+
maxBuffer: 1024 * 1024 * 1024
|
|
46
|
+
});
|
|
47
|
+
this.child = coreProcess;
|
|
48
|
+
this.pid = coreProcess.pid;
|
|
49
|
+
|
|
50
|
+
coreProcess.on('exit', (code, signal) => {
|
|
51
|
+
let data = {
|
|
52
|
+
pid: this.pid
|
|
53
|
+
}
|
|
54
|
+
this.host.emitter.emit(Channel.events.childProcessExit, data);
|
|
55
|
+
Log.coreLogger.info(`[ee-core] [corss/process] received a exit from child-process, code:${code}, signal:${signal}, pid:${this.pid}`);
|
|
56
|
+
this._exitElectron();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
coreProcess.on('error', (err) => {
|
|
60
|
+
let data = {
|
|
61
|
+
pid: this.pid
|
|
62
|
+
}
|
|
63
|
+
this.host.emitter.emit(Channel.events.childProcessError, data);
|
|
64
|
+
Log.coreLogger.error(`[ee-core] [corss/process] received a error from child-process, error: ${err}, pid:${this.pid}`);
|
|
65
|
+
this._exitElectron();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* kill
|
|
71
|
+
*/
|
|
72
|
+
kill(timeout = 1000) {
|
|
73
|
+
console.log("----- spawnProcess kill ---- ");
|
|
74
|
+
this.child.kill('SIGINT');
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
if (this.child.killed) return;
|
|
77
|
+
this.child.kill('SIGKILL');
|
|
78
|
+
}, timeout)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
send(message) {
|
|
82
|
+
return this.sendByType(message, 'message');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
close() {
|
|
86
|
+
return this.sendByType('close', 'close');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
_generateId() {
|
|
90
|
+
const rid = Helper.getRandomString();
|
|
91
|
+
return `node:${this.pid}:${rid}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async sendByType(message, type) {
|
|
95
|
+
const msg = typeof message === 'string' ? message : JSON.stringify(message);
|
|
96
|
+
const id = this._generateId();
|
|
97
|
+
|
|
98
|
+
this.child.send({
|
|
99
|
+
id,
|
|
100
|
+
type,
|
|
101
|
+
data: msg,
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
getArgsObj() {
|
|
107
|
+
const obj = UtilsPargv(this.config.args);
|
|
108
|
+
return obj;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* exit electron
|
|
113
|
+
*/
|
|
114
|
+
_exitElectron(timeout = 1000) {
|
|
115
|
+
const { CoreApp } = EE;
|
|
116
|
+
if (this.config.appExit) {
|
|
117
|
+
setTimeout(() => {
|
|
118
|
+
// 进程退出前的一些清理工作
|
|
119
|
+
CoreApp.appQuit();
|
|
120
|
+
}, timeout)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = SpawnProcess;
|
package/electron/app/index.js
CHANGED
package/main/index.js
CHANGED
|
@@ -6,6 +6,7 @@ const Ps = require('../ps');
|
|
|
6
6
|
const EE = require('../ee');
|
|
7
7
|
const UtilsCore = require('../core/lib/utils');
|
|
8
8
|
const Loader = require('../loader');
|
|
9
|
+
const UtilsPargv = require('../utils/pargv');
|
|
9
10
|
|
|
10
11
|
class ElectronEgg {
|
|
11
12
|
|
|
@@ -23,6 +24,15 @@ class ElectronEgg {
|
|
|
23
24
|
}
|
|
24
25
|
Ps.initMode(this.mode);
|
|
25
26
|
|
|
27
|
+
// env 可能为空
|
|
28
|
+
const argsObj = UtilsPargv(process.argv);
|
|
29
|
+
let isDev = false;
|
|
30
|
+
if ( argsObj['env'] == 'development' || argsObj['env'] === 'dev' || argsObj['env'] === 'local' ) {
|
|
31
|
+
isDev = true;
|
|
32
|
+
}
|
|
33
|
+
console.log("argsObj env:", argsObj)
|
|
34
|
+
console.log("isDev:", isDev)
|
|
35
|
+
|
|
26
36
|
// module mode
|
|
27
37
|
if (Ps.isModuleMode()) {
|
|
28
38
|
const { Application } = EE;
|
|
@@ -31,7 +41,7 @@ class ElectronEgg {
|
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
let baseDir = path.join(app.getAppPath(), 'electron');
|
|
34
|
-
if (Utils.isEncrypt(app.getAppPath())) {
|
|
44
|
+
if (!isDev && Utils.isEncrypt(app.getAppPath())) {
|
|
35
45
|
baseDir = Ps.getEncryptDir(app.getAppPath());
|
|
36
46
|
}
|
|
37
47
|
|
|
@@ -42,7 +52,7 @@ class ElectronEgg {
|
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
const EEApp = UtilsCore.loadFile(indexFile);
|
|
45
|
-
EE.app = new EEApp(
|
|
55
|
+
EE.app = new EEApp();
|
|
46
56
|
}
|
|
47
57
|
}
|
|
48
58
|
|
package/package.json
CHANGED