@jsenv/core 38.2.3 → 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 +53 -15
- package/package.json +2 -2
- 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,7 +2545,7 @@ callback: ${callback}`);
|
|
|
2543
2545
|
return { registerCleanupCallback, cleanup };
|
|
2544
2546
|
};
|
|
2545
2547
|
|
|
2546
|
-
const fsWatchSupportsRecursive =
|
|
2548
|
+
const fsWatchSupportsRecursive = process.platform !== "linux";
|
|
2547
2549
|
|
|
2548
2550
|
const registerDirectoryLifecycle = (
|
|
2549
2551
|
source,
|
|
@@ -2626,8 +2628,8 @@ const registerDirectoryLifecycle = (
|
|
|
2626
2628
|
try {
|
|
2627
2629
|
const relativeUrl = urlToRelativeUrl(url, source);
|
|
2628
2630
|
const previousInfo = infoMap.get(relativeUrl);
|
|
2629
|
-
const
|
|
2630
|
-
const type = statsToType(
|
|
2631
|
+
const stat = statSync(new URL(url));
|
|
2632
|
+
const type = statsToType(stat);
|
|
2631
2633
|
const patternValue = previousInfo
|
|
2632
2634
|
? previousInfo.patternValue
|
|
2633
2635
|
: getWatchPatternValue({ url, type });
|
|
@@ -2636,13 +2638,15 @@ const registerDirectoryLifecycle = (
|
|
|
2636
2638
|
url,
|
|
2637
2639
|
relativeUrl,
|
|
2638
2640
|
type,
|
|
2639
|
-
|
|
2640
|
-
mtimeMs: stats.mtimeMs,
|
|
2641
|
+
stat,
|
|
2641
2642
|
patternValue,
|
|
2642
2643
|
};
|
|
2643
2644
|
} catch (e) {
|
|
2644
2645
|
if (e.code === "ENOENT") {
|
|
2645
|
-
return
|
|
2646
|
+
return {
|
|
2647
|
+
type: null,
|
|
2648
|
+
stat: null,
|
|
2649
|
+
};
|
|
2646
2650
|
}
|
|
2647
2651
|
throw e;
|
|
2648
2652
|
}
|
|
@@ -2715,7 +2719,7 @@ const registerDirectoryLifecycle = (
|
|
|
2715
2719
|
const handleChange = (relativeUrl) => {
|
|
2716
2720
|
const entryUrl = new URL(relativeUrl, sourceUrl).href;
|
|
2717
2721
|
const entryInfo = readEntryInfo(entryUrl);
|
|
2718
|
-
if (
|
|
2722
|
+
if (entryInfo.type === null) {
|
|
2719
2723
|
const previousEntryInfo = infoMap.get(relativeUrl);
|
|
2720
2724
|
if (!previousEntryInfo) {
|
|
2721
2725
|
// on MacOS it's possible to receive a "rename" event for
|
|
@@ -2775,17 +2779,36 @@ const registerDirectoryLifecycle = (
|
|
|
2775
2779
|
readdirSync(new URL(directoryUrl)).forEach((entryName) => {
|
|
2776
2780
|
const childEntryUrl = new URL(entryName, directoryUrl).href;
|
|
2777
2781
|
const childEntryInfo = readEntryInfo(childEntryUrl);
|
|
2778
|
-
if (childEntryInfo && childEntryInfo.patternValue) {
|
|
2782
|
+
if (childEntryInfo.type !== null && childEntryInfo.patternValue) {
|
|
2779
2783
|
handleEntryFound(childEntryInfo, { notify });
|
|
2780
2784
|
}
|
|
2781
2785
|
});
|
|
2786
|
+
// we must watch manually every directory we find
|
|
2787
|
+
if (!fsWatchSupportsRecursive) {
|
|
2788
|
+
const watcher = createWatcher(urlToFileSystemPath(entryInfo.url), {
|
|
2789
|
+
persistent: keepProcessAlive,
|
|
2790
|
+
});
|
|
2791
|
+
tracker.registerCleanupCallback(() => {
|
|
2792
|
+
watcher.close();
|
|
2793
|
+
});
|
|
2794
|
+
watcher.on("change", (eventType, filename) => {
|
|
2795
|
+
handleDirectoryEvent({
|
|
2796
|
+
directoryRelativeUrl: entryInfo.relativeUrl,
|
|
2797
|
+
filename: filename
|
|
2798
|
+
? // replace back slashes with slashes
|
|
2799
|
+
filename.replace(/\\/g, "/")
|
|
2800
|
+
: "",
|
|
2801
|
+
eventType,
|
|
2802
|
+
});
|
|
2803
|
+
});
|
|
2804
|
+
}
|
|
2782
2805
|
}
|
|
2783
2806
|
if (added && entryInfo.patternValue && notify) {
|
|
2784
2807
|
added({
|
|
2785
2808
|
relativeUrl: entryInfo.relativeUrl,
|
|
2786
2809
|
type: entryInfo.type,
|
|
2787
2810
|
patternValue: entryInfo.patternValue,
|
|
2788
|
-
mtime: entryInfo.mtimeMs,
|
|
2811
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
2789
2812
|
});
|
|
2790
2813
|
}
|
|
2791
2814
|
};
|
|
@@ -2796,19 +2819,19 @@ const registerDirectoryLifecycle = (
|
|
|
2796
2819
|
relativeUrl: entryInfo.relativeUrl,
|
|
2797
2820
|
type: entryInfo.type,
|
|
2798
2821
|
patternValue: entryInfo.patternValue,
|
|
2799
|
-
mtime: entryInfo.mtimeMs,
|
|
2822
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
2800
2823
|
});
|
|
2801
2824
|
}
|
|
2802
2825
|
};
|
|
2803
2826
|
const handleEntryUpdated = (entryInfo) => {
|
|
2804
2827
|
infoMap.set(entryInfo.relativeUrl, entryInfo);
|
|
2805
|
-
if (updated && entryInfo.patternValue) {
|
|
2828
|
+
if (updated && entryInfo.patternValue && shouldCallUpdated(entryInfo)) {
|
|
2806
2829
|
updated({
|
|
2807
2830
|
relativeUrl: entryInfo.relativeUrl,
|
|
2808
2831
|
type: entryInfo.type,
|
|
2809
2832
|
patternValue: entryInfo.patternValue,
|
|
2810
|
-
mtime: entryInfo.mtimeMs,
|
|
2811
|
-
previousMtime: entryInfo.previousInfo.mtimeMs,
|
|
2833
|
+
mtime: entryInfo.stat.mtimeMs,
|
|
2834
|
+
previousMtime: entryInfo.previousInfo.stat.mtimeMs,
|
|
2812
2835
|
});
|
|
2813
2836
|
}
|
|
2814
2837
|
};
|
|
@@ -2816,7 +2839,7 @@ const registerDirectoryLifecycle = (
|
|
|
2816
2839
|
readdirSync(new URL(sourceUrl)).forEach((entry) => {
|
|
2817
2840
|
const entryUrl = new URL(entry, sourceUrl).href;
|
|
2818
2841
|
const entryInfo = readEntryInfo(entryUrl);
|
|
2819
|
-
if (entryInfo && entryInfo.patternValue) {
|
|
2842
|
+
if (entryInfo.type !== null && entryInfo.patternValue) {
|
|
2820
2843
|
handleEntryFound(entryInfo, {
|
|
2821
2844
|
notify: notifyExistent,
|
|
2822
2845
|
});
|
|
@@ -2850,6 +2873,20 @@ ${relativeUrls.join("\n")}`,
|
|
|
2850
2873
|
return tracker.cleanup;
|
|
2851
2874
|
};
|
|
2852
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
|
+
|
|
2853
2890
|
const undefinedOrFunction = (value) => {
|
|
2854
2891
|
return typeof value === "undefined" || typeof value === "function";
|
|
2855
2892
|
};
|
|
@@ -13214,6 +13251,7 @@ const createUrlInfoTransformer = ({
|
|
|
13214
13251
|
generatedUrlObject.searchParams.delete("as_json_module");
|
|
13215
13252
|
generatedUrlObject.searchParams.delete("as_text_module");
|
|
13216
13253
|
generatedUrlObject.searchParams.delete("dynamic_import");
|
|
13254
|
+
generatedUrlObject.searchParams.delete("cjs_as_js_module");
|
|
13217
13255
|
const urlForSourcemap = generatedUrlObject.href;
|
|
13218
13256
|
urlInfo.sourcemapGeneratedUrl = generateSourcemapFileUrl(urlForSourcemap);
|
|
13219
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": {
|
|
@@ -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.3.
|
|
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
|
|