@parcel/utils 2.0.0-nightly.150 → 2.0.0-nightly.1500

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.
Files changed (105) hide show
  1. package/.eslintrc.js +6 -6
  2. package/lib/index.js +37626 -318
  3. package/lib/index.js.map +1 -0
  4. package/package.json +47 -20
  5. package/src/DefaultMap.js +1 -1
  6. package/src/PromiseQueue.js +16 -12
  7. package/src/alternatives.js +145 -0
  8. package/src/ansi-html.js +2 -2
  9. package/src/blob.js +2 -1
  10. package/src/bundle-url.js +1 -1
  11. package/src/collection.js +35 -15
  12. package/src/config.js +132 -45
  13. package/src/countLines.js +5 -2
  14. package/src/debounce.js +1 -1
  15. package/src/dependency-location.js +11 -6
  16. package/src/generateBuildMetrics.js +158 -0
  17. package/src/generateCertificate.js +1 -1
  18. package/src/getCertificate.js +1 -1
  19. package/src/getExisting.js +1 -4
  20. package/src/getModuleParts.js +23 -0
  21. package/src/getRootDir.js +1 -2
  22. package/src/glob.js +51 -10
  23. package/src/hash.js +49 -0
  24. package/src/http-server.js +29 -19
  25. package/src/index.js +68 -22
  26. package/src/is-url.js +1 -1
  27. package/src/isDirectoryInside.js +11 -0
  28. package/src/openInBrowser.js +64 -0
  29. package/src/path.js +38 -6
  30. package/src/prettyDiagnostic.js +102 -30
  31. package/src/progress-message.js +22 -0
  32. package/src/relativeBundlePath.js +8 -13
  33. package/src/replaceBundleReferences.js +85 -41
  34. package/src/schema.js +100 -44
  35. package/src/shared-buffer.js +23 -0
  36. package/src/sourcemap.js +138 -0
  37. package/src/stream.js +31 -1
  38. package/src/urlJoin.js +3 -1
  39. package/test/DefaultMap.test.js +7 -4
  40. package/test/collection.test.js +13 -1
  41. package/test/config.test.js +98 -0
  42. package/test/input/config/.testrc +3 -0
  43. package/test/input/config/config.cjs +3 -0
  44. package/test/input/config/config.js +3 -0
  45. package/test/input/config/config.json +3 -0
  46. package/test/input/config/empty.json +0 -0
  47. package/test/input/config/empty.toml +0 -0
  48. package/test/input/sourcemap/referenced-min.js +2 -0
  49. package/test/input/sourcemap/referenced-min.js.map +6 -0
  50. package/test/input/sourcemap/source-root.js +2 -0
  51. package/test/input/sourcemap/source-root.js.map +7 -0
  52. package/test/replaceBundleReferences.test.js +268 -0
  53. package/test/sourcemap.test.js +207 -0
  54. package/test/throttle.test.js +1 -2
  55. package/test/urlJoin.test.js +37 -0
  56. package/lib/DefaultMap.js +0 -64
  57. package/lib/Deferred.js +0 -26
  58. package/lib/PromiseQueue.js +0 -133
  59. package/lib/TapStream.js +0 -41
  60. package/lib/ansi-html.js +0 -16
  61. package/lib/blob.js +0 -31
  62. package/lib/bundle-url.js +0 -43
  63. package/lib/collection.js +0 -62
  64. package/lib/config.js +0 -88
  65. package/lib/countLines.js +0 -18
  66. package/lib/debounce.js +0 -20
  67. package/lib/dependency-location.js +0 -21
  68. package/lib/escape-html.js +0 -24
  69. package/lib/escape-markdown.js +0 -15
  70. package/lib/generateBundleReport.js +0 -38
  71. package/lib/generateCertificate.js +0 -124
  72. package/lib/getCertificate.js +0 -19
  73. package/lib/getExisting.js +0 -23
  74. package/lib/getRootDir.js +0 -55
  75. package/lib/glob.js +0 -76
  76. package/lib/http-server.js +0 -64
  77. package/lib/is-url.js +0 -17
  78. package/lib/loadSourceMapUrl.js +0 -33
  79. package/lib/md5.js +0 -35
  80. package/lib/objectHash.js +0 -26
  81. package/lib/parseCSSImport.js +0 -16
  82. package/lib/path.js +0 -22
  83. package/lib/prettifyTime.js +0 -10
  84. package/lib/prettyDiagnostic.js +0 -57
  85. package/lib/promisify.js +0 -13
  86. package/lib/relativeBundlePath.js +0 -24
  87. package/lib/relativeUrl.js +0 -16
  88. package/lib/replaceBundleReferences.js +0 -151
  89. package/lib/resolve.js +0 -93
  90. package/lib/schema.js +0 -320
  91. package/lib/serializeObject.js +0 -28
  92. package/lib/stream.js +0 -51
  93. package/lib/throttle.js +0 -16
  94. package/lib/urlJoin.js +0 -27
  95. package/src/.babelrc +0 -3
  96. package/src/escape-markdown.js +0 -10
  97. package/src/generateBundleReport.js +0 -51
  98. package/src/loadSourceMapUrl.js +0 -33
  99. package/src/md5.js +0 -44
  100. package/src/promisify.js +0 -13
  101. package/src/resolve.js +0 -135
  102. package/src/serializeObject.js +0 -22
  103. package/test/escapeMarkdown.test.js +0 -29
  104. package/test/input/sourcemap/referenced.js +0 -7
  105. package/test/loadSourceMapUrl.test.js +0 -37
package/src/schema.js CHANGED
@@ -1,15 +1,19 @@
1
1
  // @flow strict-local
2
2
  import ThrowableDiagnostic, {
3
3
  generateJSONCodeHighlights,
4
+ escapeMarkdown,
5
+ encodeJSONKeyComponent,
4
6
  } from '@parcel/diagnostic';
5
- // $FlowFixMe untyped
6
- import levenshteinDistance from 'js-levenshtein';
7
+ import type {Mapping} from '@mischnic/json-sourcemap';
8
+ import nullthrows from 'nullthrows';
9
+ import * as levenshtein from 'fastest-levenshtein';
7
10
 
8
11
  export type SchemaEntity =
9
12
  | SchemaObject
10
13
  | SchemaArray
11
14
  | SchemaBoolean
12
15
  | SchemaString
16
+ | SchemaNumber
13
17
  | SchemaEnum
14
18
  | SchemaOneOf
15
19
  | SchemaAllOf
@@ -40,6 +44,11 @@ export type SchemaString = {|
40
44
  __validate?: (val: string) => ?string,
41
45
  __type?: string,
42
46
  |};
47
+ export type SchemaNumber = {|
48
+ type: 'number',
49
+ enum?: Array<number>,
50
+ __type?: string,
51
+ |};
43
52
  export type SchemaEnum = {|
44
53
  enum: Array<mixed>,
45
54
  |};
@@ -88,7 +97,7 @@ export type SchemaError =
88
97
  prop: string,
89
98
  expectedProps: Array<string>,
90
99
  actualProps: Array<string>,
91
- dataType: null | 'key',
100
+ dataType: 'key' | 'value',
92
101
 
93
102
  dataPath: string,
94
103
  ancestors: Array<SchemaEntity>,
@@ -99,7 +108,6 @@ export type SchemaError =
99
108
  actualValue: mixed,
100
109
  dataType: ?'key' | 'value',
101
110
  message?: string,
102
-
103
111
  dataPath: string,
104
112
  ancestors: Array<SchemaEntity>,
105
113
  |};
@@ -159,8 +167,7 @@ function validateSchema(schema: SchemaEntity, data: mixed): Array<SchemaError> {
159
167
  }
160
168
  } else if (schemaNode.__validate) {
161
169
  let validationError = schemaNode.__validate(value);
162
- // $FlowFixMe
163
- if (validationError) {
170
+ if (typeof validationError == 'string') {
164
171
  return {
165
172
  type: 'other',
166
173
  dataType: 'value',
@@ -173,6 +180,23 @@ function validateSchema(schema: SchemaEntity, data: mixed): Array<SchemaError> {
173
180
  }
174
181
  break;
175
182
  }
183
+ case 'number': {
184
+ // $FlowFixMe type was already checked
185
+ let value: number = dataNode;
186
+ if (schemaNode.enum) {
187
+ if (!schemaNode.enum.includes(value)) {
188
+ return {
189
+ type: 'enum',
190
+ dataType: 'value',
191
+ dataPath,
192
+ expectedValues: schemaNode.enum,
193
+ actualValue: value,
194
+ ancestors: schemaAncestors,
195
+ };
196
+ }
197
+ }
198
+ break;
199
+ }
176
200
  case 'object': {
177
201
  let results: Array<Array<SchemaError> | SchemaError> = [];
178
202
  let invalidProps;
@@ -187,7 +211,7 @@ function validateSchema(schema: SchemaEntity, data: mixed): Array<SchemaError> {
187
211
  k =>
188
212
  ({
189
213
  type: 'forbidden-prop',
190
- dataPath: dataPath + '/' + k,
214
+ dataPath: dataPath + '/' + encodeJSONKeyComponent(k),
191
215
  dataType: 'key',
192
216
  prop: k,
193
217
  expectedProps: Object.keys(schemaNode.properties),
@@ -209,7 +233,7 @@ function validateSchema(schema: SchemaEntity, data: mixed): Array<SchemaError> {
209
233
  ({
210
234
  type: 'missing-prop',
211
235
  dataPath,
212
- dataType: null,
236
+ dataType: 'value',
213
237
  prop: k,
214
238
  expectedProps: schemaNode.required,
215
239
  actualProps: keys,
@@ -230,7 +254,7 @@ function validateSchema(schema: SchemaEntity, data: mixed): Array<SchemaError> {
230
254
  [schemaNode.properties[k]].concat(schemaAncestors),
231
255
  // $FlowFixMe type was already checked
232
256
  dataNode[k],
233
- dataPath + '/' + k,
257
+ dataPath + '/' + encodeJSONKeyComponent(k),
234
258
  );
235
259
  if (result) results.push(result);
236
260
  } else {
@@ -239,7 +263,7 @@ function validateSchema(schema: SchemaEntity, data: mixed): Array<SchemaError> {
239
263
  results.push({
240
264
  type: 'enum',
241
265
  dataType: 'key',
242
- dataPath: dataPath + '/' + k,
266
+ dataPath: dataPath + '/' + encodeJSONKeyComponent(k),
243
267
  expectedValues: Object.keys(
244
268
  schemaNode.properties,
245
269
  ).filter(
@@ -256,7 +280,7 @@ function validateSchema(schema: SchemaEntity, data: mixed): Array<SchemaError> {
256
280
  [additionalProperties].concat(schemaAncestors),
257
281
  // $FlowFixMe type was already checked
258
282
  dataNode[k],
259
- dataPath + '/' + k,
283
+ dataPath + '/' + encodeJSONKeyComponent(k),
260
284
  );
261
285
  if (result) results.push(result);
262
286
  }
@@ -339,9 +363,12 @@ function validateSchema(schema: SchemaEntity, data: mixed): Array<SchemaError> {
339
363
  }
340
364
  export default validateSchema;
341
365
 
342
- function fuzzySearch(expectedValues: Array<string>, actualValue: string) {
366
+ export function fuzzySearch(
367
+ expectedValues: Array<string>,
368
+ actualValue: string,
369
+ ): Array<string> {
343
370
  let result = expectedValues
344
- .map(exp => [exp, levenshteinDistance(exp, actualValue)])
371
+ .map(exp => [exp, levenshtein.distance(exp, actualValue)])
345
372
  .filter(
346
373
  // Remove if more than half of the string would need to be changed
347
374
  ([, d]) => d * 2 < actualValue.length,
@@ -350,22 +377,43 @@ function fuzzySearch(expectedValues: Array<string>, actualValue: string) {
350
377
  return result.map(([v]) => v);
351
378
  }
352
379
 
353
- validateSchema.diagnostic = function(
380
+ validateSchema.diagnostic = function (
354
381
  schema: SchemaEntity,
355
- data: mixed,
356
- dataContentsPath?: ?string,
357
- dataContents: string | mixed,
382
+ data: {|
383
+ ...
384
+ | {|
385
+ source?: ?string,
386
+ data?: mixed,
387
+ |}
388
+ | {|
389
+ source: string,
390
+ map: {|
391
+ data: mixed,
392
+ pointers: {|[key: string]: Mapping|},
393
+ |},
394
+ |},
395
+ filePath?: ?string,
396
+ prependKey?: ?string,
397
+ |},
358
398
  origin: string,
359
- prependKey: string,
360
399
  message: string,
361
400
  ): void {
362
- let errors = validateSchema(schema, data);
401
+ if (
402
+ 'source' in data &&
403
+ 'data' in data &&
404
+ typeof data.source !== 'string' &&
405
+ !data
406
+ ) {
407
+ throw new Error(
408
+ 'At least one of data.source and data.data must be defined!',
409
+ );
410
+ }
411
+ let object = data.map
412
+ ? data.map.data
413
+ : // $FlowFixMe we can assume it's a JSON object
414
+ data.data ?? JSON.parse(data.source);
415
+ let errors = validateSchema(schema, object);
363
416
  if (errors.length) {
364
- let dataContentsString: string =
365
- typeof dataContents === 'string'
366
- ? dataContents
367
- : // $FlowFixMe
368
- JSON.stringify(dataContents, null, '\t');
369
417
  let keys = errors.map(e => {
370
418
  let message;
371
419
  if (e.type === 'enum') {
@@ -403,10 +451,8 @@ validateSchema.diagnostic = function(
403
451
  let {prop, actualProps} = e;
404
452
  let likely = fuzzySearch(actualProps, prop);
405
453
  if (likely.length > 0) {
406
- message = `Did you mean ${likely
407
- .map(v => JSON.stringify(v))
408
- .join(', ')}?`;
409
- e.dataPath += '/' + prop;
454
+ message = `Did you mean ${JSON.stringify(prop)}?`;
455
+ e.dataPath += '/' + likely[0];
410
456
  e.dataType = 'key';
411
457
  } else {
412
458
  message = `Missing property ${prop}`;
@@ -422,26 +468,36 @@ validateSchema.diagnostic = function(
422
468
  }
423
469
  return {key: e.dataPath, type: e.dataType, message};
424
470
  });
425
- let codeFrame = {
426
- code: dataContentsString,
427
- codeHighlights: generateJSONCodeHighlights(
428
- dataContentsString,
429
- keys.map(({key, type, message}) => ({
430
- key: prependKey + key,
431
- type: type,
432
- message,
433
- })),
434
- ),
435
- };
471
+ let map, code;
472
+ if (data.map) {
473
+ map = data.map;
474
+ code = data.source;
475
+ } else {
476
+ // $FlowFixMe we can assume that data is valid JSON
477
+ map = data.source ?? JSON.stringify(nullthrows(data.data), 0, '\t');
478
+ code = map;
479
+ }
480
+ let codeFrames = [
481
+ {
482
+ filePath: data.filePath ?? undefined,
483
+ language: 'json',
484
+ code,
485
+ codeHighlights: generateJSONCodeHighlights(
486
+ map,
487
+ keys.map(({key, type, message}) => ({
488
+ key: (data.prependKey ?? '') + key,
489
+ type: type,
490
+ message: message != null ? escapeMarkdown(message) : message,
491
+ })),
492
+ ),
493
+ },
494
+ ];
436
495
 
437
496
  throw new ThrowableDiagnostic({
438
497
  diagnostic: {
439
- message,
498
+ message: message,
440
499
  origin,
441
- // $FlowFixMe should be a sketchy string check
442
- filePath: dataContentsPath || undefined,
443
- language: 'json',
444
- codeFrame,
500
+ codeFrames,
445
501
  },
446
502
  });
447
503
  }
@@ -0,0 +1,23 @@
1
+ // @flow
2
+
3
+ export let SharedBuffer: Class<ArrayBuffer> | Class<SharedArrayBuffer>;
4
+
5
+ // $FlowFixMe[prop-missing]
6
+ if (process.browser) {
7
+ SharedBuffer = ArrayBuffer;
8
+ // Safari has removed the constructor
9
+ if (typeof SharedArrayBuffer !== 'undefined') {
10
+ let channel = new MessageChannel();
11
+ try {
12
+ // Firefox might throw when sending the Buffer over a MessagePort
13
+ channel.port1.postMessage(new SharedArrayBuffer(0));
14
+ SharedBuffer = SharedArrayBuffer;
15
+ } catch (_) {
16
+ // NOOP
17
+ }
18
+ channel.port1.close();
19
+ channel.port2.close();
20
+ }
21
+ } else {
22
+ SharedBuffer = SharedArrayBuffer;
23
+ }
@@ -0,0 +1,138 @@
1
+ // @flow
2
+ import type {SourceLocation} from '@parcel/types';
3
+ import type {FileSystem} from '@parcel/fs';
4
+ import SourceMap from '@parcel/source-map';
5
+ import path from 'path';
6
+ import {normalizeSeparators, isAbsolute} from './path';
7
+
8
+ export const SOURCEMAP_RE: RegExp =
9
+ /(?:\/\*|\/\/)\s*[@#]\s*sourceMappingURL\s*=\s*([^\s*]+)(?:\s*\*\/)?\s*$/;
10
+ const DATA_URL_RE = /^data:[^;]+(?:;charset=[^;]+)?;base64,(.*)/;
11
+ export const SOURCEMAP_EXTENSIONS: Set<string> = new Set<string>([
12
+ 'css',
13
+ 'es',
14
+ 'es6',
15
+ 'js',
16
+ 'jsx',
17
+ 'mjs',
18
+ 'ts',
19
+ 'tsx',
20
+ ]);
21
+
22
+ export function matchSourceMappingURL(
23
+ contents: string,
24
+ ): null | RegExp$matchResult {
25
+ return contents.match(SOURCEMAP_RE);
26
+ }
27
+
28
+ export async function loadSourceMapUrl(
29
+ fs: FileSystem,
30
+ filename: string,
31
+ contents: string,
32
+ ): Promise<?{|filename: string, map: any, url: string|}> {
33
+ let match = matchSourceMappingURL(contents);
34
+ if (match) {
35
+ let url = match[1].trim();
36
+ let dataURLMatch = url.match(DATA_URL_RE);
37
+
38
+ let mapFilePath;
39
+ if (dataURLMatch) {
40
+ mapFilePath = filename;
41
+ } else {
42
+ mapFilePath = url.replace(/^file:\/\//, '');
43
+ mapFilePath = isAbsolute(mapFilePath)
44
+ ? mapFilePath
45
+ : path.join(path.dirname(filename), mapFilePath);
46
+ }
47
+
48
+ return {
49
+ url,
50
+ filename: mapFilePath,
51
+ map: JSON.parse(
52
+ dataURLMatch
53
+ ? Buffer.from(dataURLMatch[1], 'base64').toString()
54
+ : await fs.readFile(mapFilePath, 'utf8'),
55
+ ),
56
+ };
57
+ }
58
+ }
59
+
60
+ export async function loadSourceMap(
61
+ filename: string,
62
+ contents: string,
63
+ options: {fs: FileSystem, projectRoot: string, ...},
64
+ ): Promise<?SourceMap> {
65
+ let foundMap = await loadSourceMapUrl(options.fs, filename, contents);
66
+ if (foundMap) {
67
+ let mapSourceRoot = path.dirname(filename);
68
+ if (
69
+ foundMap.map.sourceRoot &&
70
+ !normalizeSeparators(foundMap.map.sourceRoot).startsWith('/')
71
+ ) {
72
+ mapSourceRoot = path.join(mapSourceRoot, foundMap.map.sourceRoot);
73
+ }
74
+
75
+ let sourcemapInstance = new SourceMap(options.projectRoot);
76
+ sourcemapInstance.addVLQMap({
77
+ ...foundMap.map,
78
+ sources: foundMap.map.sources.map(s => {
79
+ return path.join(mapSourceRoot, s);
80
+ }),
81
+ });
82
+ return sourcemapInstance;
83
+ }
84
+ }
85
+
86
+ export function remapSourceLocation(
87
+ loc: SourceLocation,
88
+ originalMap: SourceMap,
89
+ ): SourceLocation {
90
+ let {
91
+ filePath,
92
+ start: {line: startLine, column: startCol},
93
+ end: {line: endLine, column: endCol},
94
+ } = loc;
95
+ let lineDiff = endLine - startLine;
96
+ let colDiff = endCol - startCol;
97
+ let start = originalMap.findClosestMapping(startLine, startCol - 1);
98
+ let end = originalMap.findClosestMapping(endLine, endCol - 1);
99
+
100
+ if (start?.original) {
101
+ if (start.source) {
102
+ filePath = start.source;
103
+ }
104
+
105
+ ({line: startLine, column: startCol} = start.original);
106
+ startCol++; // source map columns are 0-based
107
+ }
108
+
109
+ if (end?.original) {
110
+ ({line: endLine, column: endCol} = end.original);
111
+ endCol++; // source map columns are 0-based
112
+
113
+ if (endLine < startLine) {
114
+ endLine = startLine;
115
+ endCol = startCol;
116
+ } else if (endLine === startLine && endCol < startCol && lineDiff === 0) {
117
+ endCol = startCol + colDiff;
118
+ } else if (endLine === startLine && startCol === endCol && lineDiff === 0) {
119
+ // Prevent 0-length ranges
120
+ endCol = startCol + 1;
121
+ }
122
+ } else {
123
+ endLine = startLine;
124
+ endCol = startCol;
125
+ }
126
+
127
+ return {
128
+ filePath,
129
+ start: {
130
+ line: startLine,
131
+ column: startCol,
132
+ },
133
+ end: {
134
+ line: endLine,
135
+ column: endCol,
136
+ },
137
+ };
138
+ }
package/src/stream.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // @flow strict-local
2
2
 
3
- import {Readable} from 'stream';
3
+ import {Readable, PassThrough} from 'stream';
4
4
  import type {Blob} from '@parcel/types';
5
5
 
6
6
  export function measureStreamLength(stream: Readable): Promise<number> {
@@ -42,3 +42,33 @@ export function blobToStream(blob: Blob): Readable {
42
42
 
43
43
  return readableFromStringOrBuffer(blob);
44
44
  }
45
+
46
+ export function streamFromPromise(promise: Promise<Blob>): Readable {
47
+ const stream = new PassThrough();
48
+ promise.then(blob => {
49
+ if (blob instanceof Readable) {
50
+ blob.pipe(stream);
51
+ } else {
52
+ stream.end(blob);
53
+ }
54
+ });
55
+
56
+ return stream;
57
+ }
58
+
59
+ export function fallbackStream(
60
+ stream: Readable,
61
+ fallback: () => Readable,
62
+ ): Readable {
63
+ const res = new PassThrough();
64
+ stream.on('error', err => {
65
+ if (err.code === 'ENOENT') {
66
+ fallback().pipe(res);
67
+ } else {
68
+ res.emit('error', err);
69
+ }
70
+ });
71
+
72
+ stream.pipe(res);
73
+ return res;
74
+ }
package/src/urlJoin.js CHANGED
@@ -9,7 +9,9 @@ import path from 'path';
9
9
  */
10
10
  export default function urlJoin(publicURL: string, assetPath: string): string {
11
11
  const url = URL.parse(publicURL, false, true);
12
- const assetUrl = URL.parse(assetPath);
12
+ // Leading / ensures that paths with colons are not parsed as a protocol.
13
+ let p = assetPath.startsWith('/') ? assetPath : '/' + assetPath;
14
+ const assetUrl = URL.parse(p);
13
15
  url.pathname = path.posix.join(url.pathname, assetUrl.pathname);
14
16
  url.search = assetUrl.search;
15
17
  url.hash = assetUrl.hash;
@@ -5,10 +5,13 @@ import {DefaultMap} from '../src/DefaultMap';
5
5
 
6
6
  describe('DefaultMap', () => {
7
7
  it('constructs with entries just like Map', () => {
8
- let map = new DefaultMap(k => k, [
9
- [1, 3],
10
- [2, 27],
11
- ]);
8
+ let map = new DefaultMap(
9
+ k => k,
10
+ [
11
+ [1, 3],
12
+ [2, 27],
13
+ ],
14
+ );
12
15
  assert.equal(map.get(1), 3);
13
16
  assert.deepEqual(Array.from(map.entries()), [
14
17
  [1, 3],
@@ -1,7 +1,11 @@
1
1
  // @flow
2
2
 
3
3
  import assert from 'assert';
4
- import {objectSortedEntries, objectSortedEntriesDeep} from '../src/collection';
4
+ import {
5
+ objectSortedEntries,
6
+ objectSortedEntriesDeep,
7
+ setDifference,
8
+ } from '../src/collection';
5
9
 
6
10
  describe('objectSortedEntries', () => {
7
11
  it('returns a sorted list of key/value tuples', () => {
@@ -38,3 +42,11 @@ describe('objectSortedEntriesDeep', () => {
38
42
  );
39
43
  });
40
44
  });
45
+ describe('setDifference', () => {
46
+ it('returns a setDifference of two sets of T type', () => {
47
+ assert.deepEqual(
48
+ setDifference(new Set([1, 2, 3]), new Set([3, 4, 5])),
49
+ new Set([1, 2, 4, 5]),
50
+ );
51
+ });
52
+ });
@@ -0,0 +1,98 @@
1
+ // @flow strict-local
2
+
3
+ import assert from 'assert';
4
+ import {loadConfig} from '../src/config';
5
+ import {inputFS as fs} from '@parcel/test-utils';
6
+ import path from 'path';
7
+
8
+ describe('loadConfig', () => {
9
+ it('load config with json', async () => {
10
+ assert.deepEqual(
11
+ (
12
+ await loadConfig(
13
+ fs,
14
+ path.join(__dirname, './input/config/config.json'),
15
+ ['config.json'],
16
+ path.join(__dirname, './input/config/'),
17
+ )
18
+ )?.config,
19
+ {
20
+ hoge: 'fuga',
21
+ },
22
+ );
23
+ });
24
+
25
+ it('should throw error with empty string json', async () => {
26
+ // $FlowFixMe[prop-missing]
27
+ await assert.rejects(async () => {
28
+ await loadConfig(
29
+ fs,
30
+ path.join(__dirname, './input/config/empty.json'),
31
+ ['empty.json'],
32
+ path.join(__dirname, './input/config/'),
33
+ );
34
+ });
35
+ });
36
+
37
+ it('should load with empty string config toml', async () => {
38
+ assert.deepEqual(
39
+ (
40
+ await loadConfig(
41
+ fs,
42
+ path.join(__dirname, './input/config/empty.toml'),
43
+ ['empty.toml'],
44
+ path.join(__dirname, './input/config/'),
45
+ )
46
+ )?.config,
47
+ {},
48
+ );
49
+ });
50
+
51
+ it('should load with js', async () => {
52
+ assert.deepEqual(
53
+ (
54
+ await loadConfig(
55
+ fs,
56
+ path.join(__dirname, './input/config/config.js'),
57
+ ['config.js'],
58
+ path.join(__dirname, './input/config/'),
59
+ )
60
+ )?.config,
61
+ {
62
+ hoge: 'fuga',
63
+ },
64
+ );
65
+ });
66
+
67
+ it('should load with cjs', async () => {
68
+ assert.deepEqual(
69
+ (
70
+ await loadConfig(
71
+ fs,
72
+ path.join(__dirname, './input/config/config.cjs'),
73
+ ['config.cjs'],
74
+ path.join(__dirname, './input/config/'),
75
+ )
76
+ )?.config,
77
+ {
78
+ hoge: 'fuga',
79
+ },
80
+ );
81
+ });
82
+
83
+ it('should load without an extension as json', async () => {
84
+ assert.deepEqual(
85
+ (
86
+ await loadConfig(
87
+ fs,
88
+ path.join(__dirname, './input/config/.testrc'),
89
+ ['.testrc'],
90
+ path.join(__dirname, './input/config/'),
91
+ )
92
+ )?.config,
93
+ {
94
+ hoge: 'fuga',
95
+ },
96
+ );
97
+ });
98
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "hoge": "fuga"
3
+ }
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ hoge: 'fuga',
3
+ };
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ hoge: 'fuga',
3
+ };
@@ -0,0 +1,3 @@
1
+ {
2
+ "hoge": "fuga"
3
+ }
File without changes
File without changes
@@ -0,0 +1,2 @@
1
+ function hello(){var l="Hello",o="world";console.log(l+" "+o+"!")}hello();
2
+ //# sourceMappingURL=file://referenced-min.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version":3,
3
+ "sources":["./referenced.js"],
4
+ "names":["hello","l","o","console","log"],
5
+ "mappings":"AAAA,SAASA,QACP,IAAIC,EAAI,QACNC,EAAI,QACNC,QAAQC,IAAIH,EAAI,IAAMC,EAAI,KAE5BF"
6
+ }
@@ -0,0 +1,2 @@
1
+ function hello(){var l="Hello",o="world";console.log(l+" "+o+"!")}hello();
2
+ //# sourceMappingURL=source-root.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version":3,
3
+ "sourceRoot": "../",
4
+ "sources":["./source.js"],
5
+ "names":["hello","l","o","console","log"],
6
+ "mappings":"AAAA,SAASA,QACP,IAAIC,EAAI,QACNC,EAAI,QACNC,QAAQC,IAAIH,EAAI,IAAMC,EAAI,KAE5BF"
7
+ }