@jsenv/core 39.2.19 → 39.3.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/dist/jsenv_core.js +319 -211
- package/package.json +2 -2
- package/src/build/build.js +9 -4
- package/src/build/build_specifier_manager.js +50 -6
- package/src/build/build_urls_generator.js +7 -2
- package/src/dev/start_dev_server.js +6 -2
- package/src/jsenv_core_directory_url.js +1 -0
- package/src/kitchen/url_graph/references.js +3 -0
- package/src/kitchen/url_graph/url_graph_visitor.js +14 -4
- package/src/plugins/directory_reference_effect/jsenv_plugin_directory_reference_effect.js +63 -0
- package/src/plugins/plugin_controller.js +4 -4
- package/src/plugins/plugins.js +2 -1
- package/src/plugins/protocol_file/jsenv_plugin_fs_redirection.js +108 -0
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +13 -153
- package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +14 -13
- package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +4 -1
|
@@ -2,27 +2,15 @@ import {
|
|
|
2
2
|
assertAndNormalizeDirectoryUrl,
|
|
3
3
|
comparePathnames,
|
|
4
4
|
} from "@jsenv/filesystem";
|
|
5
|
-
import {
|
|
6
|
-
applyFileSystemMagicResolution,
|
|
7
|
-
getExtensionsToTry,
|
|
8
|
-
} from "@jsenv/node-esm-resolution";
|
|
9
5
|
import { pickContentType } from "@jsenv/server";
|
|
10
6
|
import {
|
|
11
7
|
ensurePathnameTrailingSlash,
|
|
12
8
|
urlIsInsideOf,
|
|
13
|
-
urlToFilename,
|
|
14
9
|
urlToRelativeUrl,
|
|
15
10
|
} from "@jsenv/urls";
|
|
16
11
|
import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
lstatSync,
|
|
20
|
-
readdirSync,
|
|
21
|
-
readFileSync,
|
|
22
|
-
realpathSync,
|
|
23
|
-
statSync,
|
|
24
|
-
} from "node:fs";
|
|
25
|
-
import { pathToFileURL } from "node:url";
|
|
12
|
+
import { existsSync, lstatSync, readdirSync, readFileSync } from "node:fs";
|
|
13
|
+
import { jsenvPluginFsRedirection } from "./jsenv_plugin_fs_redirection.js";
|
|
26
14
|
|
|
27
15
|
const html404AndParentDirIsEmptyFileUrl = new URL(
|
|
28
16
|
"./html_404_and_parent_dir_is_empty.html",
|
|
@@ -35,119 +23,16 @@ const html404AndParentDirFileUrl = new URL(
|
|
|
35
23
|
const htmlFileUrlForDirectory = new URL("./directory.html", import.meta.url);
|
|
36
24
|
|
|
37
25
|
export const jsenvPluginProtocolFile = ({
|
|
38
|
-
magicExtensions
|
|
39
|
-
magicDirectoryIndex
|
|
40
|
-
preserveSymlinks
|
|
41
|
-
directoryReferenceEffect = "error",
|
|
26
|
+
magicExtensions,
|
|
27
|
+
magicDirectoryIndex,
|
|
28
|
+
preserveSymlinks,
|
|
42
29
|
}) => {
|
|
43
30
|
return [
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (!reference.url.startsWith("file:")) {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
if (reference.isInline) {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
// ignore root file url
|
|
56
|
-
if (reference.url === "file:///" || reference.url === "file://") {
|
|
57
|
-
reference.leadsToADirectory = true;
|
|
58
|
-
return `ignore:file:///`;
|
|
59
|
-
}
|
|
60
|
-
// ignore "./" on new URL("./")
|
|
61
|
-
if (
|
|
62
|
-
reference.subtype === "new_url_first_arg" &&
|
|
63
|
-
reference.specifier === "./"
|
|
64
|
-
) {
|
|
65
|
-
return `ignore:${reference.url}`;
|
|
66
|
-
}
|
|
67
|
-
// ignore all new URL second arg
|
|
68
|
-
if (reference.subtype === "new_url_second_arg") {
|
|
69
|
-
return `ignore:${reference.url}`;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const urlObject = new URL(reference.url);
|
|
73
|
-
let stat;
|
|
74
|
-
try {
|
|
75
|
-
stat = statSync(urlObject);
|
|
76
|
-
} catch (e) {
|
|
77
|
-
if (e.code === "ENOENT") {
|
|
78
|
-
stat = null;
|
|
79
|
-
} else {
|
|
80
|
-
throw e;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const { search, hash } = urlObject;
|
|
85
|
-
let { pathname } = urlObject;
|
|
86
|
-
const pathnameUsesTrailingSlash = pathname.endsWith("/");
|
|
87
|
-
urlObject.search = "";
|
|
88
|
-
urlObject.hash = "";
|
|
89
|
-
|
|
90
|
-
// force trailing slash on directories
|
|
91
|
-
if (stat && stat.isDirectory() && !pathnameUsesTrailingSlash) {
|
|
92
|
-
urlObject.pathname = `${pathname}/`;
|
|
93
|
-
}
|
|
94
|
-
// otherwise remove trailing slash if any
|
|
95
|
-
if (stat && !stat.isDirectory() && pathnameUsesTrailingSlash) {
|
|
96
|
-
// a warning here? (because it's strange to reference a file with a trailing slash)
|
|
97
|
-
urlObject.pathname = pathname.slice(0, -1);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
let url = urlObject.href;
|
|
101
|
-
const shouldApplyDilesystemMagicResolution =
|
|
102
|
-
reference.type === "js_import";
|
|
103
|
-
if (shouldApplyDilesystemMagicResolution) {
|
|
104
|
-
const filesystemResolution = applyFileSystemMagicResolution(url, {
|
|
105
|
-
fileStat: stat,
|
|
106
|
-
magicDirectoryIndex,
|
|
107
|
-
magicExtensions: getExtensionsToTry(
|
|
108
|
-
magicExtensions,
|
|
109
|
-
reference.ownerUrlInfo.url,
|
|
110
|
-
),
|
|
111
|
-
});
|
|
112
|
-
if (filesystemResolution.stat) {
|
|
113
|
-
stat = filesystemResolution.stat;
|
|
114
|
-
url = filesystemResolution.url;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
if (!stat) {
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
reference.leadsToADirectory = stat && stat.isDirectory();
|
|
121
|
-
if (reference.leadsToADirectory) {
|
|
122
|
-
let actionForDirectory;
|
|
123
|
-
if (reference.type === "a_href") {
|
|
124
|
-
actionForDirectory = "ignore";
|
|
125
|
-
} else if (
|
|
126
|
-
reference.type === "http_request" ||
|
|
127
|
-
reference.type === "filesystem"
|
|
128
|
-
) {
|
|
129
|
-
actionForDirectory = "copy";
|
|
130
|
-
} else if (typeof directoryReferenceEffect === "string") {
|
|
131
|
-
actionForDirectory = directoryReferenceEffect;
|
|
132
|
-
} else if (typeof directoryReferenceEffect === "function") {
|
|
133
|
-
actionForDirectory = directoryReferenceEffect(reference);
|
|
134
|
-
} else {
|
|
135
|
-
actionForDirectory = "error";
|
|
136
|
-
}
|
|
137
|
-
if (actionForDirectory === "error") {
|
|
138
|
-
const error = new Error("Reference leads to a directory");
|
|
139
|
-
error.code = "DIRECTORY_REFERENCE_NOT_ALLOWED";
|
|
140
|
-
throw error;
|
|
141
|
-
}
|
|
142
|
-
if (actionForDirectory === "preserve") {
|
|
143
|
-
return `ignore:${url}${search}${hash}`;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
const urlRaw = preserveSymlinks ? url : resolveSymlink(url);
|
|
147
|
-
const resolvedUrl = `${urlRaw}${search}${hash}`;
|
|
148
|
-
return resolvedUrl;
|
|
149
|
-
},
|
|
150
|
-
},
|
|
31
|
+
jsenvPluginFsRedirection({
|
|
32
|
+
magicExtensions,
|
|
33
|
+
magicDirectoryIndex,
|
|
34
|
+
preserveSymlinks,
|
|
35
|
+
}),
|
|
151
36
|
{
|
|
152
37
|
name: "jsenv:fs_resolution",
|
|
153
38
|
appliesDuring: "*",
|
|
@@ -197,18 +82,10 @@ export const jsenvPluginProtocolFile = ({
|
|
|
197
82
|
return null;
|
|
198
83
|
}
|
|
199
84
|
const urlObject = new URL(urlInfo.url);
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (urlInfo.firstReference.type === "filesystem") {
|
|
203
|
-
urlInfo.filenameHint = `${
|
|
204
|
-
urlInfo.firstReference.ownerUrlInfo.filenameHint
|
|
205
|
-
}${urlToFilename(urlInfo.url)}/`;
|
|
206
|
-
} else {
|
|
207
|
-
urlInfo.filenameHint = `${urlToFilename(urlInfo.url)}/`;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
85
|
+
const { firstReference } = urlInfo;
|
|
86
|
+
if (firstReference.leadsToADirectory) {
|
|
210
87
|
const directoryContentArray = readdirSync(urlObject);
|
|
211
|
-
if (
|
|
88
|
+
if (firstReference.type === "filesystem") {
|
|
212
89
|
const content = JSON.stringify(directoryContentArray, null, " ");
|
|
213
90
|
return {
|
|
214
91
|
type: "directory",
|
|
@@ -236,13 +113,6 @@ export const jsenvPluginProtocolFile = ({
|
|
|
236
113
|
content: JSON.stringify(directoryContentArray, null, " "),
|
|
237
114
|
};
|
|
238
115
|
}
|
|
239
|
-
if (
|
|
240
|
-
!urlInfo.dirnameHint &&
|
|
241
|
-
urlInfo.firstReference.ownerUrlInfo.type === "directory"
|
|
242
|
-
) {
|
|
243
|
-
urlInfo.dirnameHint =
|
|
244
|
-
urlInfo.firstReference.ownerUrlInfo.filenameHint;
|
|
245
|
-
}
|
|
246
116
|
const contentType = CONTENT_TYPE.fromUrlExtension(urlInfo.url);
|
|
247
117
|
if (contentType === "text/html") {
|
|
248
118
|
try {
|
|
@@ -387,13 +257,3 @@ const replacePlaceholders = (html, replacers) => {
|
|
|
387
257
|
return replacer;
|
|
388
258
|
});
|
|
389
259
|
};
|
|
390
|
-
|
|
391
|
-
const resolveSymlink = (fileUrl) => {
|
|
392
|
-
const urlObject = new URL(fileUrl);
|
|
393
|
-
const realpath = realpathSync(urlObject);
|
|
394
|
-
const realUrlObject = pathToFileURL(realpath);
|
|
395
|
-
if (urlObject.pathname.endsWith("/")) {
|
|
396
|
-
realUrlObject.pathname += `/`;
|
|
397
|
-
}
|
|
398
|
-
return realUrlObject.href;
|
|
399
|
-
};
|
package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js
CHANGED
|
@@ -5,15 +5,17 @@ export const jsenvPluginDirectoryReferenceAnalysis = () => {
|
|
|
5
5
|
name: "jsenv:directory_reference_analysis",
|
|
6
6
|
transformUrlContent: {
|
|
7
7
|
directory: async (urlInfo) => {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
if (urlInfo.contentType !== "application/json") {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
// const isShapeBuildStep = urlInfo.kitchen.context.buildStep === "shape";
|
|
12
|
+
const originalDirectoryReference = findOriginalDirectoryReference(
|
|
13
|
+
urlInfo.firstReference,
|
|
14
|
+
);
|
|
10
15
|
const directoryRelativeUrl = urlToRelativeUrl(
|
|
11
16
|
urlInfo.url,
|
|
12
17
|
urlInfo.context.rootDirectoryUrl,
|
|
13
18
|
);
|
|
14
|
-
if (urlInfo.contentType !== "application/json") {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
19
|
const entryNames = JSON.parse(urlInfo.content);
|
|
18
20
|
const newEntryNames = [];
|
|
19
21
|
for (const entryName of entryNames) {
|
|
@@ -35,19 +37,18 @@ export const jsenvPluginDirectoryReferenceAnalysis = () => {
|
|
|
35
37
|
};
|
|
36
38
|
};
|
|
37
39
|
|
|
38
|
-
const findOriginalDirectoryReference = (
|
|
40
|
+
const findOriginalDirectoryReference = (firstReference) => {
|
|
39
41
|
const findNonFileSystemAncestor = (urlInfo) => {
|
|
40
42
|
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
41
|
-
|
|
42
|
-
if (urlInfoReferencingThisOne.type !== "directory") {
|
|
43
|
+
if (referenceFromOther.type !== "filesystem") {
|
|
43
44
|
return referenceFromOther;
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
-
if (found) {
|
|
47
|
-
return found;
|
|
48
|
-
}
|
|
46
|
+
return findNonFileSystemAncestor(referenceFromOther.ownerUrlInfo);
|
|
49
47
|
}
|
|
50
48
|
return null;
|
|
51
49
|
};
|
|
52
|
-
|
|
50
|
+
if (firstReference.type !== "filesystem") {
|
|
51
|
+
return firstReference;
|
|
52
|
+
}
|
|
53
|
+
return findNonFileSystemAncestor(firstReference.ownerUrlInfo);
|
|
53
54
|
};
|
|
@@ -10,9 +10,12 @@ export const jsenvPluginReferenceAnalysis = ({
|
|
|
10
10
|
inlineContent = true,
|
|
11
11
|
inlineConvertedScript = false,
|
|
12
12
|
fetchInlineUrls = true,
|
|
13
|
+
directoryReferenceEffect,
|
|
13
14
|
}) => {
|
|
14
15
|
return [
|
|
15
|
-
jsenvPluginDirectoryReferenceAnalysis(
|
|
16
|
+
jsenvPluginDirectoryReferenceAnalysis({
|
|
17
|
+
directoryReferenceEffect,
|
|
18
|
+
}),
|
|
16
19
|
jsenvPluginHtmlReferenceAnalysis({
|
|
17
20
|
inlineContent,
|
|
18
21
|
inlineConvertedScript,
|