@jsenv/core 40.7.0 → 40.7.2

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.
@@ -4,7 +4,7 @@ import { jsenvPluginMinification } from "@jsenv/plugin-minification";
4
4
  import { jsenvPluginTranspilation, jsenvPluginJsModuleFallback } from "@jsenv/plugin-transpilation";
5
5
  import { memoryUsage } from "node:process";
6
6
  import { readFileSync, existsSync, readdirSync, lstatSync, realpathSync } from "node:fs";
7
- import { lookupPackageDirectory, registerDirectoryLifecycle, urlToRelativeUrl, createDetailedMessage, stringifyUrlSite, generateContentFrame, validateResponseIntegrity, urlIsInsideOf, ensureWindowsDriveLetter, setUrlFilename, moveUrl, getCallerPosition, urlToBasename, urlToExtension, asSpecifierWithoutSearch, asUrlWithoutSearch, injectQueryParamsIntoSpecifier, bufferToEtag, isFileSystemPath, urlToPathname, setUrlBasename, urlToFileSystemPath, writeFileSync, createLogger, URL_META, applyNodeEsmResolution, RUNTIME_COMPAT, normalizeUrl, ANSI, CONTENT_TYPE, urlToFilename, DATA_URL, errorToHTML, normalizeImportMap, composeTwoImportMaps, resolveImport, JS_QUOTES, defaultLookupPackageScope, defaultReadPackageJson, readCustomConditionsFromProcessArgs, readEntryStatSync, ensurePathnameTrailingSlash, compareFileUrls, applyFileSystemMagicResolution, getExtensionsToTry, setUrlExtension, isSpecifierForNodeBuiltin, renderDetails, humanizeDuration, humanizeFileSize, renderTable, renderBigSection, distributePercentages, humanizeMemory, comparePathnames, UNICODE, escapeRegexpSpecialChars, injectQueryParamIntoSpecifierWithoutEncoding, renderUrlOrRelativeUrlFilename, injectQueryParams, assertAndNormalizeDirectoryUrl, Abort, raceProcessTeardownEvents, startMonitoringCpuUsage, startMonitoringMemoryUsage, createLookupPackageDirectory, readPackageAtOrNull, inferRuntimeCompatFromClosestPackage, browserDefaultRuntimeCompat, nodeDefaultRuntimeCompat, clearDirectorySync, createTaskLog, ensureEmptyDirectory, updateJsonFileSync, createDynamicLog } from "./jsenv_core_packages.js";
7
+ import { lookupPackageDirectory, registerDirectoryLifecycle, urlToRelativeUrl, createDetailedMessage, stringifyUrlSite, generateContentFrame, validateResponseIntegrity, urlIsOrIsInsideOf, ensureWindowsDriveLetter, setUrlFilename, moveUrl, getCallerPosition, urlToBasename, urlToExtension, asSpecifierWithoutSearch, asUrlWithoutSearch, injectQueryParamsIntoSpecifier, bufferToEtag, isFileSystemPath, urlToPathname, setUrlBasename, urlToFileSystemPath, writeFileSync, createLogger, URL_META, applyNodeEsmResolution, RUNTIME_COMPAT, normalizeUrl, ANSI, CONTENT_TYPE, urlToFilename, DATA_URL, errorToHTML, normalizeImportMap, composeTwoImportMaps, resolveImport, JS_QUOTES, defaultLookupPackageScope, defaultReadPackageJson, readCustomConditionsFromProcessArgs, readEntryStatSync, ensurePathnameTrailingSlash, compareFileUrls, applyFileSystemMagicResolution, getExtensionsToTry, setUrlExtension, isSpecifierForNodeBuiltin, renderDetails, humanizeDuration, humanizeFileSize, renderTable, renderBigSection, distributePercentages, humanizeMemory, comparePathnames, UNICODE, escapeRegexpSpecialChars, injectQueryParamIntoSpecifierWithoutEncoding, renderUrlOrRelativeUrlFilename, injectQueryParams, assertAndNormalizeDirectoryUrl, Abort, raceProcessTeardownEvents, startMonitoringCpuUsage, startMonitoringMemoryUsage, createLookupPackageDirectory, readPackageAtOrNull, inferRuntimeCompatFromClosestPackage, browserDefaultRuntimeCompat, nodeDefaultRuntimeCompat, clearDirectorySync, createTaskLog, ensureEmptyDirectory, updateJsonFileSync, createDynamicLog } from "./jsenv_core_packages.js";
8
8
  import { pathToFileURL } from "node:url";
9
9
  import { generateSourcemapFileUrl, createMagicSource, composeTwoSourcemaps, generateSourcemapDataUrl, SOURCEMAP } from "@jsenv/sourcemap";
10
10
  import { performance } from "node:perf_hooks";
@@ -203,6 +203,7 @@ const createFetchUrlContentError = ({
203
203
  const createFailedToFetchUrlContentError = ({
204
204
  code = error.code || "FETCH_URL_CONTENT_ERROR",
205
205
  reason,
206
+ parseErrorSourceType,
206
207
  ...details
207
208
  }) => {
208
209
  const reference = urlInfo.firstReference;
@@ -223,6 +224,7 @@ ${reason}`,
223
224
  name: "FETCH_URL_CONTENT_ERROR",
224
225
  code,
225
226
  reason,
227
+ parseErrorSourceType,
226
228
  url: urlInfo.url,
227
229
  trace: code === "PARSE_ERROR" ? error.trace : reference.trace,
228
230
  asResponse: error.asResponse,
@@ -257,6 +259,7 @@ ${reason}`,
257
259
  return createFailedToFetchUrlContentError({
258
260
  "code": "PARSE_ERROR",
259
261
  "reason": error.reasonCode,
262
+ "parseErrorSourceType": error.parseErrorSourceType,
260
263
  ...(error.cause ? { "parse error message": error.cause.message } : {}),
261
264
  "parse error trace": error.trace?.message,
262
265
  });
@@ -306,7 +309,9 @@ ${error.message}`,
306
309
  name: "TRANSFORM_URL_CONTENT_ERROR",
307
310
  code: "PARSE_ERROR",
308
311
  reason: error.message,
309
- stack: error.stack,
312
+ reasonCode: error.reasonCode,
313
+ parseErrorSourceType: error.parseErrorSourceType,
314
+ stack: transformError.stack,
310
315
  trace,
311
316
  asResponse: error.asResponse,
312
317
  });
@@ -531,7 +536,7 @@ const determineFileUrlForOutDirectory = (urlInfo) => {
531
536
  if (!url.startsWith("file:")) {
532
537
  return url;
533
538
  }
534
- if (!urlIsInsideOf(url, rootDirectoryUrl)) {
539
+ if (!urlIsOrIsInsideOf(url, rootDirectoryUrl)) {
535
540
  const fsRootUrl = ensureWindowsDriveLetter("file:///", url);
536
541
  url = `${rootDirectoryUrl}@fs/${url.slice(fsRootUrl.length)}`;
537
542
  }
@@ -4135,10 +4140,19 @@ const replacePlaceholders = (html, replacers) => {
4135
4140
  });
4136
4141
  };
4137
4142
 
4138
- const createPluginStore = (plugins) => {
4143
+ const createPluginStore = async (plugins) => {
4139
4144
  const allDevServerRoutes = [];
4145
+ const allDevServerServices = [];
4140
4146
  const pluginArray = [];
4141
- const addPlugin = (plugin) => {
4147
+
4148
+ const pluginPromises = [];
4149
+ const addPlugin = async (plugin) => {
4150
+ if (plugin && typeof plugin.then === "function") {
4151
+ pluginPromises.push(plugin);
4152
+ const value = await plugin;
4153
+ addPlugin(value);
4154
+ return;
4155
+ }
4142
4156
  if (Array.isArray(plugin)) {
4143
4157
  for (const subplugin of plugin) {
4144
4158
  addPlugin(subplugin);
@@ -4157,21 +4171,28 @@ const createPluginStore = (plugins) => {
4157
4171
  allDevServerRoutes.push(devServerRoute);
4158
4172
  }
4159
4173
  }
4174
+ if (plugin.devServerServices) {
4175
+ const devServerServices = plugin.devServerServices;
4176
+ for (const devServerService of devServerServices) {
4177
+ allDevServerServices.push(devServerService);
4178
+ }
4179
+ }
4160
4180
  pluginArray.push(plugin);
4161
4181
  };
4162
4182
  addPlugin(jsenvPluginHtmlSyntaxErrorFallback());
4163
4183
  for (const plugin of plugins) {
4164
4184
  addPlugin(plugin);
4165
4185
  }
4186
+ await Promise.all(pluginPromises);
4166
4187
 
4167
4188
  return {
4168
4189
  pluginArray,
4169
-
4170
4190
  allDevServerRoutes,
4191
+ allDevServerServices,
4171
4192
  };
4172
4193
  };
4173
4194
 
4174
- const createPluginController = (
4195
+ const createPluginController = async (
4175
4196
  pluginStore,
4176
4197
  kitchen,
4177
4198
  { initialPuginsMeta = {} } = {},
@@ -4194,7 +4215,7 @@ const createPluginController = (
4194
4215
  pluginCandidate.destroy?.();
4195
4216
  continue;
4196
4217
  }
4197
- const initPluginResult = initPlugin(pluginCandidate, kitchen);
4218
+ const initPluginResult = await initPlugin(pluginCandidate, kitchen);
4198
4219
  if (!initPluginResult) {
4199
4220
  pluginCandidate.destroy?.();
4200
4221
  continue;
@@ -4246,6 +4267,7 @@ const createPluginController = (
4246
4267
  key === "serverEvents" ||
4247
4268
  key === "mustStayFirst" ||
4248
4269
  key === "devServerRoutes" ||
4270
+ key === "devServerServices" ||
4249
4271
  key === "effect"
4250
4272
  ) {
4251
4273
  continue;
@@ -4419,6 +4441,7 @@ const createPluginController = (
4419
4441
  const HOOK_NAMES = [
4420
4442
  "init",
4421
4443
  "devServerRoutes", // is called only during dev/tests
4444
+ "devServerServices", // is called only during dev/tests
4422
4445
  "resolveReference",
4423
4446
  "redirectReference",
4424
4447
  "transformReferenceSearchParams",
@@ -4473,12 +4496,12 @@ const testAppliesDuring = (plugin, kitchen) => {
4473
4496
  `"appliesDuring" must be an object or a string, got ${appliesDuring}`,
4474
4497
  );
4475
4498
  };
4476
- const initPlugin = (plugin, kitchen) => {
4499
+ const initPlugin = async (plugin, kitchen) => {
4477
4500
  const { init } = plugin;
4478
4501
  if (!init) {
4479
4502
  return true;
4480
4503
  }
4481
- const initReturnValue = init(kitchen.context, { plugin });
4504
+ const initReturnValue = await init(kitchen.context, { plugin });
4482
4505
  if (initReturnValue === false) {
4483
4506
  return false;
4484
4507
  }
@@ -6338,10 +6361,7 @@ const jsenvPluginVersionSearchParam = () => {
6338
6361
 
6339
6362
  const FILE_AND_SERVER_URLS_CONVERTER = {
6340
6363
  asServerUrl: (fileUrl, serverRootDirectoryUrl) => {
6341
- if (fileUrl === serverRootDirectoryUrl) {
6342
- return "/";
6343
- }
6344
- if (urlIsInsideOf(fileUrl, serverRootDirectoryUrl)) {
6364
+ if (urlIsOrIsInsideOf(fileUrl, serverRootDirectoryUrl)) {
6345
6365
  const urlRelativeToServer = urlToRelativeUrl(
6346
6366
  fileUrl,
6347
6367
  serverRootDirectoryUrl,
@@ -6397,6 +6417,7 @@ const htmlFileUrlForDirectory = import.meta.resolve(
6397
6417
  );
6398
6418
 
6399
6419
  const jsenvPluginDirectoryListing = ({
6420
+ spa,
6400
6421
  urlMocks = false,
6401
6422
  autoreload = true,
6402
6423
  directoryContentMagicName,
@@ -6438,7 +6459,7 @@ const jsenvPluginDirectoryListing = ({
6438
6459
  return null;
6439
6460
  }
6440
6461
  }
6441
- return `${htmlFileUrlForDirectory}?url=${encodeURIComponent(url)}&enoent`;
6462
+ return `${htmlFileUrlForDirectory}?url=${encodeURIComponent(requestedUrl)}&enoent`;
6442
6463
  }
6443
6464
  const isDirectory = fsStat?.isDirectory();
6444
6465
  if (!isDirectory) {
@@ -6464,21 +6485,22 @@ const jsenvPluginDirectoryListing = ({
6464
6485
  if (urlWithoutSearch !== String(htmlFileUrlForDirectory)) {
6465
6486
  return null;
6466
6487
  }
6467
- const requestedUrl = urlInfo.searchParams.get("url");
6468
- if (!requestedUrl) {
6488
+ const urlNotFound = urlInfo.searchParams.get("url");
6489
+ if (!urlNotFound) {
6469
6490
  return null;
6470
6491
  }
6492
+
6471
6493
  urlInfo.headers["cache-control"] = "no-cache";
6472
6494
  const enoent = urlInfo.searchParams.has("enoent");
6473
6495
  if (enoent) {
6474
6496
  urlInfo.status = 404;
6475
- urlInfo.headers["cache-control"] = "no-cache";
6476
6497
  }
6477
6498
  const request = urlInfo.context.request;
6478
6499
  const { rootDirectoryUrl, mainFilePath } = urlInfo.context;
6479
6500
  const directoryListingInjections = generateDirectoryListingInjection(
6480
- requestedUrl,
6501
+ urlNotFound,
6481
6502
  {
6503
+ spa,
6482
6504
  autoreload,
6483
6505
  request,
6484
6506
  urlMocks,
@@ -6571,8 +6593,9 @@ const jsenvPluginDirectoryListing = ({
6571
6593
  };
6572
6594
 
6573
6595
  const generateDirectoryListingInjection = (
6574
- requestedUrl,
6596
+ urlNotFound,
6575
6597
  {
6598
+ spa,
6576
6599
  rootDirectoryUrl,
6577
6600
  mainFilePath,
6578
6601
  packageDirectory,
@@ -6585,7 +6608,7 @@ const generateDirectoryListingInjection = (
6585
6608
  ) => {
6586
6609
  let serverRootDirectoryUrl = rootDirectoryUrl;
6587
6610
  const firstExistingDirectoryUrl = getFirstExistingDirectoryUrl(
6588
- requestedUrl,
6611
+ urlNotFound,
6589
6612
  serverRootDirectoryUrl,
6590
6613
  );
6591
6614
  const directoryContentItems = getDirectoryContentItems({
@@ -6636,8 +6659,8 @@ const generateDirectoryListingInjection = (
6636
6659
  const { host } = new URL(request.url);
6637
6660
  const websocketUrl = `${websocketScheme}://${host}/.internal/directory_content.websocket?directory=${encodeURIComponent(directoryUrlRelativeToServer)}`;
6638
6661
 
6639
- const navItems = [];
6640
- {
6662
+ const generateBreadcrumb = () => {
6663
+ const breadcrumb = [];
6641
6664
  const lastItemUrl = firstExistingDirectoryUrl;
6642
6665
  const lastItemRelativeUrl = urlToRelativeUrl(lastItemUrl, rootDirectoryUrl);
6643
6666
  const rootDirectoryUrlName = urlToFilename(rootDirectoryUrl);
@@ -6647,7 +6670,6 @@ const generateDirectoryListingInjection = (
6647
6670
  } else {
6648
6671
  parts = [rootDirectoryUrlName];
6649
6672
  }
6650
-
6651
6673
  let i = 0;
6652
6674
  while (i < parts.length) {
6653
6675
  const part = parts[i];
@@ -6668,7 +6690,7 @@ const generateDirectoryListingInjection = (
6668
6690
  navItemUrl,
6669
6691
  serverRootDirectoryUrl,
6670
6692
  );
6671
- let urlRelativeToDocument = urlToRelativeUrl(navItemUrl, requestedUrl);
6693
+ let urlRelativeToDocument = urlToRelativeUrl(navItemUrl, urlNotFound);
6672
6694
  const isServerRootDirectory = navItemUrl === serverRootDirectoryUrl;
6673
6695
  if (isServerRootDirectory) {
6674
6696
  urlRelativeToServer = `/${directoryContentMagicName}`;
@@ -6676,7 +6698,7 @@ const generateDirectoryListingInjection = (
6676
6698
  }
6677
6699
  const name = part;
6678
6700
  const isCurrent = navItemUrl === String(firstExistingDirectoryUrl);
6679
- navItems.push({
6701
+ breadcrumb.push({
6680
6702
  url: navItemUrl,
6681
6703
  urlRelativeToServer,
6682
6704
  urlRelativeToDocument,
@@ -6686,34 +6708,47 @@ const generateDirectoryListingInjection = (
6686
6708
  });
6687
6709
  i++;
6688
6710
  }
6689
- }
6711
+ return breadcrumb;
6712
+ };
6713
+ const breadcrumb = generateBreadcrumb();
6690
6714
 
6691
6715
  let enoentDetails = null;
6692
6716
  if (enoent) {
6717
+ const buildEnoentPathInfo = (urlBase, closestExistingUrl) => {
6718
+ let filePathExisting;
6719
+ let filePathNotFound;
6720
+ const existingIndex = String(closestExistingUrl).length;
6721
+ filePathExisting = urlToRelativeUrl(
6722
+ closestExistingUrl,
6723
+ serverRootDirectoryUrl,
6724
+ );
6725
+ filePathNotFound = urlBase.slice(existingIndex);
6726
+ return [filePathExisting, filePathNotFound];
6727
+ };
6693
6728
  const fileRelativeUrl = urlToRelativeUrl(
6694
- requestedUrl,
6729
+ urlNotFound,
6695
6730
  serverRootDirectoryUrl,
6696
6731
  );
6697
- let filePathExisting;
6698
- let filePathNotFound;
6699
- const existingIndex = String(firstExistingDirectoryUrl).length;
6700
- filePathExisting = urlToRelativeUrl(
6701
- firstExistingDirectoryUrl,
6702
- serverRootDirectoryUrl,
6703
- );
6704
- filePathNotFound = requestedUrl.slice(existingIndex);
6705
6732
  enoentDetails = {
6706
- fileUrl: requestedUrl,
6733
+ fileUrl: urlNotFound,
6707
6734
  fileRelativeUrl,
6735
+ };
6736
+
6737
+ const [filePathExisting, filePathNotFound] = buildEnoentPathInfo(
6738
+ urlNotFound,
6739
+ firstExistingDirectoryUrl,
6740
+ );
6741
+ Object.assign(enoentDetails, {
6708
6742
  filePathExisting: `/${filePathExisting}`,
6709
6743
  filePathNotFound,
6710
- };
6744
+ });
6711
6745
  }
6712
6746
 
6713
6747
  return {
6714
6748
  __DIRECTORY_LISTING__: {
6749
+ spa,
6715
6750
  enoentDetails,
6716
- navItems,
6751
+ breadcrumb,
6717
6752
  urlMocks,
6718
6753
  directoryContentMagicName,
6719
6754
  directoryUrl: firstExistingDirectoryUrl,
@@ -6726,11 +6761,11 @@ const generateDirectoryListingInjection = (
6726
6761
  },
6727
6762
  };
6728
6763
  };
6729
- const getFirstExistingDirectoryUrl = (requestedUrl, serverRootDirectoryUrl) => {
6730
- let directoryUrlCandidate = new URL("./", requestedUrl);
6764
+ const getFirstExistingDirectoryUrl = (urlBase, serverRootDirectoryUrl) => {
6765
+ let directoryUrlCandidate = new URL("./", urlBase);
6731
6766
  while (!existsSync(directoryUrlCandidate)) {
6732
6767
  directoryUrlCandidate = new URL("../", directoryUrlCandidate);
6733
- if (!urlIsInsideOf(directoryUrlCandidate, serverRootDirectoryUrl)) {
6768
+ if (!urlIsOrIsInsideOf(directoryUrlCandidate, serverRootDirectoryUrl)) {
6734
6769
  directoryUrlCandidate = new URL(serverRootDirectoryUrl);
6735
6770
  break;
6736
6771
  }
@@ -6779,7 +6814,7 @@ const getDirectoryContentItems = ({
6779
6814
  };
6780
6815
 
6781
6816
  const jsenvPluginFsRedirection = ({
6782
- spa = true,
6817
+ spa,
6783
6818
  directoryContentMagicName,
6784
6819
  magicExtensions = ["inherit", ".js"],
6785
6820
  magicDirectoryIndex = true,
@@ -6938,17 +6973,12 @@ const getClosestHtmlRootFile = (requestedUrl, serverRootDirectoryUrl) => {
6938
6973
  if (existsSync(indexHtmlFileUrl)) {
6939
6974
  return indexHtmlFileUrl.href;
6940
6975
  }
6941
- const htmlFileUrlCandidate = new URL(
6942
- `${urlToFilename(directoryUrl)}.html`,
6943
- directoryUrl,
6944
- );
6976
+ const filename = urlToFilename(directoryUrl);
6977
+ const htmlFileUrlCandidate = new URL(`${filename}.html`, directoryUrl);
6945
6978
  if (existsSync(htmlFileUrlCandidate)) {
6946
6979
  return htmlFileUrlCandidate.href;
6947
6980
  }
6948
- if (
6949
- !urlIsInsideOf(directoryUrl, serverRootDirectoryUrl) ||
6950
- directoryUrl.href === serverRootDirectoryUrl
6951
- ) {
6981
+ if (!urlIsOrIsInsideOf(directoryUrl, serverRootDirectoryUrl)) {
6952
6982
  return null;
6953
6983
  }
6954
6984
  directoryUrl = new URL("../", directoryUrl);
@@ -6958,7 +6988,7 @@ const getClosestHtmlRootFile = (requestedUrl, serverRootDirectoryUrl) => {
6958
6988
  const directoryContentMagicName = "...";
6959
6989
 
6960
6990
  const jsenvPluginProtocolFile = ({
6961
- spa,
6991
+ spa = true,
6962
6992
  magicExtensions,
6963
6993
  magicDirectoryIndex,
6964
6994
  preserveSymlinks,
@@ -7026,6 +7056,7 @@ const jsenvPluginProtocolFile = ({
7026
7056
  ...(directoryListing
7027
7057
  ? [
7028
7058
  jsenvPluginDirectoryListing({
7059
+ spa,
7029
7060
  ...directoryListing,
7030
7061
  directoryContentMagicName,
7031
7062
  rootDirectoryUrl,
@@ -8020,7 +8051,7 @@ const jsenvPluginAutoreloadServer = ({
8020
8051
  serverEvents: {
8021
8052
  reload: (serverEventInfo) => {
8022
8053
  const formatUrlForClient = (url) => {
8023
- if (urlIsInsideOf(url, serverEventInfo.rootDirectoryUrl)) {
8054
+ if (urlIsOrIsInsideOf(url, serverEventInfo.rootDirectoryUrl)) {
8024
8055
  return urlToRelativeUrl(url, serverEventInfo.rootDirectoryUrl);
8025
8056
  }
8026
8057
  if (url.startsWith("file:")) {
@@ -8595,6 +8626,7 @@ const jsenvPluginChromeDevtoolsJson = () => {
8595
8626
  devServerRoutes: [
8596
8627
  {
8597
8628
  endpoint: "GET /.well-known/appspecific/com.chrome.devtools.json",
8629
+ declarationSource: import.meta.url,
8598
8630
  fetch: (request, { kitchen }) => {
8599
8631
  const { rootDirectoryUrl } = kitchen.context;
8600
8632
  return Response.json({
@@ -9983,7 +10015,7 @@ const createBuildSpecifierManager = ({
9983
10015
  // const urlInfoInsideThisDirectorySet = new Set();
9984
10016
  const versionsInfluencingThisDirectorySet = new Set();
9985
10017
  for (const [url, urlInfo] of finalKitchen.graph.urlInfoMap) {
9986
- if (!urlIsInsideOf(url, directoryUrl)) {
10018
+ if (!urlIsOrIsInsideOf(url, directoryUrl)) {
9987
10019
  continue;
9988
10020
  }
9989
10021
  // ideally we should exclude eventual directories as the are redundant
@@ -10382,7 +10414,7 @@ const createBuildSpecifierManager = ({
10382
10414
  }
10383
10415
  if (
10384
10416
  urlInfo.type === "asset" &&
10385
- urlIsInsideOf(urlInfo.url, buildDirectoryUrl)
10417
+ urlIsOrIsInsideOf(urlInfo.url, buildDirectoryUrl)
10386
10418
  ) {
10387
10419
  return;
10388
10420
  }
@@ -10697,7 +10729,7 @@ const createBuildUrlsGenerator = ({
10697
10729
  if (buildUrlFromMap) {
10698
10730
  return buildUrlFromMap;
10699
10731
  }
10700
- if (urlIsInsideOf(url, buildDirectoryUrl)) {
10732
+ if (urlIsOrIsInsideOf(url, buildDirectoryUrl)) {
10701
10733
  if (ownerUrlInfo.searchParams.has("dynamic_import_id")) {
10702
10734
  const ownerDirectoryPath = determineDirectoryPath({
10703
10735
  sourceDirectoryUrl,
@@ -11112,7 +11144,7 @@ const build = async ({
11112
11144
  );
11113
11145
  }
11114
11146
  }
11115
- if (!urlIsInsideOf(sourceUrl, sourceDirectoryUrl)) {
11147
+ if (!urlIsOrIsInsideOf(sourceUrl, sourceDirectoryUrl)) {
11116
11148
  throw new Error(
11117
11149
  `The key "${key}" in "entryPoints" is invalid: it must be inside the source directory at ${sourceDirectoryUrl}.`,
11118
11150
  );
@@ -11163,7 +11195,7 @@ const build = async ({
11163
11195
  `The buildRelativeUrl "${buildRelativeUrl}"${forEntryPointOrEmpty} is invalid: it must be a relative url.`,
11164
11196
  );
11165
11197
  }
11166
- if (!urlIsInsideOf(buildUrl, buildDirectoryUrl)) {
11198
+ if (!urlIsOrIsInsideOf(buildUrl, buildDirectoryUrl)) {
11167
11199
  throw new Error(
11168
11200
  `The buildRelativeUrl "${buildRelativeUrl}"${forEntryPointOrEmpty} is invalid: it must be inside the build directory at ${buildDirectoryUrl}.`,
11169
11201
  );
@@ -11663,7 +11695,7 @@ const build = async ({
11663
11695
  let hasSomeOutdatedSideEffectUrl = false;
11664
11696
  for (const packageSideEffectUrl of packageSideEffectUrlSet) {
11665
11697
  if (
11666
- urlIsInsideOf(packageSideEffectUrl, buildDirectoryUrl) &&
11698
+ urlIsOrIsInsideOf(packageSideEffectUrl, buildDirectoryUrl) &&
11667
11699
  !buildSideEffectUrlSet.has(packageSideEffectUrl)
11668
11700
  ) {
11669
11701
  hasSomeOutdatedSideEffectUrl = true;
@@ -11963,7 +11995,7 @@ const prepareEntryPointBuild = async (
11963
11995
  });
11964
11996
 
11965
11997
  let _getOtherEntryBuildInfo;
11966
- const rawPluginStore = createPluginStore([
11998
+ const rawPluginStore = await createPluginStore([
11967
11999
  ...(mappings ? [jsenvPluginMappings(mappings)] : []),
11968
12000
  {
11969
12001
  name: "jsenv:other_entry_point_build_during_craft",
@@ -12008,7 +12040,7 @@ const prepareEntryPointBuild = async (
12008
12040
  packageSideEffects,
12009
12041
  }),
12010
12042
  ]);
12011
- const rawPluginController = createPluginController(
12043
+ const rawPluginController = await createPluginController(
12012
12044
  rawPluginStore,
12013
12045
  rawKitchen,
12014
12046
  );
@@ -12079,7 +12111,7 @@ const prepareEntryPointBuild = async (
12079
12111
  rawKitchen.graph.getUrlInfo(entryReference.url).type === "html" &&
12080
12112
  rawKitchen.context.isSupportedOnCurrentClients("importmap"),
12081
12113
  });
12082
- const finalPluginStore = createPluginStore([
12114
+ const finalPluginStore = await createPluginStore([
12083
12115
  jsenvPluginReferenceAnalysis({
12084
12116
  ...referenceAnalysis,
12085
12117
  fetchInlineUrls: false,
@@ -12112,7 +12144,7 @@ const prepareEntryPointBuild = async (
12112
12144
  },
12113
12145
  buildSpecifierManager.jsenvPluginMoveToBuildDirectory,
12114
12146
  ]);
12115
- const finalPluginController = createPluginController(
12147
+ const finalPluginController = await createPluginController(
12116
12148
  finalPluginStore,
12117
12149
  finalKitchen,
12118
12150
  {
@@ -2304,7 +2304,7 @@ const resolveUrl$1 = (specifier, baseUrl) => {
2304
2304
  return String(new URL(specifier, baseUrl));
2305
2305
  };
2306
2306
 
2307
- const urlIsInsideOf = (url, otherUrl) => {
2307
+ const urlIsOrIsInsideOf = (url, otherUrl) => {
2308
2308
  const urlObject = new URL(url);
2309
2309
  const otherUrlObject = new URL(otherUrl);
2310
2310
 
@@ -2315,7 +2315,7 @@ const urlIsInsideOf = (url, otherUrl) => {
2315
2315
  const urlPathname = urlObject.pathname;
2316
2316
  const otherUrlPathname = otherUrlObject.pathname;
2317
2317
  if (urlPathname === otherUrlPathname) {
2318
- return false;
2318
+ return true;
2319
2319
  }
2320
2320
 
2321
2321
  const isInside = urlPathname.startsWith(otherUrlPathname);
@@ -10933,4 +10933,4 @@ const escapeRegexpSpecialChars = (string) => {
10933
10933
  });
10934
10934
  };
10935
10935
 
10936
- export { ANSI, Abort, CONTENT_TYPE, DATA_URL, JS_QUOTES, RUNTIME_COMPAT, UNICODE, URL_META, applyFileSystemMagicResolution, applyNodeEsmResolution, asSpecifierWithoutSearch, asUrlWithoutSearch, assertAndNormalizeDirectoryUrl, browserDefaultRuntimeCompat, bufferToEtag, clearDirectorySync, compareFileUrls, comparePathnames, composeTwoImportMaps, createDetailedMessage$1 as createDetailedMessage, createDynamicLog, createLogger, createLookupPackageDirectory, createTaskLog, defaultLookupPackageScope, defaultReadPackageJson, distributePercentages, ensureEmptyDirectory, ensurePathnameTrailingSlash, ensureWindowsDriveLetter, errorToHTML, escapeRegexpSpecialChars, generateContentFrame, getCallerPosition, getExtensionsToTry, humanizeDuration, humanizeFileSize, humanizeMemory, inferRuntimeCompatFromClosestPackage, injectQueryParamIntoSpecifierWithoutEncoding, injectQueryParams, injectQueryParamsIntoSpecifier, isFileSystemPath, isSpecifierForNodeBuiltin, lookupPackageDirectory, moveUrl, nodeDefaultRuntimeCompat, normalizeImportMap, normalizeUrl, raceProcessTeardownEvents, readCustomConditionsFromProcessArgs, readEntryStatSync, readPackageAtOrNull, registerDirectoryLifecycle, renderBigSection, renderDetails, renderTable, renderUrlOrRelativeUrlFilename, resolveImport, setUrlBasename, setUrlExtension, setUrlFilename, startMonitoringCpuUsage, startMonitoringMemoryUsage, stringifyUrlSite, updateJsonFileSync, urlIsInsideOf, urlToBasename, urlToExtension$1 as urlToExtension, urlToFileSystemPath, urlToFilename$1 as urlToFilename, urlToPathname$1 as urlToPathname, urlToRelativeUrl, validateResponseIntegrity, writeFileSync };
10936
+ export { ANSI, Abort, CONTENT_TYPE, DATA_URL, JS_QUOTES, RUNTIME_COMPAT, UNICODE, URL_META, applyFileSystemMagicResolution, applyNodeEsmResolution, asSpecifierWithoutSearch, asUrlWithoutSearch, assertAndNormalizeDirectoryUrl, browserDefaultRuntimeCompat, bufferToEtag, clearDirectorySync, compareFileUrls, comparePathnames, composeTwoImportMaps, createDetailedMessage$1 as createDetailedMessage, createDynamicLog, createLogger, createLookupPackageDirectory, createTaskLog, defaultLookupPackageScope, defaultReadPackageJson, distributePercentages, ensureEmptyDirectory, ensurePathnameTrailingSlash, ensureWindowsDriveLetter, errorToHTML, escapeRegexpSpecialChars, generateContentFrame, getCallerPosition, getExtensionsToTry, humanizeDuration, humanizeFileSize, humanizeMemory, inferRuntimeCompatFromClosestPackage, injectQueryParamIntoSpecifierWithoutEncoding, injectQueryParams, injectQueryParamsIntoSpecifier, isFileSystemPath, isSpecifierForNodeBuiltin, lookupPackageDirectory, moveUrl, nodeDefaultRuntimeCompat, normalizeImportMap, normalizeUrl, raceProcessTeardownEvents, readCustomConditionsFromProcessArgs, readEntryStatSync, readPackageAtOrNull, registerDirectoryLifecycle, renderBigSection, renderDetails, renderTable, renderUrlOrRelativeUrlFilename, resolveImport, setUrlBasename, setUrlExtension, setUrlFilename, startMonitoringCpuUsage, startMonitoringMemoryUsage, stringifyUrlSite, updateJsonFileSync, urlIsOrIsInsideOf, urlToBasename, urlToExtension$1 as urlToExtension, urlToFileSystemPath, urlToFilename$1 as urlToFilename, urlToPathname$1 as urlToPathname, urlToRelativeUrl, validateResponseIntegrity, writeFileSync };
@@ -4,7 +4,7 @@ const directoryIconUrl = new URL("../other/dir.png", import.meta.url).href;
4
4
  const fileIconUrl = new URL("../other/file.png", import.meta.url).href;
5
5
  const homeIconUrl = new URL("../other/home.svg#root", import.meta.url).href;
6
6
  let {
7
- navItems,
7
+ breadcrumb,
8
8
  mainFilePath,
9
9
  directoryContentItems,
10
10
  enoentDetails,
@@ -36,45 +36,60 @@ const DirectoryListing = () => {
36
36
  return directoryContentItems;
37
37
  });
38
38
  return u(k, {
39
- children: [enoentDetails ? u(ErrorMessage, {}) : null, u(Nav, {}), u(DirectoryContent, {
39
+ children: [enoentDetails ? u(ErrorMessage, {}) : null, u(Breadcrumb, {
40
+ items: breadcrumb
41
+ }), u(DirectoryContent, {
40
42
  items: directoryItems
41
43
  })]
42
44
  });
43
45
  };
44
46
  const ErrorMessage = () => {
45
47
  const {
46
- fileUrl,
47
48
  filePathExisting,
48
49
  filePathNotFound
49
50
  } = enoentDetails;
50
- return u("p", {
51
- className: "error_message",
51
+ let errorText;
52
+ let errorSuggestion;
53
+ errorText = u(k, {
54
+ children: [u("strong", {
55
+ children: "File not found:"
56
+ }), "\xA0", u("code", {
57
+ children: [u("span", {
58
+ className: "file_path_good",
59
+ children: filePathExisting
60
+ }), u("span", {
61
+ className: "file_path_bad",
62
+ children: filePathNotFound
63
+ })]
64
+ }), " ", "does not exist on the server."]
65
+ });
66
+ errorSuggestion = u(k, {
52
67
  children: [u("span", {
68
+ className: "icon",
69
+ children: "\uD83D\uDD0D"
70
+ }), " Check available routes in", " ", u("a", {
71
+ href: "/.internal/route_inspector",
72
+ children: "route inspector"
73
+ })]
74
+ });
75
+ return u("div", {
76
+ className: "error_message",
77
+ children: [u("p", {
53
78
  className: "error_text",
54
- children: ["No filesystem entry at", " ", u("code", {
55
- title: fileUrl,
56
- children: [u("span", {
57
- className: "file_path_good",
58
- children: filePathExisting
59
- }), u("span", {
60
- className: "file_path_bad",
61
- children: filePathNotFound
62
- })]
63
- }), "."]
64
- }), u("br", {}), u("span", {
65
- className: "error_text",
66
- style: "font-size: 70%;",
67
- children: ["See also available routes in the", " ", u("a", {
68
- href: "/.internal/route_inspector",
69
- children: "route inspector"
70
- }), "."]
79
+ children: errorText
80
+ }), u("p", {
81
+ className: "error_suggestion",
82
+ style: "font-size: 0.8em; margin-top: 10px;",
83
+ children: errorSuggestion
71
84
  })]
72
85
  });
73
86
  };
74
- const Nav = () => {
87
+ const Breadcrumb = ({
88
+ items
89
+ }) => {
75
90
  return u("h1", {
76
91
  className: "nav",
77
- children: navItems.map(navItem => {
92
+ children: items.map(navItem => {
78
93
  const {
79
94
  url,
80
95
  urlRelativeToServer,
@@ -84,7 +99,7 @@ const Nav = () => {
84
99
  } = navItem;
85
100
  const isDirectory = new URL(url).pathname.endsWith("/");
86
101
  return u(k, {
87
- children: [u(NavItem, {
102
+ children: [u(BreadcrumbItem, {
88
103
  url: urlRelativeToServer,
89
104
  isCurrent: isCurrent,
90
105
  iconImageUrl: isServerRootDirectory ? homeIconUrl : "",
@@ -98,7 +113,7 @@ const Nav = () => {
98
113
  })
99
114
  });
100
115
  };
101
- const NavItem = ({
116
+ const BreadcrumbItem = ({
102
117
  url,
103
118
  iconImageUrl,
104
119
  iconLinkUrl,