ee-core 2.4.0 → 2.5.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/addon/window/index.js +1 -0
- package/ee/eeApp.js +32 -21
- package/electron/app/index.js +0 -7
- package/electron/window/index.js +8 -3
- package/package.json +1 -1
- package/ps/index.js +8 -0
- package/socket/httpServer.js +7 -2
- package/storage/jsondbStorage.js +68 -18
- package/utils/get-port/index.js +50 -11
- package/utils/helper.js +31 -0
package/addon/window/index.js
CHANGED
package/ee/eeApp.js
CHANGED
|
@@ -14,6 +14,7 @@ const Conf = require('../config');
|
|
|
14
14
|
const Ps = require('../ps');
|
|
15
15
|
const Socket = require('../socket');
|
|
16
16
|
const GetPort = require('../utils/get-port');
|
|
17
|
+
const UtilsHelper = require('../utils/helper');
|
|
17
18
|
|
|
18
19
|
class EeApp extends BaseApp {
|
|
19
20
|
constructor(options = {}) {
|
|
@@ -103,27 +104,35 @@ class EeApp extends BaseApp {
|
|
|
103
104
|
return;
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
// 开发环境
|
|
108
|
+
if (Ps.isDev()) {
|
|
109
|
+
let modeInfo;
|
|
110
|
+
let url;
|
|
111
|
+
let load = 'url';
|
|
112
|
+
const configFile = './electron/config/bin.js';
|
|
113
|
+
|
|
114
|
+
const isBin = UtilsHelper.checkConfig(configFile);
|
|
115
|
+
if (isBin) {
|
|
116
|
+
const binConfig = UtilsHelper.loadConfig(configFile);
|
|
117
|
+
const { frontend } = binConfig.dev;
|
|
118
|
+
modeInfo = frontend;
|
|
119
|
+
} else {
|
|
120
|
+
// 兼容旧的 developmentMode
|
|
121
|
+
const developmentModeConfig = this.config.developmentMode;
|
|
122
|
+
const selectMode = developmentModeConfig.default;
|
|
123
|
+
modeInfo = developmentModeConfig.mode[selectMode];
|
|
124
|
+
}
|
|
110
125
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
126
|
+
url = modeInfo.protocol + modeInfo.hostname + ':' + modeInfo.port;
|
|
127
|
+
if (Conf.isFileProtocol(modeInfo)) {
|
|
128
|
+
url = path.join(this.config.homeDir, modeInfo.directory, modeInfo.indexPath);
|
|
129
|
+
load = 'file';
|
|
115
130
|
}
|
|
116
|
-
|
|
131
|
+
|
|
132
|
+
this.loadMainUrl('spa', url, load);
|
|
117
133
|
return;
|
|
118
134
|
}
|
|
119
135
|
|
|
120
|
-
// 单页应用
|
|
121
|
-
// 开发环境
|
|
122
|
-
if (Ps.isDev()) {
|
|
123
|
-
url = modeInfo.protocol + modeInfo.hostname + ':' + modeInfo.port;
|
|
124
|
-
this.loadMainUrl('spa', url);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
136
|
// 生产环境
|
|
128
137
|
const mainServer = this.config.mainServer;
|
|
129
138
|
if (Conf.isFileProtocol(mainServer)) {
|
|
@@ -137,7 +146,7 @@ class EeApp extends BaseApp {
|
|
|
137
146
|
/**
|
|
138
147
|
* 加载本地前端资源
|
|
139
148
|
*/
|
|
140
|
-
loadLocalWeb(mode, staticDir
|
|
149
|
+
loadLocalWeb(mode, staticDir) {
|
|
141
150
|
if (!staticDir) {
|
|
142
151
|
staticDir = path.join(this.config.homeDir, 'public', 'dist')
|
|
143
152
|
}
|
|
@@ -147,9 +156,6 @@ class EeApp extends BaseApp {
|
|
|
147
156
|
|
|
148
157
|
const mainServer = this.config.mainServer;
|
|
149
158
|
let url = mainServer.protocol + mainServer.host + ':' + mainServer.port;
|
|
150
|
-
if (mode == 'html') {
|
|
151
|
-
url += '/' + hostInfo.indexPage;
|
|
152
|
-
}
|
|
153
159
|
|
|
154
160
|
const isHttps = mainServer.protocol == 'https://' ? true : false;
|
|
155
161
|
if (isHttps) {
|
|
@@ -170,7 +176,12 @@ class EeApp extends BaseApp {
|
|
|
170
176
|
this.loadMainUrl(mode, url);
|
|
171
177
|
});
|
|
172
178
|
} else {
|
|
173
|
-
|
|
179
|
+
// 使用 host port 避免绑定到0.0.0.0
|
|
180
|
+
const koaOpt = {
|
|
181
|
+
host: mainServer.host,
|
|
182
|
+
port: mainServer.port
|
|
183
|
+
}
|
|
184
|
+
koaApp.listen(koaOpt, () => {
|
|
174
185
|
this.loadMainUrl(mode, url);
|
|
175
186
|
});
|
|
176
187
|
}
|
package/electron/app/index.js
CHANGED
|
@@ -21,16 +21,9 @@ const CoreElectronApp = {
|
|
|
21
21
|
app.quit();
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
app.on('second-instance', (event) => {
|
|
26
|
-
Window.restoreMainWindow();
|
|
27
|
-
})
|
|
28
24
|
|
|
29
25
|
app.whenReady().then(() => {
|
|
30
26
|
CoreApp.createWindow();
|
|
31
|
-
app.on('activate', () => {
|
|
32
|
-
Window.restoreMainWindow();
|
|
33
|
-
})
|
|
34
27
|
})
|
|
35
28
|
|
|
36
29
|
app.on('window-all-closed', () => {
|
package/electron/window/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
const
|
|
1
|
+
const is = require('is-type-of');
|
|
2
|
+
const { BrowserWindow, Menu } = require('electron');
|
|
2
3
|
const Conf = require('../../config');
|
|
3
4
|
const Ps = require('../../ps');
|
|
4
5
|
const EEMainWindow = Symbol('Ee#electron#mainWindow');
|
|
@@ -43,12 +44,16 @@ const Window = {
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
// DevTools
|
|
46
|
-
if (config.openDevTools) {
|
|
47
|
+
if (is.object(config.openDevTools)) {
|
|
48
|
+
win.webContents.openDevTools(config.openDevTools);
|
|
49
|
+
} else if (config.openDevTools === true) {
|
|
47
50
|
win.webContents.openDevTools({
|
|
48
51
|
mode: 'undocked'
|
|
49
52
|
});
|
|
53
|
+
} else {
|
|
54
|
+
//
|
|
50
55
|
}
|
|
51
|
-
|
|
56
|
+
|
|
52
57
|
return win;
|
|
53
58
|
},
|
|
54
59
|
|
package/package.json
CHANGED
package/ps/index.js
CHANGED
|
@@ -181,6 +181,14 @@ exports.getElectronDir = function() {
|
|
|
181
181
|
return process.env.EE_BASE_DIR;
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
/**
|
|
185
|
+
* 获取public目录
|
|
186
|
+
*/
|
|
187
|
+
exports.getPublicDir = function() {
|
|
188
|
+
const dir = path.join(process.env.EE_HOME, "public");
|
|
189
|
+
return dir;
|
|
190
|
+
}
|
|
191
|
+
|
|
184
192
|
/**
|
|
185
193
|
* 获取 额外资源目录
|
|
186
194
|
*/
|
package/socket/httpServer.js
CHANGED
|
@@ -65,13 +65,18 @@ class HttpServer {
|
|
|
65
65
|
.use(this.dispatch);
|
|
66
66
|
|
|
67
67
|
let msg = '[ee-core] [socket/http] server is: ' + url;
|
|
68
|
+
|
|
69
|
+
const listenOpt = {
|
|
70
|
+
host: httpServer.host,
|
|
71
|
+
port: httpServer.port
|
|
72
|
+
}
|
|
68
73
|
if (isHttps) {
|
|
69
|
-
https.createServer(sslOptions, koaApp.callback()).listen(
|
|
74
|
+
https.createServer(sslOptions, koaApp.callback()).listen(listenOpt, (err) => {
|
|
70
75
|
msg = err ? err : msg;
|
|
71
76
|
Log.coreLogger.info(msg);
|
|
72
77
|
});
|
|
73
78
|
} else {
|
|
74
|
-
koaApp.listen(
|
|
79
|
+
koaApp.listen(listenOpt, (e) => {
|
|
75
80
|
msg = e ? e : msg;
|
|
76
81
|
Log.coreLogger.info(msg);
|
|
77
82
|
});
|
package/storage/jsondbStorage.js
CHANGED
|
@@ -12,26 +12,22 @@ class JsondbStorage {
|
|
|
12
12
|
constructor (name, opt = {}) {
|
|
13
13
|
assert(name, `db name ${name} Cannot be empty`);
|
|
14
14
|
|
|
15
|
+
// 补全文件名
|
|
16
|
+
name = this._addExtname(name);
|
|
15
17
|
this.name = name;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
this.mode = this.getMode(name);
|
|
19
|
+
this.storageDir = this._createStorageDir();
|
|
20
|
+
this.fileName = this._formatFileName(name);
|
|
18
21
|
this.storageKey = Constants.storageKey;
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
if (!fs.existsSync(storageDir)) {
|
|
22
|
-
Helper.mkdir(storageDir);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
this.db = this.table(name);
|
|
23
|
+
this.db = this.table();
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
/**
|
|
29
27
|
* 创建 table
|
|
30
28
|
*/
|
|
31
|
-
table
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const dbFile = this.getFilePath(name);
|
|
29
|
+
table() {
|
|
30
|
+
const dbFile = this.getFilePath();
|
|
35
31
|
const adapter = new FileSync(dbFile);
|
|
36
32
|
const db = Jsondb(adapter);
|
|
37
33
|
|
|
@@ -41,21 +37,75 @@ class JsondbStorage {
|
|
|
41
37
|
}
|
|
42
38
|
|
|
43
39
|
/**
|
|
44
|
-
*
|
|
40
|
+
* 补全扩展名
|
|
41
|
+
*/
|
|
42
|
+
_addExtname(name) {
|
|
43
|
+
if (path.extname(name) != '.json') {
|
|
44
|
+
name += ".json";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return name;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 创建storage目录
|
|
52
|
+
*/
|
|
53
|
+
_createStorageDir() {
|
|
54
|
+
let storageDir = Ps.getStorageDir();
|
|
55
|
+
|
|
56
|
+
if (this.mode == 'absolute') {
|
|
57
|
+
storageDir = path.dirname(this.name);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!fs.existsSync(storageDir)) {
|
|
61
|
+
Helper.mkdir(storageDir);
|
|
62
|
+
Helper.chmodPath(storageDir, '777');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return storageDir;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 获取文件名
|
|
45
70
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
71
|
+
_formatFileName(name) {
|
|
72
|
+
let fileName = path.basename(name);
|
|
73
|
+
return fileName;
|
|
48
74
|
}
|
|
49
75
|
|
|
50
76
|
/**
|
|
51
77
|
* 获取文件绝对路径
|
|
52
78
|
*/
|
|
53
|
-
getFilePath
|
|
54
|
-
const
|
|
55
|
-
const dbFile = path.join(storageDir, this.getFileName(name));
|
|
79
|
+
getFilePath() {
|
|
80
|
+
const dbFile = path.join(this.storageDir, this.fileName);
|
|
56
81
|
return dbFile;
|
|
57
82
|
}
|
|
58
83
|
|
|
84
|
+
/**
|
|
85
|
+
* 获取file path 模式
|
|
86
|
+
*/
|
|
87
|
+
getMode(name) {
|
|
88
|
+
let mode = 'relative';
|
|
89
|
+
|
|
90
|
+
// 路径模式
|
|
91
|
+
name = name.replace(/[/\\]/g, '/');
|
|
92
|
+
if (name.indexOf('/') !== -1) {
|
|
93
|
+
const isAbsolute = path.isAbsolute(name);
|
|
94
|
+
if (isAbsolute) {
|
|
95
|
+
mode = 'absolute';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return mode;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 获取storage目录
|
|
104
|
+
*/
|
|
105
|
+
getStorageDir() {
|
|
106
|
+
return this.storageDir;
|
|
107
|
+
}
|
|
108
|
+
|
|
59
109
|
/**
|
|
60
110
|
* 为指定的 name 设置一个对应的值
|
|
61
111
|
*/
|
package/utils/get-port/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const net = require('net');
|
|
3
|
+
const os = require('os');
|
|
3
4
|
|
|
4
5
|
class Locked extends Error {
|
|
5
6
|
constructor(port) {
|
|
@@ -20,17 +21,53 @@ const releaseOldLockedPortsIntervalMs = 1000 * 15;
|
|
|
20
21
|
// Lazily create interval on first use
|
|
21
22
|
let interval;
|
|
22
23
|
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
const getLocalHosts = () => {
|
|
25
|
+
const interfaces = os.networkInterfaces();
|
|
26
|
+
|
|
27
|
+
// Add undefined value for createServer function to use default host,
|
|
28
|
+
// and default IPv4 host in case createServer defaults to IPv6.
|
|
29
|
+
const results = new Set([undefined, '0.0.0.0']);
|
|
30
|
+
|
|
31
|
+
for (const _interface of Object.values(interfaces)) {
|
|
32
|
+
for (const config of _interface) {
|
|
33
|
+
results.add(config.address);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return results;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const checkAvailablePort = options =>
|
|
41
|
+
new Promise((resolve, reject) => {
|
|
42
|
+
const server = net.createServer();
|
|
43
|
+
server.unref();
|
|
44
|
+
server.on('error', reject);
|
|
45
|
+
|
|
46
|
+
server.listen(options, () => {
|
|
47
|
+
const {port} = server.address();
|
|
48
|
+
server.close(() => {
|
|
49
|
+
resolve(port);
|
|
50
|
+
});
|
|
31
51
|
});
|
|
32
52
|
});
|
|
33
|
-
|
|
53
|
+
|
|
54
|
+
const getAvailablePort = async (options, hosts) => {
|
|
55
|
+
if (options.host || options.port === 0) {
|
|
56
|
+
return checkAvailablePort(options);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
for (const host of hosts) {
|
|
60
|
+
try {
|
|
61
|
+
await checkAvailablePort({port: options.port, host}); // eslint-disable-line no-await-in-loop
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (!['EADDRNOTAVAIL', 'EINVAL'].includes(error.code)) {
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return options.port;
|
|
70
|
+
};
|
|
34
71
|
|
|
35
72
|
const portCheckSequence = function * (ports) {
|
|
36
73
|
if (ports) {
|
|
@@ -59,15 +96,17 @@ module.exports = async options => {
|
|
|
59
96
|
}
|
|
60
97
|
}
|
|
61
98
|
|
|
99
|
+
const hosts = getLocalHosts();
|
|
100
|
+
|
|
62
101
|
for (const port of portCheckSequence(ports)) {
|
|
63
102
|
try {
|
|
64
|
-
let availablePort = await getAvailablePort({...options, port}); // eslint-disable-line no-await-in-loop
|
|
103
|
+
let availablePort = await getAvailablePort({...options, port}, hosts); // eslint-disable-line no-await-in-loop
|
|
65
104
|
while (lockedPorts.old.has(availablePort) || lockedPorts.young.has(availablePort)) {
|
|
66
105
|
if (port !== 0) {
|
|
67
106
|
throw new Locked(port);
|
|
68
107
|
}
|
|
69
108
|
|
|
70
|
-
availablePort = await getAvailablePort({...options, port}); // eslint-disable-line no-await-in-loop
|
|
109
|
+
availablePort = await getAvailablePort({...options, port}, hosts); // eslint-disable-line no-await-in-loop
|
|
71
110
|
}
|
|
72
111
|
|
|
73
112
|
lockedPorts.young.add(availablePort);
|
package/utils/helper.js
CHANGED
|
@@ -3,6 +3,10 @@ const mkdirp = require('mkdirp');
|
|
|
3
3
|
const convert = require('koa-convert');
|
|
4
4
|
const is = require('is-type-of');
|
|
5
5
|
const co = require('./co');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
|
|
9
|
+
const _basePath = process.cwd();
|
|
6
10
|
|
|
7
11
|
/**
|
|
8
12
|
* fnDebounce
|
|
@@ -138,3 +142,30 @@ exports.validValue = function(value) {
|
|
|
138
142
|
value !== ''
|
|
139
143
|
);
|
|
140
144
|
}
|
|
145
|
+
|
|
146
|
+
exports.checkConfig = function(prop) {
|
|
147
|
+
const filepath = path.join(_basePath, prop);
|
|
148
|
+
if (fs.existsSync(filepath)) {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
exports.loadConfig = function(prop) {
|
|
156
|
+
const configFile = prop;
|
|
157
|
+
const filepath = path.join(_basePath, configFile);
|
|
158
|
+
if (!fs.existsSync(filepath)) {
|
|
159
|
+
const errorTips = 'config file ' + chalk.blue(`${filepath}`) + ' does not exist !';
|
|
160
|
+
throw new Error(errorTips)
|
|
161
|
+
}
|
|
162
|
+
const obj = require(filepath);
|
|
163
|
+
if (!obj) return obj;
|
|
164
|
+
|
|
165
|
+
let ret = obj;
|
|
166
|
+
if (is.function(obj) && !is.class(obj)) {
|
|
167
|
+
ret = obj();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return ret || {};
|
|
171
|
+
};
|