@jsenv/core 38.2.2 → 38.2.4
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 +38 -4
- package/dist/jsenv_core.js +34 -17
- package/package.json +3 -3
- package/src/kitchen/url_graph/url_info_transformations.js +1 -0
package/README.md
CHANGED
|
@@ -1,9 +1,43 @@
|
|
|
1
1
|
# @jsenv/core [](https://www.npmjs.com/package/@jsenv/core)
|
|
2
2
|
|
|
3
|
-
Jsenv is a tool to develop test and build projects using JavaScript.
|
|
4
|
-
Jsenv is simple, easy to understand and well documented.
|
|
3
|
+
Jsenv is a tool to develop test and build projects using JavaScript. Jsenv is simple, easy to understand and well [documented](<https://github.com/jsenv/core/wiki/A)-directory-structure>).
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Jsenv cares a lot about the developper experience, especially when it comes to tests.
|
|
6
|
+
|
|
7
|
+
The pillars of jsenv are:
|
|
8
|
+
|
|
9
|
+
1. A dev server serving source files with autoreload
|
|
10
|
+
2. A build generating an optimized version of source files into a directory
|
|
11
|
+
3. A build server serving build files
|
|
12
|
+
4. A test runner executing test files in web browser(s)
|
|
13
|
+
|
|
14
|
+
# The best parts
|
|
15
|
+
|
|
16
|
+
## Reduce cognitive load inside test files
|
|
17
|
+
|
|
18
|
+
When coding, we spend most of our time working on source files. At some point we switch from source files to test files. Suddenly things are different:
|
|
19
|
+
|
|
20
|
+
- code does not execute as it would in source files
|
|
21
|
+
- some tools are used differently in test files, some cannot be used at all
|
|
22
|
+
- you are forced to code in a certain way that is completely different from the one in source files
|
|
23
|
+
|
|
24
|
+
This huge gap between source files and test files creates a context switching costing a lot of cognitive energy.
|
|
25
|
+
Jsenv makes a special effort to [provide a solution](<https://github.com/jsenv/core/wiki/D)-Test>) where switching from source files to test files is easy.
|
|
26
|
+
|
|
27
|
+
## Others
|
|
28
|
+
|
|
29
|
+
- A [large browser support during dev](<https://github.com/jsenv/core/wiki/B)-Dev#21-browser-support>). Because some people might be happy to use an other browser than the latest chrome during dev. Moreover it is useful to reproduce bug specific to certain browsers.
|
|
30
|
+
- A [large browser support after build](<https://github.com/jsenv/core/wiki/C)-Build#211-maximal-browser-support>). Because some product still needs to support old versions of Firefox, Chrome and Safari.
|
|
31
|
+
- A [single set of files during build](<https://github.com/jsenv/core/wiki/C)-Build#212-same-build-for-all-browsers>). Because a single one is simpler to properly support in every aspects.
|
|
32
|
+
- Versioning during build is robust and <a href="https://bundlers.tooling.report/hashing/avoid-cascade/" target="_blank">avoids cascading hash changes</a><sup>↗</sup>
|
|
33
|
+
- Ability to [execute tests in multiple browsers](<https://github.com/jsenv/core/wiki/D)-Test#32-executing-on-more-browsers>): Chrome, Safari, Firefox
|
|
34
|
+
- An advanced support of top level await, allowing to use it everywhere
|
|
35
|
+
- An advanced support of web workers including worker type module
|
|
36
|
+
- Unlock js module features on a regular `<script>` when needed. If you need the behaviour of `<script>` which is to block other `<script>` tag in the page, you'll be happy to still have the power of js modules, like imports, at your disposal.
|
|
37
|
+
|
|
38
|
+
# Demos
|
|
39
|
+
|
|
40
|
+
[H) Demos](<https://github.com/jsenv/core/wiki/H)-Demos>).
|
|
7
41
|
|
|
8
42
|
<!-- # Installation
|
|
9
43
|
|
|
@@ -11,5 +45,5 @@ Jsenv is simple, easy to understand and well documented.
|
|
|
11
45
|
npm install --save-dev @jsenv/core
|
|
12
46
|
```
|
|
13
47
|
|
|
14
|
-
_@jsenv/core_ is tested on Mac, Windows, Linux with Node.js
|
|
48
|
+
_@jsenv/core_ is tested on Mac, Windows, Linux with Node.js 20.
|
|
15
49
|
Other operating systems and Node.js versions are not tested. -->
|
package/dist/jsenv_core.js
CHANGED
|
@@ -2509,7 +2509,9 @@ const createWatcher = (sourcePath, options) => {
|
|
|
2509
2509
|
if (e.code === "ENOENT") {
|
|
2510
2510
|
return;
|
|
2511
2511
|
}
|
|
2512
|
-
console.error(
|
|
2512
|
+
console.error(
|
|
2513
|
+
`error while trying to get rid of windows EPERM: ${e.stack}`,
|
|
2514
|
+
);
|
|
2513
2515
|
throw error;
|
|
2514
2516
|
}
|
|
2515
2517
|
} else {
|
|
@@ -2543,9 +2545,7 @@ callback: ${callback}`);
|
|
|
2543
2545
|
return { registerCleanupCallback, cleanup };
|
|
2544
2546
|
};
|
|
2545
2547
|
|
|
2546
|
-
const
|
|
2547
|
-
// linux does not support recursive option
|
|
2548
|
-
const fsWatchSupportsRecursive = !isLinux;
|
|
2548
|
+
const fsWatchSupportsRecursive = process.platform !== "linux";
|
|
2549
2549
|
|
|
2550
2550
|
const registerDirectoryLifecycle = (
|
|
2551
2551
|
source,
|
|
@@ -2628,8 +2628,8 @@ const registerDirectoryLifecycle = (
|
|
|
2628
2628
|
try {
|
|
2629
2629
|
const relativeUrl = urlToRelativeUrl(url, source);
|
|
2630
2630
|
const previousInfo = infoMap.get(relativeUrl);
|
|
2631
|
-
const
|
|
2632
|
-
const type = statsToType(
|
|
2631
|
+
const stat = statSync(new URL(url));
|
|
2632
|
+
const type = statsToType(stat);
|
|
2633
2633
|
const patternValue = previousInfo
|
|
2634
2634
|
? previousInfo.patternValue
|
|
2635
2635
|
: getWatchPatternValue({ url, type });
|
|
@@ -2638,13 +2638,15 @@ const registerDirectoryLifecycle = (
|
|
|
2638
2638
|
url,
|
|
2639
2639
|
relativeUrl,
|
|
2640
2640
|
type,
|
|
2641
|
-
|
|
2642
|
-
mtimeMs: stats.mtimeMs,
|
|
2641
|
+
stat,
|
|
2643
2642
|
patternValue,
|
|
2644
2643
|
};
|
|
2645
2644
|
} catch (e) {
|
|
2646
2645
|
if (e.code === "ENOENT") {
|
|
2647
|
-
return
|
|
2646
|
+
return {
|
|
2647
|
+
type: null,
|
|
2648
|
+
stat: null,
|
|
2649
|
+
};
|
|
2648
2650
|
}
|
|
2649
2651
|
throw e;
|
|
2650
2652
|
}
|
|
@@ -2717,7 +2719,7 @@ const registerDirectoryLifecycle = (
|
|
|
2717
2719
|
const handleChange = (relativeUrl) => {
|
|
2718
2720
|
const entryUrl = new URL(relativeUrl, sourceUrl).href;
|
|
2719
2721
|
const entryInfo = readEntryInfo(entryUrl);
|
|
2720
|
-
if (
|
|
2722
|
+
if (entryInfo.type === null) {
|
|
2721
2723
|
const previousEntryInfo = infoMap.get(relativeUrl);
|
|
2722
2724
|
if (!previousEntryInfo) {
|
|
2723
2725
|
// on MacOS it's possible to receive a "rename" event for
|
|
@@ -2777,7 +2779,7 @@ const registerDirectoryLifecycle = (
|
|
|
2777
2779
|
readdirSync(new URL(directoryUrl)).forEach((entryName) => {
|
|
2778
2780
|
const childEntryUrl = new URL(entryName, directoryUrl).href;
|
|
2779
2781
|
const childEntryInfo = readEntryInfo(childEntryUrl);
|
|
2780
|
-
if (childEntryInfo && childEntryInfo.patternValue) {
|
|
2782
|
+
if (childEntryInfo.type !== null && childEntryInfo.patternValue) {
|
|
2781
2783
|
handleEntryFound(childEntryInfo, { notify });
|
|
2782
2784
|
}
|
|
2783
2785
|
});
|
|
@@ -2806,7 +2808,7 @@ const registerDirectoryLifecycle = (
|
|
|
2806
2808
|
relativeUrl: entryInfo.relativeUrl,
|
|
2807
2809
|
type: entryInfo.type,
|
|
2808
2810
|
patternValue: entryInfo.patternValue,
|
|
2809
|
-
mtime: entryInfo.mtimeMs,
|
|
2811
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
2810
2812
|
});
|
|
2811
2813
|
}
|
|
2812
2814
|
};
|
|
@@ -2817,19 +2819,19 @@ const registerDirectoryLifecycle = (
|
|
|
2817
2819
|
relativeUrl: entryInfo.relativeUrl,
|
|
2818
2820
|
type: entryInfo.type,
|
|
2819
2821
|
patternValue: entryInfo.patternValue,
|
|
2820
|
-
mtime: entryInfo.mtimeMs,
|
|
2822
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
2821
2823
|
});
|
|
2822
2824
|
}
|
|
2823
2825
|
};
|
|
2824
2826
|
const handleEntryUpdated = (entryInfo) => {
|
|
2825
2827
|
infoMap.set(entryInfo.relativeUrl, entryInfo);
|
|
2826
|
-
if (updated && entryInfo.patternValue) {
|
|
2828
|
+
if (updated && entryInfo.patternValue && shouldCallUpdated(entryInfo)) {
|
|
2827
2829
|
updated({
|
|
2828
2830
|
relativeUrl: entryInfo.relativeUrl,
|
|
2829
2831
|
type: entryInfo.type,
|
|
2830
2832
|
patternValue: entryInfo.patternValue,
|
|
2831
|
-
mtime: entryInfo.mtimeMs,
|
|
2832
|
-
previousMtime: entryInfo.previousInfo.mtimeMs,
|
|
2833
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
2834
|
+
previousMtime: entryInfo.previousInfo.stat.mtimeMs,
|
|
2833
2835
|
});
|
|
2834
2836
|
}
|
|
2835
2837
|
};
|
|
@@ -2837,7 +2839,7 @@ const registerDirectoryLifecycle = (
|
|
|
2837
2839
|
readdirSync(new URL(sourceUrl)).forEach((entry) => {
|
|
2838
2840
|
const entryUrl = new URL(entry, sourceUrl).href;
|
|
2839
2841
|
const entryInfo = readEntryInfo(entryUrl);
|
|
2840
|
-
if (entryInfo && entryInfo.patternValue) {
|
|
2842
|
+
if (entryInfo.type !== null && entryInfo.patternValue) {
|
|
2841
2843
|
handleEntryFound(entryInfo, {
|
|
2842
2844
|
notify: notifyExistent,
|
|
2843
2845
|
});
|
|
@@ -2871,6 +2873,20 @@ ${relativeUrls.join("\n")}`,
|
|
|
2871
2873
|
return tracker.cleanup;
|
|
2872
2874
|
};
|
|
2873
2875
|
|
|
2876
|
+
const shouldCallUpdated = (entryInfo) => {
|
|
2877
|
+
const { stat, previousInfo } = entryInfo;
|
|
2878
|
+
if (!stat.atimeMs) {
|
|
2879
|
+
return true;
|
|
2880
|
+
}
|
|
2881
|
+
if (stat.atimeMs < stat.mtimeMs) {
|
|
2882
|
+
return true;
|
|
2883
|
+
}
|
|
2884
|
+
if (stat.mtimeMs > previousInfo.stat.mtimeMs) {
|
|
2885
|
+
return true;
|
|
2886
|
+
}
|
|
2887
|
+
return false;
|
|
2888
|
+
};
|
|
2889
|
+
|
|
2874
2890
|
const undefinedOrFunction = (value) => {
|
|
2875
2891
|
return typeof value === "undefined" || typeof value === "function";
|
|
2876
2892
|
};
|
|
@@ -13235,6 +13251,7 @@ const createUrlInfoTransformer = ({
|
|
|
13235
13251
|
generatedUrlObject.searchParams.delete("as_json_module");
|
|
13236
13252
|
generatedUrlObject.searchParams.delete("as_text_module");
|
|
13237
13253
|
generatedUrlObject.searchParams.delete("dynamic_import");
|
|
13254
|
+
generatedUrlObject.searchParams.delete("cjs_as_js_module");
|
|
13238
13255
|
const urlForSourcemap = generatedUrlObject.href;
|
|
13239
13256
|
urlInfo.sourcemapGeneratedUrl = generateSourcemapFileUrl(urlForSourcemap);
|
|
13240
13257
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "38.2.
|
|
3
|
+
"version": "38.2.4",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "https://github.com/jsenv/core"
|
|
14
14
|
},
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": ">=
|
|
16
|
+
"node": ">=20.8.0"
|
|
17
17
|
},
|
|
18
18
|
"publishConfig": {
|
|
19
19
|
"access": "public"
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"@financial-times/polyfill-useragent-normaliser": "1.10.2",
|
|
63
63
|
"@jsenv/abort": "4.2.4",
|
|
64
64
|
"@jsenv/ast": "5.1.4",
|
|
65
|
-
"@jsenv/filesystem": "4.
|
|
65
|
+
"@jsenv/filesystem": "4.3.1",
|
|
66
66
|
"@jsenv/importmap": "1.2.1",
|
|
67
67
|
"@jsenv/integrity": "0.0.1",
|
|
68
68
|
"@jsenv/log": "3.4.0",
|
|
@@ -149,6 +149,7 @@ export const createUrlInfoTransformer = ({
|
|
|
149
149
|
generatedUrlObject.searchParams.delete("as_json_module");
|
|
150
150
|
generatedUrlObject.searchParams.delete("as_text_module");
|
|
151
151
|
generatedUrlObject.searchParams.delete("dynamic_import");
|
|
152
|
+
generatedUrlObject.searchParams.delete("cjs_as_js_module");
|
|
152
153
|
const urlForSourcemap = generatedUrlObject.href;
|
|
153
154
|
urlInfo.sourcemapGeneratedUrl = generateSourcemapFileUrl(urlForSourcemap);
|
|
154
155
|
|