@jsenv/core 38.2.10 → 38.3.0
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 +1 -0
- package/dist/jsenv_core.js +1592 -1494
- package/package.json +14 -14
- package/src/dev/file_service.js +1 -1
- package/src/kitchen/kitchen.js +1 -1
- package/src/kitchen/url_graph/references.js +2 -2
- package/src/kitchen/url_graph/url_graph.js +15 -4
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +133 -65
- package/src/plugins/autoreload/jsenv_plugin_hot_search_param.js +15 -6
- package/src/plugins/plugins.js +0 -2
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +12 -4
- package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +3 -0
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +493 -310
- package/src/plugins/ribbon/jsenv_plugin_ribbon.js +2 -2
- package/src/plugins/importmap/jsenv_plugin_importmap.js +0 -205
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "38.
|
|
3
|
+
"version": "38.3.0",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -61,20 +61,20 @@
|
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@financial-times/polyfill-useragent-normaliser": "1.10.2",
|
|
63
63
|
"@jsenv/abort": "4.2.4",
|
|
64
|
-
"@jsenv/ast": "5.
|
|
64
|
+
"@jsenv/ast": "5.2.0",
|
|
65
65
|
"@jsenv/filesystem": "4.3.2",
|
|
66
66
|
"@jsenv/importmap": "1.2.1",
|
|
67
67
|
"@jsenv/integrity": "0.0.1",
|
|
68
|
+
"@jsenv/js-module-fallback": "1.3.6",
|
|
68
69
|
"@jsenv/log": "3.4.1",
|
|
69
70
|
"@jsenv/node-esm-resolution": "1.0.1",
|
|
70
|
-
"@jsenv/js-module-fallback": "1.3.5",
|
|
71
|
-
"@jsenv/runtime-compat": "1.2.0",
|
|
72
|
-
"@jsenv/server": "15.1.3",
|
|
73
|
-
"@jsenv/sourcemap": "1.2.3",
|
|
74
71
|
"@jsenv/plugin-bundling": "2.5.7",
|
|
75
72
|
"@jsenv/plugin-minification": "1.5.3",
|
|
76
|
-
"@jsenv/plugin-
|
|
77
|
-
"@jsenv/plugin-
|
|
73
|
+
"@jsenv/plugin-supervisor": "1.3.6",
|
|
74
|
+
"@jsenv/plugin-transpilation": "1.3.5",
|
|
75
|
+
"@jsenv/runtime-compat": "1.2.0",
|
|
76
|
+
"@jsenv/server": "15.1.4",
|
|
77
|
+
"@jsenv/sourcemap": "1.2.3",
|
|
78
78
|
"@jsenv/url-meta": "8.1.0",
|
|
79
79
|
"@jsenv/urls": "2.2.1",
|
|
80
80
|
"@jsenv/utils": "2.0.1"
|
|
@@ -82,22 +82,22 @@
|
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@babel/eslint-parser": "7.22.15",
|
|
84
84
|
"@babel/plugin-syntax-import-assertions": "7.22.5",
|
|
85
|
-
"babel-plugin-transform-async-to-promises": "0.8.18",
|
|
86
85
|
"@jsenv/assert": "./packages/independent/assert/",
|
|
87
86
|
"@jsenv/core": "./",
|
|
88
87
|
"@jsenv/eslint-config": "./packages/independent/eslint-config/",
|
|
89
|
-
"@jsenv/file-size-impact": "14.1.
|
|
88
|
+
"@jsenv/file-size-impact": "14.1.3",
|
|
90
89
|
"@jsenv/https-local": "3.0.7",
|
|
91
90
|
"@jsenv/package-workspace": "0.5.3",
|
|
92
|
-
"@jsenv/performance-impact": "4.1.
|
|
91
|
+
"@jsenv/performance-impact": "4.1.3",
|
|
93
92
|
"@jsenv/plugin-as-js-classic": "./packages/related/plugin-as-js-classic/",
|
|
94
93
|
"@jsenv/test": "./packages/related/test/",
|
|
95
|
-
"
|
|
94
|
+
"babel-plugin-transform-async-to-promises": "0.8.18",
|
|
95
|
+
"eslint": "8.52.0",
|
|
96
96
|
"eslint-plugin-html": "7.1.0",
|
|
97
|
-
"eslint-plugin-import": "2.
|
|
97
|
+
"eslint-plugin-import": "2.29.0",
|
|
98
98
|
"eslint-plugin-react": "7.33.2",
|
|
99
99
|
"open": "9.1.0",
|
|
100
|
-
"playwright": "1.
|
|
100
|
+
"playwright": "1.39.0",
|
|
101
101
|
"prettier": "3.0.3"
|
|
102
102
|
}
|
|
103
103
|
}
|
package/src/dev/file_service.js
CHANGED
|
@@ -135,7 +135,7 @@ export const createFileService = ({
|
|
|
135
135
|
associations: watchAssociations,
|
|
136
136
|
});
|
|
137
137
|
urlInfoCreated.isWatched = watch;
|
|
138
|
-
//
|
|
138
|
+
// when an url depends on many others, we check all these (like package.json)
|
|
139
139
|
urlInfoCreated.isValid = () => {
|
|
140
140
|
if (!urlInfoCreated.url.startsWith("file:")) {
|
|
141
141
|
return false;
|
package/src/kitchen/kitchen.js
CHANGED
|
@@ -488,7 +488,7 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
488
488
|
// the HTML in itself it still valid
|
|
489
489
|
// keep the syntax error and continue with the HTML
|
|
490
490
|
const errorInfo =
|
|
491
|
-
e.code === "PARSE_ERROR"
|
|
491
|
+
e.code === "PARSE_ERROR" && e.cause
|
|
492
492
|
? `${e.cause.reasonCode}\n${e.traceMessage}`
|
|
493
493
|
: e.stack;
|
|
494
494
|
logger.error(
|
|
@@ -386,12 +386,12 @@ const createReference = ({
|
|
|
386
386
|
ownerUrlInfo.context.finalizeReference(reference);
|
|
387
387
|
};
|
|
388
388
|
|
|
389
|
-
// "
|
|
389
|
+
// "formatReference" can be async BUT this is an exception
|
|
390
390
|
// for most cases it will be sync. We want to favor the sync signature to keep things simpler
|
|
391
391
|
// The only case where it needs to be async is when
|
|
392
392
|
// the specifier is a `data:*` url
|
|
393
393
|
// in this case we'll wait for the promise returned by
|
|
394
|
-
// "
|
|
394
|
+
// "formatReference"
|
|
395
395
|
reference.readGeneratedSpecifier = () => {
|
|
396
396
|
if (reference.generatedSpecifier.then) {
|
|
397
397
|
return reference.generatedSpecifier.then((value) => {
|
|
@@ -181,6 +181,7 @@ const createUrlInfo = (url, context) => {
|
|
|
181
181
|
context,
|
|
182
182
|
error: null,
|
|
183
183
|
modifiedTimestamp: 0,
|
|
184
|
+
descendantModifiedTimestamp: 0,
|
|
184
185
|
dereferencedTimestamp: 0,
|
|
185
186
|
originalContentEtag: null,
|
|
186
187
|
contentEtag: null,
|
|
@@ -254,6 +255,9 @@ const createUrlInfo = (url, context) => {
|
|
|
254
255
|
continue;
|
|
255
256
|
}
|
|
256
257
|
if (ref.gotInlined()) {
|
|
258
|
+
if (ref.ownerUrlInfo.isUsed()) {
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
257
261
|
// the url info was inlined, an other reference is required
|
|
258
262
|
// to consider the non-inlined urlInfo as used
|
|
259
263
|
continue;
|
|
@@ -353,7 +357,7 @@ const createUrlInfo = (url, context) => {
|
|
|
353
357
|
};
|
|
354
358
|
urlInfo.onModified = ({ modifiedTimestamp = Date.now() } = {}) => {
|
|
355
359
|
const visitedSet = new Set();
|
|
356
|
-
const
|
|
360
|
+
const considerModified = (urlInfo) => {
|
|
357
361
|
if (visitedSet.has(urlInfo)) {
|
|
358
362
|
return;
|
|
359
363
|
}
|
|
@@ -363,14 +367,21 @@ const createUrlInfo = (url, context) => {
|
|
|
363
367
|
for (const referenceToOther of urlInfo.referenceToOthersSet) {
|
|
364
368
|
const referencedUrlInfo = referenceToOther.urlInfo;
|
|
365
369
|
if (referencedUrlInfo.isInline) {
|
|
366
|
-
|
|
370
|
+
considerModified(referencedUrlInfo);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
374
|
+
if (referenceFromOther.gotInlined()) {
|
|
375
|
+
const urlInfoReferencingThisOne = referenceFromOther.ownerUrlInfo;
|
|
376
|
+
considerModified(urlInfoReferencingThisOne);
|
|
367
377
|
}
|
|
368
378
|
}
|
|
369
379
|
for (const searchParamVariant of urlInfo.searchParamVariantSet) {
|
|
370
|
-
|
|
380
|
+
considerModified(searchParamVariant);
|
|
371
381
|
}
|
|
372
382
|
};
|
|
373
|
-
|
|
383
|
+
considerModified(urlInfo);
|
|
384
|
+
visitedSet.clear();
|
|
374
385
|
};
|
|
375
386
|
urlInfo.onDereferenced = (lastReferenceFromOther) => {
|
|
376
387
|
urlInfo.dereferencedTimestamp = Date.now();
|
|
@@ -18,89 +18,157 @@ export const jsenvPluginAutoreloadServer = ({
|
|
|
18
18
|
}
|
|
19
19
|
return url;
|
|
20
20
|
};
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
const update = (firstUrlInfo) => {
|
|
22
|
+
const boundaries = new Set();
|
|
23
|
+
const instructions = [];
|
|
24
|
+
const propagateUpdate = (firstUrlInfo) => {
|
|
25
|
+
const iterate = (urlInfo, chain) => {
|
|
26
|
+
if (urlInfo.data.hotAcceptSelf) {
|
|
27
|
+
boundaries.add(urlInfo);
|
|
28
|
+
instructions.push({
|
|
29
|
+
type: urlInfo.type,
|
|
30
|
+
boundary: formatUrlForClient(urlInfo.url),
|
|
31
|
+
acceptedBy: formatUrlForClient(urlInfo.url),
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
accepted: true,
|
|
35
|
+
reason:
|
|
36
|
+
urlInfo === firstUrlInfo
|
|
37
|
+
? `file accepts hot reload`
|
|
38
|
+
: `a dependent file accepts hot reload`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (urlInfo.data.hotDecline) {
|
|
42
|
+
return {
|
|
43
|
+
declined: true,
|
|
44
|
+
reason: `file declines hot reload`,
|
|
45
|
+
declinedBy: formatUrlForClient(urlInfo.url),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
let instructionCountBefore = instructions.length;
|
|
49
|
+
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
50
|
+
if (
|
|
51
|
+
referenceFromOther.isImplicit &&
|
|
52
|
+
referenceFromOther.isWeak
|
|
53
|
+
) {
|
|
54
|
+
if (!referenceFromOther.original) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (referenceFromOther.original.isWeak) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const urlInfoReferencingThisOne =
|
|
62
|
+
referenceFromOther.ownerUrlInfo;
|
|
63
|
+
if (urlInfoReferencingThisOne.data.hotDecline) {
|
|
64
|
+
return {
|
|
65
|
+
declined: true,
|
|
66
|
+
reason: `a dependent file declines hot reload`,
|
|
67
|
+
declinedBy: formatUrlForClient(
|
|
68
|
+
urlInfoReferencingThisOne.url,
|
|
69
|
+
),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const { hotAcceptDependencies = [] } =
|
|
73
|
+
urlInfoReferencingThisOne.data;
|
|
74
|
+
if (hotAcceptDependencies.includes(urlInfo.url)) {
|
|
75
|
+
boundaries.add(urlInfoReferencingThisOne);
|
|
76
|
+
instructions.push({
|
|
77
|
+
type: urlInfoReferencingThisOne.type,
|
|
78
|
+
boundary: formatUrlForClient(urlInfoReferencingThisOne.url),
|
|
34
79
|
acceptedBy: formatUrlForClient(urlInfo.url),
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
const instructions = [];
|
|
40
|
-
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
41
|
-
if (referenceFromOther.isImplicit && referenceFromOther.isWeak) {
|
|
42
|
-
if (!referenceFromOther.original) {
|
|
80
|
+
});
|
|
43
81
|
continue;
|
|
44
82
|
}
|
|
45
|
-
if (
|
|
83
|
+
if (chain.includes(urlInfoReferencingThisOne.url)) {
|
|
84
|
+
return {
|
|
85
|
+
declined: true,
|
|
86
|
+
reason: "dead end",
|
|
87
|
+
declinedBy: formatUrlForClient(
|
|
88
|
+
urlInfoReferencingThisOne.url,
|
|
89
|
+
),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const dependentPropagationResult = iterateMemoized(
|
|
93
|
+
urlInfoReferencingThisOne,
|
|
94
|
+
[...chain, urlInfoReferencingThisOne.url],
|
|
95
|
+
);
|
|
96
|
+
if (dependentPropagationResult.accepted) {
|
|
46
97
|
continue;
|
|
47
98
|
}
|
|
99
|
+
if (
|
|
100
|
+
// declined explicitely by an other file, it must decline the whole update
|
|
101
|
+
dependentPropagationResult.declinedBy
|
|
102
|
+
) {
|
|
103
|
+
return dependentPropagationResult;
|
|
104
|
+
}
|
|
105
|
+
// declined by absence of boundary, we can keep searching
|
|
48
106
|
}
|
|
49
|
-
|
|
50
|
-
if (urlInfoReferencingThisOne.data.hotDecline) {
|
|
107
|
+
if (instructionCountBefore === instructions.length) {
|
|
51
108
|
return {
|
|
52
109
|
declined: true,
|
|
53
|
-
reason: `
|
|
54
|
-
declinedBy: urlInfoReferencingThisOne.url,
|
|
110
|
+
reason: `there is no file accepting hot reload while propagating update`,
|
|
55
111
|
};
|
|
56
112
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
113
|
+
return {
|
|
114
|
+
accepted: true,
|
|
115
|
+
reason: `${instructions.length} dependent file(s) accepts hot reload`,
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const map = new Map();
|
|
120
|
+
const iterateMemoized = (urlInfo, chain) => {
|
|
121
|
+
const resultFromCache = map.get(urlInfo.url);
|
|
122
|
+
if (resultFromCache) {
|
|
123
|
+
return resultFromCache;
|
|
66
124
|
}
|
|
67
|
-
|
|
68
|
-
|
|
125
|
+
const result = iterate(urlInfo, chain);
|
|
126
|
+
map.set(urlInfo.url, result);
|
|
127
|
+
return result;
|
|
128
|
+
};
|
|
129
|
+
map.clear();
|
|
130
|
+
return iterateMemoized(firstUrlInfo, []);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
let propagationResult = propagateUpdate(firstUrlInfo);
|
|
134
|
+
const seen = new Set();
|
|
135
|
+
const invalidateImporters = (urlInfo) => {
|
|
136
|
+
// to indicate this urlInfo should be modified
|
|
137
|
+
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
138
|
+
const urlInfoReferencingThisOne = referenceFromOther.ownerUrlInfo;
|
|
139
|
+
const { hotDecline, hotAcceptDependencies = [] } =
|
|
140
|
+
urlInfoReferencingThisOne.data;
|
|
141
|
+
if (hotDecline) {
|
|
142
|
+
propagationResult = {
|
|
69
143
|
declined: true,
|
|
70
|
-
reason:
|
|
144
|
+
reason: `file declines hot reload`,
|
|
71
145
|
declinedBy: formatUrlForClient(urlInfoReferencingThisOne.url),
|
|
72
146
|
};
|
|
147
|
+
return;
|
|
73
148
|
}
|
|
74
|
-
|
|
75
|
-
urlInfoReferencingThisOne,
|
|
76
|
-
[...seen, urlInfoReferencingThisOne.url],
|
|
77
|
-
);
|
|
78
|
-
if (dependentPropagationResult.accepted) {
|
|
79
|
-
instructions.push(...dependentPropagationResult.instructions);
|
|
149
|
+
if (hotAcceptDependencies.includes(urlInfo.url)) {
|
|
80
150
|
continue;
|
|
81
151
|
}
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
dependentPropagationResult.declinedBy
|
|
85
|
-
) {
|
|
86
|
-
return dependentPropagationResult;
|
|
152
|
+
if (seen.has(urlInfoReferencingThisOne)) {
|
|
153
|
+
continue;
|
|
87
154
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
155
|
+
seen.add(urlInfoReferencingThisOne);
|
|
156
|
+
// see https://github.com/vitejs/vite/blob/ab5bb40942c7023046fa6f6d0b49cabc105b6073/packages/vite/src/node/server/moduleGraph.ts#L205C5-L207C6
|
|
157
|
+
if (boundaries.has(urlInfoReferencingThisOne)) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
urlInfoReferencingThisOne.descendantModifiedTimestamp =
|
|
161
|
+
Date.now();
|
|
162
|
+
invalidateImporters(urlInfoReferencingThisOne);
|
|
95
163
|
}
|
|
96
|
-
return {
|
|
97
|
-
accepted: true,
|
|
98
|
-
reason: `${instructions.length} dependent file(s) accepts hot reload`,
|
|
99
|
-
instructions,
|
|
100
|
-
};
|
|
101
164
|
};
|
|
102
|
-
|
|
103
|
-
|
|
165
|
+
invalidateImporters(firstUrlInfo);
|
|
166
|
+
boundaries.clear();
|
|
167
|
+
seen.clear();
|
|
168
|
+
return {
|
|
169
|
+
...propagationResult,
|
|
170
|
+
instructions,
|
|
171
|
+
};
|
|
104
172
|
};
|
|
105
173
|
|
|
106
174
|
// We are delaying the moment we tell client how to reload because:
|
|
@@ -134,7 +202,7 @@ export const jsenvPluginAutoreloadServer = ({
|
|
|
134
202
|
if (!changedUrlInfo.isUsed()) {
|
|
135
203
|
continue;
|
|
136
204
|
}
|
|
137
|
-
const hotUpdate =
|
|
205
|
+
const hotUpdate = update(changedUrlInfo);
|
|
138
206
|
const relativeUrl = formatUrlForClient(changedUrlInfo.url);
|
|
139
207
|
if (hotUpdate.declined) {
|
|
140
208
|
reloadMessage = {
|
|
@@ -171,7 +239,7 @@ export const jsenvPluginAutoreloadServer = ({
|
|
|
171
239
|
if (!ownerUrlInfo.isUsed()) {
|
|
172
240
|
continue;
|
|
173
241
|
}
|
|
174
|
-
const ownerHotUpdate =
|
|
242
|
+
const ownerHotUpdate = update(ownerUrlInfo);
|
|
175
243
|
const cause = `${formatUrlForClient(
|
|
176
244
|
prunedUrlInfo.url,
|
|
177
245
|
)} is no longer referenced`;
|
|
@@ -44,8 +44,16 @@ export const jsenvPluginHotSearchParam = () => {
|
|
|
44
44
|
// At this stage the parent is using ?hot and we are going to decide if
|
|
45
45
|
// we propagate the search param to child.
|
|
46
46
|
const referencedUrlInfo = reference.urlInfo;
|
|
47
|
-
const {
|
|
48
|
-
|
|
47
|
+
const {
|
|
48
|
+
modifiedTimestamp,
|
|
49
|
+
descendantModifiedTimestamp,
|
|
50
|
+
dereferencedTimestamp,
|
|
51
|
+
} = referencedUrlInfo;
|
|
52
|
+
if (
|
|
53
|
+
!modifiedTimestamp &&
|
|
54
|
+
!descendantModifiedTimestamp &&
|
|
55
|
+
!dereferencedTimestamp
|
|
56
|
+
) {
|
|
49
57
|
return null;
|
|
50
58
|
}
|
|
51
59
|
// The goal is to send an url that will bypass client (the browser) cache
|
|
@@ -58,10 +66,11 @@ export const jsenvPluginHotSearchParam = () => {
|
|
|
58
66
|
// We use the latest timestamp to ensure it's fresh
|
|
59
67
|
// The dereferencedTimestamp is needed because when a js module is re-referenced
|
|
60
68
|
// browser must re-execute it, even if the code is not modified
|
|
61
|
-
const latestTimestamp =
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
const latestTimestamp = Math.max(
|
|
70
|
+
modifiedTimestamp,
|
|
71
|
+
descendantModifiedTimestamp,
|
|
72
|
+
dereferencedTimestamp,
|
|
73
|
+
);
|
|
65
74
|
return {
|
|
66
75
|
hot: latestTimestamp,
|
|
67
76
|
};
|
package/src/plugins/plugins.js
CHANGED
|
@@ -2,7 +2,6 @@ import { jsenvPluginSupervisor } from "@jsenv/plugin-supervisor";
|
|
|
2
2
|
import { jsenvPluginTranspilation } from "@jsenv/plugin-transpilation";
|
|
3
3
|
|
|
4
4
|
import { jsenvPluginReferenceAnalysis } from "./reference_analysis/jsenv_plugin_reference_analysis.js";
|
|
5
|
-
import { jsenvPluginImportmap } from "./importmap/jsenv_plugin_importmap.js";
|
|
6
5
|
import { jsenvPluginNodeEsmResolution } from "./resolution_node_esm/jsenv_plugin_node_esm_resolution.js";
|
|
7
6
|
import { jsenvPluginWebResolution } from "./resolution_web/jsenv_plugin_web_resolution.js";
|
|
8
7
|
import { jsenvPluginVersionSearchParam } from "./version_search_param/jsenv_plugin_version_search_param.js";
|
|
@@ -55,7 +54,6 @@ export const getCorePlugins = ({
|
|
|
55
54
|
jsenvPluginReferenceAnalysis(referenceAnalysis),
|
|
56
55
|
...(injections ? [jsenvPluginInjections(injections)] : []),
|
|
57
56
|
jsenvPluginTranspilation(transpilation),
|
|
58
|
-
jsenvPluginImportmap(),
|
|
59
57
|
...(inlining ? [jsenvPluginInlining()] : []),
|
|
60
58
|
...(supervisor ? [jsenvPluginSupervisor(supervisor)] : []), // after inline as it needs inline script to be cooked
|
|
61
59
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { readFileSync,
|
|
1
|
+
import { readFileSync, realpathSync, statSync } from "node:fs";
|
|
2
|
+
import { serveDirectory } from "@jsenv/server";
|
|
2
3
|
import { pathToFileURL } from "node:url";
|
|
3
4
|
import {
|
|
4
5
|
urlIsInsideOf,
|
|
@@ -98,6 +99,7 @@ export const jsenvPluginProtocolFile = ({
|
|
|
98
99
|
reference.leadsToADirectory = stat && stat.isDirectory();
|
|
99
100
|
if (reference.leadsToADirectory) {
|
|
100
101
|
const directoryAllowed =
|
|
102
|
+
reference.type === "http_request" ||
|
|
101
103
|
reference.type === "filesystem" ||
|
|
102
104
|
(typeof directoryReferenceAllowed === "function" &&
|
|
103
105
|
directoryReferenceAllowed(reference)) ||
|
|
@@ -163,7 +165,6 @@ export const jsenvPluginProtocolFile = ({
|
|
|
163
165
|
}
|
|
164
166
|
const urlObject = new URL(urlInfo.url);
|
|
165
167
|
if (urlInfo.firstReference.leadsToADirectory) {
|
|
166
|
-
const directoryEntries = readdirSync(urlObject);
|
|
167
168
|
if (!urlInfo.filenameHint) {
|
|
168
169
|
if (urlInfo.firstReference.type === "filesystem") {
|
|
169
170
|
urlInfo.filenameHint = `${
|
|
@@ -173,10 +174,17 @@ export const jsenvPluginProtocolFile = ({
|
|
|
173
174
|
urlInfo.filenameHint = `${urlToFilename(urlInfo.url)}/`;
|
|
174
175
|
}
|
|
175
176
|
}
|
|
177
|
+
const { headers, body } = serveDirectory(urlObject.href, {
|
|
178
|
+
headers: urlInfo.context.request
|
|
179
|
+
? urlInfo.context.request.headers
|
|
180
|
+
: {},
|
|
181
|
+
rootDirectoryUrl: urlInfo.context.rootDirectoryUrl,
|
|
182
|
+
});
|
|
176
183
|
return {
|
|
177
184
|
type: "directory",
|
|
178
|
-
contentType: "
|
|
179
|
-
|
|
185
|
+
contentType: headers["content-type"],
|
|
186
|
+
contentLength: headers["content-length"],
|
|
187
|
+
content: body,
|
|
180
188
|
};
|
|
181
189
|
}
|
|
182
190
|
if (
|
package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js
CHANGED
|
@@ -11,6 +11,9 @@ export const jsenvPluginDirectoryReferenceAnalysis = () => {
|
|
|
11
11
|
urlInfo.url,
|
|
12
12
|
urlInfo.context.rootDirectoryUrl,
|
|
13
13
|
);
|
|
14
|
+
if (urlInfo.contentType !== "application/json") {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
14
17
|
const entryNames = JSON.parse(urlInfo.content);
|
|
15
18
|
const newEntryNames = [];
|
|
16
19
|
for (const entryName of entryNames) {
|