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

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
@@ -1,17 +1,22 @@
1
1
  // @flow
2
+
2
3
  export default function createDependencyLocation(
3
- start: {|
4
+ start: interface {
4
5
  line: number,
5
6
  column: number,
6
- |},
7
- moduleSpecifier: string,
7
+ },
8
+ specifier: string,
8
9
  lineOffset: number = 0,
9
10
  columnOffset: number = 0,
10
11
  // Imports are usually wrapped in quotes
11
12
  importWrapperLength: number = 2,
12
- ) {
13
+ ): {|
14
+ end: {|column: number, line: number|},
15
+ filePath: string,
16
+ start: {|column: number, line: number|},
17
+ |} {
13
18
  return {
14
- filePath: moduleSpecifier,
19
+ filePath: specifier,
15
20
  start: {
16
21
  line: start.line + lineOffset,
17
22
  column: start.column + columnOffset,
@@ -20,7 +25,7 @@ export default function createDependencyLocation(
20
25
  line: start.line + lineOffset,
21
26
  column:
22
27
  start.column +
23
- moduleSpecifier.length -
28
+ specifier.length -
24
29
  1 +
25
30
  importWrapperLength +
26
31
  columnOffset,
@@ -0,0 +1,158 @@
1
+ // @flow
2
+
3
+ import type {FilePath, PackagedBundle} from '@parcel/types';
4
+ import type {FileSystem} from '@parcel/fs';
5
+ import SourceMap from '@parcel/source-map';
6
+ import nullthrows from 'nullthrows';
7
+ import path from 'path';
8
+ import {loadSourceMapUrl} from './';
9
+
10
+ export type AssetStats = {|
11
+ filePath: string,
12
+ size: number,
13
+ originalSize: number,
14
+ time: number,
15
+ |};
16
+
17
+ export type BundleStats = {|
18
+ filePath: string,
19
+ size: number,
20
+ time: number,
21
+ assets: Array<AssetStats>,
22
+ |};
23
+
24
+ export type BuildMetrics = {|
25
+ bundles: Array<BundleStats>,
26
+ |};
27
+
28
+ async function getSourcemapSizes(
29
+ filePath: FilePath,
30
+ fs: FileSystem,
31
+ projectRoot: FilePath,
32
+ ): Promise<?Map<string, number>> {
33
+ let bundleContents = await fs.readFile(filePath, 'utf-8');
34
+ let mapUrlData = await loadSourceMapUrl(fs, filePath, bundleContents);
35
+ if (!mapUrlData) {
36
+ return null;
37
+ }
38
+
39
+ let rawMap = mapUrlData.map;
40
+ let sourceMap = new SourceMap(projectRoot);
41
+ sourceMap.addVLQMap(rawMap);
42
+ let parsedMapData = sourceMap.getMap();
43
+
44
+ if (parsedMapData.mappings.length > 2) {
45
+ let sources = parsedMapData.sources.map(s =>
46
+ path.normalize(path.join(projectRoot, s)),
47
+ );
48
+ let currLine = 1;
49
+ let currColumn = 0;
50
+ let currMappingIndex = 0;
51
+ let currMapping = parsedMapData.mappings[currMappingIndex];
52
+ let nextMapping = parsedMapData.mappings[currMappingIndex + 1];
53
+ let sourceSizes = new Array(sources.length).fill(0);
54
+ let unknownOrigin: number = 0;
55
+ for (let i = 0; i < bundleContents.length; i++) {
56
+ let character = bundleContents[i];
57
+
58
+ while (
59
+ nextMapping &&
60
+ nextMapping.generated.line === currLine &&
61
+ nextMapping.generated.column <= currColumn
62
+ ) {
63
+ currMappingIndex++;
64
+ currMapping = parsedMapData.mappings[currMappingIndex];
65
+ nextMapping = parsedMapData.mappings[currMappingIndex + 1];
66
+ }
67
+
68
+ let currentSource = currMapping.source;
69
+ let charSize = Buffer.byteLength(character, 'utf8');
70
+ if (
71
+ currentSource != null &&
72
+ currMapping.generated.line === currLine &&
73
+ currMapping.generated.column <= currColumn
74
+ ) {
75
+ sourceSizes[currentSource] += charSize;
76
+ } else {
77
+ unknownOrigin += charSize;
78
+ }
79
+
80
+ if (character === '\n') {
81
+ currColumn = 0;
82
+ currLine++;
83
+ } else {
84
+ currColumn++;
85
+ }
86
+ }
87
+
88
+ let sizeMap = new Map();
89
+ for (let i = 0; i < sourceSizes.length; i++) {
90
+ sizeMap.set(sources[i], sourceSizes[i]);
91
+ }
92
+
93
+ sizeMap.set('', unknownOrigin);
94
+
95
+ return sizeMap;
96
+ }
97
+ }
98
+
99
+ async function createBundleStats(
100
+ bundle: PackagedBundle,
101
+ fs: FileSystem,
102
+ projectRoot: FilePath,
103
+ ) {
104
+ let filePath = bundle.filePath;
105
+ let sourcemapSizes = await getSourcemapSizes(filePath, fs, projectRoot);
106
+
107
+ let assets: Map<string, AssetStats> = new Map();
108
+ bundle.traverseAssets(asset => {
109
+ let filePath = path.normalize(asset.filePath);
110
+ assets.set(filePath, {
111
+ filePath,
112
+ size: asset.stats.size,
113
+ originalSize: asset.stats.size,
114
+ time: asset.stats.time,
115
+ });
116
+ });
117
+
118
+ let assetsReport: Array<AssetStats> = [];
119
+ if (sourcemapSizes && sourcemapSizes.size) {
120
+ assetsReport = Array.from(sourcemapSizes.keys()).map((filePath: string) => {
121
+ let foundSize = sourcemapSizes.get(filePath) || 0;
122
+ let stats = assets.get(filePath) || {
123
+ filePath,
124
+ size: foundSize,
125
+ originalSize: foundSize,
126
+ time: 0,
127
+ };
128
+
129
+ return {
130
+ ...stats,
131
+ size: foundSize,
132
+ };
133
+ });
134
+ } else {
135
+ assetsReport = Array.from(assets.values());
136
+ }
137
+
138
+ return {
139
+ filePath: nullthrows(bundle.filePath),
140
+ size: bundle.stats.size,
141
+ time: bundle.stats.time,
142
+ assets: assetsReport.sort((a, b) => b.size - a.size),
143
+ };
144
+ }
145
+
146
+ export default async function generateBuildMetrics(
147
+ bundles: Array<PackagedBundle>,
148
+ fs: FileSystem,
149
+ projectRoot: FilePath,
150
+ ): Promise<BuildMetrics> {
151
+ bundles.sort((a, b) => b.stats.size - a.stats.size).filter(b => !!b.filePath);
152
+
153
+ return {
154
+ bundles: (
155
+ await Promise.all(bundles.map(b => createBundleStats(b, fs, projectRoot)))
156
+ ).filter(e => !!e),
157
+ };
158
+ }
@@ -8,7 +8,7 @@ export default async function generateCertificate(
8
8
  fs: FileSystem,
9
9
  cacheDir: string,
10
10
  host: ?string,
11
- ) {
11
+ ): Promise<{|cert: Buffer, key: Buffer|}> {
12
12
  let certDirectory = cacheDir;
13
13
 
14
14
  const privateKeyPath = path.join(certDirectory, 'private.pem');
@@ -5,7 +5,7 @@ import type {FileSystem} from '@parcel/fs';
5
5
  export default async function getCertificate(
6
6
  fs: FileSystem,
7
7
  options: HTTPSOptions,
8
- ) {
8
+ ): Promise<{|cert: Buffer, key: Buffer|}> {
9
9
  try {
10
10
  let cert = await fs.readFile(options.cert);
11
11
  let key = await fs.readFile(options.key);
@@ -14,10 +14,7 @@ export default function getExisting(
14
14
  return {
15
15
  source,
16
16
  minified: fs.existsSync(minifiedPath)
17
- ? fs
18
- .readFileSync(minifiedPath, 'utf8')
19
- .trim()
20
- .replace(/;$/, '')
17
+ ? fs.readFileSync(minifiedPath, 'utf8').trim().replace(/;$/, '')
21
18
  : source,
22
19
  };
23
20
  }
@@ -0,0 +1,23 @@
1
+ // @flow strict-local
2
+ import path from 'path';
3
+
4
+ import {normalizeSeparators} from './path';
5
+
6
+ /**
7
+ * Returns the package name and the optional subpath
8
+ */
9
+ export default function getModuleParts(_name: string): [string, ?string] {
10
+ let name = path.normalize(_name);
11
+ let splitOn = name.indexOf(path.sep);
12
+ if (name.charAt(0) === '@') {
13
+ splitOn = name.indexOf(path.sep, splitOn + 1);
14
+ }
15
+ if (splitOn < 0) {
16
+ return [normalizeSeparators(name), undefined];
17
+ } else {
18
+ return [
19
+ normalizeSeparators(name.substring(0, splitOn)),
20
+ name.substring(splitOn + 1) || undefined,
21
+ ];
22
+ }
23
+ }
package/src/getRootDir.js CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  import type {FilePath} from '@parcel/types';
4
4
  import {isGlob} from './glob';
5
-
6
- const path = require('path');
5
+ import path from 'path';
7
6
 
8
7
  export default function getRootDir(files: Array<FilePath>): FilePath {
9
8
  let cur = null;
package/src/glob.js CHANGED
@@ -5,25 +5,65 @@ import type {FileSystem} from '@parcel/fs';
5
5
 
6
6
  import _isGlob from 'is-glob';
7
7
  import fastGlob, {type FastGlobOptions} from 'fast-glob';
8
- import {isMatch} from 'micromatch';
8
+ import micromatch, {isMatch, makeRe, type Options} from 'micromatch';
9
+ import {normalizeSeparators} from './path';
9
10
 
10
- function normalizePath(p: string): string {
11
- return p.replace(/\\/g, '/');
11
+ export function isGlob(p: FilePath): any {
12
+ return _isGlob(normalizeSeparators(p));
12
13
  }
13
14
 
14
- export function isGlob(p: FilePath) {
15
- return _isGlob(normalizePath(p));
15
+ export function isGlobMatch(
16
+ filePath: FilePath,
17
+ glob: Glob | Array<Glob>,
18
+ opts?: Options,
19
+ ): any {
20
+ glob = Array.isArray(glob)
21
+ ? glob.map(normalizeSeparators)
22
+ : normalizeSeparators(glob);
23
+ return isMatch(filePath, glob, opts);
16
24
  }
17
25
 
18
- export function isGlobMatch(filePath: FilePath, glob: Glob) {
19
- return isMatch(filePath, normalizePath(glob));
26
+ export function globMatch(
27
+ values: Array<string>,
28
+ glob: Glob | Array<Glob>,
29
+ opts?: Options,
30
+ ): Array<string> {
31
+ glob = Array.isArray(glob)
32
+ ? glob.map(normalizeSeparators)
33
+ : normalizeSeparators(glob);
34
+
35
+ return micromatch(values, glob, opts);
36
+ }
37
+
38
+ export function globToRegex(glob: Glob, opts?: Options): RegExp {
39
+ return makeRe(glob, opts);
20
40
  }
21
41
 
22
42
  export function globSync(
23
43
  p: FilePath,
24
- options: FastGlobOptions<FilePath>,
44
+ fs: FileSystem,
45
+ options?: FastGlobOptions<FilePath>,
25
46
  ): Array<FilePath> {
26
- return fastGlob.sync(normalizePath(p), options);
47
+ // $FlowFixMe
48
+ options = {
49
+ ...options,
50
+ fs: {
51
+ statSync: p => {
52
+ return fs.statSync(p);
53
+ },
54
+ lstatSync: p => {
55
+ // Our FileSystem interface doesn't have lstat support at the moment,
56
+ // but this is fine for our purposes since we follow symlinks by default.
57
+ return fs.statSync(p);
58
+ },
59
+ readdirSync: (p, opts) => {
60
+ return fs.readdirSync(p, opts);
61
+ },
62
+ },
63
+ };
64
+
65
+ // $FlowFixMe
66
+ return fastGlob.sync(normalizeSeparators(p), options);
27
67
  }
28
68
 
29
69
  export function glob(
@@ -66,5 +106,6 @@ export function glob(
66
106
  },
67
107
  };
68
108
 
69
- return fastGlob(normalizePath(p), options);
109
+ // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381
110
+ return fastGlob(normalizeSeparators(p), options);
70
111
  }
package/src/hash.js ADDED
@@ -0,0 +1,49 @@
1
+ // @flow strict-local
2
+
3
+ import type {Readable} from 'stream';
4
+ import type {FileSystem} from '@parcel/fs';
5
+
6
+ import {objectSortedEntriesDeep} from './collection';
7
+ import {hashString, Hash} from '@parcel/rust';
8
+
9
+ export function hashStream(stream: Readable): Promise<string> {
10
+ let hash = new Hash();
11
+ return new Promise((resolve, reject) => {
12
+ stream.on('error', err => {
13
+ reject(err);
14
+ });
15
+ stream
16
+ .on('data', chunk => {
17
+ hash.writeBuffer(chunk);
18
+ })
19
+ .on('end', function () {
20
+ resolve(hash.finish());
21
+ })
22
+ .on('error', err => {
23
+ reject(err);
24
+ });
25
+ });
26
+ }
27
+
28
+ export function hashObject(obj: {+[string]: mixed, ...}): string {
29
+ return hashString(JSON.stringify(objectSortedEntriesDeep(obj)));
30
+ }
31
+
32
+ let testCache: {|[string]: Promise<string>|} = {
33
+ /*:: ...null */
34
+ };
35
+ export function hashFile(fs: FileSystem, filePath: string): Promise<string> {
36
+ if (process.env.PARCEL_BUILD_ENV === 'test') {
37
+ // Development builds of these native modules are especially big and slow to hash.
38
+ if (
39
+ /parcel-swc\.[^\\/]+\.node$|lightningcss.[^\\/]+.node$/.test(filePath)
40
+ ) {
41
+ let cacheEntry = testCache[filePath];
42
+ if (cacheEntry) return cacheEntry;
43
+ let v = hashStream(fs.createReadStream(filePath));
44
+ testCache[filePath] = v;
45
+ return v;
46
+ }
47
+ }
48
+ return hashStream(fs.createReadStream(filePath));
49
+ }
@@ -1,7 +1,15 @@
1
1
  // @flow strict-local
2
2
 
3
- import type {Server as HTTPOnlyServer} from 'http';
4
- import type {Server as HTTPSServer} from 'https';
3
+ import type {
4
+ Server as HTTPOnlyServer,
5
+ IncomingMessage as HTTPRequest,
6
+ ServerResponse as HTTPResponse,
7
+ } from 'http';
8
+ import type {
9
+ Server as HTTPSServer,
10
+ IncomingMessage as HTTPSRequest,
11
+ ServerResponse as HTTPSResponse,
12
+ } from 'https';
5
13
  import type {Socket} from 'net';
6
14
  import type {FilePath, HTTPSOptions} from '@parcel/types';
7
15
  import type {FileSystem} from '@parcel/fs';
@@ -9,15 +17,19 @@ import type {FileSystem} from '@parcel/fs';
9
17
  import http from 'http';
10
18
  import https from 'https';
11
19
  import nullthrows from 'nullthrows';
12
- import {getCertificate, generateCertificate} from '../';
20
+ import {getCertificate, generateCertificate} from './';
13
21
 
14
22
  type CreateHTTPServerOpts = {|
15
- https: ?(HTTPSOptions | boolean),
16
- inputFS: FileSystem,
17
- outputFS: FileSystem,
18
- cacheDir: FilePath,
19
- listener?: (mixed, mixed) => void,
23
+ listener?: (HTTPRequest | HTTPSRequest, HTTPResponse | HTTPSResponse) => void,
20
24
  host?: string,
25
+ ...
26
+ | {|
27
+ https: ?(HTTPSOptions | boolean),
28
+ inputFS: FileSystem,
29
+ outputFS: FileSystem,
30
+ cacheDir: FilePath,
31
+ |}
32
+ | {||},
21
33
  |};
22
34
 
23
35
  export type HTTPServer = HTTPOnlyServer | HTTPSServer;
@@ -34,19 +46,17 @@ export async function createHTTPServer(
34
46
  if (!options.https) {
35
47
  server = http.createServer(options.listener);
36
48
  } else if (options.https === true) {
37
- server = https.createServer(
38
- await generateCertificate(
39
- options.outputFS,
40
- options.cacheDir,
41
- options.host,
42
- ),
43
- options.listener,
49
+ let {cert, key} = await generateCertificate(
50
+ options.outputFS,
51
+ options.cacheDir,
52
+ options.host,
44
53
  );
54
+
55
+ server = https.createServer({cert, key}, options.listener);
45
56
  } else {
46
- server = https.createServer(
47
- await getCertificate(options.inputFS, options.https),
48
- options.listener,
49
- );
57
+ let {cert, key} = await getCertificate(options.inputFS, options.https);
58
+
59
+ server = https.createServer({cert, key}, options.listener);
50
60
  }
51
61
 
52
62
  // HTTPServer#close only stops accepting new connections, and does not close existing ones.
package/src/index.js CHANGED
@@ -1,42 +1,88 @@
1
1
  // @flow strict-local
2
- export type * from './generateBundleReport';
2
+ export type * from './config';
3
+ export type * from './Deferred';
4
+ export type * from './generateBuildMetrics';
5
+ export type * from './http-server';
6
+ export type * from './path';
3
7
  export type * from './prettyDiagnostic';
8
+ export type * from './schema';
4
9
 
5
10
  export {default as countLines} from './countLines';
6
- export {default as generateBundleReport} from './generateBundleReport';
11
+ export {default as generateBuildMetrics} from './generateBuildMetrics';
7
12
  export {default as generateCertificate} from './generateCertificate';
8
13
  export {default as getCertificate} from './getCertificate';
14
+ export {default as getModuleParts} from './getModuleParts';
9
15
  export {default as getRootDir} from './getRootDir';
16
+ export {default as isDirectoryInside} from './isDirectoryInside';
10
17
  export {default as isURL} from './is-url';
11
18
  export {default as objectHash} from './objectHash';
12
19
  export {default as prettifyTime} from './prettifyTime';
13
20
  export {default as prettyDiagnostic} from './prettyDiagnostic';
14
21
  export {default as PromiseQueue} from './PromiseQueue';
15
- // $FlowFixMe this is untyped
16
- export {default as promisify} from './promisify';
17
22
  export {default as validateSchema} from './schema';
18
23
  export {default as TapStream} from './TapStream';
19
24
  export {default as urlJoin} from './urlJoin';
20
- export {default as loadSourceMapUrl} from './loadSourceMapUrl';
21
25
  export {default as relativeUrl} from './relativeUrl';
22
26
  export {default as createDependencyLocation} from './dependency-location';
23
27
  export {default as debounce} from './debounce';
24
28
  export {default as throttle} from './throttle';
29
+ export {default as openInBrowser} from './openInBrowser';
25
30
 
26
- export * from './blob';
27
- export * from './collection';
28
- export * from './config';
29
- export * from './DefaultMap';
30
- export * from './Deferred';
31
- export * from './glob';
32
- export * from './md5';
33
- export * from './schema';
34
- export * from './http-server';
35
- export * from './path';
36
- export * from './replaceBundleReferences';
37
- export * from './stream';
38
- export * from './resolve';
39
- export * from './relativeBundlePath';
40
- export * from './ansi-html';
41
- export * from './escape-html';
42
- export * from './escape-markdown';
31
+ // Explicit re-exports instead of export * for lazy require performance
32
+ export {findAlternativeNodeModules, findAlternativeFiles} from './alternatives';
33
+ export {blobToBuffer, blobToString} from './blob';
34
+ export {
35
+ unique,
36
+ objectSortedEntries,
37
+ objectSortedEntriesDeep,
38
+ setDifference,
39
+ setEqual,
40
+ setIntersect,
41
+ setUnion,
42
+ } from './collection';
43
+ export {
44
+ resolveConfig,
45
+ resolveConfigSync,
46
+ loadConfig,
47
+ readConfig,
48
+ } from './config';
49
+ export {DefaultMap, DefaultWeakMap} from './DefaultMap';
50
+ export {makeDeferredWithPromise} from './Deferred';
51
+ export {getProgressMessage} from './progress-message.js';
52
+ export {
53
+ isGlob,
54
+ isGlobMatch,
55
+ globMatch,
56
+ globSync,
57
+ glob,
58
+ globToRegex,
59
+ } from './glob';
60
+ export {hashStream, hashObject, hashFile} from './hash';
61
+ export {SharedBuffer} from './shared-buffer';
62
+ export {fuzzySearch} from './schema';
63
+ export {createHTTPServer} from './http-server';
64
+ export {normalizePath, normalizeSeparators, relativePath} from './path';
65
+ export {
66
+ replaceURLReferences,
67
+ replaceInlineReferences,
68
+ } from './replaceBundleReferences';
69
+ export {
70
+ measureStreamLength,
71
+ readableFromStringOrBuffer,
72
+ bufferStream,
73
+ blobToStream,
74
+ streamFromPromise,
75
+ fallbackStream,
76
+ } from './stream';
77
+ export {relativeBundlePath} from './relativeBundlePath';
78
+ export {ansiHtml} from './ansi-html';
79
+ export {escapeHTML} from './escape-html';
80
+ export {
81
+ SOURCEMAP_RE,
82
+ SOURCEMAP_EXTENSIONS,
83
+ matchSourceMappingURL,
84
+ loadSourceMapUrl,
85
+ loadSourceMap,
86
+ remapSourceLocation,
87
+ } from './sourcemap';
88
+ export {default as stripAnsi} from 'strip-ansi';
package/src/is-url.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // @flow
2
2
 
3
- const _isURL = require('is-url');
3
+ import _isURL from 'is-url';
4
4
 
5
5
  // Matches anchor (ie: #raptors)
6
6
  const ANCHOR_REGEXP = /^#/;
@@ -0,0 +1,11 @@
1
+ // @flow strict-local
2
+ import type {FilePath} from '@parcel/types';
3
+ import path from 'path';
4
+
5
+ export default function isDirectoryInside(
6
+ child: FilePath,
7
+ parent: FilePath,
8
+ ): boolean {
9
+ const relative = path.relative(parent, child);
10
+ return !relative.startsWith('..') && !path.isAbsolute(relative);
11
+ }
@@ -0,0 +1,64 @@
1
+ // @flow
2
+
3
+ import open from 'open';
4
+ import {execSync} from 'child_process';
5
+ import logger from '@parcel/logger';
6
+
7
+ // Chrome app name is platform dependent. we should not hard code it.
8
+ // https://github.com/react-native-community/cli/blob/e2be8a905285d9b37512fc78c9755b9635ecf805/packages/cli/src/commands/server/launchDebugger.ts#L28
9
+ function getChromeAppName(): string {
10
+ switch (process.platform) {
11
+ case 'darwin':
12
+ return 'google chrome';
13
+ case 'win32':
14
+ return 'chrome';
15
+ case 'linux':
16
+ if (commandExistsUnixSync('google-chrome')) {
17
+ return 'google-chrome';
18
+ }
19
+ if (commandExistsUnixSync('chromium-browser')) {
20
+ return 'chromium-browser';
21
+ }
22
+ return 'chromium';
23
+
24
+ default:
25
+ return 'google-chrome';
26
+ }
27
+ }
28
+
29
+ function commandExistsUnixSync(commandName: string) {
30
+ try {
31
+ const stdout = execSync(
32
+ `command -v ${commandName} 2>/dev/null` +
33
+ ` && { echo >&1 '${commandName} found'; exit 0; }`,
34
+ );
35
+ return !!stdout;
36
+ } catch (error) {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ function getAppName(appName: string): string {
42
+ if (['google', 'chrome'].includes(appName)) {
43
+ return getChromeAppName();
44
+ } else if (['brave', 'Brave'].includes(appName)) {
45
+ return 'Brave Browser';
46
+ } else return appName;
47
+ }
48
+
49
+ export default async function openInBrowser(url: string, browser: string) {
50
+ try {
51
+ const options =
52
+ typeof browser === 'string' && browser.length > 0
53
+ ? {app: [getAppName(browser)]}
54
+ : undefined;
55
+
56
+ await open(url, options);
57
+ } catch (err) {
58
+ logger.error(
59
+ `Unexpected error while opening in browser: ${browser}`,
60
+ '@parcel/utils',
61
+ );
62
+ logger.error(err, '@parcel/utils');
63
+ }
64
+ }