testem 3.19.0 → 3.20.0
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/README.md +32 -9
- package/lib/api.js +1 -1
- package/lib/app.js +204 -141
- package/lib/browser_launcher.js +5 -6
- package/lib/config.js +246 -133
- package/lib/file_watcher.js +111 -37
- package/lib/file_watcher_impl.js +295 -0
- package/lib/launcher.js +14 -23
- package/lib/log.js +92 -0
- package/lib/process-ctl.js +4 -4
- package/lib/reporters/dev/index.js +2 -1
- package/lib/reporters/dev/split_log_panel.js +2 -2
- package/lib/runners/browser_test_runner.js +15 -8
- package/lib/runners/hook_runner.js +13 -12
- package/lib/runners/process_test_runner.js +4 -5
- package/lib/runners/tap_process_test_runner.js +5 -6
- package/lib/runners/to-result.js +1 -1
- package/lib/server/index.js +62 -38
- package/lib/tap_consumer.js +74 -12
- package/lib/utils/browser-args.js +1 -1
- package/lib/utils/esbuild-browser-polyfills.js +46 -0
- package/lib/utils/esbuild-buffer-inject.js +6 -0
- package/lib/utils/expand_glob_pattern.js +19 -0
- package/lib/utils/file_watch_glob_policy.js +119 -0
- package/lib/utils/fileutils.js +4 -4
- package/lib/utils/is_emfile_error.js +16 -0
- package/lib/utils/known-browsers.js +161 -123
- package/lib/utils/path_pattern_match.js +39 -0
- package/lib/utils/process.js +45 -4
- package/lib/utils/promises.js +149 -0
- package/lib/utils/report-file.js +1 -3
- package/lib/utils/reporter.js +5 -5
- package/lib/utils/run-timeout.js +4 -4
- package/lib/utils/signal-listeners.js +9 -7
- package/lib/utils/tmp-cleanup.js +26 -0
- package/package.json +42 -32
- package/testem.js +170 -79
package/lib/browser_launcher.js
CHANGED
|
@@ -8,10 +8,9 @@ This file more or less figures out how to launch any browser on any platform.
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
var Bluebird = require('bluebird');
|
|
12
|
-
|
|
13
11
|
var fileutils = require('./utils/fileutils');
|
|
14
12
|
var envWithLocalPath = require('./utils/env-with-local-path');
|
|
13
|
+
const { filter, asCallback } = require('./utils/promises');
|
|
15
14
|
|
|
16
15
|
var executableExists = function(exe, config) {
|
|
17
16
|
return fileutils.executableExists(exe, { env: envWithLocalPath(config) });
|
|
@@ -24,7 +23,7 @@ function getAvailableBrowsers(config, browsers, cb) {
|
|
|
24
23
|
b.protocol = 'browser';
|
|
25
24
|
});
|
|
26
25
|
|
|
27
|
-
return
|
|
26
|
+
return filter(browsers, function(browser) {
|
|
28
27
|
return isInstalled(browser, config).then(function(result) {
|
|
29
28
|
if (!result) {
|
|
30
29
|
return false;
|
|
@@ -33,7 +32,7 @@ function getAvailableBrowsers(config, browsers, cb) {
|
|
|
33
32
|
browser.exe = result;
|
|
34
33
|
return true;
|
|
35
34
|
});
|
|
36
|
-
}).asCallback(cb);
|
|
35
|
+
}).then(...asCallback(cb));
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
function isInstalled(browser, config) {
|
|
@@ -50,11 +49,11 @@ function isInstalled(browser, config) {
|
|
|
50
49
|
|
|
51
50
|
function checkBrowser(browser, property, method) {
|
|
52
51
|
if (!browser[property]) {
|
|
53
|
-
return
|
|
52
|
+
return Promise.resolve(false);
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
if (Array.isArray(browser[property])) {
|
|
57
|
-
return
|
|
56
|
+
return filter(browser[property], method).then(function(result) {
|
|
58
57
|
if (result.length === 0) {
|
|
59
58
|
return false;
|
|
60
59
|
}
|
package/lib/config.js
CHANGED
|
@@ -8,16 +8,14 @@ or `testem.json` config file.
|
|
|
8
8
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
const os = require('os');
|
|
13
12
|
const fs = require('fs');
|
|
14
13
|
const yaml = require('js-yaml');
|
|
15
|
-
const log = require('
|
|
14
|
+
const log = require('./log');
|
|
16
15
|
const path = require('path');
|
|
17
|
-
const glob = require('glob').glob;
|
|
18
16
|
const url = require('url');
|
|
19
17
|
const querystring = require('querystring');
|
|
20
|
-
const
|
|
18
|
+
const { filter, reduce } = require('./utils/promises');
|
|
21
19
|
|
|
22
20
|
const browser_launcher = require('./browser_launcher');
|
|
23
21
|
const LauncherFactory = require('./launcher-factory');
|
|
@@ -29,7 +27,7 @@ const _ = require('lodash');
|
|
|
29
27
|
|
|
30
28
|
const knownBrowsers = require('./utils/known-browsers');
|
|
31
29
|
const { convertToPosix } = require('./utils/posix');
|
|
32
|
-
const
|
|
30
|
+
const expandGlobPattern = require('./utils/expand_glob_pattern');
|
|
33
31
|
|
|
34
32
|
class Config {
|
|
35
33
|
constructor(appMode, progOptions, config) {
|
|
@@ -39,7 +37,7 @@ class Config {
|
|
|
39
37
|
this.fileOptions = {};
|
|
40
38
|
this.config = config || {};
|
|
41
39
|
this.getters = {
|
|
42
|
-
test_page: 'getTestPage'
|
|
40
|
+
test_page: 'getTestPage',
|
|
43
41
|
};
|
|
44
42
|
|
|
45
43
|
if (appMode === 'dev') {
|
|
@@ -71,12 +69,31 @@ class Config {
|
|
|
71
69
|
|
|
72
70
|
// Try all testem.json, testem.yml and testem.js
|
|
73
71
|
// testem.json gets precedence
|
|
74
|
-
let files = [
|
|
75
|
-
|
|
72
|
+
let files = [
|
|
73
|
+
'testem.json',
|
|
74
|
+
'.testem.json',
|
|
75
|
+
'.testem.yml',
|
|
76
|
+
'testem.yml',
|
|
77
|
+
'testem.js',
|
|
78
|
+
'.testem.js',
|
|
79
|
+
'testem.cjs',
|
|
80
|
+
'.testem.cjs',
|
|
81
|
+
];
|
|
82
|
+
return filter(
|
|
83
|
+
files.map(this.resolveConfigPath.bind(this)),
|
|
84
|
+
fileExists,
|
|
85
|
+
).then((matched) => {
|
|
76
86
|
let configFile = matched[0];
|
|
77
87
|
if (matched.length > 1) {
|
|
78
|
-
let baseNames = matched.map(fileName => path.basename(fileName));
|
|
79
|
-
console.warn(
|
|
88
|
+
let baseNames = matched.map((fileName) => path.basename(fileName));
|
|
89
|
+
console.warn(
|
|
90
|
+
'Found ' +
|
|
91
|
+
matched.length +
|
|
92
|
+
' config files (' +
|
|
93
|
+
baseNames +
|
|
94
|
+
'), using ' +
|
|
95
|
+
baseNames[0],
|
|
96
|
+
);
|
|
80
97
|
}
|
|
81
98
|
if (configFile) {
|
|
82
99
|
this.readConfigFile(configFile, callback);
|
|
@@ -99,7 +116,7 @@ class Config {
|
|
|
99
116
|
|
|
100
117
|
client() {
|
|
101
118
|
return {
|
|
102
|
-
decycle_depth: this.get('client_decycle_depth')
|
|
119
|
+
decycle_depth: this.get('client_decycle_depth'),
|
|
103
120
|
};
|
|
104
121
|
}
|
|
105
122
|
|
|
@@ -122,7 +139,8 @@ class Config {
|
|
|
122
139
|
}
|
|
123
140
|
|
|
124
141
|
readConfigFile(configFile, callback) {
|
|
125
|
-
if (!configFile) {
|
|
142
|
+
if (!configFile) {
|
|
143
|
+
// allow empty configFile for programmatic setups
|
|
126
144
|
if (callback) {
|
|
127
145
|
callback.call(this);
|
|
128
146
|
}
|
|
@@ -143,7 +161,7 @@ class Config {
|
|
|
143
161
|
readJS(configFile, callback) {
|
|
144
162
|
let exportedConfig = require(this.resolveConfigPath(configFile));
|
|
145
163
|
if (typeof exportedConfig === 'function') {
|
|
146
|
-
Promise.resolve(exportedConfig()).then(obj => {
|
|
164
|
+
Promise.resolve(exportedConfig()).then((obj) => {
|
|
147
165
|
this.fileOptions = obj;
|
|
148
166
|
if (callback) {
|
|
149
167
|
callback.call(this);
|
|
@@ -158,28 +176,36 @@ class Config {
|
|
|
158
176
|
}
|
|
159
177
|
|
|
160
178
|
readYAML(configFile, callback) {
|
|
161
|
-
fs.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
179
|
+
return fs.promises
|
|
180
|
+
.readFile(configFile)
|
|
181
|
+
.then(
|
|
182
|
+
(data) => {
|
|
183
|
+
this.fileOptions = yaml.load(String(data));
|
|
184
|
+
},
|
|
185
|
+
() => {},
|
|
186
|
+
)
|
|
187
|
+
.then(() => {
|
|
188
|
+
if (callback) {
|
|
189
|
+
callback.call(this);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
170
192
|
}
|
|
171
193
|
|
|
172
194
|
readJSON(configFile, callback) {
|
|
173
|
-
fs.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
195
|
+
return fs.promises
|
|
196
|
+
.readFile(configFile)
|
|
197
|
+
.then(
|
|
198
|
+
(data) => {
|
|
199
|
+
this.fileOptions = JSON.parse(data.toString());
|
|
200
|
+
this.progOptions.file = configFile;
|
|
201
|
+
},
|
|
202
|
+
() => {},
|
|
203
|
+
)
|
|
204
|
+
.then(() => {
|
|
205
|
+
if (callback) {
|
|
206
|
+
callback.call(this);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
183
209
|
}
|
|
184
210
|
|
|
185
211
|
mergeUrlAndQueryParams(urlString, queryParamsObj) {
|
|
@@ -196,11 +222,12 @@ class Config {
|
|
|
196
222
|
|
|
197
223
|
let urlObj = url.parse(urlString);
|
|
198
224
|
let outputQueryParams = querystring.parse(urlObj.query) || {};
|
|
199
|
-
Object.keys(queryParamsObj).forEach(param => {
|
|
225
|
+
Object.keys(queryParamsObj).forEach((param) => {
|
|
200
226
|
outputQueryParams[param] = queryParamsObj[param];
|
|
201
227
|
});
|
|
202
228
|
urlObj.query = outputQueryParams;
|
|
203
|
-
urlObj.search = querystring
|
|
229
|
+
urlObj.search = querystring
|
|
230
|
+
.stringify(outputQueryParams)
|
|
204
231
|
.replace(/=&/g, '&')
|
|
205
232
|
.replace(/=$/, '');
|
|
206
233
|
urlObj.path = urlObj.pathname + urlObj.search;
|
|
@@ -215,20 +242,32 @@ class Config {
|
|
|
215
242
|
testPage = [testPage];
|
|
216
243
|
}
|
|
217
244
|
|
|
218
|
-
return testPage.map(page =>
|
|
245
|
+
return testPage.map((page) =>
|
|
246
|
+
this.mergeUrlAndQueryParams(page, queryParams),
|
|
247
|
+
);
|
|
219
248
|
}
|
|
220
249
|
|
|
221
250
|
getConfigProperty(key) {
|
|
222
251
|
if (this.config && key in this.config) {
|
|
223
252
|
return this.config[key];
|
|
224
253
|
}
|
|
225
|
-
if (
|
|
254
|
+
if (
|
|
255
|
+
key in this.progOptions &&
|
|
256
|
+
typeof this.progOptions[key] !== 'undefined'
|
|
257
|
+
) {
|
|
226
258
|
return this.progOptions[key];
|
|
227
259
|
}
|
|
228
|
-
if (
|
|
260
|
+
if (
|
|
261
|
+
key in this.fileOptions &&
|
|
262
|
+
typeof this.fileOptions[key] !== 'undefined'
|
|
263
|
+
) {
|
|
229
264
|
return this.fileOptions[key];
|
|
230
265
|
}
|
|
231
|
-
if (
|
|
266
|
+
if (
|
|
267
|
+
this.defaultOptions &&
|
|
268
|
+
key in this.defaultOptions &&
|
|
269
|
+
typeof this.defaultOptions[key] !== 'undefined'
|
|
270
|
+
) {
|
|
232
271
|
return this.defaultOptions[key];
|
|
233
272
|
}
|
|
234
273
|
if (key in this.defaults) {
|
|
@@ -264,27 +303,35 @@ class Config {
|
|
|
264
303
|
|
|
265
304
|
getAvailableLaunchers(cb) {
|
|
266
305
|
let browsers = knownBrowsers(process.platform, this);
|
|
267
|
-
browser_launcher.getAvailableBrowsers(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
306
|
+
browser_launcher.getAvailableBrowsers(
|
|
307
|
+
this,
|
|
308
|
+
browsers,
|
|
309
|
+
(err, availableBrowsers) => {
|
|
310
|
+
if (err) {
|
|
311
|
+
return cb(err);
|
|
312
|
+
}
|
|
271
313
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
314
|
+
let availableLaunchers = {};
|
|
315
|
+
availableBrowsers.forEach((browser) => {
|
|
316
|
+
let newLauncher = new LauncherFactory(browser.name, browser, this);
|
|
317
|
+
availableLaunchers[browser.name.toLowerCase()] = newLauncher;
|
|
318
|
+
});
|
|
277
319
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
320
|
+
// add custom launchers
|
|
321
|
+
let customLaunchers = this.get('launchers');
|
|
322
|
+
if (customLaunchers) {
|
|
323
|
+
for (let name in customLaunchers) {
|
|
324
|
+
let newLauncher = new LauncherFactory(
|
|
325
|
+
name,
|
|
326
|
+
customLaunchers[name],
|
|
327
|
+
this,
|
|
328
|
+
);
|
|
329
|
+
availableLaunchers[name.toLowerCase()] = newLauncher;
|
|
330
|
+
}
|
|
284
331
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
332
|
+
cb(null, availableLaunchers);
|
|
333
|
+
},
|
|
334
|
+
);
|
|
288
335
|
}
|
|
289
336
|
|
|
290
337
|
getLaunchers(cb) {
|
|
@@ -310,7 +357,7 @@ class Config {
|
|
|
310
357
|
let skip = this.get('skip');
|
|
311
358
|
if (skip) {
|
|
312
359
|
skip = skip.toLowerCase().split(',');
|
|
313
|
-
launchers = launchers.filter(name => skip.indexOf(name) === -1);
|
|
360
|
+
launchers = launchers.filter((name) => skip.indexOf(name) === -1);
|
|
314
361
|
}
|
|
315
362
|
return launchers;
|
|
316
363
|
}
|
|
@@ -320,7 +367,7 @@ class Config {
|
|
|
320
367
|
let wanted = this.getWantedLauncherNames(available);
|
|
321
368
|
let err = null;
|
|
322
369
|
|
|
323
|
-
wanted.forEach(name => {
|
|
370
|
+
wanted.forEach((name) => {
|
|
324
371
|
let launcher = available[name.toLowerCase()];
|
|
325
372
|
if (!launcher) {
|
|
326
373
|
if (this.appMode === 'dev' || this.get('ignore_missing_launchers')) {
|
|
@@ -328,10 +375,12 @@ class Config {
|
|
|
328
375
|
} else {
|
|
329
376
|
err = new Error(
|
|
330
377
|
'Launcher ' +
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
378
|
+
name +
|
|
379
|
+
' not found. Not installed? Available: ' +
|
|
380
|
+
Object.keys(available)
|
|
381
|
+
.map((elm) => `"${elm}"`)
|
|
382
|
+
.join(', ') +
|
|
383
|
+
'.',
|
|
335
384
|
);
|
|
336
385
|
}
|
|
337
386
|
} else {
|
|
@@ -343,38 +392,62 @@ class Config {
|
|
|
343
392
|
|
|
344
393
|
printLauncherInfo() {
|
|
345
394
|
this.getAvailableLaunchers((err, launchers) => {
|
|
346
|
-
let launch_in_dev = (this.get('launch_in_dev') || [])
|
|
347
|
-
|
|
395
|
+
let launch_in_dev = (this.get('launch_in_dev') || []).map((s) =>
|
|
396
|
+
s.toLowerCase(),
|
|
397
|
+
);
|
|
348
398
|
let launch_in_ci = this.get('launch_in_ci');
|
|
349
399
|
if (launch_in_ci) {
|
|
350
|
-
launch_in_ci = launch_in_ci.map(s => s.toLowerCase());
|
|
400
|
+
launch_in_ci = launch_in_ci.map((s) => s.toLowerCase());
|
|
351
401
|
}
|
|
352
|
-
launchers = Object.keys(launchers).map(k => launchers[k]);
|
|
402
|
+
launchers = Object.keys(launchers).map((k) => launchers[k]);
|
|
353
403
|
|
|
354
|
-
const launcherColumnWidth = launchers.reduce(
|
|
404
|
+
const launcherColumnWidth = launchers.reduce(
|
|
405
|
+
(acc, current) =>
|
|
406
|
+
acc > current.name.length ? acc : current.name.length,
|
|
407
|
+
0,
|
|
408
|
+
);
|
|
355
409
|
const launcherTitle = 'Launcher'.padEnd(launcherColumnWidth, ' ');
|
|
356
410
|
const launcherTitleDivider = ''.padEnd(launcherColumnWidth, '-');
|
|
357
411
|
|
|
358
|
-
console.log(
|
|
412
|
+
console.log(
|
|
413
|
+
'Have ' +
|
|
414
|
+
launchers.length +
|
|
415
|
+
' launchers available; auto-launch info displayed on the right.',
|
|
416
|
+
);
|
|
359
417
|
console.log(); // newline
|
|
360
418
|
console.log(`${launcherTitle} Type CI Dev`);
|
|
361
419
|
console.log(`${launcherTitleDivider} ------------ -- ---`);
|
|
362
|
-
console.log(
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
420
|
+
console.log(
|
|
421
|
+
launchers
|
|
422
|
+
.map((launcher) => {
|
|
423
|
+
let protocol = launcher.settings.protocol;
|
|
424
|
+
let kind =
|
|
425
|
+
protocol === 'browser'
|
|
426
|
+
? 'browser'
|
|
427
|
+
: protocol === 'tap'
|
|
428
|
+
? 'process(TAP)'
|
|
429
|
+
: 'process';
|
|
430
|
+
let dev =
|
|
431
|
+
launch_in_dev.indexOf(launcher.name.toLowerCase()) !== -1
|
|
432
|
+
? Chars.mark
|
|
433
|
+
: ' ';
|
|
434
|
+
let ci =
|
|
435
|
+
!launch_in_ci ||
|
|
436
|
+
launch_in_ci.indexOf(launcher.name.toLowerCase()) !== -1
|
|
437
|
+
? Chars.mark
|
|
438
|
+
: ' ';
|
|
439
|
+
return (
|
|
440
|
+
pad(launcher.name, launcherColumnWidth + 2, ' ', 1) +
|
|
441
|
+
pad(kind, 12, ' ', 1) +
|
|
442
|
+
' ' +
|
|
443
|
+
ci +
|
|
444
|
+
' ' +
|
|
445
|
+
dev +
|
|
446
|
+
' '
|
|
447
|
+
);
|
|
448
|
+
})
|
|
449
|
+
.join('\n'),
|
|
450
|
+
);
|
|
378
451
|
});
|
|
379
452
|
}
|
|
380
453
|
|
|
@@ -389,7 +462,7 @@ class Config {
|
|
|
389
462
|
// Filter glob < 6 negation patterns to still support them
|
|
390
463
|
// See https://github.com/isaacs/node-glob/tree/3f883c43#comments-and-negation
|
|
391
464
|
let positiveWants = [];
|
|
392
|
-
want.forEach(patternEntry => {
|
|
465
|
+
want.forEach((patternEntry) => {
|
|
393
466
|
let pattern = isa(patternEntry, String) ? patternEntry : patternEntry.src;
|
|
394
467
|
if (pattern.indexOf('!') === 0) {
|
|
395
468
|
return dontWant.push(pattern.substring(1));
|
|
@@ -398,47 +471,71 @@ class Config {
|
|
|
398
471
|
positiveWants.push(patternEntry);
|
|
399
472
|
});
|
|
400
473
|
|
|
401
|
-
dontWant = dontWant.map(p => p ? this.resolvePath(p) : p);
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
474
|
+
dontWant = dontWant.map((p) => (p ? this.resolvePath(p) : p));
|
|
475
|
+
return reduce(
|
|
476
|
+
positiveWants,
|
|
477
|
+
(allThatIWant, patternEntry) => {
|
|
478
|
+
let pattern = isa(patternEntry, String)
|
|
479
|
+
? patternEntry
|
|
480
|
+
: patternEntry.src;
|
|
481
|
+
let attrs = patternEntry.attrs || [];
|
|
482
|
+
let patternUrl = url.parse(pattern);
|
|
483
|
+
|
|
484
|
+
if (patternUrl.protocol === 'file:') {
|
|
485
|
+
pattern = patternUrl.hostname + patternUrl.path;
|
|
486
|
+
} else if (patternUrl.protocol) {
|
|
487
|
+
return allThatIWant.concat({ src: pattern, attrs: attrs });
|
|
488
|
+
}
|
|
412
489
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
490
|
+
return expandGlobPattern(
|
|
491
|
+
convertToPosix(this.resolvePath(pattern)),
|
|
492
|
+
dontWant.map(convertToPosix),
|
|
493
|
+
).then((files) =>
|
|
494
|
+
allThatIWant.concat(
|
|
495
|
+
files.map((f) => {
|
|
496
|
+
f = this.reverseResolvePath(f);
|
|
497
|
+
return { src: f, attrs: attrs };
|
|
498
|
+
}),
|
|
499
|
+
),
|
|
500
|
+
);
|
|
501
|
+
},
|
|
502
|
+
[],
|
|
503
|
+
)
|
|
504
|
+
.then((result) => _.uniqBy(result, 'src'))
|
|
505
|
+
.then(
|
|
506
|
+
(result) => {
|
|
507
|
+
if (callback) {
|
|
508
|
+
callback(null, result);
|
|
509
|
+
}
|
|
510
|
+
return result;
|
|
511
|
+
},
|
|
512
|
+
(err) => {
|
|
513
|
+
if (callback) {
|
|
514
|
+
callback(err);
|
|
515
|
+
}
|
|
516
|
+
throw err;
|
|
517
|
+
},
|
|
518
|
+
);
|
|
422
519
|
}
|
|
423
520
|
|
|
424
521
|
getSrcFiles(callback) {
|
|
425
522
|
let srcFiles = this.get('src_files') || '*.js';
|
|
426
523
|
let srcFilesIgnore = this.get('src_files_ignore') || '';
|
|
427
|
-
this.getFileSet(srcFiles, srcFilesIgnore, callback);
|
|
524
|
+
return this.getFileSet(srcFiles, srcFilesIgnore, callback);
|
|
428
525
|
}
|
|
429
526
|
|
|
430
527
|
getFooterScripts(callback) {
|
|
431
528
|
var want = this.get('footer_scripts') || [];
|
|
432
529
|
var dontWant = this.get('src_files_ignore') || '';
|
|
433
530
|
|
|
434
|
-
this.getFileSet(want, dontWant, callback);
|
|
531
|
+
return this.getFileSet(want, dontWant, callback);
|
|
435
532
|
}
|
|
436
533
|
|
|
437
|
-
|
|
438
534
|
getServeFiles(callback) {
|
|
439
535
|
let want = this.get('serve_files') || this.get('src_files') || '*.js';
|
|
440
|
-
let dontWant =
|
|
441
|
-
|
|
536
|
+
let dontWant =
|
|
537
|
+
this.get('serve_files_ignore') || this.get('src_files_ignore') || '';
|
|
538
|
+
return this.getFileSet(want, dontWant, callback);
|
|
442
539
|
}
|
|
443
540
|
|
|
444
541
|
getUserDataDir() {
|
|
@@ -455,7 +552,7 @@ class Config {
|
|
|
455
552
|
|
|
456
553
|
getCSSFiles(callback) {
|
|
457
554
|
let want = this.get('css_files') || '';
|
|
458
|
-
this.getFileSet(want, '', callback);
|
|
555
|
+
return this.getFileSet(want, '', callback);
|
|
459
556
|
}
|
|
460
557
|
|
|
461
558
|
getAllOptions() {
|
|
@@ -465,17 +562,23 @@ class Config {
|
|
|
465
562
|
return;
|
|
466
563
|
}
|
|
467
564
|
if (o.options) {
|
|
468
|
-
o.options.forEach(o => {
|
|
565
|
+
o.options.forEach((o) => {
|
|
469
566
|
options.push(o.name());
|
|
470
567
|
});
|
|
471
568
|
}
|
|
472
569
|
getOptions(o.parent);
|
|
473
570
|
}
|
|
474
|
-
|
|
571
|
+
const progOpts = this.progOptions;
|
|
572
|
+
// In subcommand modes, progOptions is a plain object from optsWithGlobals() with
|
|
573
|
+
// a _commander reference pointing to the Command instance for option enumeration.
|
|
574
|
+
// In dev mode (no subcommand), progOptions is the Commander program object directly.
|
|
575
|
+
getOptions(
|
|
576
|
+
progOpts && progOpts._commander ? progOpts._commander : progOpts,
|
|
577
|
+
);
|
|
475
578
|
return options;
|
|
476
579
|
}
|
|
477
580
|
|
|
478
|
-
getTemplateData(cb) {
|
|
581
|
+
async getTemplateData(cb) {
|
|
479
582
|
let ret = {};
|
|
480
583
|
let options = this.getAllOptions();
|
|
481
584
|
let key;
|
|
@@ -490,24 +593,31 @@ class Config {
|
|
|
490
593
|
for (key in this.config) {
|
|
491
594
|
ret[key] = this.config[key];
|
|
492
595
|
}
|
|
493
|
-
this.getServeFiles((err, files) => {
|
|
494
|
-
let replaceSlashes = f => ({
|
|
495
|
-
src: f.src.replace(/\\/g, '/'),
|
|
496
|
-
attrs: f.attrs
|
|
497
|
-
});
|
|
498
596
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
ret.css_files = files.map(replaceSlashes);
|
|
503
|
-
this.getFooterScripts((err, files) => {
|
|
504
|
-
ret.footer_scripts = files;
|
|
505
|
-
if (cb) {
|
|
506
|
-
cb(err, ret);
|
|
507
|
-
}
|
|
508
|
-
});
|
|
509
|
-
});
|
|
597
|
+
const replaceSlashes = (f) => ({
|
|
598
|
+
src: f.src.replace(/\\/g, '/'),
|
|
599
|
+
attrs: f.attrs,
|
|
510
600
|
});
|
|
601
|
+
|
|
602
|
+
try {
|
|
603
|
+
const [serveFiles, cssFiles, footerScripts] = await Promise.all([
|
|
604
|
+
this.getServeFiles(),
|
|
605
|
+
this.getCSSFiles(),
|
|
606
|
+
this.getFooterScripts(),
|
|
607
|
+
]);
|
|
608
|
+
|
|
609
|
+
ret.serve_files = serveFiles.map(replaceSlashes);
|
|
610
|
+
ret.css_files = cssFiles.map(replaceSlashes);
|
|
611
|
+
ret.footer_scripts = footerScripts;
|
|
612
|
+
|
|
613
|
+
if (cb) {
|
|
614
|
+
cb(null, ret);
|
|
615
|
+
}
|
|
616
|
+
} catch (err) {
|
|
617
|
+
if (cb) {
|
|
618
|
+
cb(err, ret);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
511
621
|
}
|
|
512
622
|
}
|
|
513
623
|
|
|
@@ -530,10 +640,13 @@ Config.prototype.defaults = {
|
|
|
530
640
|
client_decycle_depth: 5,
|
|
531
641
|
socket_heartbeat_timeout() {
|
|
532
642
|
let browserDisconnectTimeout = this.get('browser_disconnect_timeout');
|
|
533
|
-
let defaultBrowserDisconnectTimeout =
|
|
643
|
+
let defaultBrowserDisconnectTimeout =
|
|
644
|
+
this.defaults.browser_disconnect_timeout;
|
|
534
645
|
|
|
535
|
-
return
|
|
536
|
-
|
|
646
|
+
return browserDisconnectTimeout !== defaultBrowserDisconnectTimeout
|
|
647
|
+
? browserDisconnectTimeout
|
|
648
|
+
: 5;
|
|
649
|
+
},
|
|
537
650
|
};
|
|
538
651
|
|
|
539
652
|
module.exports = Config;
|