@parcel/utils 2.0.0-nightly.137 → 2.0.0-nightly.1370
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/.eslintrc.js +6 -6
- package/lib/index.js +37566 -307
- package/lib/index.js.map +1 -0
- package/package.json +45 -20
- package/src/BitSet.js +126 -0
- package/src/DefaultMap.js +1 -1
- package/src/PromiseQueue.js +16 -12
- package/src/alternatives.js +145 -0
- package/src/ansi-html.js +2 -2
- package/src/blob.js +2 -1
- package/src/bundle-url.js +1 -1
- package/src/collection.js +35 -15
- package/src/config.js +132 -45
- package/src/countLines.js +5 -2
- package/src/debounce.js +1 -1
- package/src/dependency-location.js +11 -6
- package/src/generateBuildMetrics.js +158 -0
- package/src/generateCertificate.js +1 -1
- package/src/getCertificate.js +1 -1
- package/src/getExisting.js +1 -4
- package/src/getModuleParts.js +23 -0
- package/src/getRootDir.js +1 -2
- package/src/glob.js +51 -10
- package/src/hash.js +49 -0
- package/src/http-server.js +29 -19
- package/src/index.js +69 -21
- package/src/is-url.js +1 -1
- package/src/isDirectoryInside.js +11 -0
- package/src/openInBrowser.js +64 -0
- package/src/path.js +38 -6
- package/src/prettyDiagnostic.js +74 -24
- package/src/progress-message.js +22 -0
- package/src/relativeBundlePath.js +8 -13
- package/src/replaceBundleReferences.js +85 -41
- package/src/schema.js +100 -44
- package/src/shared-buffer.js +23 -0
- package/src/sourcemap.js +138 -0
- package/src/stream.js +31 -1
- package/src/urlJoin.js +3 -1
- package/test/BitSet.test.js +119 -0
- package/test/DefaultMap.test.js +7 -4
- package/test/collection.test.js +13 -1
- package/test/config.test.js +98 -0
- package/test/input/config/.testrc +3 -0
- package/test/input/config/config.cjs +3 -0
- package/test/input/config/config.js +3 -0
- package/test/input/config/config.json +3 -0
- package/test/input/config/empty.json +0 -0
- package/test/input/config/empty.toml +0 -0
- package/test/input/sourcemap/referenced-min.js +2 -0
- package/test/input/sourcemap/referenced-min.js.map +6 -0
- package/test/input/sourcemap/source-root.js +2 -0
- package/test/input/sourcemap/source-root.js.map +7 -0
- package/test/replaceBundleReferences.test.js +268 -0
- package/test/sourcemap.test.js +207 -0
- package/test/throttle.test.js +1 -2
- package/test/urlJoin.test.js +37 -0
- package/lib/DefaultMap.js +0 -64
- package/lib/Deferred.js +0 -26
- package/lib/PromiseQueue.js +0 -133
- package/lib/TapStream.js +0 -41
- package/lib/ansi-html.js +0 -16
- package/lib/blob.js +0 -31
- package/lib/bundle-url.js +0 -43
- package/lib/collection.js +0 -62
- package/lib/config.js +0 -88
- package/lib/countLines.js +0 -18
- package/lib/debounce.js +0 -20
- package/lib/dependency-location.js +0 -21
- package/lib/escape-html.js +0 -24
- package/lib/generateBundleReport.js +0 -38
- package/lib/generateCertificate.js +0 -124
- package/lib/getCertificate.js +0 -19
- package/lib/getExisting.js +0 -23
- package/lib/getRootDir.js +0 -55
- package/lib/glob.js +0 -76
- package/lib/http-server.js +0 -64
- package/lib/is-url.js +0 -17
- package/lib/loadSourceMapUrl.js +0 -33
- package/lib/md5.js +0 -35
- package/lib/objectHash.js +0 -26
- package/lib/parseCSSImport.js +0 -16
- package/lib/path.js +0 -22
- package/lib/prettifyTime.js +0 -10
- package/lib/prettyDiagnostic.js +0 -57
- package/lib/promisify.js +0 -13
- package/lib/relativeBundlePath.js +0 -24
- package/lib/relativeUrl.js +0 -16
- package/lib/replaceBundleReferences.js +0 -151
- package/lib/resolve.js +0 -93
- package/lib/schema.js +0 -320
- package/lib/serializeObject.js +0 -28
- package/lib/stream.js +0 -51
- package/lib/throttle.js +0 -16
- package/lib/urlJoin.js +0 -27
- package/src/.babelrc +0 -3
- package/src/generateBundleReport.js +0 -51
- package/src/loadSourceMapUrl.js +0 -33
- package/src/md5.js +0 -44
- package/src/promisify.js +0 -13
- package/src/resolve.js +0 -135
- package/src/serializeObject.js +0 -22
- package/test/input/sourcemap/referenced.js +0 -7
- package/test/loadSourceMapUrl.test.js +0 -37
package/src/config.js
CHANGED
|
@@ -2,87 +2,89 @@
|
|
|
2
2
|
|
|
3
3
|
import type {ConfigResult, File, FilePath} from '@parcel/types';
|
|
4
4
|
import type {FileSystem} from '@parcel/fs';
|
|
5
|
+
import ThrowableDiagnostic from '@parcel/diagnostic';
|
|
5
6
|
import path from 'path';
|
|
6
7
|
import clone from 'clone';
|
|
8
|
+
import json5 from 'json5';
|
|
9
|
+
import {parse as toml} from '@iarna/toml';
|
|
10
|
+
import LRU from 'lru-cache';
|
|
7
11
|
|
|
8
|
-
type ConfigOutput = {|
|
|
12
|
+
export type ConfigOutput = {|
|
|
9
13
|
config: ConfigResult,
|
|
10
14
|
files: Array<File>,
|
|
11
15
|
|};
|
|
12
16
|
|
|
13
|
-
type ConfigOptions = {|
|
|
17
|
+
export type ConfigOptions = {|
|
|
14
18
|
parse?: boolean,
|
|
19
|
+
parser?: string => any,
|
|
15
20
|
|};
|
|
16
21
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
toml: require('@iarna/toml').parse,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const existsCache = new Map();
|
|
22
|
+
const configCache = new LRU<FilePath, ConfigOutput>({max: 500});
|
|
23
|
+
const resolveCache = new Map();
|
|
23
24
|
|
|
24
|
-
export
|
|
25
|
+
export function resolveConfig(
|
|
25
26
|
fs: FileSystem,
|
|
26
27
|
filepath: FilePath,
|
|
27
28
|
filenames: Array<FilePath>,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
return
|
|
29
|
+
projectRoot: FilePath,
|
|
30
|
+
): Promise<?FilePath> {
|
|
31
|
+
// Cache the result of resolving config for this directory.
|
|
32
|
+
// This is automatically invalidated at the end of the current build.
|
|
33
|
+
let key = path.dirname(filepath) + filenames.join(',');
|
|
34
|
+
let cached = resolveCache.get(key);
|
|
35
|
+
if (cached !== undefined) {
|
|
36
|
+
return Promise.resolve(cached);
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
let resolved = fs.findAncestorFile(
|
|
40
|
+
filenames,
|
|
41
|
+
path.dirname(filepath),
|
|
42
|
+
projectRoot,
|
|
43
|
+
);
|
|
44
|
+
resolveCache.set(key, resolved);
|
|
45
|
+
return Promise.resolve(resolved);
|
|
46
|
+
}
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
export function resolveConfigSync(
|
|
49
|
+
fs: FileSystem,
|
|
50
|
+
filepath: FilePath,
|
|
51
|
+
filenames: Array<FilePath>,
|
|
52
|
+
projectRoot: FilePath,
|
|
53
|
+
): ?FilePath {
|
|
54
|
+
return fs.findAncestorFile(filenames, path.dirname(filepath), projectRoot);
|
|
46
55
|
}
|
|
47
56
|
|
|
48
57
|
export async function loadConfig(
|
|
49
58
|
fs: FileSystem,
|
|
50
59
|
filepath: FilePath,
|
|
51
60
|
filenames: Array<FilePath>,
|
|
61
|
+
projectRoot: FilePath,
|
|
52
62
|
opts: ?ConfigOptions,
|
|
53
63
|
): Promise<ConfigOutput | null> {
|
|
54
|
-
let
|
|
64
|
+
let parse = opts?.parse ?? true;
|
|
65
|
+
let configFile = await resolveConfig(fs, filepath, filenames, projectRoot);
|
|
55
66
|
if (configFile) {
|
|
67
|
+
let cachedOutput = configCache.get(String(parse) + configFile);
|
|
68
|
+
if (cachedOutput) {
|
|
69
|
+
return cachedOutput;
|
|
70
|
+
}
|
|
71
|
+
|
|
56
72
|
try {
|
|
57
73
|
let extname = path.extname(configFile).slice(1);
|
|
58
|
-
if (extname === 'js') {
|
|
59
|
-
|
|
74
|
+
if (extname === 'js' || extname === 'cjs') {
|
|
75
|
+
let output = {
|
|
60
76
|
// $FlowFixMe
|
|
61
|
-
config: clone(require(configFile)),
|
|
77
|
+
config: clone(module.require(configFile)),
|
|
62
78
|
files: [{filePath: configFile}],
|
|
63
79
|
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
let configContent = await fs.readFile(configFile, 'utf8');
|
|
67
|
-
if (!configContent) {
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
80
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
config = configContent;
|
|
74
|
-
} else {
|
|
75
|
-
let parse = PARSERS[extname] || PARSERS.json;
|
|
76
|
-
config = parse(configContent);
|
|
81
|
+
configCache.set(configFile, output);
|
|
82
|
+
return output;
|
|
77
83
|
}
|
|
78
84
|
|
|
79
|
-
return
|
|
80
|
-
config: config,
|
|
81
|
-
files: [{filePath: configFile}],
|
|
82
|
-
};
|
|
85
|
+
return readConfig(fs, configFile, opts);
|
|
83
86
|
} catch (err) {
|
|
84
87
|
if (err.code === 'MODULE_NOT_FOUND' || err.code === 'ENOENT') {
|
|
85
|
-
existsCache.delete(configFile);
|
|
86
88
|
return null;
|
|
87
89
|
}
|
|
88
90
|
|
|
@@ -92,3 +94,88 @@ export async function loadConfig(
|
|
|
92
94
|
|
|
93
95
|
return null;
|
|
94
96
|
}
|
|
97
|
+
|
|
98
|
+
loadConfig.clear = () => {
|
|
99
|
+
configCache.reset();
|
|
100
|
+
resolveCache.clear();
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export async function readConfig(
|
|
104
|
+
fs: FileSystem,
|
|
105
|
+
configFile: FilePath,
|
|
106
|
+
opts: ?ConfigOptions,
|
|
107
|
+
): Promise<ConfigOutput | null> {
|
|
108
|
+
let parse = opts?.parse ?? true;
|
|
109
|
+
let cachedOutput = configCache.get(String(parse) + configFile);
|
|
110
|
+
if (cachedOutput) {
|
|
111
|
+
return cachedOutput;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
let configContent = await fs.readFile(configFile, 'utf8');
|
|
116
|
+
let config;
|
|
117
|
+
if (parse === false) {
|
|
118
|
+
config = configContent;
|
|
119
|
+
} else {
|
|
120
|
+
let extname = path.extname(configFile).slice(1);
|
|
121
|
+
let parse = opts?.parser ?? getParser(extname);
|
|
122
|
+
try {
|
|
123
|
+
config = parse(configContent);
|
|
124
|
+
} catch (e) {
|
|
125
|
+
if (extname !== '' && extname !== 'json') {
|
|
126
|
+
throw e;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let pos = {
|
|
130
|
+
line: e.lineNumber,
|
|
131
|
+
column: e.columnNumber,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
throw new ThrowableDiagnostic({
|
|
135
|
+
diagnostic: {
|
|
136
|
+
message: `Failed to parse ${path.basename(configFile)}`,
|
|
137
|
+
origin: '@parcel/utils',
|
|
138
|
+
codeFrames: [
|
|
139
|
+
{
|
|
140
|
+
language: 'json5',
|
|
141
|
+
filePath: configFile,
|
|
142
|
+
code: configContent,
|
|
143
|
+
codeHighlights: [
|
|
144
|
+
{
|
|
145
|
+
start: pos,
|
|
146
|
+
end: pos,
|
|
147
|
+
message: e.message,
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let output = {
|
|
158
|
+
config,
|
|
159
|
+
files: [{filePath: configFile}],
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
configCache.set(String(parse) + configFile, output);
|
|
163
|
+
return output;
|
|
164
|
+
} catch (err) {
|
|
165
|
+
if (err.code === 'MODULE_NOT_FOUND' || err.code === 'ENOENT') {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
throw err;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function getParser(extname) {
|
|
174
|
+
switch (extname) {
|
|
175
|
+
case 'toml':
|
|
176
|
+
return toml;
|
|
177
|
+
case 'json':
|
|
178
|
+
default:
|
|
179
|
+
return json5.parse;
|
|
180
|
+
}
|
|
181
|
+
}
|
package/src/countLines.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
// @flow strict-local
|
|
2
2
|
|
|
3
|
-
export default function countLines(
|
|
3
|
+
export default function countLines(
|
|
4
|
+
string: string,
|
|
5
|
+
startIndex: number = 0,
|
|
6
|
+
): number {
|
|
4
7
|
let lines = 1;
|
|
5
|
-
for (let i =
|
|
8
|
+
for (let i = startIndex; i < string.length; i++) {
|
|
6
9
|
if (string.charAt(i) === '\n') {
|
|
7
10
|
lines++;
|
|
8
11
|
}
|
package/src/debounce.js
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
+
}
|
package/src/getCertificate.js
CHANGED
|
@@ -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);
|
package/src/getExisting.js
CHANGED
|
@@ -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
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
|
|
11
|
-
return p
|
|
11
|
+
export function isGlob(p: FilePath): any {
|
|
12
|
+
return _isGlob(normalizeSeparators(p));
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
export function
|
|
15
|
-
|
|
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
|
|
19
|
-
|
|
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
|
-
|
|
44
|
+
fs: FileSystem,
|
|
45
|
+
options?: FastGlobOptions<FilePath>,
|
|
25
46
|
): Array<FilePath> {
|
|
26
|
-
|
|
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
|
-
|
|
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
|
+
}
|