@jsenv/core 40.6.0 → 40.6.1

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.
@@ -183,6 +183,12 @@ ${reason}`,
183
183
  });
184
184
  return error;
185
185
  }
186
+ if (error.code === "PROTOCOL_NOT_SUPPORTED") {
187
+ const notSupportedError = createFailedToResolveUrlError({
188
+ reason: error.message,
189
+ });
190
+ return notSupportedError;
191
+ }
186
192
  return createFailedToResolveUrlError({
187
193
  reason: `An error occured during specifier resolution`,
188
194
  ...detailsFromValueThrown(error),
@@ -223,7 +229,6 @@ ${reason}`,
223
229
  });
224
230
  return fetchError;
225
231
  };
226
-
227
232
  if (error.code === "EPERM") {
228
233
  return createFailedToFetchUrlContentError({
229
234
  code: "NOT_ALLOWED",
@@ -270,6 +275,9 @@ const createTransformUrlContentError = ({
270
275
  if (error.code === "MODULE_NOT_FOUND") {
271
276
  return error;
272
277
  }
278
+ if (error.code === "PROTOCOL_NOT_SUPPORTED") {
279
+ return error;
280
+ }
273
281
  if (error.code === "DIRECTORY_REFERENCE_NOT_ALLOWED") {
274
282
  return error;
275
283
  }
@@ -277,47 +285,8 @@ const createTransformUrlContentError = ({
277
285
  if (error.isJsenvCookingError) {
278
286
  return error;
279
287
  }
288
+ const trace = getErrorTrace(error, urlInfo.firstReference);
280
289
  const reference = urlInfo.firstReference;
281
- let trace = reference.trace;
282
- let line = error.line;
283
- let column = error.column;
284
- if (urlInfo.isInline) {
285
- line = trace.line + line;
286
- line = line - 1;
287
- trace = {
288
- ...trace,
289
- line,
290
- column,
291
- codeFrame: generateContentFrame({
292
- line,
293
- column,
294
- content: urlInfo.inlineUrlSite.content,
295
- }),
296
- message: stringifyUrlSite({
297
- url: urlInfo.inlineUrlSite.url,
298
- line,
299
- column,
300
- content: urlInfo.inlineUrlSite.content,
301
- }),
302
- };
303
- } else {
304
- trace = {
305
- url: urlInfo.url,
306
- line,
307
- column: error.column,
308
- codeFrame: generateContentFrame({
309
- line,
310
- column: error.column,
311
- content: urlInfo.content,
312
- }),
313
- message: stringifyUrlSite({
314
- url: urlInfo.url,
315
- line,
316
- column: error.column,
317
- content: urlInfo.content,
318
- }),
319
- };
320
- }
321
290
  const transformError = new Error(
322
291
  createDetailedMessage(
323
292
  `parse error on "${urlInfo.type}"
@@ -408,9 +377,55 @@ ${reference.trace.message}`,
408
377
  return finalizeError;
409
378
  };
410
379
 
380
+ const getErrorTrace = (error, reference) => {
381
+ const urlInfo = reference.urlInfo;
382
+ let trace = reference.trace;
383
+ let line = error.line;
384
+ let column = error.column;
385
+ if (urlInfo.isInline) {
386
+ line = trace.line + line;
387
+ line = line - 1;
388
+ return {
389
+ ...trace,
390
+ line,
391
+ column,
392
+ codeFrame: generateContentFrame({
393
+ line,
394
+ column,
395
+ content: urlInfo.inlineUrlSite.content,
396
+ }),
397
+ message: stringifyUrlSite({
398
+ url: urlInfo.inlineUrlSite.url,
399
+ line,
400
+ column,
401
+ content: urlInfo.inlineUrlSite.content,
402
+ }),
403
+ };
404
+ }
405
+ return {
406
+ url: urlInfo.url,
407
+ line,
408
+ column: error.column,
409
+ codeFrame: generateContentFrame({
410
+ line,
411
+ column: error.column,
412
+ content: urlInfo.content,
413
+ }),
414
+ message: stringifyUrlSite({
415
+ url: urlInfo.url,
416
+ line,
417
+ column: error.column,
418
+ content: urlInfo.content,
419
+ }),
420
+ };
421
+ };
422
+
411
423
  const detailsFromFirstReference = (reference) => {
412
424
  const referenceInProject = getFirstReferenceInProject(reference);
413
- if (referenceInProject === reference) {
425
+ if (
426
+ referenceInProject === reference ||
427
+ referenceInProject.type === "http_request"
428
+ ) {
414
429
  return {};
415
430
  }
416
431
  return {
@@ -419,6 +434,9 @@ const detailsFromFirstReference = (reference) => {
419
434
  };
420
435
  const getFirstReferenceInProject = (reference) => {
421
436
  const ownerUrlInfo = reference.ownerUrlInfo;
437
+ if (ownerUrlInfo.isRoot) {
438
+ return reference;
439
+ }
422
440
  if (
423
441
  !ownerUrlInfo.url.includes("/node_modules/") &&
424
442
  ownerUrlInfo.packageDirectoryUrl ===
@@ -426,7 +444,8 @@ const getFirstReferenceInProject = (reference) => {
426
444
  ) {
427
445
  return reference;
428
446
  }
429
- return getFirstReferenceInProject(ownerUrlInfo.firstReference);
447
+ const { firstReference } = ownerUrlInfo;
448
+ return getFirstReferenceInProject(firstReference);
430
449
  };
431
450
 
432
451
  const detailsFromPluginController = (pluginController) => {
@@ -2668,7 +2687,28 @@ const createKitchen = ({
2668
2687
 
2669
2688
  ignore,
2670
2689
  ignoreProtocol = "remove",
2671
- supportedProtocols = ["file:", "data:", "virtual:", "http:", "https:"],
2690
+ supportedProtocols = [
2691
+ "file:",
2692
+ "data:",
2693
+ // eslint-disable-next-line no-script-url
2694
+ "javascript:",
2695
+ "virtual:",
2696
+ "ignore:",
2697
+ "http:",
2698
+ "https:",
2699
+ "chrome:",
2700
+ "chrome-extension:",
2701
+ "chrome-untrusted:",
2702
+ "isolated-app:",
2703
+ ],
2704
+ includedProtocols = [
2705
+ "file:",
2706
+ "data:",
2707
+ "virtual:",
2708
+ "ignore:",
2709
+ "http:",
2710
+ "https:",
2711
+ ],
2672
2712
 
2673
2713
  // during dev/test clientRuntimeCompat is a single runtime
2674
2714
  // during build clientRuntimeCompat is runtimeCompat
@@ -2688,6 +2728,9 @@ const createKitchen = ({
2688
2728
 
2689
2729
  const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node");
2690
2730
  const packageConditions = [nodeRuntimeEnabled ? "node" : "browser", "import"];
2731
+ if (nodeRuntimeEnabled) {
2732
+ supportedProtocols.push("node:");
2733
+ }
2691
2734
 
2692
2735
  if (packageDependencies === "auto") {
2693
2736
  packageDependencies = build && nodeRuntimeEnabled ? "ignore" : "include";
@@ -2759,8 +2802,11 @@ const createKitchen = ({
2759
2802
 
2760
2803
  const isIgnoredByProtocol = (url) => {
2761
2804
  const { protocol } = new URL(url);
2762
- const protocolIsSupported = supportedProtocols.includes(protocol);
2763
- return !protocolIsSupported;
2805
+ const protocolIsIncluded = includedProtocols.includes(protocol);
2806
+ if (protocolIsIncluded) {
2807
+ return false;
2808
+ }
2809
+ return true;
2764
2810
  };
2765
2811
  const isIgnoredBecauseInPackageDependencies = (() => {
2766
2812
  if (packageDependencies === undefined) {
@@ -2967,6 +3013,21 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
2967
3013
  }
2968
3014
  reference.generatedUrl = reference.url;
2969
3015
  reference.generatedSearchParams = reference.searchParams;
3016
+ if (dev) {
3017
+ let url = reference.url;
3018
+ let { protocol } = new URL(url);
3019
+ if (protocol === "ignore:") {
3020
+ url = url.slice("ignore:".length);
3021
+ protocol = new URL(url, "http://example.com").protocol;
3022
+ }
3023
+ if (!supportedProtocols.includes(protocol)) {
3024
+ const protocolNotSupportedError = new Error(
3025
+ `Unsupported protocol "${protocol}" for url "${url}"`,
3026
+ );
3027
+ protocolNotSupportedError.code = "PROTOCOL_NOT_SUPPORTED";
3028
+ throw protocolNotSupportedError;
3029
+ }
3030
+ }
2970
3031
  return reference;
2971
3032
  } catch (error) {
2972
3033
  throw createResolveUrlError({
@@ -6843,6 +6904,9 @@ const jsenvPluginProtocolFile = ({
6843
6904
  name: "jsenv:directory_as_json",
6844
6905
  appliesDuring: "*",
6845
6906
  fetchUrlContent: (urlInfo) => {
6907
+ if (!urlInfo.url.startsWith("file:")) {
6908
+ return null;
6909
+ }
6846
6910
  const { firstReference } = urlInfo;
6847
6911
  let { fsStat } = firstReference;
6848
6912
  if (!fsStat) {
@@ -11782,7 +11846,7 @@ const prepareEntryPointBuild = async (
11782
11846
  // - no plugin putting reference.mustIgnore on https urls
11783
11847
  // At this stage it's only about redirecting urls to the build directory
11784
11848
  // consequently only a subset or urls are supported
11785
- supportedProtocols: ["file:", "data:", "virtual:", "ignore:"],
11849
+ includedProtocols: ["file:", "data:", "virtual:", "ignore:"],
11786
11850
  ignore,
11787
11851
  ignoreProtocol: "remove",
11788
11852
  build: true,
@@ -516,6 +516,79 @@ const SIGINT_CALLBACK = {
516
516
  },
517
517
  };
518
518
 
519
+ const isFileSystemPath = (value) => {
520
+ if (typeof value !== "string") {
521
+ throw new TypeError(
522
+ `isFileSystemPath first arg must be a string, got ${value}`,
523
+ );
524
+ }
525
+ if (value[0] === "/") {
526
+ return true;
527
+ }
528
+ return startsWithWindowsDriveLetter(value);
529
+ };
530
+
531
+ const startsWithWindowsDriveLetter = (string) => {
532
+ const firstChar = string[0];
533
+ if (!/[a-zA-Z]/.test(firstChar)) return false;
534
+
535
+ const secondChar = string[1];
536
+ if (secondChar !== ":") return false;
537
+
538
+ return true;
539
+ };
540
+
541
+ const fileSystemPathToUrl = (value) => {
542
+ if (!isFileSystemPath(value)) {
543
+ throw new Error(`value must be a filesystem path, got ${value}`);
544
+ }
545
+ return String(pathToFileURL(value));
546
+ };
547
+
548
+ const getCallerPosition = () => {
549
+ const { prepareStackTrace } = Error;
550
+ Error.prepareStackTrace = (error, stack) => {
551
+ Error.prepareStackTrace = prepareStackTrace;
552
+ return stack;
553
+ };
554
+ const { stack } = new Error();
555
+ const callerCallsite = stack[2];
556
+ const fileName = callerCallsite.getFileName();
557
+ return {
558
+ url:
559
+ fileName && isFileSystemPath(fileName)
560
+ ? fileSystemPathToUrl(fileName)
561
+ : fileName,
562
+ line: callerCallsite.getLineNumber(),
563
+ column: callerCallsite.getColumnNumber(),
564
+ };
565
+ };
566
+
567
+ const urlToFileSystemPath = (url) => {
568
+ const urlObject = new URL(url);
569
+ let { origin, pathname, hash } = urlObject;
570
+ if (urlObject.protocol === "file:") {
571
+ origin = "file://";
572
+ }
573
+ pathname = pathname
574
+ .split("/")
575
+ .map((part) => {
576
+ return part.replace(/%(?![0-9A-F][0-9A-F])/g, "%25");
577
+ })
578
+ .join("/");
579
+ if (hash) {
580
+ pathname += `%23${encodeURIComponent(hash.slice(1))}`;
581
+ }
582
+ const urlString = `${origin}${pathname}`;
583
+ const fileSystemPath = fileURLToPath(urlString);
584
+ if (fileSystemPath[fileSystemPath.length - 1] === "/") {
585
+ // remove trailing / so that nodejs path becomes predictable otherwise it logs
586
+ // the trailing slash on linux but does not on windows
587
+ return fileSystemPath.slice(0, -1);
588
+ }
589
+ return fileSystemPath;
590
+ };
591
+
519
592
  /*
520
593
  * data:[<mediatype>][;base64],<data>
521
594
  * https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs#syntax
@@ -1947,6 +2020,75 @@ const urlToOrigin$1 = (url) => {
1947
2020
  return new URL(urlString).origin;
1948
2021
  };
1949
2022
 
2023
+ const setUrlExtension = (url, extension) => {
2024
+ const origin = urlToOrigin$1(url);
2025
+ const currentExtension = urlToExtension$1(url);
2026
+ if (typeof extension === "function") {
2027
+ extension = extension(currentExtension);
2028
+ }
2029
+ const resource = urlToResource(url);
2030
+ const [pathname, search] = resource.split("?");
2031
+ const pathnameWithoutExtension = currentExtension
2032
+ ? pathname.slice(0, -currentExtension.length)
2033
+ : pathname;
2034
+ let newPathname;
2035
+ if (pathnameWithoutExtension.endsWith("/")) {
2036
+ newPathname = pathnameWithoutExtension.slice(0, -1);
2037
+ newPathname += extension;
2038
+ newPathname += "/";
2039
+ } else {
2040
+ newPathname = pathnameWithoutExtension;
2041
+ newPathname += extension;
2042
+ }
2043
+ return `${origin}${newPathname}${search ? `?${search}` : ""}`;
2044
+ };
2045
+
2046
+ const setUrlFilename = (url, filename) => {
2047
+ const parentPathname = new URL("./", url).pathname;
2048
+ return transformUrlPathname(url, (pathname) => {
2049
+ if (typeof filename === "function") {
2050
+ filename = filename(pathnameToFilename(pathname));
2051
+ }
2052
+ return `${parentPathname}${filename}`;
2053
+ });
2054
+ };
2055
+
2056
+ const setUrlBasename = (url, basename) => {
2057
+ return setUrlFilename(url, (filename) => {
2058
+ if (typeof basename === "function") {
2059
+ basename = basename(filenameToBasename(filename));
2060
+ }
2061
+ return `${basename}${urlToExtension$1(url)}`;
2062
+ });
2063
+ };
2064
+
2065
+ const transformUrlPathname = (url, transformer) => {
2066
+ if (typeof url === "string") {
2067
+ const urlObject = new URL(url);
2068
+ const { pathname } = urlObject;
2069
+ const pathnameTransformed = transformer(pathname);
2070
+ if (pathnameTransformed === pathname) {
2071
+ return url;
2072
+ }
2073
+ let { origin } = urlObject;
2074
+ // origin is "null" for "file://" urls with Node.js
2075
+ if (origin === "null" && urlObject.href.startsWith("file:")) {
2076
+ origin = "file://";
2077
+ }
2078
+ const { search, hash } = urlObject;
2079
+ const urlWithPathnameTransformed = `${origin}${pathnameTransformed}${search}${hash}`;
2080
+ return urlWithPathnameTransformed;
2081
+ }
2082
+ const pathnameTransformed = transformer(url.pathname);
2083
+ url.pathname = pathnameTransformed;
2084
+ return url;
2085
+ };
2086
+ const ensurePathnameTrailingSlash = (url) => {
2087
+ return transformUrlPathname(url, (pathname) => {
2088
+ return pathname.endsWith("/") ? pathname : `${pathname}/`;
2089
+ });
2090
+ };
2091
+
1950
2092
  const asUrlWithoutSearch = (url) => {
1951
2093
  url = String(url);
1952
2094
  if (url.includes("?")) {
@@ -2099,130 +2241,6 @@ const renderUrlOrRelativeUrlFilename = (urlOrRelativeUrl, renderer) => {
2099
2241
  return `${beforeFilename}${newFilename}${afterQuestion}`;
2100
2242
  };
2101
2243
 
2102
- const setUrlExtension = (url, extension) => {
2103
- const origin = urlToOrigin$1(url);
2104
- const currentExtension = urlToExtension$1(url);
2105
- if (typeof extension === "function") {
2106
- extension = extension(currentExtension);
2107
- }
2108
- const resource = urlToResource(url);
2109
- const [pathname, search] = resource.split("?");
2110
- const pathnameWithoutExtension = currentExtension
2111
- ? pathname.slice(0, -currentExtension.length)
2112
- : pathname;
2113
- let newPathname;
2114
- if (pathnameWithoutExtension.endsWith("/")) {
2115
- newPathname = pathnameWithoutExtension.slice(0, -1);
2116
- newPathname += extension;
2117
- newPathname += "/";
2118
- } else {
2119
- newPathname = pathnameWithoutExtension;
2120
- newPathname += extension;
2121
- }
2122
- return `${origin}${newPathname}${search ? `?${search}` : ""}`;
2123
- };
2124
-
2125
- const setUrlFilename = (url, filename) => {
2126
- const parentPathname = new URL("./", url).pathname;
2127
- return transformUrlPathname(url, (pathname) => {
2128
- if (typeof filename === "function") {
2129
- filename = filename(pathnameToFilename(pathname));
2130
- }
2131
- return `${parentPathname}${filename}`;
2132
- });
2133
- };
2134
-
2135
- const setUrlBasename = (url, basename) => {
2136
- return setUrlFilename(url, (filename) => {
2137
- if (typeof basename === "function") {
2138
- basename = basename(filenameToBasename(filename));
2139
- }
2140
- return `${basename}${urlToExtension$1(url)}`;
2141
- });
2142
- };
2143
-
2144
- const transformUrlPathname = (url, transformer) => {
2145
- if (typeof url === "string") {
2146
- const urlObject = new URL(url);
2147
- const { pathname } = urlObject;
2148
- const pathnameTransformed = transformer(pathname);
2149
- if (pathnameTransformed === pathname) {
2150
- return url;
2151
- }
2152
- let { origin } = urlObject;
2153
- // origin is "null" for "file://" urls with Node.js
2154
- if (origin === "null" && urlObject.href.startsWith("file:")) {
2155
- origin = "file://";
2156
- }
2157
- const { search, hash } = urlObject;
2158
- const urlWithPathnameTransformed = `${origin}${pathnameTransformed}${search}${hash}`;
2159
- return urlWithPathnameTransformed;
2160
- }
2161
- const pathnameTransformed = transformer(url.pathname);
2162
- url.pathname = pathnameTransformed;
2163
- return url;
2164
- };
2165
- const ensurePathnameTrailingSlash = (url) => {
2166
- return transformUrlPathname(url, (pathname) => {
2167
- return pathname.endsWith("/") ? pathname : `${pathname}/`;
2168
- });
2169
- };
2170
-
2171
- const isFileSystemPath = (value) => {
2172
- if (typeof value !== "string") {
2173
- throw new TypeError(
2174
- `isFileSystemPath first arg must be a string, got ${value}`,
2175
- );
2176
- }
2177
- if (value[0] === "/") {
2178
- return true;
2179
- }
2180
- return startsWithWindowsDriveLetter(value);
2181
- };
2182
-
2183
- const startsWithWindowsDriveLetter = (string) => {
2184
- const firstChar = string[0];
2185
- if (!/[a-zA-Z]/.test(firstChar)) return false;
2186
-
2187
- const secondChar = string[1];
2188
- if (secondChar !== ":") return false;
2189
-
2190
- return true;
2191
- };
2192
-
2193
- const fileSystemPathToUrl = (value) => {
2194
- if (!isFileSystemPath(value)) {
2195
- throw new Error(`value must be a filesystem path, got ${value}`);
2196
- }
2197
- return String(pathToFileURL(value));
2198
- };
2199
-
2200
- const getCallerPosition = () => {
2201
- const { prepareStackTrace } = Error;
2202
- Error.prepareStackTrace = (error, stack) => {
2203
- Error.prepareStackTrace = prepareStackTrace;
2204
- return stack;
2205
- };
2206
- const { stack } = new Error();
2207
- const callerCallsite = stack[2];
2208
- const fileName = callerCallsite.getFileName();
2209
- return {
2210
- url:
2211
- fileName && isFileSystemPath(fileName)
2212
- ? fileSystemPathToUrl(fileName)
2213
- : fileName,
2214
- line: callerCallsite.getLineNumber(),
2215
- column: callerCallsite.getColumnNumber(),
2216
- };
2217
- };
2218
-
2219
- const resolveUrl$1 = (specifier, baseUrl) => {
2220
- if (typeof baseUrl === "undefined") {
2221
- throw new TypeError(`baseUrl missing to resolve ${specifier}`);
2222
- }
2223
- return String(new URL(specifier, baseUrl));
2224
- };
2225
-
2226
2244
  const getCommonPathname = (pathname, otherPathname) => {
2227
2245
  if (pathname === otherPathname) {
2228
2246
  return pathname;
@@ -2332,6 +2350,13 @@ const moveUrl = ({ url, from, to, preferRelative }) => {
2332
2350
  return absoluteUrl;
2333
2351
  };
2334
2352
 
2353
+ const resolveUrl$1 = (specifier, baseUrl) => {
2354
+ if (typeof baseUrl === "undefined") {
2355
+ throw new TypeError(`baseUrl missing to resolve ${specifier}`);
2356
+ }
2357
+ return String(new URL(specifier, baseUrl));
2358
+ };
2359
+
2335
2360
  const urlIsInsideOf = (url, otherUrl) => {
2336
2361
  const urlObject = new URL(url);
2337
2362
  const otherUrlObject = new URL(otherUrl);
@@ -2350,31 +2375,6 @@ const urlIsInsideOf = (url, otherUrl) => {
2350
2375
  return isInside;
2351
2376
  };
2352
2377
 
2353
- const urlToFileSystemPath = (url) => {
2354
- const urlObject = new URL(url);
2355
- let { origin, pathname, hash } = urlObject;
2356
- if (urlObject.protocol === "file:") {
2357
- origin = "file://";
2358
- }
2359
- pathname = pathname
2360
- .split("/")
2361
- .map((part) => {
2362
- return part.replace(/%(?![0-9A-F][0-9A-F])/g, "%25");
2363
- })
2364
- .join("/");
2365
- if (hash) {
2366
- pathname += `%23${encodeURIComponent(hash.slice(1))}`;
2367
- }
2368
- const urlString = `${origin}${pathname}`;
2369
- const fileSystemPath = fileURLToPath(urlString);
2370
- if (fileSystemPath[fileSystemPath.length - 1] === "/") {
2371
- // remove trailing / so that nodejs path becomes predictable otherwise it logs
2372
- // the trailing slash on linux but does not on windows
2373
- return fileSystemPath.slice(0, -1);
2374
- }
2375
- return fileSystemPath;
2376
- };
2377
-
2378
2378
  const validateDirectoryUrl = (value) => {
2379
2379
  let urlString;
2380
2380
 
@@ -511,6 +511,35 @@ const SIGINT_CALLBACK = {
511
511
  },
512
512
  };
513
513
 
514
+ const isFileSystemPath = (value) => {
515
+ if (typeof value !== "string") {
516
+ throw new TypeError(
517
+ `isFileSystemPath first arg must be a string, got ${value}`,
518
+ );
519
+ }
520
+ if (value[0] === "/") {
521
+ return true;
522
+ }
523
+ return startsWithWindowsDriveLetter(value);
524
+ };
525
+
526
+ const startsWithWindowsDriveLetter = (string) => {
527
+ const firstChar = string[0];
528
+ if (!/[a-zA-Z]/.test(firstChar)) return false;
529
+
530
+ const secondChar = string[1];
531
+ if (secondChar !== ":") return false;
532
+
533
+ return true;
534
+ };
535
+
536
+ const fileSystemPathToUrl = (value) => {
537
+ if (!isFileSystemPath(value)) {
538
+ throw new Error(`value must be a filesystem path, got ${value}`);
539
+ }
540
+ return String(pathToFileURL(value));
541
+ };
542
+
514
543
  // https://github.com/Marak/colors.js/blob/master/lib/styles.js
515
544
  // https://stackoverflow.com/a/75985833/2634179
516
545
  const RESET = "\x1b[0m";
@@ -1462,35 +1491,6 @@ const ensurePathnameTrailingSlash = (url) => {
1462
1491
  });
1463
1492
  };
1464
1493
 
1465
- const isFileSystemPath = (value) => {
1466
- if (typeof value !== "string") {
1467
- throw new TypeError(
1468
- `isFileSystemPath first arg must be a string, got ${value}`,
1469
- );
1470
- }
1471
- if (value[0] === "/") {
1472
- return true;
1473
- }
1474
- return startsWithWindowsDriveLetter(value);
1475
- };
1476
-
1477
- const startsWithWindowsDriveLetter = (string) => {
1478
- const firstChar = string[0];
1479
- if (!/[a-zA-Z]/.test(firstChar)) return false;
1480
-
1481
- const secondChar = string[1];
1482
- if (secondChar !== ":") return false;
1483
-
1484
- return true;
1485
- };
1486
-
1487
- const fileSystemPathToUrl = (value) => {
1488
- if (!isFileSystemPath(value)) {
1489
- throw new Error(`value must be a filesystem path, got ${value}`);
1490
- }
1491
- return String(pathToFileURL(value));
1492
- };
1493
-
1494
1494
  const validateDirectoryUrl = (value) => {
1495
1495
  let urlString;
1496
1496