@jsenv/core 40.1.6 → 40.2.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.
@@ -1,7 +1,7 @@
1
1
  import { parseHtml, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, stringifyHtmlAst, applyBabelPlugins, generateUrlForInlineContent, parseJsWithAcorn, visitHtmlNodes, analyzeScriptNode, getHtmlNodeText, getHtmlNodeAttribute, getHtmlNodePosition, getUrlForContentInsideHtml, setHtmlNodeAttributes, setHtmlNodeText, parseCssUrls, getHtmlNodeAttributePosition, parseSrcSet, removeHtmlNodeText, parseJsUrls, getUrlForContentInsideJs, analyzeLinkNode, injectJsenvScript, findHtmlNode, removeHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
2
2
  import { memoryUsage } from "node:process";
3
3
  import { readFileSync, existsSync, readdirSync, lstatSync, realpathSync } from "node:fs";
4
- import { lookupPackageDirectory$1 as lookupPackageDirectory, registerDirectoryLifecycle$1 as registerDirectoryLifecycle, urlToRelativeUrl$1 as urlToRelativeUrl, createDetailedMessage$1 as createDetailedMessage, stringifyUrlSite$1 as stringifyUrlSite, generateContentFrame$1 as generateContentFrame, validateResponseIntegrity$1 as validateResponseIntegrity, urlIsInsideOf$1 as urlIsInsideOf, ensureWindowsDriveLetter$1 as ensureWindowsDriveLetter, setUrlFilename$1 as setUrlFilename, moveUrl$1 as moveUrl, getCallerPosition$1 as getCallerPosition, urlToBasename$1 as urlToBasename, urlToExtension$1 as urlToExtension, asSpecifierWithoutSearch$1 as asSpecifierWithoutSearch, asUrlWithoutSearch$1 as asUrlWithoutSearch, injectQueryParamsIntoSpecifier$1 as injectQueryParamsIntoSpecifier, bufferToEtag$1 as bufferToEtag, isFileSystemPath$1 as isFileSystemPath, urlToPathname$1 as urlToPathname, setUrlBasename$1 as setUrlBasename, urlToFileSystemPath$1 as urlToFileSystemPath, writeFileSync$1 as writeFileSync, createLogger$1 as createLogger, URL_META$1 as URL_META, applyNodeEsmResolution$1 as applyNodeEsmResolution, RUNTIME_COMPAT$1 as RUNTIME_COMPAT, normalizeUrl$1 as normalizeUrl, ANSI$1 as ANSI, CONTENT_TYPE$1 as CONTENT_TYPE, urlToFilename$1 as urlToFilename, DATA_URL$1 as DATA_URL, normalizeImportMap$1 as normalizeImportMap, composeTwoImportMaps$1 as composeTwoImportMaps, resolveImport$1 as resolveImport, JS_QUOTES$1 as JS_QUOTES, defaultLookupPackageScope$1 as defaultLookupPackageScope, defaultReadPackageJson$1 as defaultReadPackageJson, readCustomConditionsFromProcessArgs$1 as readCustomConditionsFromProcessArgs, readEntryStatSync$1 as readEntryStatSync, ensurePathnameTrailingSlash$1 as ensurePathnameTrailingSlash, compareFileUrls$1 as compareFileUrls, applyFileSystemMagicResolution$1 as applyFileSystemMagicResolution, getExtensionsToTry$1 as getExtensionsToTry, setUrlExtension$1 as setUrlExtension, jsenvPluginTranspilation$1 as jsenvPluginTranspilation, renderDetails, humanizeDuration, humanizeFileSize, renderTable, renderBigSection, distributePercentages, humanizeMemory, comparePathnames, UNICODE, escapeRegexpSpecialChars, injectQueryParamIntoSpecifierWithoutEncoding, renderUrlOrRelativeUrlFilename, assertAndNormalizeDirectoryUrl$1 as assertAndNormalizeDirectoryUrl, Abort, raceProcessTeardownEvents, startMonitoringCpuUsage, startMonitoringMemoryUsage, inferRuntimeCompatFromClosestPackage, browserDefaultRuntimeCompat, nodeDefaultRuntimeCompat, clearDirectorySync, createTaskLog$1 as createTaskLog, jsenvPluginBundling, jsenvPluginMinification, ensureEmptyDirectory, jsenvPluginJsModuleFallback, createDynamicLog } from "../jsenv_core_packages.js";
4
+ import { lookupPackageDirectory$1 as lookupPackageDirectory, registerDirectoryLifecycle$1 as registerDirectoryLifecycle, urlToRelativeUrl$1 as urlToRelativeUrl, createDetailedMessage$1 as createDetailedMessage, stringifyUrlSite$1 as stringifyUrlSite, generateContentFrame$1 as generateContentFrame, validateResponseIntegrity$1 as validateResponseIntegrity, urlIsInsideOf$1 as urlIsInsideOf, ensureWindowsDriveLetter$1 as ensureWindowsDriveLetter, setUrlFilename$1 as setUrlFilename, moveUrl$1 as moveUrl, getCallerPosition$1 as getCallerPosition, urlToBasename$1 as urlToBasename, urlToExtension$1 as urlToExtension, asSpecifierWithoutSearch$1 as asSpecifierWithoutSearch, asUrlWithoutSearch$1 as asUrlWithoutSearch, injectQueryParamsIntoSpecifier$1 as injectQueryParamsIntoSpecifier, bufferToEtag$1 as bufferToEtag, isFileSystemPath$1 as isFileSystemPath, urlToPathname$1 as urlToPathname, setUrlBasename$1 as setUrlBasename, urlToFileSystemPath$1 as urlToFileSystemPath, writeFileSync$1 as writeFileSync, createLogger$1 as createLogger, URL_META$1 as URL_META, applyNodeEsmResolution$1 as applyNodeEsmResolution, RUNTIME_COMPAT$1 as RUNTIME_COMPAT, normalizeUrl$1 as normalizeUrl, ANSI$1 as ANSI, CONTENT_TYPE$1 as CONTENT_TYPE, urlToFilename$1 as urlToFilename, DATA_URL$1 as DATA_URL, normalizeImportMap$1 as normalizeImportMap, composeTwoImportMaps$1 as composeTwoImportMaps, resolveImport$1 as resolveImport, JS_QUOTES$1 as JS_QUOTES, defaultLookupPackageScope$1 as defaultLookupPackageScope, defaultReadPackageJson$1 as defaultReadPackageJson, readCustomConditionsFromProcessArgs$1 as readCustomConditionsFromProcessArgs, readEntryStatSync$1 as readEntryStatSync, ensurePathnameTrailingSlash$1 as ensurePathnameTrailingSlash, compareFileUrls$1 as compareFileUrls, applyFileSystemMagicResolution$1 as applyFileSystemMagicResolution, getExtensionsToTry$1 as getExtensionsToTry, setUrlExtension$1 as setUrlExtension, jsenvPluginTranspilation$1 as jsenvPluginTranspilation, renderDetails, humanizeDuration, humanizeFileSize, renderTable, renderBigSection, distributePercentages, humanizeMemory, comparePathnames, UNICODE, escapeRegexpSpecialChars, injectQueryParamIntoSpecifierWithoutEncoding, renderUrlOrRelativeUrlFilename, assertAndNormalizeDirectoryUrl$1 as assertAndNormalizeDirectoryUrl, Abort, raceProcessTeardownEvents, startMonitoringCpuUsage, startMonitoringMemoryUsage, readPackageAtOrNull, inferRuntimeCompatFromClosestPackage, browserDefaultRuntimeCompat, nodeDefaultRuntimeCompat, clearDirectorySync, createTaskLog$1 as createTaskLog, jsenvPluginBundling, jsenvPluginMinification, ensureEmptyDirectory, jsenvPluginJsModuleFallback, createDynamicLog } from "../jsenv_core_packages.js";
5
5
  import { pathToFileURL } from "node:url";
6
6
  import { generateSourcemapFileUrl, createMagicSource, composeTwoSourcemaps, generateSourcemapDataUrl, SOURCEMAP } from "@jsenv/sourcemap";
7
7
  import { performance } from "node:perf_hooks";
@@ -8122,7 +8122,7 @@ const jsenvPluginChromeDevtoolsJson = () => {
8122
8122
  appliesDuring: "dev",
8123
8123
  devServerRoutes: [
8124
8124
  {
8125
- route: "GET /.well-known/appspecific/com.chrome.devtools.json",
8125
+ endpoint: "GET /.well-known/appspecific/com.chrome.devtools.json",
8126
8126
  fetch: (request, { kitchen }) => {
8127
8127
  const { rootDirectoryUrl } = kitchen.context;
8128
8128
  return Response.json({
@@ -8137,6 +8137,39 @@ const jsenvPluginChromeDevtoolsJson = () => {
8137
8137
  };
8138
8138
  };
8139
8139
 
8140
+ const jsenvPluginAutoreloadOnServerRestart = () => {
8141
+ const autoreloadOnRestartClientFileUrl = import.meta.resolve(
8142
+ "@jsenv/server/src/services/autoreload_on_server_restart/client/autoreload_on_server_restart.js",
8143
+ );
8144
+
8145
+ return {
8146
+ name: "jsenv:autoreload_on_server_restart",
8147
+ appliesDuring: "dev",
8148
+ transformUrlContent: {
8149
+ html: (urlInfo) => {
8150
+ // we should not do this for inspector and 4xx.html
8151
+ const htmlAst = parseHtml({
8152
+ html: urlInfo.content,
8153
+ url: urlInfo.url,
8154
+ });
8155
+ const autoreloadOnRestartClientFileReference =
8156
+ urlInfo.dependencies.inject({
8157
+ type: "script",
8158
+ subtype: "js_classic",
8159
+ expectedType: "js_classic",
8160
+ specifier: autoreloadOnRestartClientFileUrl,
8161
+ });
8162
+ injectJsenvScript(htmlAst, {
8163
+ "src": autoreloadOnRestartClientFileReference.generatedSpecifier,
8164
+ "pluginName": "jsenv:autoreload_on_server_restart",
8165
+ "data-ws-endpoint": "/.internal/events.websocket",
8166
+ });
8167
+ return stringifyHtmlAst(htmlAst);
8168
+ },
8169
+ },
8170
+ };
8171
+ };
8172
+
8140
8173
  // tslint:disable:ordered-imports
8141
8174
 
8142
8175
 
@@ -8160,6 +8193,7 @@ const getCorePlugins = ({
8160
8193
  http = false,
8161
8194
 
8162
8195
  clientAutoreload,
8196
+ clientAutoreloadOnServerRestart,
8163
8197
  cacheControl,
8164
8198
  scenarioPlaceholders = true,
8165
8199
  ribbon = true,
@@ -8229,6 +8263,9 @@ const getCorePlugins = ({
8229
8263
 
8230
8264
  // "jsenvPluginSupervisor" MUST be after "jsenvPluginInlining" as it needs inline script to be cooked
8231
8265
  ...(supervisor ? [jsenvPluginSupervisor(supervisor)] : []),
8266
+ ...(clientAutoreloadOnServerRestart
8267
+ ? [jsenvPluginAutoreloadOnServerRestart()]
8268
+ : []),
8232
8269
 
8233
8270
  jsenvPluginCommonJsGlobals(),
8234
8271
  jsenvPluginImportMetaScenarios(),
@@ -8669,6 +8706,7 @@ const createBuildSpecifierManager = ({
8669
8706
  versioningMethod,
8670
8707
  versionLength,
8671
8708
  canUseImportmap,
8709
+ onSourceFileBuild,
8672
8710
  }) => {
8673
8711
  const placeholderAPI = createPlaceholderAPI({
8674
8712
  length,
@@ -8680,18 +8718,18 @@ const createBuildSpecifierManager = ({
8680
8718
 
8681
8719
  const generateReplacement = (reference) => {
8682
8720
  let buildUrl;
8721
+ const buildUrlInfo = reference.urlInfo;
8683
8722
  if (reference.type === "sourcemap_comment") {
8684
8723
  const parentBuildUrl = urlInfoToBuildUrlMap.get(reference.ownerUrlInfo);
8685
8724
  buildUrl = generateSourcemapFileUrl(parentBuildUrl);
8686
8725
  reference.generatedSpecifier = buildUrl;
8687
8726
  } else {
8688
8727
  const url = reference.generatedUrl;
8689
- let urlInfo;
8690
8728
  const rawUrlInfo = rawKitchen.graph.getUrlInfo(reference.url);
8729
+ let urlInfo;
8691
8730
  if (rawUrlInfo) {
8692
8731
  urlInfo = rawUrlInfo;
8693
8732
  } else {
8694
- const buildUrlInfo = reference.urlInfo;
8695
8733
  buildUrlInfo.type = reference.expectedType || "asset";
8696
8734
  buildUrlInfo.subtype = reference.expectedSubtype;
8697
8735
  urlInfo = buildUrlInfo;
@@ -8735,6 +8773,31 @@ const createBuildSpecifierManager = ({
8735
8773
  buildSpecifier,
8736
8774
  reference,
8737
8775
  );
8776
+
8777
+ if (buildUrlInfo.sourceUrls) {
8778
+ for (const sourceUrl of buildUrlInfo.sourceUrls) {
8779
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(sourceUrl);
8780
+ if (rawUrlInfo) {
8781
+ onSourceFileBuild({
8782
+ sourceUrlInfo: rawUrlInfo,
8783
+ buildUrlInfo,
8784
+ sourceFileUrl: rawUrlInfo.url,
8785
+ buildFileUrl: buildUrl,
8786
+ });
8787
+ }
8788
+ }
8789
+ } else if (buildUrlInfo.originalUrl) {
8790
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(buildUrlInfo.originalUrl);
8791
+ if (rawUrlInfo) {
8792
+ onSourceFileBuild({
8793
+ sourceUrlInfo: rawUrlInfo,
8794
+ buildUrlInfo,
8795
+ sourceFileUrl: rawUrlInfo.url,
8796
+ buildFileUrl: buildUrl,
8797
+ });
8798
+ }
8799
+ }
8800
+
8738
8801
  return buildGeneratedSpecifier;
8739
8802
  };
8740
8803
  const internalRedirections = new Map();
@@ -8911,6 +8974,7 @@ const createBuildSpecifierManager = ({
8911
8974
  if (!finalUrlInfo.filenameHint && bundleInfo.data.bundleRelativeUrl) {
8912
8975
  finalUrlInfo.filenameHint = bundleInfo.data.bundleRelativeUrl;
8913
8976
  }
8977
+ finalUrlInfo.sourceUrls = bundleInfo.sourceUrls;
8914
8978
  return {
8915
8979
  // url: bundleInfo.url,
8916
8980
  originalUrl: bundleInfo.originalUrl,
@@ -8923,6 +8987,7 @@ const createBuildSpecifierManager = ({
8923
8987
  }
8924
8988
  const rawUrlInfo = rawKitchen.graph.getUrlInfo(rawUrl);
8925
8989
  if (rawUrlInfo) {
8990
+ // if the rawUrl info had
8926
8991
  if (rawUrlInfo.type === "entry_build") {
8927
8992
  const otherEntryBuildInfo = rawUrlInfo.otherEntryBuildInfo;
8928
8993
  if (
@@ -10697,6 +10762,67 @@ const build = async ({
10697
10762
  const startDate = Date.now();
10698
10763
  const { onBuildEnd, onEntryPointBuildStart } = startBuildLogs();
10699
10764
 
10765
+ const sourceFileBuildCallbackMap = new Map();
10766
+ const registerSourceFileBuildEffect = (url, callback) => {
10767
+ const buildCallbackSet = sourceFileBuildCallbackMap.get(url);
10768
+ if (buildCallbackSet) {
10769
+ buildCallbackSet.add(callback);
10770
+ } else {
10771
+ const set = new Set();
10772
+ set.add(callback);
10773
+ sourceFileBuildCallbackMap.set(url, set);
10774
+ }
10775
+ };
10776
+ const onSourceFileBuild = ({ sourceFileUrl, buildFileUrl }) => {
10777
+ const buildCallbackSet = sourceFileBuildCallbackMap.get(sourceFileUrl);
10778
+ if (buildCallbackSet) {
10779
+ for (const buildCallback of buildCallbackSet) {
10780
+ buildCallback({ buildFileUrl });
10781
+ }
10782
+ }
10783
+ };
10784
+ sync_package_side_effects: {
10785
+ if (!packageDirectoryUrl) {
10786
+ break sync_package_side_effects;
10787
+ }
10788
+ const packageJson = readPackageAtOrNull(packageDirectoryUrl);
10789
+ if (!packageJson) {
10790
+ break sync_package_side_effects;
10791
+ }
10792
+ const { sideEffects } = packageJson;
10793
+ if (!sideEffects || !Array.isArray(sideEffects)) {
10794
+ break sync_package_side_effects;
10795
+ }
10796
+ const sideEffectFileUrlSet = new Set();
10797
+ const packageJsonFileUrl = new URL("./package.json", packageDirectoryUrl)
10798
+ .href;
10799
+ for (const sideEffectFileRelativeUrl of sideEffects) {
10800
+ const sideEffectFileUrl = new URL(
10801
+ sideEffectFileRelativeUrl,
10802
+ packageDirectoryUrl,
10803
+ ).href;
10804
+ sideEffectFileUrlSet.add(sideEffectFileUrl);
10805
+ registerSourceFileBuildEffect(sideEffectFileUrl, ({ buildFileUrl }) => {
10806
+ const urlRelativeToPackage = urlToRelativeUrl(
10807
+ buildFileUrl,
10808
+ packageDirectoryUrl,
10809
+ );
10810
+ if (sideEffectFileUrlSet.has(buildFileUrl)) {
10811
+ return;
10812
+ }
10813
+ sideEffects.push(
10814
+ urlRelativeToPackage[0] === "."
10815
+ ? urlRelativeToPackage
10816
+ : `./${urlRelativeToPackage}`,
10817
+ );
10818
+ writeFileSync(
10819
+ packageJsonFileUrl,
10820
+ JSON.stringify(packageJson, null, " "),
10821
+ );
10822
+ });
10823
+ }
10824
+ }
10825
+
10700
10826
  const buildUrlsGenerator = createBuildUrlsGenerator({
10701
10827
  sourceDirectoryUrl,
10702
10828
  buildDirectoryUrl,
@@ -10749,6 +10875,7 @@ const build = async ({
10749
10875
  sourceRelativeUrl: entryPoint.sourceRelativeUrl,
10750
10876
  buildUrlsGenerator,
10751
10877
  someEntryPointUseNode,
10878
+ onSourceFileBuild,
10752
10879
  },
10753
10880
  entryPoint.params,
10754
10881
  );
@@ -10832,12 +10959,10 @@ const build = async ({
10832
10959
  if (writeOnFileSystem) {
10833
10960
  clearDirectorySync(buildDirectoryUrl, buildDirectoryCleanPatterns);
10834
10961
  const buildRelativeUrls = Object.keys(buildFileContents);
10835
- buildRelativeUrls.forEach((buildRelativeUrl) => {
10836
- writeFileSync(
10837
- new URL(buildRelativeUrl, buildDirectoryUrl),
10838
- buildFileContents[buildRelativeUrl],
10839
- );
10840
- });
10962
+ for (const buildRelativeUrl of buildRelativeUrls) {
10963
+ const buildUrl = new URL(buildRelativeUrl, buildDirectoryUrl);
10964
+ writeFileSync(buildUrl, buildFileContents[buildRelativeUrl]);
10965
+ }
10841
10966
  }
10842
10967
  onBuildEnd({
10843
10968
  buildFileContents,
@@ -10973,6 +11098,7 @@ const prepareEntryPointBuild = async (
10973
11098
  outDirectoryUrl,
10974
11099
  buildUrlsGenerator,
10975
11100
  someEntryPointUseNode,
11101
+ onSourceFileBuild,
10976
11102
  },
10977
11103
  entryPointParams,
10978
11104
  ) => {
@@ -11216,6 +11342,7 @@ const prepareEntryPointBuild = async (
11216
11342
  versioningViaImportmap &&
11217
11343
  rawKitchen.graph.getUrlInfo(entryReference.url).type === "html" &&
11218
11344
  rawKitchen.context.isSupportedOnCurrentClients("importmap"),
11345
+ onSourceFileBuild,
11219
11346
  });
11220
11347
  const finalPluginStore = createPluginStore([
11221
11348
  jsenvPluginReferenceAnalysis({
@@ -23677,4 +23677,4 @@ const assertAndNormalizeDirectoryUrl = (
23677
23677
  return value;
23678
23678
  };
23679
23679
 
23680
- export { ANSI$2 as ANSI, ANSI$1, Abort$1 as Abort, Abort as Abort$1, CONTENT_TYPE$1 as CONTENT_TYPE, CONTENT_TYPE as CONTENT_TYPE$1, DATA_URL$1 as DATA_URL, DATA_URL as DATA_URL$1, JS_QUOTES$1 as JS_QUOTES, JS_QUOTES as JS_QUOTES$1, RUNTIME_COMPAT$1 as RUNTIME_COMPAT, RUNTIME_COMPAT as RUNTIME_COMPAT$1, UNICODE$1 as UNICODE, URL_META$1 as URL_META, URL_META as URL_META$1, applyFileSystemMagicResolution$1 as applyFileSystemMagicResolution, applyFileSystemMagicResolution as applyFileSystemMagicResolution$1, applyNodeEsmResolution$1 as applyNodeEsmResolution, applyNodeEsmResolution as applyNodeEsmResolution$1, asSpecifierWithoutSearch$1 as asSpecifierWithoutSearch, asSpecifierWithoutSearch as asSpecifierWithoutSearch$1, asUrlWithoutSearch$1 as asUrlWithoutSearch, asUrlWithoutSearch as asUrlWithoutSearch$1, assertAndNormalizeDirectoryUrl$2 as assertAndNormalizeDirectoryUrl, assertAndNormalizeDirectoryUrl$1, assertAndNormalizeDirectoryUrl as assertAndNormalizeDirectoryUrl$2, browserDefaultRuntimeCompat, bufferToEtag$1 as bufferToEtag, bufferToEtag as bufferToEtag$1, clearDirectorySync, compareFileUrls$1 as compareFileUrls, compareFileUrls as compareFileUrls$1, comparePathnames, composeTwoImportMaps$1 as composeTwoImportMaps, composeTwoImportMaps as composeTwoImportMaps$1, createDetailedMessage$3 as createDetailedMessage, createDetailedMessage$1, createDynamicLog$1 as createDynamicLog, createLogger$2 as createLogger, createLogger$1, createLogger as createLogger$2, createTaskLog$2 as createTaskLog, createTaskLog$1, createTaskLog as createTaskLog$2, defaultLookupPackageScope$1 as defaultLookupPackageScope, defaultLookupPackageScope as defaultLookupPackageScope$1, defaultReadPackageJson$1 as defaultReadPackageJson, defaultReadPackageJson as defaultReadPackageJson$1, distributePercentages, ensureEmptyDirectory, ensurePathnameTrailingSlash$2 as ensurePathnameTrailingSlash, ensurePathnameTrailingSlash$1, ensureWindowsDriveLetter$1 as ensureWindowsDriveLetter, ensureWindowsDriveLetter as ensureWindowsDriveLetter$1, escapeRegexpSpecialChars, generateContentFrame$1 as generateContentFrame, generateContentFrame as generateContentFrame$1, getCallerPosition$1 as getCallerPosition, getCallerPosition as getCallerPosition$1, getExtensionsToTry$1 as getExtensionsToTry, getExtensionsToTry as getExtensionsToTry$1, humanizeDuration$1 as humanizeDuration, humanizeFileSize, humanizeMemory, inferRuntimeCompatFromClosestPackage, injectQueryParamIntoSpecifierWithoutEncoding, injectQueryParamsIntoSpecifier$1 as injectQueryParamsIntoSpecifier, injectQueryParamsIntoSpecifier as injectQueryParamsIntoSpecifier$1, isFileSystemPath$2 as isFileSystemPath, isFileSystemPath$1, jsenvPluginBundling, jsenvPluginJsModuleFallback, jsenvPluginMinification, jsenvPluginTranspilation$1 as jsenvPluginTranspilation, jsenvPluginTranspilation as jsenvPluginTranspilation$1, lookupPackageDirectory$1 as lookupPackageDirectory, lookupPackageDirectory as lookupPackageDirectory$1, memoizeByFirstArgument, moveUrl$1 as moveUrl, moveUrl as moveUrl$1, nodeDefaultRuntimeCompat, normalizeImportMap$1 as normalizeImportMap, normalizeImportMap as normalizeImportMap$1, normalizeUrl$1 as normalizeUrl, normalizeUrl as normalizeUrl$1, raceProcessTeardownEvents$1 as raceProcessTeardownEvents, raceProcessTeardownEvents as raceProcessTeardownEvents$1, readCustomConditionsFromProcessArgs$1 as readCustomConditionsFromProcessArgs, readCustomConditionsFromProcessArgs as readCustomConditionsFromProcessArgs$1, readEntryStatSync$1 as readEntryStatSync, readEntryStatSync as readEntryStatSync$1, registerDirectoryLifecycle$1 as registerDirectoryLifecycle, registerDirectoryLifecycle as registerDirectoryLifecycle$1, renderBigSection, renderDetails, renderTable, renderUrlOrRelativeUrlFilename, resolveImport$1 as resolveImport, resolveImport as resolveImport$1, setUrlBasename$1 as setUrlBasename, setUrlBasename as setUrlBasename$1, setUrlExtension$1 as setUrlExtension, setUrlExtension as setUrlExtension$1, setUrlFilename$1 as setUrlFilename, setUrlFilename as setUrlFilename$1, startMonitoringCpuUsage, startMonitoringMemoryUsage, stringifyUrlSite$1 as stringifyUrlSite, stringifyUrlSite as stringifyUrlSite$1, urlIsInsideOf$1 as urlIsInsideOf, urlIsInsideOf as urlIsInsideOf$1, urlToBasename$1 as urlToBasename, urlToBasename as urlToBasename$1, urlToExtension$4 as urlToExtension, urlToExtension$2 as urlToExtension$1, urlToExtension as urlToExtension$2, urlToFileSystemPath$1 as urlToFileSystemPath, urlToFileSystemPath as urlToFileSystemPath$1, urlToFilename$3 as urlToFilename, urlToFilename$1, urlToPathname$4 as urlToPathname, urlToPathname$2 as urlToPathname$1, urlToPathname as urlToPathname$2, urlToRelativeUrl$1 as urlToRelativeUrl, urlToRelativeUrl as urlToRelativeUrl$1, validateResponseIntegrity$1 as validateResponseIntegrity, validateResponseIntegrity as validateResponseIntegrity$1, writeFileSync$1 as writeFileSync, writeFileSync as writeFileSync$1 };
23680
+ export { ANSI$2 as ANSI, ANSI$1, Abort$1 as Abort, Abort as Abort$1, CONTENT_TYPE$1 as CONTENT_TYPE, CONTENT_TYPE as CONTENT_TYPE$1, DATA_URL$1 as DATA_URL, DATA_URL as DATA_URL$1, JS_QUOTES$1 as JS_QUOTES, JS_QUOTES as JS_QUOTES$1, RUNTIME_COMPAT$1 as RUNTIME_COMPAT, RUNTIME_COMPAT as RUNTIME_COMPAT$1, UNICODE$1 as UNICODE, URL_META$1 as URL_META, URL_META as URL_META$1, applyFileSystemMagicResolution$1 as applyFileSystemMagicResolution, applyFileSystemMagicResolution as applyFileSystemMagicResolution$1, applyNodeEsmResolution$1 as applyNodeEsmResolution, applyNodeEsmResolution as applyNodeEsmResolution$1, asSpecifierWithoutSearch$1 as asSpecifierWithoutSearch, asSpecifierWithoutSearch as asSpecifierWithoutSearch$1, asUrlWithoutSearch$1 as asUrlWithoutSearch, asUrlWithoutSearch as asUrlWithoutSearch$1, assertAndNormalizeDirectoryUrl$2 as assertAndNormalizeDirectoryUrl, assertAndNormalizeDirectoryUrl$1, assertAndNormalizeDirectoryUrl as assertAndNormalizeDirectoryUrl$2, browserDefaultRuntimeCompat, bufferToEtag$1 as bufferToEtag, bufferToEtag as bufferToEtag$1, clearDirectorySync, compareFileUrls$1 as compareFileUrls, compareFileUrls as compareFileUrls$1, comparePathnames, composeTwoImportMaps$1 as composeTwoImportMaps, composeTwoImportMaps as composeTwoImportMaps$1, createDetailedMessage$3 as createDetailedMessage, createDetailedMessage$1, createDynamicLog$1 as createDynamicLog, createLogger$2 as createLogger, createLogger$1, createLogger as createLogger$2, createTaskLog$2 as createTaskLog, createTaskLog$1, createTaskLog as createTaskLog$2, defaultLookupPackageScope$1 as defaultLookupPackageScope, defaultLookupPackageScope as defaultLookupPackageScope$1, defaultReadPackageJson$1 as defaultReadPackageJson, defaultReadPackageJson as defaultReadPackageJson$1, distributePercentages, ensureEmptyDirectory, ensurePathnameTrailingSlash$2 as ensurePathnameTrailingSlash, ensurePathnameTrailingSlash$1, ensureWindowsDriveLetter$1 as ensureWindowsDriveLetter, ensureWindowsDriveLetter as ensureWindowsDriveLetter$1, escapeRegexpSpecialChars, generateContentFrame$1 as generateContentFrame, generateContentFrame as generateContentFrame$1, getCallerPosition$1 as getCallerPosition, getCallerPosition as getCallerPosition$1, getExtensionsToTry$1 as getExtensionsToTry, getExtensionsToTry as getExtensionsToTry$1, humanizeDuration$1 as humanizeDuration, humanizeFileSize, humanizeMemory, inferRuntimeCompatFromClosestPackage, injectQueryParamIntoSpecifierWithoutEncoding, injectQueryParamsIntoSpecifier$1 as injectQueryParamsIntoSpecifier, injectQueryParamsIntoSpecifier as injectQueryParamsIntoSpecifier$1, isFileSystemPath$2 as isFileSystemPath, isFileSystemPath$1, jsenvPluginBundling, jsenvPluginJsModuleFallback, jsenvPluginMinification, jsenvPluginTranspilation$1 as jsenvPluginTranspilation, jsenvPluginTranspilation as jsenvPluginTranspilation$1, lookupPackageDirectory$1 as lookupPackageDirectory, lookupPackageDirectory as lookupPackageDirectory$1, memoizeByFirstArgument, moveUrl$1 as moveUrl, moveUrl as moveUrl$1, nodeDefaultRuntimeCompat, normalizeImportMap$1 as normalizeImportMap, normalizeImportMap as normalizeImportMap$1, normalizeUrl$1 as normalizeUrl, normalizeUrl as normalizeUrl$1, raceProcessTeardownEvents$1 as raceProcessTeardownEvents, raceProcessTeardownEvents as raceProcessTeardownEvents$1, readCustomConditionsFromProcessArgs$1 as readCustomConditionsFromProcessArgs, readCustomConditionsFromProcessArgs as readCustomConditionsFromProcessArgs$1, readEntryStatSync$1 as readEntryStatSync, readEntryStatSync as readEntryStatSync$1, readPackageAtOrNull, registerDirectoryLifecycle$1 as registerDirectoryLifecycle, registerDirectoryLifecycle as registerDirectoryLifecycle$1, renderBigSection, renderDetails, renderTable, renderUrlOrRelativeUrlFilename, resolveImport$1 as resolveImport, resolveImport as resolveImport$1, setUrlBasename$1 as setUrlBasename, setUrlBasename as setUrlBasename$1, setUrlExtension$1 as setUrlExtension, setUrlExtension as setUrlExtension$1, setUrlFilename$1 as setUrlFilename, setUrlFilename as setUrlFilename$1, startMonitoringCpuUsage, startMonitoringMemoryUsage, stringifyUrlSite$1 as stringifyUrlSite, stringifyUrlSite as stringifyUrlSite$1, urlIsInsideOf$1 as urlIsInsideOf, urlIsInsideOf as urlIsInsideOf$1, urlToBasename$1 as urlToBasename, urlToBasename as urlToBasename$1, urlToExtension$4 as urlToExtension, urlToExtension$2 as urlToExtension$1, urlToExtension as urlToExtension$2, urlToFileSystemPath$1 as urlToFileSystemPath, urlToFileSystemPath as urlToFileSystemPath$1, urlToFilename$3 as urlToFilename, urlToFilename$1, urlToPathname$4 as urlToPathname, urlToPathname$2 as urlToPathname$1, urlToPathname as urlToPathname$2, urlToRelativeUrl$1 as urlToRelativeUrl, urlToRelativeUrl as urlToRelativeUrl$1, validateResponseIntegrity$1 as validateResponseIntegrity, validateResponseIntegrity as validateResponseIntegrity$1, writeFileSync$1 as writeFileSync, writeFileSync as writeFileSync$1 };
@@ -8163,7 +8163,7 @@ const jsenvPluginChromeDevtoolsJson = () => {
8163
8163
  appliesDuring: "dev",
8164
8164
  devServerRoutes: [
8165
8165
  {
8166
- route: "GET /.well-known/appspecific/com.chrome.devtools.json",
8166
+ endpoint: "GET /.well-known/appspecific/com.chrome.devtools.json",
8167
8167
  fetch: (request, { kitchen }) => {
8168
8168
  const { rootDirectoryUrl } = kitchen.context;
8169
8169
  return Response.json({
@@ -8178,6 +8178,39 @@ const jsenvPluginChromeDevtoolsJson = () => {
8178
8178
  };
8179
8179
  };
8180
8180
 
8181
+ const jsenvPluginAutoreloadOnServerRestart = () => {
8182
+ const autoreloadOnRestartClientFileUrl = import.meta.resolve(
8183
+ "@jsenv/server/src/services/autoreload_on_server_restart/client/autoreload_on_server_restart.js",
8184
+ );
8185
+
8186
+ return {
8187
+ name: "jsenv:autoreload_on_server_restart",
8188
+ appliesDuring: "dev",
8189
+ transformUrlContent: {
8190
+ html: (urlInfo) => {
8191
+ // we should not do this for inspector and 4xx.html
8192
+ const htmlAst = parseHtml({
8193
+ html: urlInfo.content,
8194
+ url: urlInfo.url,
8195
+ });
8196
+ const autoreloadOnRestartClientFileReference =
8197
+ urlInfo.dependencies.inject({
8198
+ type: "script",
8199
+ subtype: "js_classic",
8200
+ expectedType: "js_classic",
8201
+ specifier: autoreloadOnRestartClientFileUrl,
8202
+ });
8203
+ injectJsenvScript(htmlAst, {
8204
+ "src": autoreloadOnRestartClientFileReference.generatedSpecifier,
8205
+ "pluginName": "jsenv:autoreload_on_server_restart",
8206
+ "data-ws-endpoint": "/.internal/events.websocket",
8207
+ });
8208
+ return stringifyHtmlAst(htmlAst);
8209
+ },
8210
+ },
8211
+ };
8212
+ };
8213
+
8181
8214
  // tslint:disable:ordered-imports
8182
8215
 
8183
8216
 
@@ -8201,6 +8234,7 @@ const getCorePlugins = ({
8201
8234
  http = false,
8202
8235
 
8203
8236
  clientAutoreload,
8237
+ clientAutoreloadOnServerRestart,
8204
8238
  cacheControl,
8205
8239
  scenarioPlaceholders = true,
8206
8240
  ribbon = true,
@@ -8270,6 +8304,9 @@ const getCorePlugins = ({
8270
8304
 
8271
8305
  // "jsenvPluginSupervisor" MUST be after "jsenvPluginInlining" as it needs inline script to be cooked
8272
8306
  ...(supervisor ? [jsenvPluginSupervisor(supervisor)] : []),
8307
+ ...(clientAutoreloadOnServerRestart
8308
+ ? [jsenvPluginAutoreloadOnServerRestart()]
8309
+ : []),
8273
8310
 
8274
8311
  jsenvPluginCommonJsGlobals(),
8275
8312
  jsenvPluginImportMetaScenarios(),
@@ -8455,6 +8492,7 @@ const startDevServer = async ({
8455
8492
 
8456
8493
  sourceFilesConfig = {},
8457
8494
  clientAutoreload = true,
8495
+ clientAutoreloadOnServerRestart = true,
8458
8496
 
8459
8497
  // runtimeCompat is the runtimeCompat for the build
8460
8498
  // when specified, dev server use it to warn in case
@@ -8636,6 +8674,7 @@ const startDevServer = async ({
8636
8674
  transpilation,
8637
8675
 
8638
8676
  clientAutoreload,
8677
+ clientAutoreloadOnServerRestart,
8639
8678
  cacheControl,
8640
8679
  ribbon,
8641
8680
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "40.1.6",
3
+ "version": "40.2.0",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -90,7 +90,7 @@
90
90
  "@jsenv/plugin-minification": "1.6.2",
91
91
  "@jsenv/plugin-supervisor": "1.6.12",
92
92
  "@jsenv/plugin-transpilation": "1.5.9",
93
- "@jsenv/server": "16.0.6",
93
+ "@jsenv/server": "16.0.7",
94
94
  "@jsenv/sourcemap": "1.3.4",
95
95
  "@jsenv/url-meta": "8.5.6",
96
96
  "@jsenv/urls": "2.7.1",
@@ -24,6 +24,7 @@ import {
24
24
  compareFileUrls,
25
25
  ensureEmptyDirectory,
26
26
  lookupPackageDirectory,
27
+ readPackageAtOrNull,
27
28
  writeFileSync,
28
29
  } from "@jsenv/filesystem";
29
30
  import {
@@ -515,6 +516,67 @@ export const build = async ({
515
516
  const startDate = Date.now();
516
517
  const { onBuildEnd, onEntryPointBuildStart } = startBuildLogs();
517
518
 
519
+ const sourceFileBuildCallbackMap = new Map();
520
+ const registerSourceFileBuildEffect = (url, callback) => {
521
+ const buildCallbackSet = sourceFileBuildCallbackMap.get(url);
522
+ if (buildCallbackSet) {
523
+ buildCallbackSet.add(callback);
524
+ } else {
525
+ const set = new Set();
526
+ set.add(callback);
527
+ sourceFileBuildCallbackMap.set(url, set);
528
+ }
529
+ };
530
+ const onSourceFileBuild = ({ sourceFileUrl, buildFileUrl }) => {
531
+ const buildCallbackSet = sourceFileBuildCallbackMap.get(sourceFileUrl);
532
+ if (buildCallbackSet) {
533
+ for (const buildCallback of buildCallbackSet) {
534
+ buildCallback({ buildFileUrl });
535
+ }
536
+ }
537
+ };
538
+ sync_package_side_effects: {
539
+ if (!packageDirectoryUrl) {
540
+ break sync_package_side_effects;
541
+ }
542
+ const packageJson = readPackageAtOrNull(packageDirectoryUrl);
543
+ if (!packageJson) {
544
+ break sync_package_side_effects;
545
+ }
546
+ const { sideEffects } = packageJson;
547
+ if (!sideEffects || !Array.isArray(sideEffects)) {
548
+ break sync_package_side_effects;
549
+ }
550
+ const sideEffectFileUrlSet = new Set();
551
+ const packageJsonFileUrl = new URL("./package.json", packageDirectoryUrl)
552
+ .href;
553
+ for (const sideEffectFileRelativeUrl of sideEffects) {
554
+ const sideEffectFileUrl = new URL(
555
+ sideEffectFileRelativeUrl,
556
+ packageDirectoryUrl,
557
+ ).href;
558
+ sideEffectFileUrlSet.add(sideEffectFileUrl);
559
+ registerSourceFileBuildEffect(sideEffectFileUrl, ({ buildFileUrl }) => {
560
+ const urlRelativeToPackage = urlToRelativeUrl(
561
+ buildFileUrl,
562
+ packageDirectoryUrl,
563
+ );
564
+ if (sideEffectFileUrlSet.has(buildFileUrl)) {
565
+ return;
566
+ }
567
+ sideEffects.push(
568
+ urlRelativeToPackage[0] === "."
569
+ ? urlRelativeToPackage
570
+ : `./${urlRelativeToPackage}`,
571
+ );
572
+ writeFileSync(
573
+ packageJsonFileUrl,
574
+ JSON.stringify(packageJson, null, " "),
575
+ );
576
+ });
577
+ }
578
+ }
579
+
518
580
  const buildUrlsGenerator = createBuildUrlsGenerator({
519
581
  sourceDirectoryUrl,
520
582
  buildDirectoryUrl,
@@ -567,6 +629,7 @@ export const build = async ({
567
629
  sourceRelativeUrl: entryPoint.sourceRelativeUrl,
568
630
  buildUrlsGenerator,
569
631
  someEntryPointUseNode,
632
+ onSourceFileBuild,
570
633
  },
571
634
  entryPoint.params,
572
635
  );
@@ -650,12 +713,10 @@ export const build = async ({
650
713
  if (writeOnFileSystem) {
651
714
  clearDirectorySync(buildDirectoryUrl, buildDirectoryCleanPatterns);
652
715
  const buildRelativeUrls = Object.keys(buildFileContents);
653
- buildRelativeUrls.forEach((buildRelativeUrl) => {
654
- writeFileSync(
655
- new URL(buildRelativeUrl, buildDirectoryUrl),
656
- buildFileContents[buildRelativeUrl],
657
- );
658
- });
716
+ for (const buildRelativeUrl of buildRelativeUrls) {
717
+ const buildUrl = new URL(buildRelativeUrl, buildDirectoryUrl);
718
+ writeFileSync(buildUrl, buildFileContents[buildRelativeUrl]);
719
+ }
659
720
  }
660
721
  onBuildEnd({
661
722
  buildFileContents,
@@ -791,6 +852,7 @@ const prepareEntryPointBuild = async (
791
852
  outDirectoryUrl,
792
853
  buildUrlsGenerator,
793
854
  someEntryPointUseNode,
855
+ onSourceFileBuild,
794
856
  },
795
857
  entryPointParams,
796
858
  ) => {
@@ -1034,6 +1096,7 @@ const prepareEntryPointBuild = async (
1034
1096
  versioningViaImportmap &&
1035
1097
  rawKitchen.graph.getUrlInfo(entryReference.url).type === "html" &&
1036
1098
  rawKitchen.context.isSupportedOnCurrentClients("importmap"),
1099
+ onSourceFileBuild,
1037
1100
  });
1038
1101
  const finalPluginStore = createPluginStore([
1039
1102
  jsenvPluginReferenceAnalysis({
@@ -20,9 +20,8 @@ import {
20
20
  urlToRelativeUrl,
21
21
  } from "@jsenv/urls";
22
22
  import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
23
- import { createHash } from "node:crypto";
24
-
25
23
  import { escapeRegexpSpecialChars } from "@jsenv/utils/src/string/escape_regexp_special_chars.js";
24
+ import { createHash } from "node:crypto";
26
25
  import { prependContent } from "../kitchen/prepend_content.js";
27
26
  import { GRAPH_VISITOR } from "../kitchen/url_graph/url_graph_visitor.js";
28
27
  import { isWebWorkerUrlInfo } from "../kitchen/web_workers.js";
@@ -46,6 +45,7 @@ export const createBuildSpecifierManager = ({
46
45
  versioningMethod,
47
46
  versionLength,
48
47
  canUseImportmap,
48
+ onSourceFileBuild,
49
49
  }) => {
50
50
  const placeholderAPI = createPlaceholderAPI({
51
51
  length,
@@ -57,18 +57,18 @@ export const createBuildSpecifierManager = ({
57
57
 
58
58
  const generateReplacement = (reference) => {
59
59
  let buildUrl;
60
+ const buildUrlInfo = reference.urlInfo;
60
61
  if (reference.type === "sourcemap_comment") {
61
62
  const parentBuildUrl = urlInfoToBuildUrlMap.get(reference.ownerUrlInfo);
62
63
  buildUrl = generateSourcemapFileUrl(parentBuildUrl);
63
64
  reference.generatedSpecifier = buildUrl;
64
65
  } else {
65
66
  const url = reference.generatedUrl;
66
- let urlInfo;
67
67
  const rawUrlInfo = rawKitchen.graph.getUrlInfo(reference.url);
68
+ let urlInfo;
68
69
  if (rawUrlInfo) {
69
70
  urlInfo = rawUrlInfo;
70
71
  } else {
71
- const buildUrlInfo = reference.urlInfo;
72
72
  buildUrlInfo.type = reference.expectedType || "asset";
73
73
  buildUrlInfo.subtype = reference.expectedSubtype;
74
74
  urlInfo = buildUrlInfo;
@@ -112,6 +112,31 @@ export const createBuildSpecifierManager = ({
112
112
  buildSpecifier,
113
113
  reference,
114
114
  );
115
+
116
+ if (buildUrlInfo.sourceUrls) {
117
+ for (const sourceUrl of buildUrlInfo.sourceUrls) {
118
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(sourceUrl);
119
+ if (rawUrlInfo) {
120
+ onSourceFileBuild({
121
+ sourceUrlInfo: rawUrlInfo,
122
+ buildUrlInfo,
123
+ sourceFileUrl: rawUrlInfo.url,
124
+ buildFileUrl: buildUrl,
125
+ });
126
+ }
127
+ }
128
+ } else if (buildUrlInfo.originalUrl) {
129
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(buildUrlInfo.originalUrl);
130
+ if (rawUrlInfo) {
131
+ onSourceFileBuild({
132
+ sourceUrlInfo: rawUrlInfo,
133
+ buildUrlInfo,
134
+ sourceFileUrl: rawUrlInfo.url,
135
+ buildFileUrl: buildUrl,
136
+ });
137
+ }
138
+ }
139
+
115
140
  return buildGeneratedSpecifier;
116
141
  };
117
142
  const internalRedirections = new Map();
@@ -288,6 +313,7 @@ export const createBuildSpecifierManager = ({
288
313
  if (!finalUrlInfo.filenameHint && bundleInfo.data.bundleRelativeUrl) {
289
314
  finalUrlInfo.filenameHint = bundleInfo.data.bundleRelativeUrl;
290
315
  }
316
+ finalUrlInfo.sourceUrls = bundleInfo.sourceUrls;
291
317
  return {
292
318
  // url: bundleInfo.url,
293
319
  originalUrl: bundleInfo.originalUrl,
@@ -300,6 +326,7 @@ export const createBuildSpecifierManager = ({
300
326
  }
301
327
  const rawUrlInfo = rawKitchen.graph.getUrlInfo(rawUrl);
302
328
  if (rawUrlInfo) {
329
+ // if the rawUrl info had
303
330
  if (rawUrlInfo.type === "entry_build") {
304
331
  const otherEntryBuildInfo = rawUrlInfo.otherEntryBuildInfo;
305
332
  if (
@@ -76,6 +76,7 @@ export const startDevServer = async ({
76
76
 
77
77
  sourceFilesConfig = {},
78
78
  clientAutoreload = true,
79
+ clientAutoreloadOnServerRestart = true,
79
80
 
80
81
  // runtimeCompat is the runtimeCompat for the build
81
82
  // when specified, dev server use it to warn in case
@@ -258,6 +259,7 @@ export const startDevServer = async ({
258
259
  transpilation,
259
260
 
260
261
  clientAutoreload,
262
+ clientAutoreloadOnServerRestart,
261
263
  cacheControl,
262
264
  ribbon,
263
265
  }),
@@ -0,0 +1,34 @@
1
+ import { injectJsenvScript, parseHtml, stringifyHtmlAst } from "@jsenv/ast";
2
+
3
+ export const jsenvPluginAutoreloadOnServerRestart = () => {
4
+ const autoreloadOnRestartClientFileUrl = import.meta.resolve(
5
+ "@jsenv/server/src/services/autoreload_on_server_restart/client/autoreload_on_server_restart.js",
6
+ );
7
+
8
+ return {
9
+ name: "jsenv:autoreload_on_server_restart",
10
+ appliesDuring: "dev",
11
+ transformUrlContent: {
12
+ html: (urlInfo) => {
13
+ // we should not do this for inspector and 4xx.html
14
+ const htmlAst = parseHtml({
15
+ html: urlInfo.content,
16
+ url: urlInfo.url,
17
+ });
18
+ const autoreloadOnRestartClientFileReference =
19
+ urlInfo.dependencies.inject({
20
+ type: "script",
21
+ subtype: "js_classic",
22
+ expectedType: "js_classic",
23
+ specifier: autoreloadOnRestartClientFileUrl,
24
+ });
25
+ injectJsenvScript(htmlAst, {
26
+ "src": autoreloadOnRestartClientFileReference.generatedSpecifier,
27
+ "pluginName": "jsenv:autoreload_on_server_restart",
28
+ "data-ws-endpoint": "/.internal/events.websocket",
29
+ });
30
+ return stringifyHtmlAst(htmlAst);
31
+ },
32
+ },
33
+ };
34
+ };
@@ -27,7 +27,7 @@ export const jsenvPluginChromeDevtoolsJson = () => {
27
27
  appliesDuring: "dev",
28
28
  devServerRoutes: [
29
29
  {
30
- route: "GET /.well-known/appspecific/com.chrome.devtools.json",
30
+ endpoint: "GET /.well-known/appspecific/com.chrome.devtools.json",
31
31
  fetch: (request, { kitchen }) => {
32
32
  const { rootDirectoryUrl } = kitchen.context;
33
33
  return Response.json({
@@ -24,6 +24,7 @@ import { jsenvPluginCacheControl } from "./cache_control/jsenv_plugin_cache_cont
24
24
  import { jsenvPluginRibbon } from "./ribbon/jsenv_plugin_ribbon.js";
25
25
  import { jsenvPluginCleanHTML } from "./clean_html/jsenv_plugin_clean_html.js";
26
26
  import { jsenvPluginChromeDevtoolsJson } from "./chrome_devtools_json/jsenv_plugin_chrome_devtools_json.js";
27
+ import { jsenvPluginAutoreloadOnServerRestart } from "./autoreload_on_server_restart/jsenv_plugin_autoreload_on_server_restart.js";
27
28
 
28
29
  export const getCorePlugins = ({
29
30
  rootDirectoryUrl,
@@ -45,6 +46,7 @@ export const getCorePlugins = ({
45
46
  http = false,
46
47
 
47
48
  clientAutoreload,
49
+ clientAutoreloadOnServerRestart,
48
50
  cacheControl,
49
51
  scenarioPlaceholders = true,
50
52
  ribbon = true,
@@ -114,6 +116,9 @@ export const getCorePlugins = ({
114
116
 
115
117
  // "jsenvPluginSupervisor" MUST be after "jsenvPluginInlining" as it needs inline script to be cooked
116
118
  ...(supervisor ? [jsenvPluginSupervisor(supervisor)] : []),
119
+ ...(clientAutoreloadOnServerRestart
120
+ ? [jsenvPluginAutoreloadOnServerRestart()]
121
+ : []),
117
122
 
118
123
  jsenvPluginCommonJsGlobals(),
119
124
  jsenvPluginImportMetaScenarios(),