@jsenv/core 40.0.10 → 40.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/build/build.js +1792 -1101
- package/dist/client/autoreload/autoreload.js +1 -27
- package/dist/jsenv_core_node_modules.js +2045 -0
- package/dist/jsenv_core_packages.js +9397 -5830
- package/dist/start_build_server/start_build_server.js +4 -2
- package/dist/start_dev_server/start_dev_server.js +228 -70
- package/package.json +16 -15
- package/src/build/build.js +1084 -560
- package/src/build/build_content_report.js +377 -0
- package/src/build/build_params.js +1 -4
- package/src/build/build_specifier_manager.js +70 -21
- package/src/build/build_urls_generator.js +29 -28
- package/src/kitchen/fetched_content_compliance.js +2 -2
- package/src/kitchen/kitchen.js +1 -1
- package/src/plugins/directory_reference_effect/jsenv_plugin_directory_reference_effect.js +20 -5
- package/src/plugins/plugins.js +5 -2
- package/src/plugins/protocol_file/jsenv_plugin_directory_listing.js +3 -4
- package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +1 -4
- package/src/plugins/resolution_node_esm/jsenv_plugin_node_esm_resolution.js +56 -34
- package/src/plugins/resolution_node_esm/node_esm_resolver.js +132 -11
- package/src/build/jsenv_plugin_subbuilds.js +0 -76
- package/src/kitchen/url_graph/url_graph_report.js +0 -202
- /package/dist/client/{server_events_client → server_events}/server_events_client.js +0 -0
|
@@ -1,9 +1,28 @@
|
|
|
1
|
+
import { URL_META } from "@jsenv/url-meta";
|
|
1
2
|
import { urlToFilename } from "@jsenv/urls";
|
|
2
3
|
import { defineNonEnumerableProperties } from "../../kitchen/errors.js";
|
|
3
4
|
|
|
4
5
|
export const jsenvPluginDirectoryReferenceEffect = (
|
|
5
6
|
directoryReferenceEffect = "error",
|
|
7
|
+
{ rootDirectoryUrl },
|
|
6
8
|
) => {
|
|
9
|
+
let getDirectoryReferenceEffect;
|
|
10
|
+
if (typeof directoryReferenceEffect === "string") {
|
|
11
|
+
getDirectoryReferenceEffect = () => directoryReferenceEffect;
|
|
12
|
+
} else if (typeof directoryReferenceEffect === "function") {
|
|
13
|
+
getDirectoryReferenceEffect = directoryReferenceEffect;
|
|
14
|
+
} else if (typeof directoryReferenceEffect === "object") {
|
|
15
|
+
const associations = URL_META.resolveAssociations(
|
|
16
|
+
{ effect: directoryReferenceEffect },
|
|
17
|
+
rootDirectoryUrl,
|
|
18
|
+
);
|
|
19
|
+
getDirectoryReferenceEffect = (reference) => {
|
|
20
|
+
const { url } = reference;
|
|
21
|
+
const meta = URL_META.applyAssociations({ url, associations });
|
|
22
|
+
return meta.effect || "error";
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
7
26
|
return {
|
|
8
27
|
name: "jsenv:directory_reference_effect",
|
|
9
28
|
appliesDuring: "*",
|
|
@@ -41,12 +60,8 @@ export const jsenvPluginDirectoryReferenceEffect = (
|
|
|
41
60
|
actionForDirectory = "copy";
|
|
42
61
|
} else if (reference.type === "http_request") {
|
|
43
62
|
actionForDirectory = "preserve";
|
|
44
|
-
} else if (typeof directoryReferenceEffect === "string") {
|
|
45
|
-
actionForDirectory = directoryReferenceEffect;
|
|
46
|
-
} else if (typeof directoryReferenceEffect === "function") {
|
|
47
|
-
actionForDirectory = directoryReferenceEffect(reference);
|
|
48
63
|
} else {
|
|
49
|
-
actionForDirectory =
|
|
64
|
+
actionForDirectory = getDirectoryReferenceEffect(reference);
|
|
50
65
|
}
|
|
51
66
|
reference.actionForDirectory = actionForDirectory;
|
|
52
67
|
if (actionForDirectory !== "copy") {
|
package/src/plugins/plugins.js
CHANGED
|
@@ -32,6 +32,7 @@ export const getCorePlugins = ({
|
|
|
32
32
|
|
|
33
33
|
referenceAnalysis = {},
|
|
34
34
|
nodeEsmResolution = {},
|
|
35
|
+
packageConditions,
|
|
35
36
|
magicExtensions,
|
|
36
37
|
magicDirectoryIndex,
|
|
37
38
|
directoryListing = true,
|
|
@@ -102,10 +103,12 @@ export const getCorePlugins = ({
|
|
|
102
103
|
},
|
|
103
104
|
},
|
|
104
105
|
...(nodeEsmResolution
|
|
105
|
-
? [jsenvPluginNodeEsmResolution(nodeEsmResolution)]
|
|
106
|
+
? [jsenvPluginNodeEsmResolution(nodeEsmResolution, packageConditions)]
|
|
106
107
|
: []),
|
|
107
108
|
jsenvPluginWebResolution(),
|
|
108
|
-
jsenvPluginDirectoryReferenceEffect(directoryReferenceEffect
|
|
109
|
+
jsenvPluginDirectoryReferenceEffect(directoryReferenceEffect, {
|
|
110
|
+
rootDirectoryUrl,
|
|
111
|
+
}),
|
|
109
112
|
jsenvPluginVersionSearchParam(),
|
|
110
113
|
|
|
111
114
|
// "jsenvPluginSupervisor" MUST be after "jsenvPluginInlining" as it needs inline script to be cooked
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
import {
|
|
26
|
-
|
|
26
|
+
compareFileUrls,
|
|
27
27
|
lookupPackageDirectory,
|
|
28
28
|
readEntryStatSync,
|
|
29
29
|
registerDirectoryLifecycle,
|
|
@@ -399,9 +399,8 @@ const getDirectoryContentItems = ({
|
|
|
399
399
|
fileUrls.push(fileUrlObject);
|
|
400
400
|
}
|
|
401
401
|
}
|
|
402
|
-
fileUrls.sort(
|
|
403
|
-
|
|
404
|
-
});
|
|
402
|
+
fileUrls.sort(compareFileUrls);
|
|
403
|
+
|
|
405
404
|
const items = [];
|
|
406
405
|
for (const fileUrl of fileUrls) {
|
|
407
406
|
const urlRelativeToCurrentDirectory = urlToRelativeUrl(
|
|
@@ -10,12 +10,9 @@ export const jsenvPluginReferenceAnalysis = ({
|
|
|
10
10
|
inlineContent = true,
|
|
11
11
|
inlineConvertedScript = false,
|
|
12
12
|
fetchInlineUrls = true,
|
|
13
|
-
directoryReferenceEffect,
|
|
14
13
|
}) => {
|
|
15
14
|
return [
|
|
16
|
-
jsenvPluginDirectoryReferenceAnalysis(
|
|
17
|
-
directoryReferenceEffect,
|
|
18
|
-
}),
|
|
15
|
+
jsenvPluginDirectoryReferenceAnalysis(),
|
|
19
16
|
jsenvPluginHtmlReferenceAnalysis({
|
|
20
17
|
inlineContent,
|
|
21
18
|
inlineConvertedScript,
|
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
import { createNodeEsmResolver } from "./node_esm_resolver.js";
|
|
2
2
|
|
|
3
|
-
export const jsenvPluginNodeEsmResolution = (
|
|
3
|
+
export const jsenvPluginNodeEsmResolution = (
|
|
4
|
+
resolutionConfig = {},
|
|
5
|
+
packageConditions,
|
|
6
|
+
) => {
|
|
4
7
|
let nodeEsmResolverDefault;
|
|
5
|
-
const
|
|
8
|
+
const resolverMap = new Map();
|
|
9
|
+
let anyTypeResolver;
|
|
10
|
+
|
|
11
|
+
const resolverFromObject = (
|
|
12
|
+
{ preservesSymlink, ...rest },
|
|
13
|
+
{ kitchenContext, urlType },
|
|
14
|
+
) => {
|
|
15
|
+
const unexpectedKeys = Object.keys(rest);
|
|
16
|
+
if (unexpectedKeys.length) {
|
|
17
|
+
throw new TypeError(
|
|
18
|
+
`${unexpectedKeys.join(
|
|
19
|
+
",",
|
|
20
|
+
)}: there is no such configuration on "${urlType}"`,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
return createNodeEsmResolver({
|
|
24
|
+
build: kitchenContext.build,
|
|
25
|
+
runtimeCompat: kitchenContext.runtimeCompat,
|
|
26
|
+
rootDirectoryUrl: kitchenContext.rootDirectoryUrl,
|
|
27
|
+
packageConditions,
|
|
28
|
+
preservesSymlink,
|
|
29
|
+
});
|
|
30
|
+
};
|
|
6
31
|
|
|
7
32
|
return {
|
|
8
33
|
name: "jsenv:node_esm_resolution",
|
|
@@ -11,47 +36,38 @@ export const jsenvPluginNodeEsmResolution = (resolutionConfig = {}) => {
|
|
|
11
36
|
nodeEsmResolverDefault = createNodeEsmResolver({
|
|
12
37
|
build: kitchenContext.build,
|
|
13
38
|
runtimeCompat: kitchenContext.runtimeCompat,
|
|
39
|
+
rootDirectoryUrl: kitchenContext.rootDirectoryUrl,
|
|
14
40
|
preservesSymlink: true,
|
|
41
|
+
packageConditions,
|
|
15
42
|
});
|
|
16
|
-
Object.keys(resolutionConfig)
|
|
43
|
+
for (const urlType of Object.keys(resolutionConfig)) {
|
|
44
|
+
let resolver;
|
|
17
45
|
const config = resolutionConfig[urlType];
|
|
18
46
|
if (config === true) {
|
|
19
|
-
|
|
47
|
+
resolver = nodeEsmResolverDefault;
|
|
20
48
|
} else if (config === false) {
|
|
21
|
-
|
|
49
|
+
// resolverMap.set(urlType, () => null);
|
|
50
|
+
continue;
|
|
22
51
|
} else if (typeof config === "object") {
|
|
23
|
-
|
|
24
|
-
runtimeCompat,
|
|
25
|
-
packageConditions,
|
|
26
|
-
preservesSymlink,
|
|
27
|
-
...rest
|
|
28
|
-
} = config;
|
|
29
|
-
const unexpectedKeys = Object.keys(rest);
|
|
30
|
-
if (unexpectedKeys.length) {
|
|
31
|
-
throw new TypeError(
|
|
32
|
-
`${unexpectedKeys.join(
|
|
33
|
-
",",
|
|
34
|
-
)}: there is no such configuration on "${urlType}"`,
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
resolvers[urlType] = createNodeEsmResolver({
|
|
38
|
-
build: kitchenContext.build,
|
|
39
|
-
runtimeCompat,
|
|
40
|
-
packageConditions,
|
|
41
|
-
preservesSymlink,
|
|
42
|
-
});
|
|
52
|
+
resolver = resolverFromObject(config, { kitchenContext, urlType });
|
|
43
53
|
} else {
|
|
44
54
|
throw new TypeError(
|
|
45
|
-
`config must be true, false or an object
|
|
55
|
+
`The value "${config}" for ${urlType} in nodeEsmResolution is invalid: it must be true, false or an object.`,
|
|
46
56
|
);
|
|
47
57
|
}
|
|
48
|
-
});
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
if (urlType === "*") {
|
|
60
|
+
anyTypeResolver = resolver;
|
|
61
|
+
} else {
|
|
62
|
+
resolverMap.set(urlType, resolver);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!resolverMap.has("js_module")) {
|
|
67
|
+
resolverMap.set("js_module", nodeEsmResolverDefault);
|
|
52
68
|
}
|
|
53
|
-
if (
|
|
54
|
-
|
|
69
|
+
if (!resolverMap.has("js_classic")) {
|
|
70
|
+
resolverMap.set("js_classic", (reference) => {
|
|
55
71
|
if (reference.subtype === "self_import_scripts_arg") {
|
|
56
72
|
return nodeEsmResolverDefault(reference);
|
|
57
73
|
}
|
|
@@ -60,7 +76,7 @@ export const jsenvPluginNodeEsmResolution = (resolutionConfig = {}) => {
|
|
|
60
76
|
return nodeEsmResolverDefault(reference);
|
|
61
77
|
}
|
|
62
78
|
return null;
|
|
63
|
-
};
|
|
79
|
+
});
|
|
64
80
|
}
|
|
65
81
|
},
|
|
66
82
|
resolveReference: (reference) => {
|
|
@@ -70,8 +86,14 @@ export const jsenvPluginNodeEsmResolution = (resolutionConfig = {}) => {
|
|
|
70
86
|
return result;
|
|
71
87
|
}
|
|
72
88
|
const urlType = urlTypeFromReference(reference);
|
|
73
|
-
const resolver =
|
|
74
|
-
|
|
89
|
+
const resolver = resolverMap.get(urlType);
|
|
90
|
+
if (resolver) {
|
|
91
|
+
return resolver(reference);
|
|
92
|
+
}
|
|
93
|
+
if (anyTypeResolver) {
|
|
94
|
+
return anyTypeResolver(reference);
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
75
97
|
},
|
|
76
98
|
// when specifier is prefixed by "file:///@ignore/"
|
|
77
99
|
// we return an empty js module
|
|
@@ -13,22 +13,23 @@ import {
|
|
|
13
13
|
defaultReadPackageJson,
|
|
14
14
|
readCustomConditionsFromProcessArgs,
|
|
15
15
|
} from "@jsenv/node-esm-resolution";
|
|
16
|
+
import { URL_META } from "@jsenv/url-meta";
|
|
16
17
|
import { urlToBasename, urlToExtension } from "@jsenv/urls";
|
|
17
18
|
import { readFileSync } from "node:fs";
|
|
18
19
|
|
|
19
20
|
export const createNodeEsmResolver = ({
|
|
20
|
-
build,
|
|
21
21
|
runtimeCompat,
|
|
22
|
-
|
|
22
|
+
rootDirectoryUrl,
|
|
23
|
+
packageConditions = {},
|
|
23
24
|
preservesSymlink,
|
|
24
25
|
}) => {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
const buildPackageConditions = createBuildPackageConditions(
|
|
27
|
+
packageConditions,
|
|
28
|
+
{
|
|
29
|
+
rootDirectoryUrl,
|
|
30
|
+
runtimeCompat,
|
|
31
|
+
},
|
|
32
|
+
);
|
|
32
33
|
|
|
33
34
|
return (reference) => {
|
|
34
35
|
if (reference.type === "package_json") {
|
|
@@ -49,10 +50,12 @@ export const createNodeEsmResolver = ({
|
|
|
49
50
|
if (!parentUrl.startsWith("file:")) {
|
|
50
51
|
return null; // let it to jsenv_web_resolution
|
|
51
52
|
}
|
|
53
|
+
const { specifier } = reference;
|
|
54
|
+
const conditions = buildPackageConditions(specifier, parentUrl);
|
|
52
55
|
const { url, type, isMain, packageDirectoryUrl } = applyNodeEsmResolution({
|
|
53
|
-
conditions
|
|
56
|
+
conditions,
|
|
54
57
|
parentUrl,
|
|
55
|
-
specifier
|
|
58
|
+
specifier,
|
|
56
59
|
preservesSymlink,
|
|
57
60
|
});
|
|
58
61
|
// try to give a more meaningful filename after build
|
|
@@ -116,6 +119,107 @@ export const createNodeEsmResolver = ({
|
|
|
116
119
|
};
|
|
117
120
|
};
|
|
118
121
|
|
|
122
|
+
const createBuildPackageConditions = (
|
|
123
|
+
packageConditions,
|
|
124
|
+
{ rootDirectoryUrl, runtimeCompat },
|
|
125
|
+
) => {
|
|
126
|
+
const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node");
|
|
127
|
+
// https://nodejs.org/api/esm.html#resolver-algorithm-specification
|
|
128
|
+
const processArgConditions = readCustomConditionsFromProcessArgs();
|
|
129
|
+
const packageConditionsDefaultResolvers = {};
|
|
130
|
+
for (const processArgCondition of processArgConditions) {
|
|
131
|
+
packageConditionsDefaultResolvers[processArgCondition] = true;
|
|
132
|
+
}
|
|
133
|
+
const packageConditionResolvers = {
|
|
134
|
+
...packageConditionsDefaultResolvers,
|
|
135
|
+
development: (specifier, importer) => {
|
|
136
|
+
if (isBareSpecifier(specifier)) {
|
|
137
|
+
const { url } = applyNodeEsmResolution({
|
|
138
|
+
specifier,
|
|
139
|
+
parentUrl: importer,
|
|
140
|
+
});
|
|
141
|
+
return !url.includes("/node_modules/");
|
|
142
|
+
}
|
|
143
|
+
return !importer.includes("/node_modules/");
|
|
144
|
+
},
|
|
145
|
+
node: nodeRuntimeEnabled,
|
|
146
|
+
browser: !nodeRuntimeEnabled,
|
|
147
|
+
import: true,
|
|
148
|
+
};
|
|
149
|
+
for (const condition of Object.keys(packageConditions)) {
|
|
150
|
+
const value = packageConditions[condition];
|
|
151
|
+
let customResolver;
|
|
152
|
+
if (typeof value === "object") {
|
|
153
|
+
const associations = URL_META.resolveAssociations(
|
|
154
|
+
{ applies: value },
|
|
155
|
+
(pattern) => {
|
|
156
|
+
if (isBareSpecifier(pattern)) {
|
|
157
|
+
try {
|
|
158
|
+
if (pattern.endsWith("/")) {
|
|
159
|
+
// avoid package path not exported
|
|
160
|
+
const { packageDirectoryUrl } = applyNodeEsmResolution({
|
|
161
|
+
specifier: pattern.slice(0, -1),
|
|
162
|
+
parentUrl: rootDirectoryUrl,
|
|
163
|
+
});
|
|
164
|
+
return packageDirectoryUrl;
|
|
165
|
+
}
|
|
166
|
+
const { url } = applyNodeEsmResolution({
|
|
167
|
+
specifier: pattern,
|
|
168
|
+
parentUrl: rootDirectoryUrl,
|
|
169
|
+
});
|
|
170
|
+
return url;
|
|
171
|
+
} catch {
|
|
172
|
+
return new URL(pattern, rootDirectoryUrl);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return new URL(pattern, rootDirectoryUrl);
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
customResolver = (specifier, importer) => {
|
|
179
|
+
if (isBareSpecifier(specifier)) {
|
|
180
|
+
const { url } = applyNodeEsmResolution({
|
|
181
|
+
specifier,
|
|
182
|
+
parentUrl: importer,
|
|
183
|
+
});
|
|
184
|
+
const { applies } = URL_META.applyAssociations({ url, associations });
|
|
185
|
+
return applies;
|
|
186
|
+
}
|
|
187
|
+
return URL_META.applyAssociations({ url: importer, associations })
|
|
188
|
+
.applies;
|
|
189
|
+
};
|
|
190
|
+
} else if (typeof value === "function") {
|
|
191
|
+
customResolver = value;
|
|
192
|
+
} else {
|
|
193
|
+
customResolver = () => value;
|
|
194
|
+
}
|
|
195
|
+
const existing = packageConditionResolvers[condition];
|
|
196
|
+
if (existing) {
|
|
197
|
+
packageConditionResolvers[condition] = (...args) => {
|
|
198
|
+
const customResult = customResolver(...args);
|
|
199
|
+
return customResult === undefined ? existing(...args) : customResult;
|
|
200
|
+
};
|
|
201
|
+
} else {
|
|
202
|
+
packageConditionResolvers[condition] = customResolver;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return (specifier, importer) => {
|
|
207
|
+
const conditions = [];
|
|
208
|
+
for (const conditionCandidate of Object.keys(packageConditionResolvers)) {
|
|
209
|
+
const packageConditionResolver =
|
|
210
|
+
packageConditionResolvers[conditionCandidate];
|
|
211
|
+
if (typeof packageConditionResolver === "function") {
|
|
212
|
+
if (packageConditionResolver(specifier, importer)) {
|
|
213
|
+
conditions.push(conditionCandidate);
|
|
214
|
+
}
|
|
215
|
+
} else if (packageConditionResolver) {
|
|
216
|
+
conditions.push(conditionCandidate);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return conditions;
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
|
|
119
223
|
const addRelationshipWithPackageJson = ({
|
|
120
224
|
reference,
|
|
121
225
|
packageJsonUrl,
|
|
@@ -149,3 +253,20 @@ const addRelationshipWithPackageJson = ({
|
|
|
149
253
|
);
|
|
150
254
|
}
|
|
151
255
|
};
|
|
256
|
+
|
|
257
|
+
const isBareSpecifier = (specifier) => {
|
|
258
|
+
if (
|
|
259
|
+
specifier[0] === "/" ||
|
|
260
|
+
specifier.startsWith("./") ||
|
|
261
|
+
specifier.startsWith("../")
|
|
262
|
+
) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
// eslint-disable-next-line no-new
|
|
267
|
+
new URL(specifier);
|
|
268
|
+
return false;
|
|
269
|
+
} catch {
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
};
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { urlToRelativeUrl } from "@jsenv/urls";
|
|
2
|
-
import { defaultRuntimeCompat, getDefaultBase } from "./build_params.js";
|
|
3
|
-
|
|
4
|
-
export const jsenvPluginSubbuilds = (
|
|
5
|
-
subBuildParamsArray,
|
|
6
|
-
{ parentBuildParams, onCustomBuildDirectory, buildStart },
|
|
7
|
-
) => {
|
|
8
|
-
if (subBuildParamsArray.length === 0) {
|
|
9
|
-
return [];
|
|
10
|
-
}
|
|
11
|
-
return subBuildParamsArray.map((subBuildParams, index) => {
|
|
12
|
-
const defaultChildBuildParams = {};
|
|
13
|
-
const childBuildParams = {
|
|
14
|
-
...parentBuildParams,
|
|
15
|
-
logs: {
|
|
16
|
-
level: "warn",
|
|
17
|
-
disabled: true,
|
|
18
|
-
},
|
|
19
|
-
...defaultChildBuildParams,
|
|
20
|
-
...subBuildParams,
|
|
21
|
-
outDirectoryUrl: new URL(
|
|
22
|
-
`./subbuild_${index}/`,
|
|
23
|
-
parentBuildParams.outDirectoryUrl,
|
|
24
|
-
),
|
|
25
|
-
};
|
|
26
|
-
const subBuildDirectoryUrl = subBuildParams.buildDirectoryUrl;
|
|
27
|
-
if (subBuildDirectoryUrl) {
|
|
28
|
-
const subBuildRelativeUrl = urlToRelativeUrl(
|
|
29
|
-
subBuildDirectoryUrl,
|
|
30
|
-
parentBuildParams.buildDirectoryUrl,
|
|
31
|
-
);
|
|
32
|
-
childBuildParams.base =
|
|
33
|
-
parentBuildParams.base === "./"
|
|
34
|
-
? `./`
|
|
35
|
-
: subBuildParams.base ||
|
|
36
|
-
getDefaultBase(
|
|
37
|
-
childBuildParams.runtimeCompat || defaultRuntimeCompat,
|
|
38
|
-
);
|
|
39
|
-
onCustomBuildDirectory(subBuildRelativeUrl);
|
|
40
|
-
}
|
|
41
|
-
const buildPromise = buildStart(childBuildParams, index);
|
|
42
|
-
const entryPointBuildUrlMap = new Map();
|
|
43
|
-
const entryPointSourceUrlSet = new Set();
|
|
44
|
-
const entryPointBuildUrlSet = new Set();
|
|
45
|
-
const childBuildEntryPoints = childBuildParams.entryPoints;
|
|
46
|
-
for (const key of Object.keys(childBuildEntryPoints)) {
|
|
47
|
-
const entryPointUrl = new URL(key, childBuildParams.sourceDirectoryUrl)
|
|
48
|
-
.href;
|
|
49
|
-
const entryPointBuildUrl = new URL(
|
|
50
|
-
childBuildEntryPoints[key],
|
|
51
|
-
childBuildParams.buildDirectoryUrl,
|
|
52
|
-
).href;
|
|
53
|
-
entryPointBuildUrlMap.set(entryPointUrl, entryPointBuildUrl);
|
|
54
|
-
entryPointSourceUrlSet.add(entryPointUrl);
|
|
55
|
-
entryPointBuildUrlSet.add(entryPointBuildUrl);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
name: `jsenv:subbuild_${index}`,
|
|
60
|
-
redirectReference: (reference) => {
|
|
61
|
-
const entryPointBuildUrl = entryPointBuildUrlMap.get(reference.url);
|
|
62
|
-
if (!entryPointBuildUrl) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
return entryPointBuildUrl;
|
|
66
|
-
},
|
|
67
|
-
fetchUrlContent: async (urlInfo) => {
|
|
68
|
-
if (!entryPointBuildUrlSet.has(urlInfo.url)) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
await buildPromise;
|
|
72
|
-
urlInfo.typeHint = "asset"; // this ensure the rest of jsenv do not scan or modify the content of this file
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
});
|
|
76
|
-
};
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import { ANSI, distributePercentages, humanizeFileSize } from "@jsenv/humanize";
|
|
2
|
-
|
|
3
|
-
import { GRAPH_VISITOR } from "./url_graph_visitor.js";
|
|
4
|
-
|
|
5
|
-
export const createUrlGraphSummary = (
|
|
6
|
-
urlGraph,
|
|
7
|
-
{ title = "graph summary" } = {},
|
|
8
|
-
) => {
|
|
9
|
-
const graphReport = createUrlGraphReport(urlGraph);
|
|
10
|
-
return `--- ${title} ---
|
|
11
|
-
${createRepartitionMessage(graphReport)}
|
|
12
|
-
--------------------`;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const createUrlGraphReport = (urlGraph) => {
|
|
16
|
-
const countGroups = {
|
|
17
|
-
sourcemaps: 0,
|
|
18
|
-
html: 0,
|
|
19
|
-
css: 0,
|
|
20
|
-
js: 0,
|
|
21
|
-
json: 0,
|
|
22
|
-
other: 0,
|
|
23
|
-
total: 0,
|
|
24
|
-
};
|
|
25
|
-
const sizeGroups = {
|
|
26
|
-
sourcemaps: 0,
|
|
27
|
-
html: 0,
|
|
28
|
-
css: 0,
|
|
29
|
-
js: 0,
|
|
30
|
-
json: 0,
|
|
31
|
-
other: 0,
|
|
32
|
-
total: 0,
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
GRAPH_VISITOR.forEachUrlInfoStronglyReferenced(
|
|
36
|
-
urlGraph.rootUrlInfo,
|
|
37
|
-
(urlInfo) => {
|
|
38
|
-
// ignore:
|
|
39
|
-
// - ignored files: we don't know their content
|
|
40
|
-
// - inline files and data files: they are already taken into account in the file where they appear
|
|
41
|
-
if (urlInfo.url.startsWith("ignore:")) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (urlInfo.isInline) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (urlInfo.url.startsWith("data:")) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// file loaded via import assertion are already inside the graph
|
|
52
|
-
// their js module equivalent are ignored to avoid counting it twice
|
|
53
|
-
// in the build graph the file targeted by import assertion will likely be gone
|
|
54
|
-
// and only the js module remain (likely bundled)
|
|
55
|
-
if (
|
|
56
|
-
urlInfo.searchParams.has("as_json_module") ||
|
|
57
|
-
urlInfo.searchParams.has("as_css_module") ||
|
|
58
|
-
urlInfo.searchParams.has("as_text_module")
|
|
59
|
-
) {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const urlContentSize = Buffer.byteLength(urlInfo.content);
|
|
64
|
-
const category = determineCategory(urlInfo);
|
|
65
|
-
if (category === "sourcemap") {
|
|
66
|
-
countGroups.sourcemaps++;
|
|
67
|
-
sizeGroups.sourcemaps += urlContentSize;
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
countGroups.total++;
|
|
71
|
-
sizeGroups.total += urlContentSize;
|
|
72
|
-
if (category === "html") {
|
|
73
|
-
countGroups.html++;
|
|
74
|
-
sizeGroups.html += urlContentSize;
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
if (category === "css") {
|
|
78
|
-
countGroups.css++;
|
|
79
|
-
sizeGroups.css += urlContentSize;
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
if (category === "js") {
|
|
83
|
-
countGroups.js++;
|
|
84
|
-
sizeGroups.js += urlContentSize;
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
if (category === "json") {
|
|
88
|
-
countGroups.json++;
|
|
89
|
-
sizeGroups.json += urlContentSize;
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
countGroups.other++;
|
|
93
|
-
sizeGroups.other += urlContentSize;
|
|
94
|
-
return;
|
|
95
|
-
},
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
const sizesToDistribute = {};
|
|
99
|
-
Object.keys(sizeGroups).forEach((groupName) => {
|
|
100
|
-
if (groupName !== "sourcemaps" && groupName !== "total") {
|
|
101
|
-
sizesToDistribute[groupName] = sizeGroups[groupName];
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
const percentageGroups = distributePercentages(sizesToDistribute);
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
// sourcemaps are special, there size are ignored
|
|
108
|
-
// so there is no "percentage" associated
|
|
109
|
-
sourcemaps: {
|
|
110
|
-
count: countGroups.sourcemaps,
|
|
111
|
-
size: sizeGroups.sourcemaps,
|
|
112
|
-
percentage: undefined,
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
html: {
|
|
116
|
-
count: countGroups.html,
|
|
117
|
-
size: sizeGroups.html,
|
|
118
|
-
percentage: percentageGroups.html,
|
|
119
|
-
},
|
|
120
|
-
css: {
|
|
121
|
-
count: countGroups.css,
|
|
122
|
-
size: sizeGroups.css,
|
|
123
|
-
percentage: percentageGroups.css,
|
|
124
|
-
},
|
|
125
|
-
js: {
|
|
126
|
-
count: countGroups.js,
|
|
127
|
-
size: sizeGroups.js,
|
|
128
|
-
percentage: percentageGroups.js,
|
|
129
|
-
},
|
|
130
|
-
json: {
|
|
131
|
-
count: countGroups.json,
|
|
132
|
-
size: sizeGroups.json,
|
|
133
|
-
percentage: percentageGroups.json,
|
|
134
|
-
},
|
|
135
|
-
other: {
|
|
136
|
-
count: countGroups.other,
|
|
137
|
-
size: sizeGroups.other,
|
|
138
|
-
percentage: percentageGroups.other,
|
|
139
|
-
},
|
|
140
|
-
total: {
|
|
141
|
-
count: countGroups.total,
|
|
142
|
-
size: sizeGroups.total,
|
|
143
|
-
percentage: 100,
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
const determineCategory = (urlInfo) => {
|
|
149
|
-
if (urlInfo.type === "sourcemap") {
|
|
150
|
-
return "sourcemap";
|
|
151
|
-
}
|
|
152
|
-
if (urlInfo.type === "html") {
|
|
153
|
-
return "html";
|
|
154
|
-
}
|
|
155
|
-
if (urlInfo.type === "css") {
|
|
156
|
-
return "css";
|
|
157
|
-
}
|
|
158
|
-
if (urlInfo.type === "js_module" || urlInfo.type === "js_classic") {
|
|
159
|
-
return "js";
|
|
160
|
-
}
|
|
161
|
-
if (urlInfo.type === "json") {
|
|
162
|
-
return "json";
|
|
163
|
-
}
|
|
164
|
-
return "other";
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const createRepartitionMessage = ({ html, css, js, json, other, total }) => {
|
|
168
|
-
const addPart = (name, { count, size, percentage }) => {
|
|
169
|
-
parts.push(
|
|
170
|
-
`${ANSI.color(`${name}:`, ANSI.GREY)} ${count} (${humanizeFileSize(
|
|
171
|
-
size,
|
|
172
|
-
)} / ${percentage} %)`,
|
|
173
|
-
);
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const parts = [];
|
|
177
|
-
// if (sourcemaps.count) {
|
|
178
|
-
// parts.push(
|
|
179
|
-
// `${ANSI.color(`sourcemaps:`, ANSI.GREY)} ${
|
|
180
|
-
// sourcemaps.count
|
|
181
|
-
// } (${humanizeFileSize(sourcemaps.size)})`,
|
|
182
|
-
// )
|
|
183
|
-
// }
|
|
184
|
-
if (html.count) {
|
|
185
|
-
addPart("html ", html);
|
|
186
|
-
}
|
|
187
|
-
if (css.count) {
|
|
188
|
-
addPart("css ", css);
|
|
189
|
-
}
|
|
190
|
-
if (js.count) {
|
|
191
|
-
addPart("js ", js);
|
|
192
|
-
}
|
|
193
|
-
if (json.count) {
|
|
194
|
-
addPart("json ", json);
|
|
195
|
-
}
|
|
196
|
-
if (other.count) {
|
|
197
|
-
addPart("other", other);
|
|
198
|
-
}
|
|
199
|
-
addPart("total", total);
|
|
200
|
-
return `- ${parts.join(`
|
|
201
|
-
- `)}`;
|
|
202
|
-
};
|
|
File without changes
|