ee-core 2.6.0 → 2.7.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.
@@ -0,0 +1,39 @@
1
+ const EE = require('../ee');
2
+
3
+ const conf = {
4
+
5
+ /**
6
+ * 获取 内存中的config
7
+ */
8
+ _getConfig() {
9
+ const { CoreApp } = EE;
10
+ if (!CoreApp) {
11
+ throw new Error(`[ee-core] [config] Frame initialization is not complete !`);
12
+ }
13
+
14
+ return CoreApp.config;
15
+ },
16
+
17
+ /**
18
+ * all
19
+ */
20
+ all() {
21
+ return this._getConfig();
22
+ },
23
+
24
+ /**
25
+ * getValue
26
+ */
27
+ getValue(key) {
28
+ const v = this._objectGet(this._getConfig(), key);
29
+ return v;
30
+ },
31
+
32
+ _objectGet(object, path, defaultValue) {
33
+ const pathParts = Array.isArray(path) ? path : path.split('.');
34
+ const value = pathParts.reduce((obj, key) => obj && key in obj ? obj[key] : undefined, object);
35
+ return value === undefined ? defaultValue : value;
36
+ }
37
+ };
38
+
39
+ module.exports = conf;
@@ -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,137 @@
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/cache');
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(service) {
101
+ const cfg = Conf.getValue('cross');
102
+ const servicesCfg = cfg[service];
103
+
104
+ const args = this.getArgs(servicesCfg.args);
105
+ let protocol = 'http://';
106
+ if (args.hasOwnProperty('ssl') && (args.ssl == 'true' || args.ssl == '1')) {
107
+ protocol = 'https://';
108
+ }
109
+ const hostname = args.hostname ? args.hostname : '127.0.0.1';
110
+ const url = protocol + hostname + ":" + args.port;
111
+
112
+ return url;
113
+ },
114
+
115
+ _getCmdPath(name) {
116
+ const coreName = UtilsIs.windows() ? name + ".exe" : name;
117
+ const p = path.join(Ps.getExtraResourcesDir(), coreName);
118
+ return p;
119
+ },
120
+
121
+ /**
122
+ * init path
123
+ */
124
+ _initPath() {
125
+ try {
126
+ const pathname = Ps.getUserHomeConfigDir();
127
+ if (!fs.existsSync(pathname)) {
128
+ UtilsHelper.mkdir(pathname, {mode: 0o755});
129
+ }
130
+ } catch (e) {
131
+ Log.coreLogger.error(e);
132
+ throw new Error(`[ee-core] [cross] mkdir ${pathname} failed !`);
133
+ }
134
+ }
135
+ }
136
+
137
+ 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,18 +113,21 @@ 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;
111
121
  let url;
112
122
  let load = 'url';
113
123
  const configFile = './electron/config/bin.js';
124
+ let electronCfg = {};
114
125
 
115
126
  const isBin = UtilsHelper.checkConfig(configFile);
116
127
  if (isBin) {
117
128
  const binConfig = UtilsHelper.loadConfig(configFile);
118
- const { frontend } = binConfig.dev;
119
- modeInfo = frontend;
129
+ modeInfo = binConfig.dev.frontend;
130
+ electronCfg = binConfig.dev.electron;
120
131
  } else {
121
132
  // 兼容旧的 developmentMode
122
133
  const developmentModeConfig = this.config.developmentMode;
@@ -132,12 +143,17 @@ class EeApp extends BaseApp {
132
143
 
133
144
  // 检查 UI serve是否启动,先加载一个boot page
134
145
  if (load == 'url') {
135
- const bootPage = path.join(__dirname, '..', 'html', 'boot.html');
136
- this.mainWindow.loadFile(bootPage);
146
+ // loading page
147
+ let lp = path.join(__dirname, '..', 'html', 'boot.html');
148
+ if (electronCfg.hasOwnProperty('loadingPage') && electronCfg.loadingPage != '') {
149
+ lp = path.join(this.config.homeDir, electronCfg.loadingPage);
150
+ }
151
+ this._loadingPage(lp);
152
+
137
153
  let count = 0;
138
154
  let frontendReady = false;
139
155
  const hc = new HttpClient();
140
- while(!frontendReady && count < 30){
156
+ while(!frontendReady && count < 60){
141
157
  await UtilsHelper.sleep(1 * 1000);
142
158
  try {
143
159
  await hc.request(url, {
@@ -165,7 +181,13 @@ class EeApp extends BaseApp {
165
181
  }
166
182
 
167
183
  // 生产环境
168
- const mainServer = this.config.mainServer;
184
+ // cross service takeover web
185
+ if (mainServer.hasOwnProperty('takeover')) {
186
+ await this._crossTakeover(mainServer)
187
+ return
188
+ }
189
+
190
+ // 主进程
169
191
  if (Conf.isFileProtocol(mainServer)) {
170
192
  url = path.join(this.config.homeDir, mainServer.indexPath);
171
193
  this.loadMainUrl('spa', url, 'file');
@@ -174,6 +196,61 @@ class EeApp extends BaseApp {
174
196
  }
175
197
  }
176
198
 
199
+ /**
200
+ * cross service takeover web
201
+ */
202
+ async _crossTakeover(mainCfg = {}) {
203
+ const crossConfig = this.config.cross;
204
+
205
+ // loading page
206
+ if (mainCfg.hasOwnProperty('loadingPage')) {
207
+ const lp = path.join(this.config.homeDir, mainCfg.loadingPage);
208
+ this._loadingPage(lp);
209
+ }
210
+
211
+ // cross service url
212
+ const service = mainCfg.takeover;
213
+ if (!crossConfig.hasOwnProperty(service)) {
214
+ throw new Error(`[ee-core] Please Check the value of mainServer.takeover in the config file !`);
215
+ }
216
+ // check service
217
+ if (crossConfig[service].enable != true) {
218
+ throw new Error(`[ee-core] Please Check the value of cross.${service} enable is true !`);
219
+ }
220
+
221
+ const url = Cross.getUrl(service);
222
+
223
+ let count = 0;
224
+ let serviceReady = false;
225
+ const hc = new HttpClient();
226
+
227
+ // 循环检查
228
+ const times = Ps.isDev() ? 20 : 100;
229
+ const sleeptime = Ps.isDev() ? 1000 : 100;
230
+ while(!serviceReady && count < times){
231
+ await UtilsHelper.sleep(sleeptime);
232
+ try {
233
+ await hc.request(url, {
234
+ method: 'GET',
235
+ timeout: 100,
236
+ });
237
+ serviceReady = true;
238
+ } catch(err) {
239
+ //console.log('The cross service is starting');
240
+ }
241
+ count++;
242
+ }
243
+ //console.log('count:', count)
244
+ if (serviceReady == false) {
245
+ const bootFailurePage = path.join(__dirname, '..', 'html', 'cross-failure.html');
246
+ this.mainWindow.loadFile(bootFailurePage);
247
+ throw new Error(`[ee-core] Please check cross service [${service}] ${url} !`)
248
+ }
249
+
250
+ Log.coreLogger.info(`[ee-core] cross service [${service}] is started successfully`);
251
+ this.loadMainUrl('spa', url);
252
+ }
253
+
177
254
  /**
178
255
  * 加载本地前端资源
179
256
  */
@@ -241,6 +318,17 @@ class EeApp extends BaseApp {
241
318
  }
242
319
  }
243
320
 
321
+ /**
322
+ * loading page
323
+ */
324
+ _loadingPage(name) {
325
+ if (!fs.existsSync(name)) {
326
+ return
327
+ }
328
+
329
+ this.mainWindow.loadFile(name);
330
+ }
331
+
244
332
  /**
245
333
  * electron app退出
246
334
  */
@@ -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.2",
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
+ };