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.
@@ -24,6 +24,7 @@ class WinAddon {
24
24
  // throw new Error(`[addon] [window] Name: ${name} already exists!`);
25
25
  // }
26
26
 
27
+ // [todo] 使用 extend, 避免多维对象被覆盖
27
28
  const options = Object.assign({
28
29
  x: 10,
29
30
  y: 10,
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
- const developmentModeConfig = this.config.developmentMode;
107
- const selectMode = developmentModeConfig.default;
108
- const modeInfo = developmentModeConfig.mode[selectMode];
109
- let staticDir = null;
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
- // html模式
112
- if (selectMode == 'html') {
113
- if (Ps.isDev()) {
114
- staticDir = path.join(this.config.homeDir, 'frontend', 'dist');
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
- this.loadLocalWeb('html', staticDir, modeInfo);
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, hostInfo) {
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
- koaApp.listen(mainServer.port, () => {
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
  }
@@ -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', () => {
@@ -1,4 +1,5 @@
1
- const { app, BrowserWindow, Menu } = require('electron');
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ee-core",
3
- "version": "2.4.0",
3
+ "version": "2.5.0-beta.2",
4
4
  "description": "ee core",
5
5
  "main": "index.js",
6
6
  "scripts": {
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
  */
@@ -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(httpServer.port, (err) => {
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(httpServer.port, (e) => {
79
+ koaApp.listen(listenOpt, (e) => {
75
80
  msg = e ? e : msg;
76
81
  Log.coreLogger.info(msg);
77
82
  });
@@ -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
- // 数据库key列表
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
- const storageDir = Ps.getStorageDir();
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 (name) {
32
- assert(name, 'table name is required');
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
- * 获取db文件名
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
- getFileName (name) {
47
- return name + ".json";
71
+ _formatFileName(name) {
72
+ let fileName = path.basename(name);
73
+ return fileName;
48
74
  }
49
75
 
50
76
  /**
51
77
  * 获取文件绝对路径
52
78
  */
53
- getFilePath (name) {
54
- const storageDir = Ps.getStorageDir();
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
  */
@@ -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 getAvailablePort = options => new Promise((resolve, reject) => {
24
- const server = net.createServer();
25
- server.unref();
26
- server.on('error', reject);
27
- server.listen(options, () => {
28
- const {port} = server.address();
29
- server.close(() => {
30
- resolve(port);
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
+ };