@rindo/core 2.17.4 → 2.22.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/cli/config-flags.d.ts +33 -21
- package/cli/index.cjs +693 -401
- package/cli/index.d.ts +3 -0
- package/cli/index.js +693 -401
- package/cli/package.json +1 -1
- package/compiler/lib.dom.d.ts +898 -184
- package/compiler/lib.dom.iterable.d.ts +22 -4
- package/compiler/lib.es2015.collection.d.ts +62 -1
- package/compiler/lib.es2015.core.d.ts +3 -3
- package/compiler/lib.es2015.iterable.d.ts +2 -1
- package/compiler/lib.es2015.promise.d.ts +9 -4
- package/compiler/lib.es2015.proxy.d.ts +91 -2
- package/compiler/lib.es2015.reflect.d.ts +26 -3
- package/compiler/lib.es2015.symbol.wellknown.d.ts +3 -3
- package/compiler/lib.es2017.intl.d.ts +16 -1
- package/compiler/lib.es2019.d.ts +1 -0
- package/compiler/lib.es2019.intl.d.ts +25 -0
- package/compiler/lib.es2020.bigint.d.ts +7 -5
- package/compiler/lib.es2020.d.ts +2 -0
- package/compiler/lib.es2020.date.d.ts +44 -0
- package/compiler/lib.es2020.intl.d.ts +81 -16
- package/compiler/lib.es2020.number.d.ts +30 -0
- package/compiler/lib.es2021.intl.d.ts +116 -6
- package/compiler/lib.es2022.array.d.ts +123 -0
- package/compiler/lib.es2022.d.ts +27 -0
- package/compiler/lib.es2022.error.d.ts +75 -0
- package/compiler/lib.es2022.full.d.ts +25 -0
- package/compiler/lib.es2022.intl.d.ts +111 -0
- package/compiler/lib.es2022.object.d.ts +28 -0
- package/compiler/lib.es2022.sharedmemory.d.ts +27 -0
- package/compiler/lib.es2022.string.d.ts +27 -0
- package/compiler/lib.es5.d.ts +62 -31
- package/compiler/lib.esnext.d.ts +1 -1
- package/compiler/lib.esnext.intl.d.ts +8 -1
- package/compiler/lib.webworker.d.ts +540 -81
- package/compiler/lib.webworker.iterable.d.ts +19 -4
- package/compiler/package.json +1 -1
- package/compiler/rindo.d.ts +3 -25
- package/compiler/rindo.js +54678 -52205
- package/compiler/rindo.min.js +2 -2
- package/compiler/sys/in-memory-fs.d.ts +218 -0
- package/compiler/transpile.d.ts +32 -0
- package/dependencies.json +12 -1
- package/dev-server/client/app-error.d.ts +1 -1
- package/dev-server/client/index.d.ts +2 -2
- package/dev-server/client/index.js +241 -241
- package/dev-server/client/package.json +1 -1
- package/dev-server/connector.html +3 -3
- package/dev-server/index.d.ts +1 -1
- package/dev-server/index.js +2 -2
- package/dev-server/open-in-editor-api.js +1 -1
- package/dev-server/package.json +1 -1
- package/dev-server/server-process.js +1192 -1158
- package/dev-server/ws.js +1 -1
- package/internal/app-data/package.json +1 -1
- package/internal/client/css-shim.js +2 -2
- package/internal/client/dom.js +1 -1
- package/internal/client/index.js +1130 -823
- package/internal/client/package.json +1 -1
- package/internal/client/patch-browser.js +19 -1
- package/internal/client/patch-esm.js +1 -1
- package/internal/client/polyfills/css-shim.js +1 -1
- package/internal/client/shadow-css.js +1 -1
- package/internal/hydrate/index.js +154 -143
- package/internal/hydrate/package.json +1 -1
- package/internal/hydrate/runner.d.ts +1 -1
- package/internal/hydrate/runner.js +106 -106
- package/internal/package.json +1 -1
- package/internal/rindo-core/index.d.ts +9 -10
- package/internal/rindo-private.d.ts +149 -184
- package/internal/rindo-public-compiler.d.ts +83 -38
- package/internal/rindo-public-docs.d.ts +24 -0
- package/internal/rindo-public-runtime.d.ts +79 -7
- package/internal/testing/index.js +187 -175
- package/internal/testing/package.json +1 -1
- package/mock-doc/index.cjs +526 -501
- package/mock-doc/index.d.ts +15 -14
- package/mock-doc/index.js +526 -501
- package/mock-doc/package.json +1 -1
- package/package.json +48 -59
- package/readme.md +44 -31
- package/screenshot/compare/build/p-f4745c2f.entry.js +1 -1
- package/screenshot/index.d.ts +1 -1
- package/screenshot/index.js +13 -13
- package/screenshot/package.json +1 -1
- package/screenshot/pixel-match.js +983 -849
- package/sys/node/autoprefixer.js +2 -2
- package/sys/node/glob.js +1 -1
- package/sys/node/index.d.ts +4 -0
- package/sys/node/index.js +399 -413
- package/sys/node/package.json +1 -1
- package/sys/node/prompts.js +1 -1
- package/sys/node/worker.js +1 -1
- package/testing/index.d.ts +6 -6
- package/testing/index.js +684 -839
- package/testing/jest/jest-config.d.ts +1 -1
- package/testing/jest/jest-preprocessor.d.ts +3 -3
- package/testing/jest/jest-serializer.d.ts +1 -2
- package/testing/matchers/index.d.ts +3 -3
- package/testing/mock-fetch.d.ts +1 -1
- package/testing/mocks.d.ts +2 -2
- package/testing/package.json +1 -1
- package/testing/puppeteer/puppeteer-declarations.d.ts +5 -5
- package/testing/puppeteer/puppeteer-element.d.ts +2 -2
- package/testing/puppeteer/puppeteer-events.d.ts +1 -1
- package/testing/testing-logger.d.ts +1 -1
- package/testing/testing-utils.d.ts +6 -5
- package/testing/testing.d.ts +1 -1
package/cli/index.js
CHANGED
|
@@ -1,41 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
Rindo CLI v2.
|
|
2
|
+
Rindo CLI v2.22.2 | MIT Licensed | https://rindojs.web.app
|
|
3
3
|
*/
|
|
4
|
-
/**
|
|
5
|
-
* This sets the log level hierarchy for our terminal logger, ranging from
|
|
6
|
-
* most to least verbose.
|
|
7
|
-
*
|
|
8
|
-
* Ordering the levels like this lets us easily check whether we should log a
|
|
9
|
-
* message at a given time. For instance, if the log level is set to `'warn'`,
|
|
10
|
-
* then anything passed to the logger with level `'warn'` or `'error'` should
|
|
11
|
-
* be logged, but we should _not_ log anything with level `'info'` or `'debug'`.
|
|
12
|
-
*
|
|
13
|
-
* If we have a current log level `currentLevel` and a message with level
|
|
14
|
-
* `msgLevel` is passed to the logger, we can determine whether or not we should
|
|
15
|
-
* log it by checking if the log level on the message is further up or at the
|
|
16
|
-
* same level in the hierarchy than `currentLevel`, like so:
|
|
17
|
-
*
|
|
18
|
-
* ```ts
|
|
19
|
-
* LOG_LEVELS.indexOf(msgLevel) >= LOG_LEVELS.indexOf(currentLevel)
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* NOTE: for the reasons described above, do not change the order of the entries
|
|
23
|
-
* in this array without good reason!
|
|
24
|
-
*/
|
|
25
|
-
const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Convert a string from PascalCase to dash-case
|
|
29
|
-
*
|
|
30
|
-
* @param str the string to convert
|
|
31
|
-
* @returns a converted string
|
|
32
|
-
*/
|
|
33
|
-
const toDashCase = (str) => str
|
|
34
|
-
.replace(/([A-Z0-9])/g, (match) => ` ${match[0]}`)
|
|
35
|
-
.trim()
|
|
36
|
-
.split(' ')
|
|
37
|
-
.join('-')
|
|
38
|
-
.toLowerCase();
|
|
39
4
|
/**
|
|
40
5
|
* Convert a string from dash-case / kebab-case to PascalCase (or CamelCase,
|
|
41
6
|
* or whatever you call it!)
|
|
@@ -48,6 +13,16 @@ const dashToPascalCase = (str) => str
|
|
|
48
13
|
.split('-')
|
|
49
14
|
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|
50
15
|
.join('');
|
|
16
|
+
/**
|
|
17
|
+
* Convert a string to 'camelCase'
|
|
18
|
+
*
|
|
19
|
+
* @param str the string to convert
|
|
20
|
+
* @returns the converted string
|
|
21
|
+
*/
|
|
22
|
+
const toCamelCase = (str) => {
|
|
23
|
+
const pascalCase = dashToPascalCase(str);
|
|
24
|
+
return pascalCase.charAt(0).toLowerCase() + pascalCase.slice(1);
|
|
25
|
+
};
|
|
51
26
|
const isFunction = (v) => typeof v === 'function';
|
|
52
27
|
const isString = (v) => typeof v === 'string';
|
|
53
28
|
|
|
@@ -199,18 +174,18 @@ const getEncodedRootLength = (path) => {
|
|
|
199
174
|
return 0;
|
|
200
175
|
const ch0 = path.charCodeAt(0);
|
|
201
176
|
// POSIX or UNC
|
|
202
|
-
if (ch0 === 47 /* slash */ || ch0 === 92 /* backslash */) {
|
|
177
|
+
if (ch0 === 47 /* CharacterCodes.slash */ || ch0 === 92 /* CharacterCodes.backslash */) {
|
|
203
178
|
if (path.charCodeAt(1) !== ch0)
|
|
204
179
|
return 1; // POSIX: "/" (or non-normalized "\")
|
|
205
|
-
const p1 = path.indexOf(ch0 === 47 /* slash */ ? '/' : altDirectorySeparator, 2);
|
|
180
|
+
const p1 = path.indexOf(ch0 === 47 /* CharacterCodes.slash */ ? '/' : altDirectorySeparator, 2);
|
|
206
181
|
if (p1 < 0)
|
|
207
182
|
return path.length; // UNC: "//server" or "\\server"
|
|
208
183
|
return p1 + 1; // UNC: "//server/" or "\\server\"
|
|
209
184
|
}
|
|
210
185
|
// DOS
|
|
211
|
-
if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* colon */) {
|
|
186
|
+
if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* CharacterCodes.colon */) {
|
|
212
187
|
const ch2 = path.charCodeAt(2);
|
|
213
|
-
if (ch2 === 47 /* slash */ || ch2 === 92 /* backslash */)
|
|
188
|
+
if (ch2 === 47 /* CharacterCodes.slash */ || ch2 === 92 /* CharacterCodes.backslash */)
|
|
214
189
|
return 3; // DOS: "c:/" or "c:\"
|
|
215
190
|
if (path.length === 2)
|
|
216
191
|
return 2; // DOS: "c:" (but not "c:d")
|
|
@@ -232,7 +207,7 @@ const getEncodedRootLength = (path) => {
|
|
|
232
207
|
isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) {
|
|
233
208
|
const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2);
|
|
234
209
|
if (volumeSeparatorEnd !== -1) {
|
|
235
|
-
if (path.charCodeAt(volumeSeparatorEnd) === 47 /* slash */) {
|
|
210
|
+
if (path.charCodeAt(volumeSeparatorEnd) === 47 /* CharacterCodes.slash */) {
|
|
236
211
|
// URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/"
|
|
237
212
|
return ~(volumeSeparatorEnd + 1);
|
|
238
213
|
}
|
|
@@ -250,15 +225,15 @@ const getEncodedRootLength = (path) => {
|
|
|
250
225
|
// relative
|
|
251
226
|
return 0;
|
|
252
227
|
};
|
|
253
|
-
const isVolumeCharacter = (charCode) => (charCode >= 97 /* a */ && charCode <= 122 /* z */) ||
|
|
254
|
-
(charCode >= 65 /* A */ && charCode <= 90 /* Z */);
|
|
228
|
+
const isVolumeCharacter = (charCode) => (charCode >= 97 /* CharacterCodes.a */ && charCode <= 122 /* CharacterCodes.z */) ||
|
|
229
|
+
(charCode >= 65 /* CharacterCodes.A */ && charCode <= 90 /* CharacterCodes.Z */);
|
|
255
230
|
const getFileUrlVolumeSeparatorEnd = (url, start) => {
|
|
256
231
|
const ch0 = url.charCodeAt(start);
|
|
257
|
-
if (ch0 === 58 /* colon */)
|
|
232
|
+
if (ch0 === 58 /* CharacterCodes.colon */)
|
|
258
233
|
return start + 1;
|
|
259
|
-
if (ch0 === 37 /* percent */ && url.charCodeAt(start + 1) === 51 /* _3 */) {
|
|
234
|
+
if (ch0 === 37 /* CharacterCodes.percent */ && url.charCodeAt(start + 1) === 51 /* CharacterCodes._3 */) {
|
|
260
235
|
const ch2 = url.charCodeAt(start + 2);
|
|
261
|
-
if (ch2 === 97 /* a */ || ch2 === 65 /* A */)
|
|
236
|
+
if (ch2 === 97 /* CharacterCodes.a */ || ch2 === 65 /* CharacterCodes.A */)
|
|
262
237
|
return start + 3;
|
|
263
238
|
}
|
|
264
239
|
return -1;
|
|
@@ -273,6 +248,22 @@ const pathComponents = (path, rootLength) => {
|
|
|
273
248
|
return [root, ...rest];
|
|
274
249
|
};
|
|
275
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Check whether a string is a member of a ReadonlyArray<string>
|
|
253
|
+
*
|
|
254
|
+
* We need a little helper for this because unfortunately `includes` is typed
|
|
255
|
+
* on `ReadonlyArray<T>` as `(el: T): boolean` so a `string` cannot be passed
|
|
256
|
+
* to `includes` on a `ReadonlyArray` 😢 thus we have a little helper function
|
|
257
|
+
* where we do the type coercion just once.
|
|
258
|
+
*
|
|
259
|
+
* see microsoft/TypeScript#31018 for some discussion of this
|
|
260
|
+
*
|
|
261
|
+
* @param readOnlyArray the array we're checking
|
|
262
|
+
* @param maybeMember a value which is possibly a member of the array
|
|
263
|
+
* @returns whether the array contains the member or not
|
|
264
|
+
*/
|
|
265
|
+
const readOnlyArrayHasStringMember = (readOnlyArray, maybeMember) => readOnlyArray.includes(maybeMember);
|
|
266
|
+
|
|
276
267
|
/**
|
|
277
268
|
* Validates that a component tag meets required naming conventions to be used for a web component
|
|
278
269
|
* @param tag the tag to validate
|
|
@@ -317,10 +308,33 @@ const validateComponentTag = (tag) => {
|
|
|
317
308
|
return undefined;
|
|
318
309
|
};
|
|
319
310
|
|
|
311
|
+
/**
|
|
312
|
+
* This sets the log level hierarchy for our terminal logger, ranging from
|
|
313
|
+
* most to least verbose.
|
|
314
|
+
*
|
|
315
|
+
* Ordering the levels like this lets us easily check whether we should log a
|
|
316
|
+
* message at a given time. For instance, if the log level is set to `'warn'`,
|
|
317
|
+
* then anything passed to the logger with level `'warn'` or `'error'` should
|
|
318
|
+
* be logged, but we should _not_ log anything with level `'info'` or `'debug'`.
|
|
319
|
+
*
|
|
320
|
+
* If we have a current log level `currentLevel` and a message with level
|
|
321
|
+
* `msgLevel` is passed to the logger, we can determine whether or not we should
|
|
322
|
+
* log it by checking if the log level on the message is further up or at the
|
|
323
|
+
* same level in the hierarchy than `currentLevel`, like so:
|
|
324
|
+
*
|
|
325
|
+
* ```ts
|
|
326
|
+
* LOG_LEVELS.indexOf(msgLevel) >= LOG_LEVELS.indexOf(currentLevel)
|
|
327
|
+
* ```
|
|
328
|
+
*
|
|
329
|
+
* NOTE: for the reasons described above, do not change the order of the entries
|
|
330
|
+
* in this array without good reason!
|
|
331
|
+
*/
|
|
332
|
+
const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
|
|
333
|
+
|
|
320
334
|
/**
|
|
321
335
|
* All the Boolean options supported by the Rindo CLI
|
|
322
336
|
*/
|
|
323
|
-
const
|
|
337
|
+
const BOOLEAN_CLI_FLAGS = [
|
|
324
338
|
'build',
|
|
325
339
|
'cache',
|
|
326
340
|
'checkVersion',
|
|
@@ -403,7 +417,7 @@ const BOOLEAN_CLI_ARGS = [
|
|
|
403
417
|
/**
|
|
404
418
|
* All the Number options supported by the Rindo CLI
|
|
405
419
|
*/
|
|
406
|
-
const
|
|
420
|
+
const NUMBER_CLI_FLAGS = [
|
|
407
421
|
'port',
|
|
408
422
|
// JEST CLI ARGS
|
|
409
423
|
'maxConcurrency',
|
|
@@ -412,7 +426,7 @@ const NUMBER_CLI_ARGS = [
|
|
|
412
426
|
/**
|
|
413
427
|
* All the String options supported by the Rindo CLI
|
|
414
428
|
*/
|
|
415
|
-
const
|
|
429
|
+
const STRING_CLI_FLAGS = [
|
|
416
430
|
'address',
|
|
417
431
|
'config',
|
|
418
432
|
'docsApi',
|
|
@@ -451,7 +465,8 @@ const STRING_CLI_ARGS = [
|
|
|
451
465
|
'testURL',
|
|
452
466
|
'timers',
|
|
453
467
|
'transform',
|
|
454
|
-
|
|
468
|
+
];
|
|
469
|
+
const STRING_ARRAY_CLI_FLAGS = [
|
|
455
470
|
'collectCoverageOnlyFrom',
|
|
456
471
|
'coveragePathIgnorePatterns',
|
|
457
472
|
'coverageReporters',
|
|
@@ -480,7 +495,7 @@ const STRING_CLI_ARGS = [
|
|
|
480
495
|
* `maxWorkers` is an argument which is used both by Rindo _and_ by Jest,
|
|
481
496
|
* which means that we need to support parsing both string and number values.
|
|
482
497
|
*/
|
|
483
|
-
const
|
|
498
|
+
const STRING_NUMBER_CLI_FLAGS = ['maxWorkers'];
|
|
484
499
|
/**
|
|
485
500
|
* All the LogLevel-type options supported by the Rindo CLI
|
|
486
501
|
*
|
|
@@ -488,16 +503,21 @@ const STRING_NUMBER_CLI_ARGS = ['maxWorkers'];
|
|
|
488
503
|
* but this approach lets us make sure that we're handling all
|
|
489
504
|
* our arguments in a type-safe way.
|
|
490
505
|
*/
|
|
491
|
-
const
|
|
506
|
+
const LOG_LEVEL_CLI_FLAGS = ['logLevel'];
|
|
492
507
|
/**
|
|
493
508
|
* For a small subset of CLI options we support a short alias e.g. `'h'` for `'help'`
|
|
494
509
|
*/
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
510
|
+
const CLI_FLAG_ALIASES = {
|
|
511
|
+
c: 'config',
|
|
512
|
+
h: 'help',
|
|
513
|
+
p: 'port',
|
|
514
|
+
v: 'version',
|
|
500
515
|
};
|
|
516
|
+
/**
|
|
517
|
+
* A regular expression which can be used to match a CLI flag for one of our
|
|
518
|
+
* short aliases.
|
|
519
|
+
*/
|
|
520
|
+
const CLI_FLAG_REGEX = new RegExp(`^-[chpv]{1}$`);
|
|
501
521
|
/**
|
|
502
522
|
* Helper function for initializing a `ConfigFlags` object. Provide any overrides
|
|
503
523
|
* for default values and off you go!
|
|
@@ -530,8 +550,14 @@ const parseFlags = (args, _sys) => {
|
|
|
530
550
|
flags.args = Array.isArray(args) ? args.slice() : [];
|
|
531
551
|
if (flags.args.length > 0 && flags.args[0] && !flags.args[0].startsWith('-')) {
|
|
532
552
|
flags.task = flags.args[0];
|
|
553
|
+
// if the first argument was a "task" (like `build`, `test`, etc) then
|
|
554
|
+
// we go on to parse the _rest_ of the CLI args
|
|
555
|
+
parseArgs(flags, args.slice(1));
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
// we didn't find a leading flag, so we should just parse them all
|
|
559
|
+
parseArgs(flags, flags.args);
|
|
533
560
|
}
|
|
534
|
-
parseArgs(flags, flags.args);
|
|
535
561
|
if (flags.task != null) {
|
|
536
562
|
const i = flags.args.indexOf(flags.task);
|
|
537
563
|
if (i > -1) {
|
|
@@ -548,120 +574,259 @@ const parseFlags = (args, _sys) => {
|
|
|
548
574
|
return flags;
|
|
549
575
|
};
|
|
550
576
|
/**
|
|
551
|
-
* Parse command line
|
|
552
|
-
* module. Handles leading dashes on arguments, aliases that are
|
|
553
|
-
* small number of arguments, and parsing values for non-boolean
|
|
554
|
-
* (e.g. port number for the dev server).
|
|
577
|
+
* Parse the supported command line flags which are enumerated in the
|
|
578
|
+
* `config-flags` module. Handles leading dashes on arguments, aliases that are
|
|
579
|
+
* defined for a small number of arguments, and parsing values for non-boolean
|
|
580
|
+
* arguments (e.g. port number for the dev server).
|
|
581
|
+
*
|
|
582
|
+
* This parses the following grammar:
|
|
583
|
+
*
|
|
584
|
+
* CLIArguments → ""
|
|
585
|
+
* | CLITerm ( " " CLITerm )* ;
|
|
586
|
+
* CLITerm → EqualsArg
|
|
587
|
+
* | AliasEqualsArg
|
|
588
|
+
* | AliasArg
|
|
589
|
+
* | NegativeDashArg
|
|
590
|
+
* | NegativeArg
|
|
591
|
+
* | SimpleArg ;
|
|
592
|
+
* EqualsArg → "--" ArgName "=" CLIValue ;
|
|
593
|
+
* AliasEqualsArg → "-" AliasName "=" CLIValue ;
|
|
594
|
+
* AliasArg → "-" AliasName ( " " CLIValue )? ;
|
|
595
|
+
* NegativeDashArg → "--no-" ArgName ;
|
|
596
|
+
* NegativeArg → "--no" ArgName ;
|
|
597
|
+
* SimpleArg → "--" ArgName ( " " CLIValue )? ;
|
|
598
|
+
* ArgName → /^[a-zA-Z-]+$/ ;
|
|
599
|
+
* AliasName → /^[a-z]{1}$/ ;
|
|
600
|
+
* CLIValue → '"' /^[a-zA-Z0-9]+$/ '"'
|
|
601
|
+
* | /^[a-zA-Z0-9]+$/ ;
|
|
602
|
+
*
|
|
603
|
+
* There are additional constraints (not shown in the grammar for brevity's sake)
|
|
604
|
+
* on the type of `CLIValue` which will be associated with a particular argument.
|
|
605
|
+
* We enforce this by declaring lists of boolean, string, etc arguments and
|
|
606
|
+
* checking the types of values before setting them.
|
|
607
|
+
*
|
|
608
|
+
* We don't need to turn the list of CLI arg tokens into any kind of
|
|
609
|
+
* intermediate representation since we aren't concerned with doing anything
|
|
610
|
+
* other than setting the correct values on our ConfigFlags object. So we just
|
|
611
|
+
* parse the array of string arguments using a recursive-descent approach
|
|
612
|
+
* (which is not very deep since our grammar is pretty simple) and make the
|
|
613
|
+
* modifications we need to make to the {@link ConfigFlags} object as we go.
|
|
555
614
|
*
|
|
556
615
|
* @param flags a ConfigFlags object to which parsed arguments will be added
|
|
557
616
|
* @param args an array of command-line arguments to parse
|
|
558
617
|
*/
|
|
559
618
|
const parseArgs = (flags, args) => {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
619
|
+
const argsCopy = args.concat();
|
|
620
|
+
while (argsCopy.length > 0) {
|
|
621
|
+
// there are still unprocessed args to deal with
|
|
622
|
+
parseCLITerm(flags, argsCopy);
|
|
623
|
+
}
|
|
565
624
|
};
|
|
566
625
|
/**
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
* - `--booleanArg`
|
|
570
|
-
* - `--boolean-arg`
|
|
571
|
-
* - `--noBooleanArg`
|
|
572
|
-
* - `--no-boolean-arg`
|
|
573
|
-
*
|
|
574
|
-
* The final two variants should be parsed to a value of `false` on the config
|
|
575
|
-
* object.
|
|
626
|
+
* Given an array of CLI arguments, parse it and perform a series of side
|
|
627
|
+
* effects (setting values on the provided `ConfigFlags` object).
|
|
576
628
|
*
|
|
577
|
-
* @param flags
|
|
578
|
-
*
|
|
579
|
-
* @param
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
629
|
+
* @param flags a {@link ConfigFlags} object which is updated as we parse the CLI
|
|
630
|
+
* arguments
|
|
631
|
+
* @param args a list of args to work through. This function (and some functions
|
|
632
|
+
* it calls) calls `Array.prototype.shift` to get the next argument to look at,
|
|
633
|
+
* so this parameter will be modified.
|
|
634
|
+
*/
|
|
635
|
+
const parseCLITerm = (flags, args) => {
|
|
636
|
+
// pull off the first arg from the argument array
|
|
637
|
+
const arg = args.shift();
|
|
638
|
+
// array is empty, we're done!
|
|
639
|
+
if (arg === undefined)
|
|
640
|
+
return;
|
|
641
|
+
// EqualsArg → "--" ArgName "=" CLIValue ;
|
|
642
|
+
if (arg.startsWith('--') && arg.includes('=')) {
|
|
643
|
+
// we're dealing with an EqualsArg, we have a special helper for that
|
|
644
|
+
const [originalArg, value] = parseEqualsArg(arg);
|
|
645
|
+
setCLIArg(flags, arg.split('=')[0], normalizeFlagName(originalArg), value);
|
|
646
|
+
}
|
|
647
|
+
// AliasEqualsArg → "-" AliasName "=" CLIValue ;
|
|
648
|
+
else if (arg.startsWith('-') && arg.includes('=')) {
|
|
649
|
+
// we're dealing with an AliasEqualsArg, we have a special helper for that
|
|
650
|
+
const [originalArg, value] = parseEqualsArg(arg);
|
|
651
|
+
setCLIArg(flags, arg.split('=')[0], normalizeFlagName(originalArg), value);
|
|
652
|
+
}
|
|
653
|
+
// AliasArg → "-" AliasName ( " " CLIValue )? ;
|
|
654
|
+
else if (CLI_FLAG_REGEX.test(arg)) {
|
|
655
|
+
// this is a short alias, like `-c` for Config
|
|
656
|
+
setCLIArg(flags, arg, normalizeFlagName(arg), parseCLIValue(args));
|
|
657
|
+
}
|
|
658
|
+
// NegativeDashArg → "--no-" ArgName ;
|
|
659
|
+
else if (arg.startsWith('--no-') && arg.length > '--no-'.length) {
|
|
660
|
+
// this is a `NegativeDashArg` term, so we need to normalize the negative
|
|
661
|
+
// flag name and then set an appropriate value
|
|
662
|
+
const normalized = normalizeNegativeFlagName(arg);
|
|
663
|
+
setCLIArg(flags, arg, normalized, '');
|
|
664
|
+
}
|
|
665
|
+
// NegativeArg → "--no" ArgName ;
|
|
666
|
+
else if (arg.startsWith('--no') &&
|
|
667
|
+
!readOnlyArrayHasStringMember(BOOLEAN_CLI_FLAGS, normalizeFlagName(arg)) &&
|
|
668
|
+
readOnlyArrayHasStringMember(BOOLEAN_CLI_FLAGS, normalizeNegativeFlagName(arg))) {
|
|
669
|
+
// possibly dealing with a `NegativeArg` here. There is a little ambiguity
|
|
670
|
+
// here because we have arguments that already begin with `no` like
|
|
671
|
+
// `notify`, so we need to test if a normalized form of the raw argument is
|
|
672
|
+
// a valid and supported boolean flag.
|
|
673
|
+
setCLIArg(flags, arg, normalizeNegativeFlagName(arg), '');
|
|
674
|
+
}
|
|
675
|
+
// SimpleArg → "--" ArgName ( " " CLIValue )? ;
|
|
676
|
+
else if (arg.startsWith('--') && arg.length > '--'.length) {
|
|
677
|
+
setCLIArg(flags, arg, normalizeFlagName(arg), parseCLIValue(args));
|
|
678
|
+
}
|
|
679
|
+
// if we get here it is not an argument in our list of supported arguments.
|
|
680
|
+
// This doesn't necessarily mean we want to report an error or anything
|
|
681
|
+
// though! Instead, with unknown / unrecognized arguments we stick them into
|
|
682
|
+
// the `unknownArgs` array, which is used when we pass CLI args to Jest, for
|
|
683
|
+
// instance. So we just return void here.
|
|
605
684
|
};
|
|
606
685
|
/**
|
|
607
|
-
*
|
|
686
|
+
* Normalize a 'negative' flag name, just to do a little pre-processing before
|
|
687
|
+
* we pass it to `setCLIArg`.
|
|
608
688
|
*
|
|
609
|
-
* @param
|
|
610
|
-
* @
|
|
611
|
-
* @param configCaseName the argument we want to look at right now
|
|
689
|
+
* @param flagName the flag name to normalize
|
|
690
|
+
* @returns a normalized flag name
|
|
612
691
|
*/
|
|
613
|
-
const
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
617
|
-
const { value, matchingArg } = getValue(args, configCaseName);
|
|
618
|
-
if (value !== undefined && matchingArg !== undefined) {
|
|
619
|
-
flags[configCaseName] = value;
|
|
620
|
-
flags.knownArgs.push(matchingArg);
|
|
621
|
-
flags.knownArgs.push(value);
|
|
622
|
-
}
|
|
692
|
+
const normalizeNegativeFlagName = (flagName) => {
|
|
693
|
+
const trimmed = flagName.replace(/^--no[-]?/, '');
|
|
694
|
+
return normalizeFlagName(trimmed.charAt(0).toLowerCase() + trimmed.slice(1));
|
|
623
695
|
};
|
|
624
696
|
/**
|
|
625
|
-
*
|
|
697
|
+
* Normalize a flag name by:
|
|
698
|
+
*
|
|
699
|
+
* - replacing any leading dashes (`--foo` -> `foo`)
|
|
700
|
+
* - converting `dash-case` to camelCase (if necessary)
|
|
701
|
+
*
|
|
702
|
+
* Normalizing in this context basically means converting the various
|
|
703
|
+
* supported flag spelling variants to the variant defined in our lists of
|
|
704
|
+
* supported arguments (e.g. BOOLEAN_CLI_FLAGS, etc). So, for instance,
|
|
705
|
+
* `--log-level` should be converted to `logLevel`.
|
|
706
|
+
*
|
|
707
|
+
* @param flagName the flag name to normalize
|
|
708
|
+
* @returns a normalized flag name
|
|
626
709
|
*
|
|
627
|
-
* @param flags the config flags object, while we'll modify
|
|
628
|
-
* @param args our CLI arguments
|
|
629
|
-
* @param configCaseName the argument we want to look at right now
|
|
630
710
|
*/
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
}
|
|
635
|
-
const { value, matchingArg } = getValue(args, configCaseName);
|
|
636
|
-
if (value !== undefined && matchingArg !== undefined) {
|
|
637
|
-
flags[configCaseName] = parseInt(value, 10);
|
|
638
|
-
flags.knownArgs.push(matchingArg);
|
|
639
|
-
flags.knownArgs.push(value);
|
|
640
|
-
}
|
|
711
|
+
const normalizeFlagName = (flagName) => {
|
|
712
|
+
const trimmed = flagName.replace(/^-+/, '');
|
|
713
|
+
return trimmed.includes('-') ? toCamelCase(trimmed) : trimmed;
|
|
641
714
|
};
|
|
642
715
|
/**
|
|
643
|
-
*
|
|
716
|
+
* Set a value on a provided {@link ConfigFlags} object, given an argument
|
|
717
|
+
* name and a raw string value. This function dispatches to other functions
|
|
718
|
+
* which make sure that the string value can be properly parsed into a JS
|
|
719
|
+
* runtime value of the right type (e.g. number, string, etc).
|
|
644
720
|
*
|
|
645
|
-
* @
|
|
646
|
-
* @param
|
|
647
|
-
* @param
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
721
|
+
* @throws if a value cannot be parsed to the right type for a given flag
|
|
722
|
+
* @param flags a {@link ConfigFlags} object
|
|
723
|
+
* @param rawArg the raw argument name matched by the parser
|
|
724
|
+
* @param normalizedArg an argument with leading control characters (`--`,
|
|
725
|
+
* `--no-`, etc) removed
|
|
726
|
+
* @param value the raw value to be set onto the config flags object
|
|
727
|
+
*/
|
|
728
|
+
const setCLIArg = (flags, rawArg, normalizedArg, value) => {
|
|
729
|
+
normalizedArg = dereferenceAlias(normalizedArg);
|
|
730
|
+
// We're setting a boolean!
|
|
731
|
+
if (readOnlyArrayHasStringMember(BOOLEAN_CLI_FLAGS, normalizedArg)) {
|
|
732
|
+
flags[normalizedArg] =
|
|
733
|
+
typeof value === 'string'
|
|
734
|
+
? Boolean(value)
|
|
735
|
+
: // no value was supplied, default to true
|
|
736
|
+
true;
|
|
737
|
+
flags.knownArgs.push(rawArg);
|
|
738
|
+
}
|
|
739
|
+
// We're setting a string!
|
|
740
|
+
else if (readOnlyArrayHasStringMember(STRING_CLI_FLAGS, normalizedArg)) {
|
|
741
|
+
if (typeof value === 'string') {
|
|
742
|
+
flags[normalizedArg] = value;
|
|
743
|
+
flags.knownArgs.push(rawArg);
|
|
744
|
+
flags.knownArgs.push(value);
|
|
745
|
+
}
|
|
746
|
+
else {
|
|
747
|
+
throwCLIParsingError(rawArg, 'expected a string argument but received nothing');
|
|
748
|
+
}
|
|
652
749
|
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
flags[
|
|
750
|
+
// We're setting a string, but it's one where the user can pass multiple values,
|
|
751
|
+
// like `--reporters="default" --reporters="jest-junit"`
|
|
752
|
+
else if (readOnlyArrayHasStringMember(STRING_ARRAY_CLI_FLAGS, normalizedArg)) {
|
|
753
|
+
if (typeof value === 'string') {
|
|
754
|
+
if (!Array.isArray(flags[normalizedArg])) {
|
|
755
|
+
flags[normalizedArg] = [];
|
|
756
|
+
}
|
|
757
|
+
const targetArray = flags[normalizedArg];
|
|
758
|
+
// this is irritating, but TS doesn't know that the `!Array.isArray`
|
|
759
|
+
// check above guarantees we have an array to work with here, and it
|
|
760
|
+
// doesn't want to narrow the type of `flags[normalizedArg]`, so we need
|
|
761
|
+
// to grab a reference to that array and then `Array.isArray` that. Bah!
|
|
762
|
+
if (Array.isArray(targetArray)) {
|
|
763
|
+
targetArray.push(value);
|
|
764
|
+
flags.knownArgs.push(rawArg);
|
|
765
|
+
flags.knownArgs.push(value);
|
|
766
|
+
}
|
|
658
767
|
}
|
|
659
768
|
else {
|
|
660
|
-
|
|
661
|
-
|
|
769
|
+
throwCLIParsingError(rawArg, 'expected a string argument but received nothing');
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
// We're setting a number!
|
|
773
|
+
else if (readOnlyArrayHasStringMember(NUMBER_CLI_FLAGS, normalizedArg)) {
|
|
774
|
+
if (typeof value === 'string') {
|
|
775
|
+
const parsed = parseInt(value, 10);
|
|
776
|
+
if (isNaN(parsed)) {
|
|
777
|
+
throwNumberParsingError(rawArg, value);
|
|
778
|
+
}
|
|
779
|
+
else {
|
|
780
|
+
flags[normalizedArg] = parsed;
|
|
781
|
+
flags.knownArgs.push(rawArg);
|
|
782
|
+
flags.knownArgs.push(value);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
else {
|
|
786
|
+
throwCLIParsingError(rawArg, 'expected a number argument but received nothing');
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
// We're setting a value which could be either a string _or_ a number
|
|
790
|
+
else if (readOnlyArrayHasStringMember(STRING_NUMBER_CLI_FLAGS, normalizedArg)) {
|
|
791
|
+
if (typeof value === 'string') {
|
|
792
|
+
if (CLI_ARG_STRING_REGEX.test(value)) {
|
|
793
|
+
// if it matches the regex we treat it like a string
|
|
794
|
+
flags[normalizedArg] = value;
|
|
795
|
+
}
|
|
796
|
+
else {
|
|
797
|
+
const parsed = Number(value);
|
|
798
|
+
if (isNaN(parsed)) {
|
|
799
|
+
// parsing didn't go so well, we gotta get out of here
|
|
800
|
+
// this is unlikely given our regex guard above
|
|
801
|
+
// but hey, this is ultimately JS so let's be safe
|
|
802
|
+
throwNumberParsingError(rawArg, value);
|
|
803
|
+
}
|
|
804
|
+
else {
|
|
805
|
+
flags[normalizedArg] = parsed;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
flags.knownArgs.push(rawArg);
|
|
809
|
+
flags.knownArgs.push(value);
|
|
810
|
+
}
|
|
811
|
+
else {
|
|
812
|
+
throwCLIParsingError(rawArg, 'expected a string or a number but received nothing');
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
// We're setting the log level, which can only be a set of specific string values
|
|
816
|
+
else if (readOnlyArrayHasStringMember(LOG_LEVEL_CLI_FLAGS, normalizedArg)) {
|
|
817
|
+
if (typeof value === 'string') {
|
|
818
|
+
if (isLogLevel(value)) {
|
|
819
|
+
flags[normalizedArg] = value;
|
|
820
|
+
flags.knownArgs.push(rawArg);
|
|
821
|
+
flags.knownArgs.push(value);
|
|
822
|
+
}
|
|
823
|
+
else {
|
|
824
|
+
throwCLIParsingError(rawArg, `expected to receive a valid log level but received "${String(value)}"`);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
else {
|
|
828
|
+
throwCLIParsingError(rawArg, 'expected to receive a valid log level but received nothing');
|
|
662
829
|
}
|
|
663
|
-
flags.knownArgs.push(matchingArg);
|
|
664
|
-
flags.knownArgs.push(value);
|
|
665
830
|
}
|
|
666
831
|
};
|
|
667
832
|
/**
|
|
@@ -682,73 +847,34 @@ const parseStringNumberArg = (flags, args, configCaseName) => {
|
|
|
682
847
|
* to a number.
|
|
683
848
|
*/
|
|
684
849
|
const CLI_ARG_STRING_REGEX = /[^\d\.Ee\+\-]+/g;
|
|
850
|
+
const Empty = Symbol('Empty');
|
|
685
851
|
/**
|
|
686
|
-
*
|
|
687
|
-
*
|
|
688
|
-
* the value is correct.
|
|
852
|
+
* A little helper which tries to parse a CLI value (as opposed to a flag) off
|
|
853
|
+
* of the argument array.
|
|
689
854
|
*
|
|
690
|
-
*
|
|
691
|
-
*
|
|
692
|
-
*
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
if (
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
*
|
|
711
|
-
* - `--my-cli-argument value`
|
|
712
|
-
* - `--my-cli-argument=value`
|
|
713
|
-
* - `--myCliArgument value`
|
|
714
|
-
* - `--myCliArgument=value`
|
|
715
|
-
*
|
|
716
|
-
* We also check for shortened aliases, which we define for a few arguments.
|
|
717
|
-
*
|
|
718
|
-
* @param args the CLI args we're dealing with
|
|
719
|
-
* @param configCaseName the ConfigFlag key which we're looking to pull out a value for
|
|
720
|
-
* @returns the value for the flag as well as the exact string which it matched from
|
|
721
|
-
* the user input.
|
|
722
|
-
*/
|
|
723
|
-
const getValue = (args, configCaseName) => {
|
|
724
|
-
// for some CLI args we have a short alias, like 'c' for 'config'
|
|
725
|
-
const alias = CLI_ARG_ALIASES[configCaseName];
|
|
726
|
-
// we support supplying arguments in both dash-case and configCase
|
|
727
|
-
// for ease of use
|
|
728
|
-
const dashCaseName = toDashCase(configCaseName);
|
|
729
|
-
let value;
|
|
730
|
-
let matchingArg;
|
|
731
|
-
args.forEach((arg, i) => {
|
|
732
|
-
if (arg.startsWith(`--${dashCaseName}=`) || arg.startsWith(`--${configCaseName}=`)) {
|
|
733
|
-
// our argument was passed at the command-line in the format --argName=arg-value
|
|
734
|
-
[matchingArg, value] = parseEqualsArg(arg);
|
|
735
|
-
}
|
|
736
|
-
else if (arg === `--${dashCaseName}` || arg === `--${configCaseName}`) {
|
|
737
|
-
// the next value in the array is assumed to be a value for this argument
|
|
738
|
-
value = args[i + 1];
|
|
739
|
-
matchingArg = arg;
|
|
740
|
-
}
|
|
741
|
-
else if (alias) {
|
|
742
|
-
if (arg.startsWith(`-${alias}=`)) {
|
|
743
|
-
[matchingArg, value] = parseEqualsArg(arg);
|
|
744
|
-
}
|
|
745
|
-
else if (arg === `-${alias}`) {
|
|
746
|
-
value = args[i + 1];
|
|
747
|
-
matchingArg = arg;
|
|
748
|
-
}
|
|
855
|
+
* We support a variety of different argument formats, but all of them start
|
|
856
|
+
* with `-`, so we can check the first character to test whether the next token
|
|
857
|
+
* in our array of CLI arguments is a flag name or a value.
|
|
858
|
+
*
|
|
859
|
+
* @param args an array of CLI args
|
|
860
|
+
* @returns either a string result or an Empty sentinel
|
|
861
|
+
*/
|
|
862
|
+
const parseCLIValue = (args) => {
|
|
863
|
+
// it's possible the arguments array is empty, if so, return empty
|
|
864
|
+
if (args[0] === undefined) {
|
|
865
|
+
return Empty;
|
|
866
|
+
}
|
|
867
|
+
// all we're concerned with here is that it does not start with `"-"`,
|
|
868
|
+
// which would indicate it should be parsed as a CLI flag and not a value.
|
|
869
|
+
if (!args[0].startsWith('-')) {
|
|
870
|
+
// It's not a flag, so we return the value and defer any specific parsing
|
|
871
|
+
// until later on.
|
|
872
|
+
const value = args.shift();
|
|
873
|
+
if (typeof value === 'string') {
|
|
874
|
+
return value;
|
|
749
875
|
}
|
|
750
|
-
}
|
|
751
|
-
return
|
|
876
|
+
}
|
|
877
|
+
return Empty;
|
|
752
878
|
};
|
|
753
879
|
/**
|
|
754
880
|
* Parse an 'equals' argument, which is a CLI argument-value pair in the
|
|
@@ -784,8 +910,9 @@ const getValue = (args, configCaseName) => {
|
|
|
784
910
|
* @returns a tuple containing the arg name and the value (if present)
|
|
785
911
|
*/
|
|
786
912
|
const parseEqualsArg = (arg) => {
|
|
787
|
-
const [originalArg, ...
|
|
788
|
-
|
|
913
|
+
const [originalArg, ...splitSections] = arg.split('=');
|
|
914
|
+
const value = splitSections.join('=');
|
|
915
|
+
return [originalArg, value === '' ? Empty : value];
|
|
789
916
|
};
|
|
790
917
|
/**
|
|
791
918
|
* Small helper for getting type-system-level assurance that a `string` can be
|
|
@@ -794,18 +921,51 @@ const parseEqualsArg = (arg) => {
|
|
|
794
921
|
* @param maybeLogLevel the string to check
|
|
795
922
|
* @returns whether this is a `LogLevel`
|
|
796
923
|
*/
|
|
797
|
-
const isLogLevel = (maybeLogLevel) =>
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
924
|
+
const isLogLevel = (maybeLogLevel) => readOnlyArrayHasStringMember(LOG_LEVELS, maybeLogLevel);
|
|
925
|
+
/**
|
|
926
|
+
* A little helper for constructing and throwing an error message with info
|
|
927
|
+
* about what went wrong
|
|
928
|
+
*
|
|
929
|
+
* @param flag the flag which encountered the error
|
|
930
|
+
* @param message a message specific to the error which was encountered
|
|
931
|
+
*/
|
|
932
|
+
const throwCLIParsingError = (flag, message) => {
|
|
933
|
+
throw new Error(`when parsing CLI flag "${flag}": ${message}`);
|
|
934
|
+
};
|
|
935
|
+
/**
|
|
936
|
+
* Throw a specific error for the situation where we ran into an issue parsing
|
|
937
|
+
* a number.
|
|
938
|
+
*
|
|
939
|
+
* @param flag the flag for which we encountered the issue
|
|
940
|
+
* @param value what we were trying to parse
|
|
941
|
+
*/
|
|
942
|
+
const throwNumberParsingError = (flag, value) => {
|
|
943
|
+
throwCLIParsingError(flag, `expected a number but received "${value}"`);
|
|
944
|
+
};
|
|
945
|
+
/**
|
|
946
|
+
* A little helper to 'dereference' a flag alias, which if you squint a little
|
|
947
|
+
* you can think of like a pointer to a full flag name. Thus 'c' is like a
|
|
948
|
+
* pointer to 'config', so here we're doing something like `*c`. Of course, this
|
|
949
|
+
* being JS, this is just a metaphor!
|
|
950
|
+
*
|
|
951
|
+
* If no 'dereference' is found for the possible alias we just return the
|
|
952
|
+
* passed string unmodified.
|
|
953
|
+
*
|
|
954
|
+
* @param maybeAlias a string which _could_ be an alias to a full flag name
|
|
955
|
+
* @returns the full aliased flag name, if found, or the passed string if not
|
|
956
|
+
*/
|
|
957
|
+
const dereferenceAlias = (maybeAlias) => {
|
|
958
|
+
const possibleDereference = CLI_FLAG_ALIASES[maybeAlias];
|
|
959
|
+
if (typeof possibleDereference === 'string') {
|
|
960
|
+
return possibleDereference;
|
|
961
|
+
}
|
|
962
|
+
return maybeAlias;
|
|
963
|
+
};
|
|
804
964
|
|
|
805
965
|
const dependencies = [
|
|
806
966
|
{
|
|
807
967
|
name: "@rindo/core",
|
|
808
|
-
version: "2.
|
|
968
|
+
version: "2.22.2",
|
|
809
969
|
main: "compiler/rindo.js",
|
|
810
970
|
resources: [
|
|
811
971
|
"package.json",
|
|
@@ -842,13 +1002,16 @@ const dependencies = [
|
|
|
842
1002
|
"compiler/lib.es2019.array.d.ts",
|
|
843
1003
|
"compiler/lib.es2019.d.ts",
|
|
844
1004
|
"compiler/lib.es2019.full.d.ts",
|
|
1005
|
+
"compiler/lib.es2019.intl.d.ts",
|
|
845
1006
|
"compiler/lib.es2019.object.d.ts",
|
|
846
1007
|
"compiler/lib.es2019.string.d.ts",
|
|
847
1008
|
"compiler/lib.es2019.symbol.d.ts",
|
|
848
1009
|
"compiler/lib.es2020.bigint.d.ts",
|
|
849
1010
|
"compiler/lib.es2020.d.ts",
|
|
1011
|
+
"compiler/lib.es2020.date.d.ts",
|
|
850
1012
|
"compiler/lib.es2020.full.d.ts",
|
|
851
1013
|
"compiler/lib.es2020.intl.d.ts",
|
|
1014
|
+
"compiler/lib.es2020.number.d.ts",
|
|
852
1015
|
"compiler/lib.es2020.promise.d.ts",
|
|
853
1016
|
"compiler/lib.es2020.sharedmemory.d.ts",
|
|
854
1017
|
"compiler/lib.es2020.string.d.ts",
|
|
@@ -859,6 +1022,14 @@ const dependencies = [
|
|
|
859
1022
|
"compiler/lib.es2021.promise.d.ts",
|
|
860
1023
|
"compiler/lib.es2021.string.d.ts",
|
|
861
1024
|
"compiler/lib.es2021.weakref.d.ts",
|
|
1025
|
+
"compiler/lib.es2022.array.d.ts",
|
|
1026
|
+
"compiler/lib.es2022.d.ts",
|
|
1027
|
+
"compiler/lib.es2022.error.d.ts",
|
|
1028
|
+
"compiler/lib.es2022.full.d.ts",
|
|
1029
|
+
"compiler/lib.es2022.intl.d.ts",
|
|
1030
|
+
"compiler/lib.es2022.object.d.ts",
|
|
1031
|
+
"compiler/lib.es2022.sharedmemory.d.ts",
|
|
1032
|
+
"compiler/lib.es2022.string.d.ts",
|
|
862
1033
|
"compiler/lib.es5.d.ts",
|
|
863
1034
|
"compiler/lib.es6.d.ts",
|
|
864
1035
|
"compiler/lib.esnext.d.ts",
|
|
@@ -903,16 +1074,112 @@ const dependencies = [
|
|
|
903
1074
|
},
|
|
904
1075
|
{
|
|
905
1076
|
name: "terser",
|
|
906
|
-
version: "5.
|
|
1077
|
+
version: "5.16.1",
|
|
907
1078
|
main: "dist/bundle.min.js"
|
|
908
1079
|
},
|
|
909
1080
|
{
|
|
910
1081
|
name: "typescript",
|
|
911
|
-
version: "4.
|
|
1082
|
+
version: "4.9.4",
|
|
912
1083
|
main: "lib/typescript.js"
|
|
913
1084
|
}
|
|
914
1085
|
];
|
|
915
1086
|
|
|
1087
|
+
const IS_NODE_ENV = typeof global !== 'undefined' &&
|
|
1088
|
+
typeof require === 'function' &&
|
|
1089
|
+
!!global.process &&
|
|
1090
|
+
typeof __filename === 'string' &&
|
|
1091
|
+
(!global.origin || typeof global.origin !== 'string');
|
|
1092
|
+
const IS_BROWSER_ENV = typeof location !== 'undefined' && typeof navigator !== 'undefined' && typeof XMLHttpRequest !== 'undefined';
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* Creates an instance of a logger
|
|
1096
|
+
* @returns the new logger instance
|
|
1097
|
+
*/
|
|
1098
|
+
const createLogger = () => {
|
|
1099
|
+
let useColors = IS_BROWSER_ENV;
|
|
1100
|
+
let level = 'info';
|
|
1101
|
+
return {
|
|
1102
|
+
enableColors: (uc) => (useColors = uc),
|
|
1103
|
+
getLevel: () => level,
|
|
1104
|
+
setLevel: (l) => (level = l),
|
|
1105
|
+
emoji: (e) => e,
|
|
1106
|
+
info: console.log.bind(console),
|
|
1107
|
+
warn: console.warn.bind(console),
|
|
1108
|
+
error: console.error.bind(console),
|
|
1109
|
+
debug: console.debug.bind(console),
|
|
1110
|
+
red: (msg) => msg,
|
|
1111
|
+
green: (msg) => msg,
|
|
1112
|
+
yellow: (msg) => msg,
|
|
1113
|
+
blue: (msg) => msg,
|
|
1114
|
+
magenta: (msg) => msg,
|
|
1115
|
+
cyan: (msg) => msg,
|
|
1116
|
+
gray: (msg) => msg,
|
|
1117
|
+
bold: (msg) => msg,
|
|
1118
|
+
dim: (msg) => msg,
|
|
1119
|
+
bgRed: (msg) => msg,
|
|
1120
|
+
createTimeSpan: (_startMsg, _debug = false) => ({
|
|
1121
|
+
duration: () => 0,
|
|
1122
|
+
finish: () => 0,
|
|
1123
|
+
}),
|
|
1124
|
+
printDiagnostics(diagnostics) {
|
|
1125
|
+
diagnostics.forEach((diagnostic) => logDiagnostic(diagnostic, useColors));
|
|
1126
|
+
},
|
|
1127
|
+
};
|
|
1128
|
+
};
|
|
1129
|
+
const logDiagnostic = (diagnostic, useColors) => {
|
|
1130
|
+
let color = BLUE;
|
|
1131
|
+
let prefix = 'Build';
|
|
1132
|
+
let msg = '';
|
|
1133
|
+
if (diagnostic.level === 'error') {
|
|
1134
|
+
color = RED;
|
|
1135
|
+
prefix = 'Error';
|
|
1136
|
+
}
|
|
1137
|
+
else if (diagnostic.level === 'warn') {
|
|
1138
|
+
color = YELLOW;
|
|
1139
|
+
prefix = 'Warning';
|
|
1140
|
+
}
|
|
1141
|
+
if (diagnostic.header) {
|
|
1142
|
+
prefix = diagnostic.header;
|
|
1143
|
+
}
|
|
1144
|
+
const filePath = diagnostic.relFilePath || diagnostic.absFilePath;
|
|
1145
|
+
if (filePath) {
|
|
1146
|
+
msg += filePath;
|
|
1147
|
+
if (typeof diagnostic.lineNumber === 'number' && diagnostic.lineNumber > 0) {
|
|
1148
|
+
msg += ', line ' + diagnostic.lineNumber;
|
|
1149
|
+
if (typeof diagnostic.columnNumber === 'number' && diagnostic.columnNumber > 0) {
|
|
1150
|
+
msg += ', column ' + diagnostic.columnNumber;
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
msg += '\n';
|
|
1154
|
+
}
|
|
1155
|
+
msg += diagnostic.messageText;
|
|
1156
|
+
if (diagnostic.lines && diagnostic.lines.length > 0) {
|
|
1157
|
+
diagnostic.lines.forEach((l) => {
|
|
1158
|
+
msg += '\n' + l.lineNumber + ': ' + l.text;
|
|
1159
|
+
});
|
|
1160
|
+
msg += '\n';
|
|
1161
|
+
}
|
|
1162
|
+
if (useColors) {
|
|
1163
|
+
const styledPrefix = [
|
|
1164
|
+
'%c' + prefix,
|
|
1165
|
+
`background: ${color}; color: white; padding: 2px 3px; border-radius: 2px; font-size: 0.8em;`,
|
|
1166
|
+
];
|
|
1167
|
+
console.log(...styledPrefix, msg);
|
|
1168
|
+
}
|
|
1169
|
+
else if (diagnostic.level === 'error') {
|
|
1170
|
+
console.error(msg);
|
|
1171
|
+
}
|
|
1172
|
+
else if (diagnostic.level === 'warn') {
|
|
1173
|
+
console.warn(msg);
|
|
1174
|
+
}
|
|
1175
|
+
else {
|
|
1176
|
+
console.log(msg);
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
const YELLOW = `#f39c12`;
|
|
1180
|
+
const RED = `#c0392b`;
|
|
1181
|
+
const BLUE = `#3498db`;
|
|
1182
|
+
|
|
916
1183
|
/**
|
|
917
1184
|
* Attempt to find a Rindo configuration file on the file system
|
|
918
1185
|
* @param opts the options needed to find the configuration file
|
|
@@ -921,11 +1188,7 @@ const dependencies = [
|
|
|
921
1188
|
const findConfig = async (opts) => {
|
|
922
1189
|
const sys = opts.sys;
|
|
923
1190
|
const cwd = sys.getCurrentDirectory();
|
|
924
|
-
const
|
|
925
|
-
configPath: null,
|
|
926
|
-
rootDir: normalizePath(cwd),
|
|
927
|
-
diagnostics: [],
|
|
928
|
-
};
|
|
1191
|
+
const rootDir = normalizePath(cwd);
|
|
929
1192
|
let configPath = opts.configPath;
|
|
930
1193
|
if (isString(configPath)) {
|
|
931
1194
|
if (!sys.platformPath.isAbsolute(configPath)) {
|
|
@@ -940,8 +1203,13 @@ const findConfig = async (opts) => {
|
|
|
940
1203
|
}
|
|
941
1204
|
else {
|
|
942
1205
|
// nothing was passed in, use the current working directory
|
|
943
|
-
configPath =
|
|
1206
|
+
configPath = rootDir;
|
|
944
1207
|
}
|
|
1208
|
+
const results = {
|
|
1209
|
+
configPath,
|
|
1210
|
+
rootDir: normalizePath(cwd),
|
|
1211
|
+
diagnostics: [],
|
|
1212
|
+
};
|
|
945
1213
|
const stat = await sys.stat(configPath);
|
|
946
1214
|
if (stat.error) {
|
|
947
1215
|
const diagnostic = buildError(results.diagnostics);
|
|
@@ -974,12 +1242,33 @@ const loadCoreCompiler = async (sys) => {
|
|
|
974
1242
|
return globalThis.rindo;
|
|
975
1243
|
};
|
|
976
1244
|
|
|
1245
|
+
/**
|
|
1246
|
+
* Log the name of this package (`@rindo/core`) to an output stream
|
|
1247
|
+
*
|
|
1248
|
+
* The output stream is determined by the {@link Logger} instance that is provided as an argument to this function
|
|
1249
|
+
*
|
|
1250
|
+
* The name of the package may not be logged, by design, for certain `task` types and logging levels
|
|
1251
|
+
*
|
|
1252
|
+
* @param logger the logging entity to use to output the name of the package
|
|
1253
|
+
* @param task the current task
|
|
1254
|
+
*/
|
|
977
1255
|
const startupLog = (logger, task) => {
|
|
978
1256
|
if (task === 'info' || task === 'serve' || task === 'version') {
|
|
979
1257
|
return;
|
|
980
1258
|
}
|
|
981
1259
|
logger.info(logger.cyan(`@rindo/core`));
|
|
982
1260
|
};
|
|
1261
|
+
/**
|
|
1262
|
+
* Log this package's version to an output stream
|
|
1263
|
+
*
|
|
1264
|
+
* The output stream is determined by the {@link Logger} instance that is provided as an argument to this function
|
|
1265
|
+
*
|
|
1266
|
+
* The package version may not be logged, by design, for certain `task` types and logging levels
|
|
1267
|
+
*
|
|
1268
|
+
* @param logger the logging entity to use for output
|
|
1269
|
+
* @param task the current task
|
|
1270
|
+
* @param coreCompiler the compiler instance to derive version information from
|
|
1271
|
+
*/
|
|
983
1272
|
const startupLogVersion = (logger, task, coreCompiler) => {
|
|
984
1273
|
if (task === 'info' || task === 'serve' || task === 'version') {
|
|
985
1274
|
return;
|
|
@@ -995,11 +1284,25 @@ const startupLogVersion = (logger, task, coreCompiler) => {
|
|
|
995
1284
|
startupMsg += logger.emoji(' ' + coreCompiler.vermoji);
|
|
996
1285
|
logger.info(startupMsg);
|
|
997
1286
|
};
|
|
1287
|
+
/**
|
|
1288
|
+
* Log details from a {@link CompilerSystem} used by Rindo to an output stream
|
|
1289
|
+
*
|
|
1290
|
+
* The output stream is determined by the {@link Logger} instance that is provided as an argument to this function
|
|
1291
|
+
*
|
|
1292
|
+
* @param sys the `CompilerSystem` to report details on
|
|
1293
|
+
* @param logger the logging entity to use for output
|
|
1294
|
+
* @param flags user set flags for the current invocation of Rindo
|
|
1295
|
+
* @param coreCompiler the compiler instance being used for this invocation of Rindo
|
|
1296
|
+
*/
|
|
998
1297
|
const loadedCompilerLog = (sys, logger, flags, coreCompiler) => {
|
|
999
1298
|
const sysDetails = sys.details;
|
|
1000
1299
|
const runtimeInfo = `${sys.name} ${sys.version}`;
|
|
1001
|
-
const platformInfo =
|
|
1002
|
-
|
|
1300
|
+
const platformInfo = sysDetails
|
|
1301
|
+
? `${sysDetails.platform}, ${sysDetails.cpuModel}`
|
|
1302
|
+
: `Unknown Platform, Unknown CPU Model`;
|
|
1303
|
+
const statsInfo = sysDetails
|
|
1304
|
+
? `cpus: ${sys.hardwareConcurrency}, freemem: ${Math.round(sysDetails.freemem() / 1000000)}MB, totalmem: ${Math.round(sysDetails.totalmem / 1000000)}MB`
|
|
1305
|
+
: 'Unknown CPU Core Count, Unknown Memory';
|
|
1003
1306
|
if (logger.getLevel() === 'debug') {
|
|
1004
1307
|
logger.debug(runtimeInfo);
|
|
1005
1308
|
logger.debug(platformInfo);
|
|
@@ -1013,6 +1316,14 @@ const loadedCompilerLog = (sys, logger, flags, coreCompiler) => {
|
|
|
1013
1316
|
logger.info(statsInfo);
|
|
1014
1317
|
}
|
|
1015
1318
|
};
|
|
1319
|
+
/**
|
|
1320
|
+
* Log various warnings to an output stream
|
|
1321
|
+
*
|
|
1322
|
+
* The output stream is determined by the {@link Logger} instance attached to the `config` argument to this function
|
|
1323
|
+
*
|
|
1324
|
+
* @param coreCompiler the compiler instance being used for this invocation of Rindo
|
|
1325
|
+
* @param config a validated configuration object to be used for this run of Rindo
|
|
1326
|
+
*/
|
|
1016
1327
|
const startupCompilerLog = (coreCompiler, config) => {
|
|
1017
1328
|
if (config.suppressLogs === true) {
|
|
1018
1329
|
return;
|
|
@@ -1034,6 +1345,21 @@ const startupCompilerLog = (coreCompiler, config) => {
|
|
|
1034
1345
|
}
|
|
1035
1346
|
};
|
|
1036
1347
|
|
|
1348
|
+
const startCheckVersion = async (config, currentVersion) => {
|
|
1349
|
+
if (config.devMode && !config.flags.ci && !currentVersion.includes('-dev.') && isFunction(config.sys.checkVersion)) {
|
|
1350
|
+
return config.sys.checkVersion(config.logger, currentVersion);
|
|
1351
|
+
}
|
|
1352
|
+
return null;
|
|
1353
|
+
};
|
|
1354
|
+
const printCheckVersionResults = async (versionChecker) => {
|
|
1355
|
+
if (versionChecker) {
|
|
1356
|
+
const checkVersionResults = await versionChecker;
|
|
1357
|
+
if (isFunction(checkVersionResults)) {
|
|
1358
|
+
checkVersionResults();
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
};
|
|
1362
|
+
|
|
1037
1363
|
const taskPrerender = async (coreCompiler, config) => {
|
|
1038
1364
|
startupCompilerLog(coreCompiler, config);
|
|
1039
1365
|
const hydrateAppFilePath = config.flags.unknownArgs[0];
|
|
@@ -1065,21 +1391,6 @@ const runPrerenderTask = async (coreCompiler, config, hydrateAppFilePath, compon
|
|
|
1065
1391
|
return diagnostics;
|
|
1066
1392
|
};
|
|
1067
1393
|
|
|
1068
|
-
const startCheckVersion = async (config, currentVersion) => {
|
|
1069
|
-
if (config.devMode && !config.flags.ci && !currentVersion.includes('-dev.') && isFunction(config.sys.checkVersion)) {
|
|
1070
|
-
return config.sys.checkVersion(config.logger, currentVersion);
|
|
1071
|
-
}
|
|
1072
|
-
return null;
|
|
1073
|
-
};
|
|
1074
|
-
const printCheckVersionResults = async (versionChecker) => {
|
|
1075
|
-
if (versionChecker) {
|
|
1076
|
-
const checkVersionResults = await versionChecker;
|
|
1077
|
-
if (isFunction(checkVersionResults)) {
|
|
1078
|
-
checkVersionResults();
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
};
|
|
1082
|
-
|
|
1083
1394
|
const taskWatch = async (coreCompiler, config) => {
|
|
1084
1395
|
let devServer = null;
|
|
1085
1396
|
let exitCode = 0;
|
|
@@ -1126,6 +1437,15 @@ const taskWatch = async (coreCompiler, config) => {
|
|
|
1126
1437
|
}
|
|
1127
1438
|
};
|
|
1128
1439
|
|
|
1440
|
+
const isOutputTargetHydrate = (o) => o.type === DIST_HYDRATE_SCRIPT;
|
|
1441
|
+
const isOutputTargetDocs = (o) => o.type === DOCS_README || o.type === DOCS_JSON || o.type === DOCS_CUSTOM || o.type === DOCS_VSCODE;
|
|
1442
|
+
const DIST_HYDRATE_SCRIPT = 'dist-hydrate-script';
|
|
1443
|
+
const DOCS_CUSTOM = 'docs-custom';
|
|
1444
|
+
const DOCS_JSON = 'docs-json';
|
|
1445
|
+
const DOCS_README = 'docs-readme';
|
|
1446
|
+
const DOCS_VSCODE = 'docs-vscode';
|
|
1447
|
+
const WWW = 'www';
|
|
1448
|
+
|
|
1129
1449
|
const tryFn = async (fn, ...args) => {
|
|
1130
1450
|
try {
|
|
1131
1451
|
return await fn(...args);
|
|
@@ -1139,12 +1459,12 @@ const isInteractive = (sys, flags, object) => {
|
|
|
1139
1459
|
const terminalInfo = object ||
|
|
1140
1460
|
Object.freeze({
|
|
1141
1461
|
tty: sys.isTTY() ? true : false,
|
|
1142
|
-
ci: ['CI', 'BUILD_ID', 'BUILD_NUMBER', 'BITBUCKET_COMMIT', 'CODEBUILD_BUILD_ARN'].filter((v) => !!sys.getEnvironmentVar(v)).length > 0 || !!flags.ci,
|
|
1462
|
+
ci: ['CI', 'BUILD_ID', 'BUILD_NUMBER', 'BITBUCKET_COMMIT', 'CODEBUILD_BUILD_ARN'].filter((v) => { var _a; return !!((_a = sys.getEnvironmentVar) === null || _a === void 0 ? void 0 : _a.call(sys, v)); }).length > 0 || !!flags.ci,
|
|
1143
1463
|
});
|
|
1144
1464
|
return terminalInfo.tty && !terminalInfo.ci;
|
|
1145
1465
|
};
|
|
1146
1466
|
const UUID_REGEX = new RegExp(/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i);
|
|
1147
|
-
// Plucked from https://github.com/
|
|
1467
|
+
// Plucked from https://github.com/familyjs/jigra/blob/HEAD/cli/src/util/uuid.ts
|
|
1148
1468
|
function uuidv4() {
|
|
1149
1469
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
1150
1470
|
const r = (Math.random() * 16) | 0;
|
|
@@ -1168,7 +1488,7 @@ async function readJson(sys, path) {
|
|
|
1168
1488
|
* @returns true if --debug has been passed, otherwise false
|
|
1169
1489
|
*/
|
|
1170
1490
|
function hasDebug(flags) {
|
|
1171
|
-
return flags.debug;
|
|
1491
|
+
return !!flags.debug;
|
|
1172
1492
|
}
|
|
1173
1493
|
/**
|
|
1174
1494
|
* Does the command have the verbose and debug flags?
|
|
@@ -1176,25 +1496,14 @@ function hasDebug(flags) {
|
|
|
1176
1496
|
* @returns true if both --debug and --verbose have been passed, otherwise false
|
|
1177
1497
|
*/
|
|
1178
1498
|
function hasVerbose(flags) {
|
|
1179
|
-
return flags.verbose && hasDebug(flags);
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
/**
|
|
1183
|
-
* Used to determine if tracking should occur.
|
|
1184
|
-
* @param config The config passed into the Rindo command
|
|
1185
|
-
* @param sys The system where the command is invoked
|
|
1186
|
-
* @param ci whether or not the process is running in a Continuous Integration (CI) environment
|
|
1187
|
-
* @returns true if telemetry should be sent, false otherwise
|
|
1188
|
-
*/
|
|
1189
|
-
async function shouldTrack(config, sys, ci) {
|
|
1190
|
-
return !ci && isInteractive(sys, config.flags) && (await checkTelemetry(sys));
|
|
1499
|
+
return !!flags.verbose && hasDebug(flags);
|
|
1191
1500
|
}
|
|
1192
1501
|
|
|
1193
1502
|
const isTest$1 = () => process.env.JEST_WORKER_ID !== undefined;
|
|
1194
|
-
const defaultConfig = (sys) => sys.resolvePath(`${sys.homeDir()}/.
|
|
1195
|
-
const defaultConfigDirectory = (sys) => sys.resolvePath(`${sys.homeDir()}/.
|
|
1503
|
+
const defaultConfig = (sys) => sys.resolvePath(`${sys.homeDir()}/.family/${isTest$1() ? 'tmp-config.json' : 'config.json'}`);
|
|
1504
|
+
const defaultConfigDirectory = (sys) => sys.resolvePath(`${sys.homeDir()}/.family`);
|
|
1196
1505
|
/**
|
|
1197
|
-
* Reads an
|
|
1506
|
+
* Reads an Family configuration file from disk, parses it, and performs any necessary corrections to it if certain
|
|
1198
1507
|
* values are deemed to be malformed
|
|
1199
1508
|
* @param sys The system where the command is invoked
|
|
1200
1509
|
* @returns the config read from disk that has been potentially been updated
|
|
@@ -1208,7 +1517,7 @@ async function readConfig(sys) {
|
|
|
1208
1517
|
};
|
|
1209
1518
|
await writeConfig(sys, config);
|
|
1210
1519
|
}
|
|
1211
|
-
else if (!UUID_REGEX.test(config['tokens.telemetry'])) {
|
|
1520
|
+
else if (!config['tokens.telemetry'] || !UUID_REGEX.test(config['tokens.telemetry'])) {
|
|
1212
1521
|
const newUuid = uuidv4();
|
|
1213
1522
|
await writeConfig(sys, { ...config, 'tokens.telemetry': newUuid });
|
|
1214
1523
|
config['tokens.telemetry'] = newUuid;
|
|
@@ -1216,7 +1525,7 @@ async function readConfig(sys) {
|
|
|
1216
1525
|
return config;
|
|
1217
1526
|
}
|
|
1218
1527
|
/**
|
|
1219
|
-
* Writes an
|
|
1528
|
+
* Writes an Family configuration file to disk.
|
|
1220
1529
|
* @param sys The system where the command is invoked
|
|
1221
1530
|
* @param config The config passed into the Rindo command
|
|
1222
1531
|
* @returns boolean If the command was successful
|
|
@@ -1234,7 +1543,7 @@ async function writeConfig(sys, config) {
|
|
|
1234
1543
|
return result;
|
|
1235
1544
|
}
|
|
1236
1545
|
/**
|
|
1237
|
-
* Update a subset of the
|
|
1546
|
+
* Update a subset of the Family config.
|
|
1238
1547
|
* @param sys The system where the command is invoked
|
|
1239
1548
|
* @param newOptions The new options to save
|
|
1240
1549
|
* @returns boolean If the command was successful
|
|
@@ -1244,14 +1553,16 @@ async function updateConfig(sys, newOptions) {
|
|
|
1244
1553
|
return await writeConfig(sys, Object.assign(config, newOptions));
|
|
1245
1554
|
}
|
|
1246
1555
|
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1556
|
+
/**
|
|
1557
|
+
* Used to determine if tracking should occur.
|
|
1558
|
+
* @param config The config passed into the Rindo command
|
|
1559
|
+
* @param sys The system where the command is invoked
|
|
1560
|
+
* @param ci whether or not the process is running in a Continuous Integration (CI) environment
|
|
1561
|
+
* @returns true if telemetry should be sent, false otherwise
|
|
1562
|
+
*/
|
|
1563
|
+
async function shouldTrack(config, sys, ci) {
|
|
1564
|
+
return !ci && isInteractive(sys, config.flags) && (await checkTelemetry(sys));
|
|
1565
|
+
}
|
|
1255
1566
|
|
|
1256
1567
|
/**
|
|
1257
1568
|
* Used to within taskBuild to provide the component_count property.
|
|
@@ -1262,11 +1573,11 @@ const WWW = 'www';
|
|
|
1262
1573
|
* @param result The results of a compiler build.
|
|
1263
1574
|
*/
|
|
1264
1575
|
async function telemetryBuildFinishedAction(sys, config, coreCompiler, result) {
|
|
1265
|
-
const tracking = await shouldTrack(config, sys, config.flags.ci);
|
|
1576
|
+
const tracking = await shouldTrack(config, sys, !!config.flags.ci);
|
|
1266
1577
|
if (!tracking) {
|
|
1267
1578
|
return;
|
|
1268
1579
|
}
|
|
1269
|
-
const component_count = Object.keys(result.componentGraph).length;
|
|
1580
|
+
const component_count = result.componentGraph ? Object.keys(result.componentGraph).length : undefined;
|
|
1270
1581
|
const data = await prepareData(coreCompiler, config, sys, result.duration, component_count);
|
|
1271
1582
|
await sendMetric(sys, config, 'rindo_cli_command', data);
|
|
1272
1583
|
config.logger.debug(`${config.logger.blue('Telemetry')}: ${config.logger.gray(JSON.stringify(data))}`);
|
|
@@ -1345,38 +1656,41 @@ function getActiveTargets(config) {
|
|
|
1345
1656
|
* @returns a Promise wrapping data for the telemetry endpoint
|
|
1346
1657
|
*/
|
|
1347
1658
|
const prepareData = async (coreCompiler, config, sys, duration_ms, component_count = undefined) => {
|
|
1659
|
+
var _a, _b, _c;
|
|
1348
1660
|
const { typescript, rollup } = coreCompiler.versions || { typescript: 'unknown', rollup: 'unknown' };
|
|
1349
1661
|
const { packages, packagesNoVersions } = await getInstalledPackages(sys, config);
|
|
1350
1662
|
const targets = getActiveTargets(config);
|
|
1351
1663
|
const yarn = isUsingYarn(sys);
|
|
1352
1664
|
const rindo = coreCompiler.version || 'unknown';
|
|
1353
1665
|
const system = `${sys.name} ${sys.version}`;
|
|
1354
|
-
const os_name = sys.details.platform;
|
|
1355
|
-
const os_version = sys.details.release;
|
|
1356
|
-
const cpu_model = sys.details.cpuModel;
|
|
1666
|
+
const os_name = (_a = sys.details) === null || _a === void 0 ? void 0 : _a.platform;
|
|
1667
|
+
const os_version = (_b = sys.details) === null || _b === void 0 ? void 0 : _b.release;
|
|
1668
|
+
const cpu_model = (_c = sys.details) === null || _c === void 0 ? void 0 : _c.cpuModel;
|
|
1357
1669
|
const build = coreCompiler.buildId || 'unknown';
|
|
1358
1670
|
const has_app_pwa_config = hasAppTarget(config);
|
|
1359
1671
|
const anonymizedConfig = anonymizeConfigForTelemetry(config);
|
|
1672
|
+
const is_browser_env = IS_BROWSER_ENV;
|
|
1360
1673
|
return {
|
|
1361
|
-
|
|
1362
|
-
|
|
1674
|
+
arguments: config.flags.args,
|
|
1675
|
+
build,
|
|
1363
1676
|
component_count,
|
|
1364
|
-
|
|
1677
|
+
config: anonymizedConfig,
|
|
1678
|
+
cpu_model,
|
|
1679
|
+
duration_ms,
|
|
1680
|
+
has_app_pwa_config,
|
|
1681
|
+
is_browser_env,
|
|
1682
|
+
os_name,
|
|
1683
|
+
os_version,
|
|
1365
1684
|
packages,
|
|
1366
1685
|
packages_no_versions: packagesNoVersions,
|
|
1367
|
-
|
|
1368
|
-
task: config.flags.task,
|
|
1686
|
+
rollup,
|
|
1369
1687
|
rindo,
|
|
1370
1688
|
system,
|
|
1371
1689
|
system_major: getMajorVersion(system),
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
cpu_model,
|
|
1375
|
-
build,
|
|
1690
|
+
targets,
|
|
1691
|
+
task: config.flags.task,
|
|
1376
1692
|
typescript,
|
|
1377
|
-
|
|
1378
|
-
has_app_pwa_config,
|
|
1379
|
-
config: anonymizedConfig,
|
|
1693
|
+
yarn,
|
|
1380
1694
|
};
|
|
1381
1695
|
};
|
|
1382
1696
|
// props in output targets for which we retain their original values when
|
|
@@ -1400,7 +1714,16 @@ const CONFIG_PROPS_TO_ANONYMIZE = [
|
|
|
1400
1714
|
// Props we delete entirely from the config for telemetry
|
|
1401
1715
|
//
|
|
1402
1716
|
// TODO: Investigate improving anonymization for tsCompilerOptions and devServer
|
|
1403
|
-
const CONFIG_PROPS_TO_DELETE = [
|
|
1717
|
+
const CONFIG_PROPS_TO_DELETE = [
|
|
1718
|
+
'commonjs',
|
|
1719
|
+
'devServer',
|
|
1720
|
+
'env',
|
|
1721
|
+
'logger',
|
|
1722
|
+
'rollupConfig',
|
|
1723
|
+
'sys',
|
|
1724
|
+
'testing',
|
|
1725
|
+
'tsCompilerOptions',
|
|
1726
|
+
];
|
|
1404
1727
|
/**
|
|
1405
1728
|
* Anonymize the config for telemetry, replacing potentially revealing config props
|
|
1406
1729
|
* with a placeholder string if they are present (this lets us still track how frequently
|
|
@@ -1450,7 +1773,7 @@ const anonymizeConfigForTelemetry = (config) => {
|
|
|
1450
1773
|
/**
|
|
1451
1774
|
* Reads package-lock.json, yarn.lock, and package.json files in order to cross-reference
|
|
1452
1775
|
* the dependencies and devDependencies properties. Pulls up the current installed version
|
|
1453
|
-
* of each package under the @rindo, @
|
|
1776
|
+
* of each package under the @rindo, @familyjs, and @jigra scopes.
|
|
1454
1777
|
*
|
|
1455
1778
|
* @param sys the system instance where telemetry is invoked
|
|
1456
1779
|
* @param config the Rindo configuration associated with the current task that triggered telemetry
|
|
@@ -1472,16 +1795,16 @@ async function getInstalledPackages(sys, config) {
|
|
|
1472
1795
|
...packageJson.devDependencies,
|
|
1473
1796
|
...packageJson.dependencies,
|
|
1474
1797
|
});
|
|
1475
|
-
// Collect packages only in the rindo,
|
|
1798
|
+
// Collect packages only in the rindo, familyjs, or jigra org's:
|
|
1476
1799
|
// https://www.npmjs.com/org/rindo
|
|
1477
|
-
const
|
|
1800
|
+
const familyPackages = rawPackages.filter(([k]) => k.startsWith('@rindo/') || k.startsWith('@familyjs/') || k.startsWith('@jigra/'));
|
|
1478
1801
|
try {
|
|
1479
|
-
packages = yarn ? await yarnPackages(sys,
|
|
1802
|
+
packages = yarn ? await yarnPackages(sys, familyPackages) : await npmPackages(sys, familyPackages);
|
|
1480
1803
|
}
|
|
1481
1804
|
catch (e) {
|
|
1482
|
-
packages =
|
|
1805
|
+
packages = familyPackages.map(([k, v]) => `${k}@${v.replace('^', '')}`);
|
|
1483
1806
|
}
|
|
1484
|
-
packagesNoVersions =
|
|
1807
|
+
packagesNoVersions = familyPackages.map(([k]) => `${k}`);
|
|
1485
1808
|
return { packages, packagesNoVersions };
|
|
1486
1809
|
}
|
|
1487
1810
|
catch (err) {
|
|
@@ -1492,13 +1815,13 @@ async function getInstalledPackages(sys, config) {
|
|
|
1492
1815
|
/**
|
|
1493
1816
|
* Visits the npm lock file to find the exact versions that are installed
|
|
1494
1817
|
* @param sys The system where the command is invoked
|
|
1495
|
-
* @param
|
|
1818
|
+
* @param familyPackages a list of the found packages matching `@rindo`, `@jigra`, or `@familyjs` from the package.json file.
|
|
1496
1819
|
* @returns an array of strings of all the packages and their versions.
|
|
1497
1820
|
*/
|
|
1498
|
-
async function npmPackages(sys,
|
|
1821
|
+
async function npmPackages(sys, familyPackages) {
|
|
1499
1822
|
const appRootDir = sys.getCurrentDirectory();
|
|
1500
1823
|
const packageLockJson = await tryFn(readJson, sys, sys.resolvePath(appRootDir + '/package-lock.json'));
|
|
1501
|
-
return
|
|
1824
|
+
return familyPackages.map(([k, v]) => {
|
|
1502
1825
|
var _a, _b, _c, _d;
|
|
1503
1826
|
let version = (_d = (_b = (_a = packageLockJson === null || packageLockJson === void 0 ? void 0 : packageLockJson.dependencies[k]) === null || _a === void 0 ? void 0 : _a.version) !== null && _b !== void 0 ? _b : (_c = packageLockJson === null || packageLockJson === void 0 ? void 0 : packageLockJson.devDependencies[k]) === null || _c === void 0 ? void 0 : _c.version) !== null && _d !== void 0 ? _d : v;
|
|
1504
1827
|
version = version.includes('file:') ? sanitizeDeclaredVersion(v) : version;
|
|
@@ -1508,14 +1831,14 @@ async function npmPackages(sys, navifyPackages) {
|
|
|
1508
1831
|
/**
|
|
1509
1832
|
* Visits the yarn lock file to find the exact versions that are installed
|
|
1510
1833
|
* @param sys The system where the command is invoked
|
|
1511
|
-
* @param
|
|
1834
|
+
* @param familyPackages a list of the found packages matching `@rindo`, `@jigra`, or `@familyjs` from the package.json file.
|
|
1512
1835
|
* @returns an array of strings of all the packages and their versions.
|
|
1513
1836
|
*/
|
|
1514
|
-
async function yarnPackages(sys,
|
|
1837
|
+
async function yarnPackages(sys, familyPackages) {
|
|
1515
1838
|
const appRootDir = sys.getCurrentDirectory();
|
|
1516
1839
|
const yarnLock = sys.readFileSync(sys.resolvePath(appRootDir + '/yarn.lock'));
|
|
1517
1840
|
const yarnLockYml = sys.parseYarnLockFile(yarnLock);
|
|
1518
|
-
return
|
|
1841
|
+
return familyPackages.map(([k, v]) => {
|
|
1519
1842
|
var _a;
|
|
1520
1843
|
const identifiedVersion = `${k}@${v}`;
|
|
1521
1844
|
let version = (_a = yarnLockYml.object[identifiedVersion]) === null || _a === void 0 ? void 0 : _a.version;
|
|
@@ -1580,7 +1903,7 @@ async function sendTelemetry(sys, config, data) {
|
|
|
1580
1903
|
sent_at: now,
|
|
1581
1904
|
};
|
|
1582
1905
|
// This request is only made if telemetry is on.
|
|
1583
|
-
const response = await sys.fetch('https://api
|
|
1906
|
+
const response = await sys.fetch('https://familyjs-api.web.app/events/metrics', {
|
|
1584
1907
|
method: 'POST',
|
|
1585
1908
|
headers: {
|
|
1586
1909
|
'Content-Type': 'application/json',
|
|
@@ -1683,13 +2006,6 @@ const taskDocs = async (coreCompiler, config) => {
|
|
|
1683
2006
|
await compiler.destroy();
|
|
1684
2007
|
};
|
|
1685
2008
|
|
|
1686
|
-
const IS_NODE_ENV = typeof global !== 'undefined' &&
|
|
1687
|
-
typeof require === 'function' &&
|
|
1688
|
-
!!global.process &&
|
|
1689
|
-
typeof __filename === 'string' &&
|
|
1690
|
-
(!global.origin || typeof global.origin !== 'string');
|
|
1691
|
-
const IS_BROWSER_ENV = typeof location !== 'undefined' && typeof navigator !== 'undefined' && typeof XMLHttpRequest !== 'undefined';
|
|
1692
|
-
|
|
1693
2009
|
/**
|
|
1694
2010
|
* Task to generate component boilerplate and write it to disk. This task can
|
|
1695
2011
|
* cause the program to exit with an error under various circumstances, such as
|
|
@@ -1718,13 +2034,24 @@ const taskGenerate = async (coreCompiler, config) => {
|
|
|
1718
2034
|
const { prompt } = await import('../sys/node/prompts.js');
|
|
1719
2035
|
const input = config.flags.unknownArgs.find((arg) => !arg.startsWith('-')) ||
|
|
1720
2036
|
(await prompt({ name: 'tagName', type: 'text', message: 'Component tag name (dash-case):' })).tagName;
|
|
2037
|
+
if (undefined === input) {
|
|
2038
|
+
// in some shells (e.g. Windows PowerShell), hitting Ctrl+C results in a TypeError printed to the console.
|
|
2039
|
+
// explicitly return here to avoid printing the error message.
|
|
2040
|
+
return;
|
|
2041
|
+
}
|
|
1721
2042
|
const { dir, base: componentName } = path.parse(input);
|
|
1722
2043
|
const tagError = validateComponentTag(componentName);
|
|
1723
2044
|
if (tagError) {
|
|
1724
2045
|
config.logger.error(tagError);
|
|
1725
2046
|
return config.sys.exit(1);
|
|
1726
2047
|
}
|
|
1727
|
-
const
|
|
2048
|
+
const filesToGenerateExt = await chooseFilesToGenerate();
|
|
2049
|
+
if (undefined === filesToGenerateExt) {
|
|
2050
|
+
// in some shells (e.g. Windows PowerShell), hitting Ctrl+C results in a TypeError printed to the console.
|
|
2051
|
+
// explicitly return here to avoid printing the error message.
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
const extensionsToGenerate = ['tsx', ...filesToGenerateExt];
|
|
1728
2055
|
const testFolder = extensionsToGenerate.some(isTest) ? 'test' : '';
|
|
1729
2056
|
const outDir = path.join(absoluteSrcDir, 'components', dir, componentName);
|
|
1730
2057
|
await config.sys.createDir(path.join(outDir, testFolder), { recursive: true });
|
|
@@ -1948,7 +2275,7 @@ const taskTelemetry = async (flags, sys, logger) => {
|
|
|
1948
2275
|
const prompt = logger.dim(sys.details.platform === 'windows' ? '>' : '$');
|
|
1949
2276
|
const isEnabling = flags.args.includes('on');
|
|
1950
2277
|
const isDisabling = flags.args.includes('off');
|
|
1951
|
-
const INFORMATION = `Opt in or
|
|
2278
|
+
const INFORMATION = `Opt in or out of telemetry. Information about the data we collect is available on our website: ${logger.bold('https://rindojs.web.app/telemetry')}`;
|
|
1952
2279
|
const THANK_YOU = `Thank you for helping to make Rindo better! 💖`;
|
|
1953
2280
|
const ENABLED_MESSAGE = `${logger.green('Enabled')}. ${THANK_YOU}\n\n`;
|
|
1954
2281
|
const DISABLED_MESSAGE = `${logger.red('Disabled')}\n\n`;
|
|
@@ -2071,93 +2398,54 @@ const taskServe = async (config) => {
|
|
|
2071
2398
|
};
|
|
2072
2399
|
|
|
2073
2400
|
/**
|
|
2074
|
-
*
|
|
2075
|
-
* @
|
|
2401
|
+
* Entrypoint for any Rindo tests
|
|
2402
|
+
* @param config a validated Rindo configuration entity
|
|
2076
2403
|
*/
|
|
2077
|
-
const
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
enableColors: (uc) => (useColors = uc),
|
|
2082
|
-
getLevel: () => level,
|
|
2083
|
-
setLevel: (l) => (level = l),
|
|
2084
|
-
emoji: (e) => e,
|
|
2085
|
-
info: console.log.bind(console),
|
|
2086
|
-
warn: console.warn.bind(console),
|
|
2087
|
-
error: console.error.bind(console),
|
|
2088
|
-
debug: console.debug.bind(console),
|
|
2089
|
-
red: (msg) => msg,
|
|
2090
|
-
green: (msg) => msg,
|
|
2091
|
-
yellow: (msg) => msg,
|
|
2092
|
-
blue: (msg) => msg,
|
|
2093
|
-
magenta: (msg) => msg,
|
|
2094
|
-
cyan: (msg) => msg,
|
|
2095
|
-
gray: (msg) => msg,
|
|
2096
|
-
bold: (msg) => msg,
|
|
2097
|
-
dim: (msg) => msg,
|
|
2098
|
-
bgRed: (msg) => msg,
|
|
2099
|
-
createTimeSpan: (_startMsg, _debug = false) => ({
|
|
2100
|
-
duration: () => 0,
|
|
2101
|
-
finish: () => 0,
|
|
2102
|
-
}),
|
|
2103
|
-
printDiagnostics(diagnostics) {
|
|
2104
|
-
diagnostics.forEach((diagnostic) => logDiagnostic(diagnostic, useColors));
|
|
2105
|
-
},
|
|
2106
|
-
};
|
|
2107
|
-
};
|
|
2108
|
-
const logDiagnostic = (diagnostic, useColors) => {
|
|
2109
|
-
let color = BLUE;
|
|
2110
|
-
let prefix = 'Build';
|
|
2111
|
-
let msg = '';
|
|
2112
|
-
if (diagnostic.level === 'error') {
|
|
2113
|
-
color = RED;
|
|
2114
|
-
prefix = 'Error';
|
|
2115
|
-
}
|
|
2116
|
-
else if (diagnostic.level === 'warn') {
|
|
2117
|
-
color = YELLOW;
|
|
2118
|
-
prefix = 'Warning';
|
|
2119
|
-
}
|
|
2120
|
-
if (diagnostic.header) {
|
|
2121
|
-
prefix = diagnostic.header;
|
|
2404
|
+
const taskTest = async (config) => {
|
|
2405
|
+
if (!IS_NODE_ENV) {
|
|
2406
|
+
config.logger.error(`"test" command is currently only implemented for a NodeJS environment`);
|
|
2407
|
+
return config.sys.exit(1);
|
|
2122
2408
|
}
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2409
|
+
config.buildDocs = false;
|
|
2410
|
+
const testingRunOpts = {
|
|
2411
|
+
e2e: !!config.flags.e2e,
|
|
2412
|
+
screenshot: !!config.flags.screenshot,
|
|
2413
|
+
spec: !!config.flags.spec,
|
|
2414
|
+
updateScreenshot: !!config.flags.updateScreenshot,
|
|
2415
|
+
};
|
|
2416
|
+
// always ensure we have jest modules installed
|
|
2417
|
+
const ensureModuleIds = ['@types/jest', 'jest', 'jest-cli'];
|
|
2418
|
+
if (testingRunOpts.e2e) {
|
|
2419
|
+
// if it's an e2e test, also make sure we're got
|
|
2420
|
+
// puppeteer modules installed and if browserExecutablePath is provided don't download Chromium use only puppeteer-core instead
|
|
2421
|
+
const puppeteer = config.testing.browserExecutablePath ? 'puppeteer-core' : 'puppeteer';
|
|
2422
|
+
ensureModuleIds.push(puppeteer);
|
|
2423
|
+
if (testingRunOpts.screenshot) {
|
|
2424
|
+
// ensure we've got pixelmatch for screenshots
|
|
2425
|
+
config.logger.warn(config.logger.yellow(`EXPERIMENTAL: screenshot visual diff testing is currently under heavy development and has not reached a stable status. However, any assistance testing would be appreciated.`));
|
|
2131
2426
|
}
|
|
2132
|
-
msg += '\n';
|
|
2133
|
-
}
|
|
2134
|
-
msg += diagnostic.messageText;
|
|
2135
|
-
if (diagnostic.lines && diagnostic.lines.length > 0) {
|
|
2136
|
-
diagnostic.lines.forEach((l) => {
|
|
2137
|
-
msg += '\n' + l.lineNumber + ': ' + l.text;
|
|
2138
|
-
});
|
|
2139
|
-
msg += '\n';
|
|
2140
2427
|
}
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
console.log(...styledPrefix, msg);
|
|
2147
|
-
}
|
|
2148
|
-
else if (diagnostic.level === 'error') {
|
|
2149
|
-
console.error(msg);
|
|
2428
|
+
// ensure we've got the required modules installed
|
|
2429
|
+
const diagnostics = await config.sys.lazyRequire.ensure(config.rootDir, ensureModuleIds);
|
|
2430
|
+
if (diagnostics.length > 0) {
|
|
2431
|
+
config.logger.printDiagnostics(diagnostics);
|
|
2432
|
+
return config.sys.exit(1);
|
|
2150
2433
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2434
|
+
try {
|
|
2435
|
+
// let's test!
|
|
2436
|
+
const { createTesting } = await import('../testing/index.js');
|
|
2437
|
+
const testing = await createTesting(config);
|
|
2438
|
+
const passed = await testing.run(testingRunOpts);
|
|
2439
|
+
await testing.destroy();
|
|
2440
|
+
if (!passed) {
|
|
2441
|
+
return config.sys.exit(1);
|
|
2442
|
+
}
|
|
2153
2443
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2444
|
+
catch (e) {
|
|
2445
|
+
config.logger.error(e);
|
|
2446
|
+
return config.sys.exit(1);
|
|
2156
2447
|
}
|
|
2157
|
-
};
|
|
2158
|
-
const YELLOW = `#f39c12`;
|
|
2159
|
-
const RED = `#c0392b`;
|
|
2160
|
-
const BLUE = `#3498db`;
|
|
2448
|
+
};
|
|
2161
2449
|
|
|
2162
2450
|
const run = async (init) => {
|
|
2163
2451
|
const { args, logger, sys } = init;
|
|
@@ -2173,7 +2461,7 @@ const run = async (init) => {
|
|
|
2173
2461
|
if (isFunction(sys.applyGlobalPatch)) {
|
|
2174
2462
|
sys.applyGlobalPatch(sys.getCurrentDirectory());
|
|
2175
2463
|
}
|
|
2176
|
-
if (task === 'help' || flags.help) {
|
|
2464
|
+
if (!task || task === 'help' || flags.help) {
|
|
2177
2465
|
await taskHelp(createConfigFlags({ task: 'help', args }), logger, sys);
|
|
2178
2466
|
return;
|
|
2179
2467
|
}
|
|
@@ -2242,15 +2530,16 @@ const run = async (init) => {
|
|
|
2242
2530
|
* @public
|
|
2243
2531
|
*/
|
|
2244
2532
|
const runTask = async (coreCompiler, config, task, sys) => {
|
|
2245
|
-
var _a, _b, _c, _d, _e;
|
|
2533
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2246
2534
|
const logger = (_a = config.logger) !== null && _a !== void 0 ? _a : createLogger();
|
|
2247
2535
|
const strictConfig = {
|
|
2248
2536
|
...config,
|
|
2249
2537
|
flags: createConfigFlags((_b = config.flags) !== null && _b !== void 0 ? _b : { task }),
|
|
2250
2538
|
logger,
|
|
2251
2539
|
outputTargets: (_c = config.outputTargets) !== null && _c !== void 0 ? _c : [],
|
|
2252
|
-
|
|
2253
|
-
|
|
2540
|
+
rootDir: (_d = config.rootDir) !== null && _d !== void 0 ? _d : '/',
|
|
2541
|
+
sys: (_e = sys !== null && sys !== void 0 ? sys : config.sys) !== null && _e !== void 0 ? _e : coreCompiler.createSystem({ logger }),
|
|
2542
|
+
testing: (_f = config.testing) !== null && _f !== void 0 ? _f : {},
|
|
2254
2543
|
};
|
|
2255
2544
|
switch (task) {
|
|
2256
2545
|
case 'build':
|
|
@@ -2275,6 +2564,9 @@ const runTask = async (coreCompiler, config, task, sys) => {
|
|
|
2275
2564
|
case 'telemetry':
|
|
2276
2565
|
await taskTelemetry(strictConfig.flags, sys, strictConfig.logger);
|
|
2277
2566
|
break;
|
|
2567
|
+
case 'test':
|
|
2568
|
+
await taskTest(strictConfig);
|
|
2569
|
+
break;
|
|
2278
2570
|
case 'version':
|
|
2279
2571
|
console.log(coreCompiler.version);
|
|
2280
2572
|
break;
|