@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.
@@ -1,43 +1,46 @@
1
1
  const injectRibbon = ({ text }) => {
2
2
  const css = /* css */ `
3
- #jsenv_ribbon_container {
4
- position: fixed;
5
- z-index: 1001;
6
- top: 0;
7
- right: 0;
8
- width: 100px;
9
- height: 100px;
10
- overflow: hidden;
11
- opacity: 0.5;
12
- pointer-events: none;
13
- }
14
- #jsenv_ribbon {
15
- position: absolute;
16
- top: -10px;
17
- right: -10px;
18
- width: 100%;
19
- height: 100%;
20
- }
21
- #jsenv_ribbon_text {
22
- position: absolute;
23
- left: 0px;
24
- top: 20px;
25
- transform: rotate(45deg);
26
- display: block;
27
- width: 125px;
28
- line-height: 36px;
29
- background-color: orange;
30
- color: rgb(55, 7, 7);
31
- box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
32
- font-weight: 700;
33
- font-size: 16px;
34
- font-family: "Lato", sans-serif;
35
- text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
36
- text-align: center;
37
- user-select: none;
38
- }`;
3
+ #jsenv_ribbon_container {
4
+ position: fixed;
5
+ z-index: 1001;
6
+ top: 0;
7
+ right: 0;
8
+ width: 100px;
9
+ height: 100px;
10
+ overflow: hidden;
11
+ opacity: 0.5;
12
+ pointer-events: none;
13
+ }
14
+ #jsenv_ribbon {
15
+ position: absolute;
16
+ top: -10px;
17
+ right: -10px;
18
+ width: 100%;
19
+ height: 100%;
20
+ }
21
+ #jsenv_ribbon_text {
22
+ position: absolute;
23
+ left: 0px;
24
+ top: 20px;
25
+ transform: rotate(45deg);
26
+ display: block;
27
+ width: 125px;
28
+ line-height: 36px;
29
+ background-color: orange;
30
+ color: rgb(55, 7, 7);
31
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
32
+ font-weight: 700;
33
+ font-size: 16px;
34
+ font-family: "Lato", sans-serif;
35
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
36
+ text-align: center;
37
+ user-select: none;
38
+ }
39
+ `;
39
40
  const html = /* html */ `<div id="jsenv_ribbon_container">
40
- <style>${css}</style>
41
+ <style>
42
+ ${css}
43
+ </style>
41
44
  <div id="jsenv_ribbon">
42
45
  <div id="jsenv_ribbon_text">${text}</div>
43
46
  </div>
@@ -1609,7 +1609,7 @@ const resolveUrl$1 = (specifier, baseUrl) => {
1609
1609
  return String(new URL(specifier, baseUrl));
1610
1610
  };
1611
1611
 
1612
- const urlIsInsideOf = (url, otherUrl) => {
1612
+ const urlIsOrIsInsideOf = (url, otherUrl) => {
1613
1613
  const urlObject = new URL(url);
1614
1614
  const otherUrlObject = new URL(otherUrl);
1615
1615
 
@@ -1620,7 +1620,7 @@ const urlIsInsideOf = (url, otherUrl) => {
1620
1620
  const urlPathname = urlObject.pathname;
1621
1621
  const otherUrlPathname = otherUrlObject.pathname;
1622
1622
  if (urlPathname === otherUrlPathname) {
1623
- return false;
1623
+ return true;
1624
1624
  }
1625
1625
 
1626
1626
  const isInside = urlPathname.startsWith(otherUrlPathname);
@@ -6255,4 +6255,4 @@ const memoizeByFirstArgument = (compute) => {
6255
6255
  return fnWithMemoization;
6256
6256
  };
6257
6257
 
6258
- export { ANSI, CONTENT_TYPE, DATA_URL, JS_QUOTES, RUNTIME_COMPAT, URL_META, applyFileSystemMagicResolution, applyNodeEsmResolution, asSpecifierWithoutSearch, asUrlWithoutSearch, assertAndNormalizeDirectoryUrl, bufferToEtag, compareFileUrls, composeTwoImportMaps, createDetailedMessage$1 as createDetailedMessage, createLogger, createTaskLog, defaultLookupPackageScope, defaultReadPackageJson, ensurePathnameTrailingSlash, ensureWindowsDriveLetter, errorToHTML, formatError, generateContentFrame, getCallerPosition, getExtensionsToTry, injectQueryParamsIntoSpecifier, isFileSystemPath, isSpecifierForNodeBuiltin, lookupPackageDirectory, memoizeByFirstArgument, moveUrl, normalizeImportMap, normalizeUrl, readCustomConditionsFromProcessArgs, readEntryStatSync, readPackageAtOrNull, registerDirectoryLifecycle, resolveImport, setUrlBasename, setUrlExtension, setUrlFilename, stringifyUrlSite, urlIsInsideOf, urlToBasename, urlToExtension$1 as urlToExtension, urlToFileSystemPath, urlToFilename$1 as urlToFilename, urlToPathname$1 as urlToPathname, urlToRelativeUrl, validateResponseIntegrity, writeFileSync };
6258
+ export { ANSI, CONTENT_TYPE, DATA_URL, JS_QUOTES, RUNTIME_COMPAT, URL_META, applyFileSystemMagicResolution, applyNodeEsmResolution, asSpecifierWithoutSearch, asUrlWithoutSearch, assertAndNormalizeDirectoryUrl, bufferToEtag, compareFileUrls, composeTwoImportMaps, createDetailedMessage$1 as createDetailedMessage, createLogger, createTaskLog, defaultLookupPackageScope, defaultReadPackageJson, ensurePathnameTrailingSlash, ensureWindowsDriveLetter, errorToHTML, formatError, generateContentFrame, getCallerPosition, getExtensionsToTry, injectQueryParamsIntoSpecifier, isFileSystemPath, isSpecifierForNodeBuiltin, lookupPackageDirectory, memoizeByFirstArgument, moveUrl, normalizeImportMap, normalizeUrl, readCustomConditionsFromProcessArgs, readEntryStatSync, readPackageAtOrNull, registerDirectoryLifecycle, resolveImport, setUrlBasename, setUrlExtension, setUrlFilename, stringifyUrlSite, urlIsOrIsInsideOf, urlToBasename, urlToExtension$1 as urlToExtension, urlToFileSystemPath, urlToFilename$1 as urlToFilename, urlToPathname$1 as urlToPathname, urlToRelativeUrl, validateResponseIntegrity, writeFileSync };
@@ -1,6 +1,6 @@
1
1
  import { WebSocketResponse, pickContentType, ServerEvents, jsenvServiceCORS, jsenvAccessControlAllowedHeaders, composeTwoResponses, serveDirectory, jsenvServiceErrorHandler, startServer } from "@jsenv/server";
2
2
  import { convertFileSystemErrorToResponseProperties } from "@jsenv/server/src/internal/convertFileSystemErrorToResponseProperties.js";
3
- import { lookupPackageDirectory, registerDirectoryLifecycle, urlToRelativeUrl, moveUrl, urlIsInsideOf, ensureWindowsDriveLetter, createDetailedMessage, stringifyUrlSite, generateContentFrame, validateResponseIntegrity, setUrlFilename, getCallerPosition, urlToBasename, urlToExtension, asSpecifierWithoutSearch, asUrlWithoutSearch, injectQueryParamsIntoSpecifier, bufferToEtag, isFileSystemPath, urlToPathname, setUrlBasename, urlToFileSystemPath, writeFileSync, createLogger, URL_META, applyNodeEsmResolution, RUNTIME_COMPAT, normalizeUrl, ANSI, CONTENT_TYPE, errorToHTML, DATA_URL, normalizeImportMap, composeTwoImportMaps, resolveImport, JS_QUOTES, defaultLookupPackageScope, defaultReadPackageJson, readCustomConditionsFromProcessArgs, readEntryStatSync, urlToFilename, ensurePathnameTrailingSlash, compareFileUrls, applyFileSystemMagicResolution, getExtensionsToTry, setUrlExtension, isSpecifierForNodeBuiltin, memoizeByFirstArgument, assertAndNormalizeDirectoryUrl, createTaskLog, formatError, readPackageAtOrNull } from "./jsenv_core_packages.js";
3
+ import { lookupPackageDirectory, registerDirectoryLifecycle, urlToRelativeUrl, moveUrl, urlIsOrIsInsideOf, ensureWindowsDriveLetter, createDetailedMessage, stringifyUrlSite, generateContentFrame, validateResponseIntegrity, setUrlFilename, getCallerPosition, urlToBasename, urlToExtension, asSpecifierWithoutSearch, asUrlWithoutSearch, injectQueryParamsIntoSpecifier, bufferToEtag, isFileSystemPath, urlToPathname, setUrlBasename, urlToFileSystemPath, writeFileSync, createLogger, URL_META, applyNodeEsmResolution, RUNTIME_COMPAT, normalizeUrl, ANSI, CONTENT_TYPE, errorToHTML, DATA_URL, normalizeImportMap, composeTwoImportMaps, resolveImport, JS_QUOTES, defaultLookupPackageScope, defaultReadPackageJson, readCustomConditionsFromProcessArgs, readEntryStatSync, ensurePathnameTrailingSlash, compareFileUrls, urlToFilename, applyFileSystemMagicResolution, getExtensionsToTry, setUrlExtension, isSpecifierForNodeBuiltin, memoizeByFirstArgument, assertAndNormalizeDirectoryUrl, createTaskLog, formatError, readPackageAtOrNull } from "./jsenv_core_packages.js";
4
4
  import { readFileSync, existsSync, readdirSync, lstatSync, realpathSync } from "node:fs";
5
5
  import { pathToFileURL } from "node:url";
6
6
  import { generateSourcemapFileUrl, createMagicSource, composeTwoSourcemaps, generateSourcemapDataUrl, SOURCEMAP } from "@jsenv/sourcemap";
@@ -165,7 +165,7 @@ const watchSourceFiles = (
165
165
 
166
166
  const WEB_URL_CONVERTER = {
167
167
  asWebUrl: (fileUrl, webServer) => {
168
- if (urlIsInsideOf(fileUrl, webServer.rootDirectoryUrl)) {
168
+ if (urlIsOrIsInsideOf(fileUrl, webServer.rootDirectoryUrl)) {
169
169
  return moveUrl({
170
170
  url: fileUrl,
171
171
  from: webServer.rootDirectoryUrl,
@@ -262,6 +262,7 @@ const createFetchUrlContentError = ({
262
262
  const createFailedToFetchUrlContentError = ({
263
263
  code = error.code || "FETCH_URL_CONTENT_ERROR",
264
264
  reason,
265
+ parseErrorSourceType,
265
266
  ...details
266
267
  }) => {
267
268
  const reference = urlInfo.firstReference;
@@ -282,6 +283,7 @@ ${reason}`,
282
283
  name: "FETCH_URL_CONTENT_ERROR",
283
284
  code,
284
285
  reason,
286
+ parseErrorSourceType,
285
287
  url: urlInfo.url,
286
288
  trace: code === "PARSE_ERROR" ? error.trace : reference.trace,
287
289
  asResponse: error.asResponse,
@@ -316,6 +318,7 @@ ${reason}`,
316
318
  return createFailedToFetchUrlContentError({
317
319
  "code": "PARSE_ERROR",
318
320
  "reason": error.reasonCode,
321
+ "parseErrorSourceType": error.parseErrorSourceType,
319
322
  ...(error.cause ? { "parse error message": error.cause.message } : {}),
320
323
  "parse error trace": error.trace?.message,
321
324
  });
@@ -365,7 +368,9 @@ ${error.message}`,
365
368
  name: "TRANSFORM_URL_CONTENT_ERROR",
366
369
  code: "PARSE_ERROR",
367
370
  reason: error.message,
368
- stack: error.stack,
371
+ reasonCode: error.reasonCode,
372
+ parseErrorSourceType: error.parseErrorSourceType,
373
+ stack: transformError.stack,
369
374
  trace,
370
375
  asResponse: error.asResponse,
371
376
  });
@@ -590,7 +595,7 @@ const determineFileUrlForOutDirectory = (urlInfo) => {
590
595
  if (!url.startsWith("file:")) {
591
596
  return url;
592
597
  }
593
- if (!urlIsInsideOf(url, rootDirectoryUrl)) {
598
+ if (!urlIsOrIsInsideOf(url, rootDirectoryUrl)) {
594
599
  const fsRootUrl = ensureWindowsDriveLetter("file:///", url);
595
600
  url = `${rootDirectoryUrl}@fs/${url.slice(fsRootUrl.length)}`;
596
601
  }
@@ -3840,10 +3845,19 @@ const replacePlaceholders = (html, replacers) => {
3840
3845
  });
3841
3846
  };
3842
3847
 
3843
- const createPluginStore = (plugins) => {
3848
+ const createPluginStore = async (plugins) => {
3844
3849
  const allDevServerRoutes = [];
3850
+ const allDevServerServices = [];
3845
3851
  const pluginArray = [];
3846
- const addPlugin = (plugin) => {
3852
+
3853
+ const pluginPromises = [];
3854
+ const addPlugin = async (plugin) => {
3855
+ if (plugin && typeof plugin.then === "function") {
3856
+ pluginPromises.push(plugin);
3857
+ const value = await plugin;
3858
+ addPlugin(value);
3859
+ return;
3860
+ }
3847
3861
  if (Array.isArray(plugin)) {
3848
3862
  for (const subplugin of plugin) {
3849
3863
  addPlugin(subplugin);
@@ -3862,21 +3876,28 @@ const createPluginStore = (plugins) => {
3862
3876
  allDevServerRoutes.push(devServerRoute);
3863
3877
  }
3864
3878
  }
3879
+ if (plugin.devServerServices) {
3880
+ const devServerServices = plugin.devServerServices;
3881
+ for (const devServerService of devServerServices) {
3882
+ allDevServerServices.push(devServerService);
3883
+ }
3884
+ }
3865
3885
  pluginArray.push(plugin);
3866
3886
  };
3867
3887
  addPlugin(jsenvPluginHtmlSyntaxErrorFallback());
3868
3888
  for (const plugin of plugins) {
3869
3889
  addPlugin(plugin);
3870
3890
  }
3891
+ await Promise.all(pluginPromises);
3871
3892
 
3872
3893
  return {
3873
3894
  pluginArray,
3874
-
3875
3895
  allDevServerRoutes,
3896
+ allDevServerServices,
3876
3897
  };
3877
3898
  };
3878
3899
 
3879
- const createPluginController = (
3900
+ const createPluginController = async (
3880
3901
  pluginStore,
3881
3902
  kitchen,
3882
3903
  { initialPuginsMeta = {} } = {},
@@ -3899,7 +3920,7 @@ const createPluginController = (
3899
3920
  pluginCandidate.destroy?.();
3900
3921
  continue;
3901
3922
  }
3902
- const initPluginResult = initPlugin(pluginCandidate, kitchen);
3923
+ const initPluginResult = await initPlugin(pluginCandidate, kitchen);
3903
3924
  if (!initPluginResult) {
3904
3925
  pluginCandidate.destroy?.();
3905
3926
  continue;
@@ -3951,6 +3972,7 @@ const createPluginController = (
3951
3972
  key === "serverEvents" ||
3952
3973
  key === "mustStayFirst" ||
3953
3974
  key === "devServerRoutes" ||
3975
+ key === "devServerServices" ||
3954
3976
  key === "effect"
3955
3977
  ) {
3956
3978
  continue;
@@ -4124,6 +4146,7 @@ const createPluginController = (
4124
4146
  const HOOK_NAMES = [
4125
4147
  "init",
4126
4148
  "devServerRoutes", // is called only during dev/tests
4149
+ "devServerServices", // is called only during dev/tests
4127
4150
  "resolveReference",
4128
4151
  "redirectReference",
4129
4152
  "transformReferenceSearchParams",
@@ -4178,12 +4201,12 @@ const testAppliesDuring = (plugin, kitchen) => {
4178
4201
  `"appliesDuring" must be an object or a string, got ${appliesDuring}`,
4179
4202
  );
4180
4203
  };
4181
- const initPlugin = (plugin, kitchen) => {
4204
+ const initPlugin = async (plugin, kitchen) => {
4182
4205
  const { init } = plugin;
4183
4206
  if (!init) {
4184
4207
  return true;
4185
4208
  }
4186
- const initReturnValue = init(kitchen.context, { plugin });
4209
+ const initReturnValue = await init(kitchen.context, { plugin });
4187
4210
  if (initReturnValue === false) {
4188
4211
  return false;
4189
4212
  }
@@ -6043,10 +6066,7 @@ const jsenvPluginVersionSearchParam = () => {
6043
6066
 
6044
6067
  const FILE_AND_SERVER_URLS_CONVERTER = {
6045
6068
  asServerUrl: (fileUrl, serverRootDirectoryUrl) => {
6046
- if (fileUrl === serverRootDirectoryUrl) {
6047
- return "/";
6048
- }
6049
- if (urlIsInsideOf(fileUrl, serverRootDirectoryUrl)) {
6069
+ if (urlIsOrIsInsideOf(fileUrl, serverRootDirectoryUrl)) {
6050
6070
  const urlRelativeToServer = urlToRelativeUrl(
6051
6071
  fileUrl,
6052
6072
  serverRootDirectoryUrl,
@@ -6102,6 +6122,7 @@ const htmlFileUrlForDirectory = import.meta.resolve(
6102
6122
  );
6103
6123
 
6104
6124
  const jsenvPluginDirectoryListing = ({
6125
+ spa,
6105
6126
  urlMocks = false,
6106
6127
  autoreload = true,
6107
6128
  directoryContentMagicName,
@@ -6143,7 +6164,7 @@ const jsenvPluginDirectoryListing = ({
6143
6164
  return null;
6144
6165
  }
6145
6166
  }
6146
- return `${htmlFileUrlForDirectory}?url=${encodeURIComponent(url)}&enoent`;
6167
+ return `${htmlFileUrlForDirectory}?url=${encodeURIComponent(requestedUrl)}&enoent`;
6147
6168
  }
6148
6169
  const isDirectory = fsStat?.isDirectory();
6149
6170
  if (!isDirectory) {
@@ -6169,21 +6190,22 @@ const jsenvPluginDirectoryListing = ({
6169
6190
  if (urlWithoutSearch !== String(htmlFileUrlForDirectory)) {
6170
6191
  return null;
6171
6192
  }
6172
- const requestedUrl = urlInfo.searchParams.get("url");
6173
- if (!requestedUrl) {
6193
+ const urlNotFound = urlInfo.searchParams.get("url");
6194
+ if (!urlNotFound) {
6174
6195
  return null;
6175
6196
  }
6197
+
6176
6198
  urlInfo.headers["cache-control"] = "no-cache";
6177
6199
  const enoent = urlInfo.searchParams.has("enoent");
6178
6200
  if (enoent) {
6179
6201
  urlInfo.status = 404;
6180
- urlInfo.headers["cache-control"] = "no-cache";
6181
6202
  }
6182
6203
  const request = urlInfo.context.request;
6183
6204
  const { rootDirectoryUrl, mainFilePath } = urlInfo.context;
6184
6205
  const directoryListingInjections = generateDirectoryListingInjection(
6185
- requestedUrl,
6206
+ urlNotFound,
6186
6207
  {
6208
+ spa,
6187
6209
  autoreload,
6188
6210
  request,
6189
6211
  urlMocks,
@@ -6276,8 +6298,9 @@ const jsenvPluginDirectoryListing = ({
6276
6298
  };
6277
6299
 
6278
6300
  const generateDirectoryListingInjection = (
6279
- requestedUrl,
6301
+ urlNotFound,
6280
6302
  {
6303
+ spa,
6281
6304
  rootDirectoryUrl,
6282
6305
  mainFilePath,
6283
6306
  packageDirectory,
@@ -6290,7 +6313,7 @@ const generateDirectoryListingInjection = (
6290
6313
  ) => {
6291
6314
  let serverRootDirectoryUrl = rootDirectoryUrl;
6292
6315
  const firstExistingDirectoryUrl = getFirstExistingDirectoryUrl(
6293
- requestedUrl,
6316
+ urlNotFound,
6294
6317
  serverRootDirectoryUrl,
6295
6318
  );
6296
6319
  const directoryContentItems = getDirectoryContentItems({
@@ -6341,8 +6364,8 @@ const generateDirectoryListingInjection = (
6341
6364
  const { host } = new URL(request.url);
6342
6365
  const websocketUrl = `${websocketScheme}://${host}/.internal/directory_content.websocket?directory=${encodeURIComponent(directoryUrlRelativeToServer)}`;
6343
6366
 
6344
- const navItems = [];
6345
- {
6367
+ const generateBreadcrumb = () => {
6368
+ const breadcrumb = [];
6346
6369
  const lastItemUrl = firstExistingDirectoryUrl;
6347
6370
  const lastItemRelativeUrl = urlToRelativeUrl(lastItemUrl, rootDirectoryUrl);
6348
6371
  const rootDirectoryUrlName = urlToFilename(rootDirectoryUrl);
@@ -6352,7 +6375,6 @@ const generateDirectoryListingInjection = (
6352
6375
  } else {
6353
6376
  parts = [rootDirectoryUrlName];
6354
6377
  }
6355
-
6356
6378
  let i = 0;
6357
6379
  while (i < parts.length) {
6358
6380
  const part = parts[i];
@@ -6373,7 +6395,7 @@ const generateDirectoryListingInjection = (
6373
6395
  navItemUrl,
6374
6396
  serverRootDirectoryUrl,
6375
6397
  );
6376
- let urlRelativeToDocument = urlToRelativeUrl(navItemUrl, requestedUrl);
6398
+ let urlRelativeToDocument = urlToRelativeUrl(navItemUrl, urlNotFound);
6377
6399
  const isServerRootDirectory = navItemUrl === serverRootDirectoryUrl;
6378
6400
  if (isServerRootDirectory) {
6379
6401
  urlRelativeToServer = `/${directoryContentMagicName}`;
@@ -6381,7 +6403,7 @@ const generateDirectoryListingInjection = (
6381
6403
  }
6382
6404
  const name = part;
6383
6405
  const isCurrent = navItemUrl === String(firstExistingDirectoryUrl);
6384
- navItems.push({
6406
+ breadcrumb.push({
6385
6407
  url: navItemUrl,
6386
6408
  urlRelativeToServer,
6387
6409
  urlRelativeToDocument,
@@ -6391,34 +6413,47 @@ const generateDirectoryListingInjection = (
6391
6413
  });
6392
6414
  i++;
6393
6415
  }
6394
- }
6416
+ return breadcrumb;
6417
+ };
6418
+ const breadcrumb = generateBreadcrumb();
6395
6419
 
6396
6420
  let enoentDetails = null;
6397
6421
  if (enoent) {
6422
+ const buildEnoentPathInfo = (urlBase, closestExistingUrl) => {
6423
+ let filePathExisting;
6424
+ let filePathNotFound;
6425
+ const existingIndex = String(closestExistingUrl).length;
6426
+ filePathExisting = urlToRelativeUrl(
6427
+ closestExistingUrl,
6428
+ serverRootDirectoryUrl,
6429
+ );
6430
+ filePathNotFound = urlBase.slice(existingIndex);
6431
+ return [filePathExisting, filePathNotFound];
6432
+ };
6398
6433
  const fileRelativeUrl = urlToRelativeUrl(
6399
- requestedUrl,
6434
+ urlNotFound,
6400
6435
  serverRootDirectoryUrl,
6401
6436
  );
6402
- let filePathExisting;
6403
- let filePathNotFound;
6404
- const existingIndex = String(firstExistingDirectoryUrl).length;
6405
- filePathExisting = urlToRelativeUrl(
6406
- firstExistingDirectoryUrl,
6407
- serverRootDirectoryUrl,
6408
- );
6409
- filePathNotFound = requestedUrl.slice(existingIndex);
6410
6437
  enoentDetails = {
6411
- fileUrl: requestedUrl,
6438
+ fileUrl: urlNotFound,
6412
6439
  fileRelativeUrl,
6440
+ };
6441
+
6442
+ const [filePathExisting, filePathNotFound] = buildEnoentPathInfo(
6443
+ urlNotFound,
6444
+ firstExistingDirectoryUrl,
6445
+ );
6446
+ Object.assign(enoentDetails, {
6413
6447
  filePathExisting: `/${filePathExisting}`,
6414
6448
  filePathNotFound,
6415
- };
6449
+ });
6416
6450
  }
6417
6451
 
6418
6452
  return {
6419
6453
  __DIRECTORY_LISTING__: {
6454
+ spa,
6420
6455
  enoentDetails,
6421
- navItems,
6456
+ breadcrumb,
6422
6457
  urlMocks,
6423
6458
  directoryContentMagicName,
6424
6459
  directoryUrl: firstExistingDirectoryUrl,
@@ -6431,11 +6466,11 @@ const generateDirectoryListingInjection = (
6431
6466
  },
6432
6467
  };
6433
6468
  };
6434
- const getFirstExistingDirectoryUrl = (requestedUrl, serverRootDirectoryUrl) => {
6435
- let directoryUrlCandidate = new URL("./", requestedUrl);
6469
+ const getFirstExistingDirectoryUrl = (urlBase, serverRootDirectoryUrl) => {
6470
+ let directoryUrlCandidate = new URL("./", urlBase);
6436
6471
  while (!existsSync(directoryUrlCandidate)) {
6437
6472
  directoryUrlCandidate = new URL("../", directoryUrlCandidate);
6438
- if (!urlIsInsideOf(directoryUrlCandidate, serverRootDirectoryUrl)) {
6473
+ if (!urlIsOrIsInsideOf(directoryUrlCandidate, serverRootDirectoryUrl)) {
6439
6474
  directoryUrlCandidate = new URL(serverRootDirectoryUrl);
6440
6475
  break;
6441
6476
  }
@@ -6484,7 +6519,7 @@ const getDirectoryContentItems = ({
6484
6519
  };
6485
6520
 
6486
6521
  const jsenvPluginFsRedirection = ({
6487
- spa = true,
6522
+ spa,
6488
6523
  directoryContentMagicName,
6489
6524
  magicExtensions = ["inherit", ".js"],
6490
6525
  magicDirectoryIndex = true,
@@ -6643,17 +6678,12 @@ const getClosestHtmlRootFile = (requestedUrl, serverRootDirectoryUrl) => {
6643
6678
  if (existsSync(indexHtmlFileUrl)) {
6644
6679
  return indexHtmlFileUrl.href;
6645
6680
  }
6646
- const htmlFileUrlCandidate = new URL(
6647
- `${urlToFilename(directoryUrl)}.html`,
6648
- directoryUrl,
6649
- );
6681
+ const filename = urlToFilename(directoryUrl);
6682
+ const htmlFileUrlCandidate = new URL(`${filename}.html`, directoryUrl);
6650
6683
  if (existsSync(htmlFileUrlCandidate)) {
6651
6684
  return htmlFileUrlCandidate.href;
6652
6685
  }
6653
- if (
6654
- !urlIsInsideOf(directoryUrl, serverRootDirectoryUrl) ||
6655
- directoryUrl.href === serverRootDirectoryUrl
6656
- ) {
6686
+ if (!urlIsOrIsInsideOf(directoryUrl, serverRootDirectoryUrl)) {
6657
6687
  return null;
6658
6688
  }
6659
6689
  directoryUrl = new URL("../", directoryUrl);
@@ -6663,7 +6693,7 @@ const getClosestHtmlRootFile = (requestedUrl, serverRootDirectoryUrl) => {
6663
6693
  const directoryContentMagicName = "...";
6664
6694
 
6665
6695
  const jsenvPluginProtocolFile = ({
6666
- spa,
6696
+ spa = true,
6667
6697
  magicExtensions,
6668
6698
  magicDirectoryIndex,
6669
6699
  preserveSymlinks,
@@ -6731,6 +6761,7 @@ const jsenvPluginProtocolFile = ({
6731
6761
  ...(directoryListing
6732
6762
  ? [
6733
6763
  jsenvPluginDirectoryListing({
6764
+ spa,
6734
6765
  ...directoryListing,
6735
6766
  directoryContentMagicName,
6736
6767
  rootDirectoryUrl,
@@ -8060,7 +8091,7 @@ const jsenvPluginAutoreloadServer = ({
8060
8091
  serverEvents: {
8061
8092
  reload: (serverEventInfo) => {
8062
8093
  const formatUrlForClient = (url) => {
8063
- if (urlIsInsideOf(url, serverEventInfo.rootDirectoryUrl)) {
8094
+ if (urlIsOrIsInsideOf(url, serverEventInfo.rootDirectoryUrl)) {
8064
8095
  return urlToRelativeUrl(url, serverEventInfo.rootDirectoryUrl);
8065
8096
  }
8066
8097
  if (url.startsWith("file:")) {
@@ -8635,6 +8666,7 @@ const jsenvPluginChromeDevtoolsJson = () => {
8635
8666
  devServerRoutes: [
8636
8667
  {
8637
8668
  endpoint: "GET /.well-known/appspecific/com.chrome.devtools.json",
8669
+ declarationSource: import.meta.url,
8638
8670
  fetch: (request, { kitchen }) => {
8639
8671
  const { rootDirectoryUrl } = kitchen.context;
8640
8672
  return Response.json({
@@ -9307,7 +9339,7 @@ const startDevServer = async ({
9307
9339
  read: readPackageAtOrNull,
9308
9340
  };
9309
9341
 
9310
- const devServerPluginStore = createPluginStore([
9342
+ const devServerPluginStore = await createPluginStore([
9311
9343
  jsenvPluginServerEvents({ clientAutoreload }),
9312
9344
  ...plugins,
9313
9345
  ...getCorePlugins({
@@ -9333,7 +9365,7 @@ const startDevServer = async ({
9333
9365
  ribbon,
9334
9366
  }),
9335
9367
  ]);
9336
- const getOrCreateKitchen = (request) => {
9368
+ const getOrCreateKitchen = async (request) => {
9337
9369
  const { runtimeName, runtimeVersion } = parseUserAgentHeader(
9338
9370
  request.headers["user-agent"] || "",
9339
9371
  );
@@ -9455,7 +9487,7 @@ const startDevServer = async ({
9455
9487
  );
9456
9488
  },
9457
9489
  );
9458
- const devServerPluginController = createPluginController(
9490
+ const devServerPluginController = await createPluginController(
9459
9491
  devServerPluginStore,
9460
9492
  kitchen,
9461
9493
  );
@@ -9471,8 +9503,8 @@ const startDevServer = async ({
9471
9503
 
9472
9504
  finalServices.push({
9473
9505
  name: "jsenv:dev_server_routes",
9474
- augmentRouteFetchSecondArg: (request) => {
9475
- const kitchen = getOrCreateKitchen(request);
9506
+ augmentRouteFetchSecondArg: async (request) => {
9507
+ const kitchen = await getOrCreateKitchen(request);
9476
9508
  return { kitchen };
9477
9509
  },
9478
9510
  routes: [
@@ -9675,6 +9707,7 @@ const startDevServer = async ({
9675
9707
  },
9676
9708
  ],
9677
9709
  });
9710
+ finalServices.push(...devServerPluginStore.allDevServerServices);
9678
9711
  }
9679
9712
  // jsenv error handler service
9680
9713
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "40.7.0",
3
+ "version": "40.7.2",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -77,23 +77,28 @@
77
77
  "playwright:install": "npx playwright install-deps && npx playwright install",
78
78
  "https:setup": "npx @jsenv/https-local setup",
79
79
  "prepublishOnly": "npm run build",
80
+ "database:install": "npx @jsenv/database install",
81
+ "database:start": "npx @jsenv/database start",
82
+ "database:stop": "npx @jsenv/database stop",
83
+ "database:setup": "npx @jsenv/database setup",
80
84
  "oto:start": "npm run start -w oto"
81
85
  },
82
86
  "dependencies": {
83
87
  "@financial-times/polyfill-useragent-normaliser": "1.10.2",
84
- "@jsenv/ast": "6.7.3",
85
- "@jsenv/js-module-fallback": "1.4.14",
86
- "@jsenv/plugin-bundling": "2.9.7",
88
+ "@jsenv/ast": "6.7.6",
89
+ "@jsenv/js-module-fallback": "1.4.18",
90
+ "@jsenv/plugin-bundling": "2.9.8",
87
91
  "@jsenv/plugin-minification": "1.7.0",
88
- "@jsenv/plugin-supervisor": "1.7.2",
89
- "@jsenv/plugin-transpilation": "1.5.21",
92
+ "@jsenv/plugin-supervisor": "1.7.3",
93
+ "@jsenv/plugin-transpilation": "1.5.50",
90
94
  "@jsenv/server": "16.1.2",
91
- "@jsenv/sourcemap": "1.3.8"
95
+ "@jsenv/sourcemap": "1.3.9",
96
+ "react-table": "7.8.0"
92
97
  },
93
98
  "devDependencies": {
94
- "@babel/plugin-syntax-decorators": "7.25.9",
95
- "@babel/plugin-syntax-import-attributes": "7.26.0",
96
- "@babel/plugin-syntax-optional-chaining-assign": "7.25.9",
99
+ "@babel/plugin-syntax-decorators": "7.27.1",
100
+ "@babel/plugin-syntax-import-attributes": "7.27.1",
101
+ "@babel/plugin-syntax-optional-chaining-assign": "7.27.1",
97
102
  "@jsenv/abort": "workspace:*",
98
103
  "@jsenv/assert": "workspace:*",
99
104
  "@jsenv/cli": "workspace:*",
@@ -111,6 +116,7 @@
111
116
  "@jsenv/os-metrics": "workspace:*",
112
117
  "@jsenv/performance-impact": "workspace:*",
113
118
  "@jsenv/plugin-as-js-classic": "workspace:*",
119
+ "@jsenv/plugin-database-manager": "workspace:*",
114
120
  "@jsenv/router": "workspace:*",
115
121
  "@jsenv/runtime-compat": "workspace:*",
116
122
  "@jsenv/snapshot": "workspace:*",
@@ -123,12 +129,15 @@
123
129
  "@playwright/browser-firefox": "1.52.0",
124
130
  "@playwright/browser-webkit": "1.52.0",
125
131
  "babel-plugin-transform-async-to-promises": "0.8.18",
126
- "eslint": "9.25.1",
127
- "open": "10.1.1",
132
+ "eslint": "9.26.0",
133
+ "open": "10.1.2",
128
134
  "playwright": "1.52.0",
129
135
  "preact": "10.26.5",
136
+ "preact-iso": "2.9.1",
130
137
  "prettier": "3.5.3",
138
+ "prettier-plugin-embed": "0.5.0",
131
139
  "prettier-plugin-organize-imports": "4.1.0",
140
+ "prettier-plugin-sql": "0.19.0",
132
141
  "strip-ansi": "7.1.0"
133
142
  }
134
143
  }