@jsenv/test 1.1.6 → 1.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.
@@ -7,17 +7,15 @@ import process$1, { memoryUsage } from "node:process";
7
7
  import os from "node:os";
8
8
  import tty from "node:tty";
9
9
  import stringWidth from "string-width";
10
- import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js";
11
- import { pingServer } from "@jsenv/core/src/helpers/ping_server.js";
12
- import { basicFetch } from "@jsenv/core/src/helpers/basic_fetch.js";
10
+ import { createRequire } from "node:module";
11
+ import { createServer } from "node:net";
13
12
  import v8, { takeCoverage } from "node:v8";
14
13
  import stripAnsi from "strip-ansi";
15
14
  import { applyBabelPlugins } from "@jsenv/ast";
16
15
  import { createId } from "@paralleldrive/cuid2";
17
16
  import { runInNewContext } from "node:vm";
18
17
  import wrapAnsi from "wrap-ansi";
19
- import { WEB_URL_CONVERTER } from "@jsenv/core/src/helpers/web_url_converter.js";
20
- import { injectSupervisorIntoHTML, supervisorFileUrl } from "@jsenv/core/src/plugins/supervisor/html_supervisor_injection.js";
18
+ import { injectSupervisorIntoHTML, supervisorFileUrl } from "@jsenv/plugin-supervisor/src/html_supervisor_injection.js";
21
19
  import { SOURCEMAP, generateSourcemapDataUrl } from "@jsenv/sourcemap";
22
20
  import { fork } from "node:child_process";
23
21
  import { findFreePort } from "@jsenv/server";
@@ -218,6 +216,24 @@ const pathnameToParentPathname = pathname => {
218
216
  return pathname.slice(0, slashLastIndex + 1);
219
217
  };
220
218
 
219
+ const moveUrl = ({
220
+ url,
221
+ from,
222
+ to,
223
+ preferRelative
224
+ }) => {
225
+ let relativeUrl = urlToRelativeUrl(url, from);
226
+ if (relativeUrl.slice(0, 2) === "//") {
227
+ // restore the protocol
228
+ relativeUrl = new URL(relativeUrl, url).href;
229
+ }
230
+ const absoluteUrl = new URL(relativeUrl, to).href;
231
+ if (preferRelative) {
232
+ return urlToRelativeUrl(absoluteUrl, to);
233
+ }
234
+ return absoluteUrl;
235
+ };
236
+
221
237
  const urlIsInsideOf = (url, otherUrl) => {
222
238
  const urlObject = new URL(url);
223
239
  const otherUrlObject = new URL(otherUrl);
@@ -458,7 +474,7 @@ const getPermissionOrComputeDefault = (action, subject, permissions) => {
458
474
  * https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_class_fs_stats
459
475
  */
460
476
 
461
- const isWindows$1 = process.platform === "win32";
477
+ const isWindows$2 = process.platform === "win32";
462
478
  const readEntryStat = async (source, {
463
479
  nullIfNotFound = false,
464
480
  followLink = true
@@ -472,7 +488,7 @@ const readEntryStat = async (source, {
472
488
  return readStat(sourcePath, {
473
489
  followLink,
474
490
  ...handleNotFoundOption,
475
- ...(isWindows$1 ? {
491
+ ...(isWindows$2 ? {
476
492
  // Windows can EPERM on stat
477
493
  handlePermissionDeniedError: async error => {
478
494
  console.error(`trying to fix windows EPERM after stats on ${sourcePath}`);
@@ -1399,8 +1415,60 @@ const ensureParentDirectories = async destination => {
1399
1415
  });
1400
1416
  };
1401
1417
 
1402
- process.platform === "win32";
1403
- fileSystemPathToUrl(process.cwd());
1418
+ const isWindows$1 = process.platform === "win32";
1419
+ const baseUrlFallback = fileSystemPathToUrl(process.cwd());
1420
+
1421
+ /**
1422
+ * Some url might be resolved or remapped to url without the windows drive letter.
1423
+ * For instance
1424
+ * new URL('/foo.js', 'file:///C:/dir/file.js')
1425
+ * resolves to
1426
+ * 'file:///foo.js'
1427
+ *
1428
+ * But on windows it becomes a problem because we need the drive letter otherwise
1429
+ * url cannot be converted to a filesystem path.
1430
+ *
1431
+ * ensureWindowsDriveLetter ensure a resolved url still contains the drive letter.
1432
+ */
1433
+
1434
+ const ensureWindowsDriveLetter = (url, baseUrl) => {
1435
+ try {
1436
+ url = String(new URL(url));
1437
+ } catch (e) {
1438
+ throw new Error(`absolute url expected but got ${url}`);
1439
+ }
1440
+ if (!isWindows$1) {
1441
+ return url;
1442
+ }
1443
+ try {
1444
+ baseUrl = String(new URL(baseUrl));
1445
+ } catch (e) {
1446
+ throw new Error(`absolute baseUrl expected but got ${baseUrl} to ensure windows drive letter on ${url}`);
1447
+ }
1448
+ if (!url.startsWith("file://")) {
1449
+ return url;
1450
+ }
1451
+ const afterProtocol = url.slice("file://".length);
1452
+ // we still have the windows drive letter
1453
+ if (extractDriveLetter(afterProtocol)) {
1454
+ return url;
1455
+ }
1456
+
1457
+ // drive letter was lost, restore it
1458
+ const baseUrlOrFallback = baseUrl.startsWith("file://") ? baseUrl : baseUrlFallback;
1459
+ const driveLetter = extractDriveLetter(baseUrlOrFallback.slice("file://".length));
1460
+ if (!driveLetter) {
1461
+ throw new Error(`drive letter expected on baseUrl but got ${baseUrl} to ensure windows drive letter on ${url}`);
1462
+ }
1463
+ return `file:///${driveLetter}:${afterProtocol}`;
1464
+ };
1465
+ const extractDriveLetter = resource => {
1466
+ // we still have the windows drive letter
1467
+ if (/[a-zA-Z]/.test(resource[1]) && resource[2] === ":") {
1468
+ return resource[1];
1469
+ }
1470
+ return null;
1471
+ };
1404
1472
 
1405
1473
  process.platform === "win32";
1406
1474
 
@@ -2349,10 +2417,12 @@ const generateCoverageJsonFile = async ({
2349
2417
  await writeFile(coverageJsonFileUrl, coverageAsText);
2350
2418
  };
2351
2419
 
2420
+ const importWithRequire = createRequire(import.meta.url);
2421
+
2352
2422
  const istanbulCoverageMapFromCoverage = coverage => {
2353
2423
  const {
2354
2424
  createCoverageMap
2355
- } = requireFromJsenv("istanbul-lib-coverage");
2425
+ } = importWithRequire("istanbul-lib-coverage");
2356
2426
  const coverageAdjusted = {};
2357
2427
  Object.keys(coverage).forEach(key => {
2358
2428
  coverageAdjusted[key.slice(2)] = {
@@ -2370,8 +2440,8 @@ const generateCoverageHtmlDirectory = async (coverage, {
2370
2440
  coverageReportSkipEmpty,
2371
2441
  coverageReportSkipFull
2372
2442
  }) => {
2373
- const libReport = requireFromJsenv("istanbul-lib-report");
2374
- const reports = requireFromJsenv("istanbul-reports");
2443
+ const libReport = importWithRequire("istanbul-lib-report");
2444
+ const reports = importWithRequire("istanbul-reports");
2375
2445
  const context = libReport.createContext({
2376
2446
  dir: fileURLToPath(rootDirectoryUrl),
2377
2447
  coverageMap: istanbulCoverageMapFromCoverage(coverage),
@@ -2389,8 +2459,8 @@ const generateCoverageTextLog = (coverage, {
2389
2459
  coverageReportSkipEmpty,
2390
2460
  coverageReportSkipFull
2391
2461
  }) => {
2392
- const libReport = requireFromJsenv("istanbul-lib-report");
2393
- const reports = requireFromJsenv("istanbul-reports");
2462
+ const libReport = importWithRequire("istanbul-lib-report");
2463
+ const reports = importWithRequire("istanbul-reports");
2394
2464
  const context = libReport.createContext({
2395
2465
  coverageMap: istanbulCoverageMapFromCoverage(coverage)
2396
2466
  });
@@ -2401,6 +2471,92 @@ const generateCoverageTextLog = (coverage, {
2401
2471
  report.execute(context);
2402
2472
  };
2403
2473
 
2474
+ const pingServer = async url => {
2475
+ const server = createServer();
2476
+ const {
2477
+ hostname,
2478
+ port
2479
+ } = new URL(url);
2480
+ try {
2481
+ await new Promise((resolve, reject) => {
2482
+ server.on("error", reject);
2483
+ server.on("listening", () => {
2484
+ resolve();
2485
+ });
2486
+ server.listen(port, hostname);
2487
+ });
2488
+ } catch (error) {
2489
+ if (error && error.code === "EADDRINUSE") {
2490
+ return true;
2491
+ }
2492
+ if (error && error.code === "EACCES") {
2493
+ return true;
2494
+ }
2495
+ throw error;
2496
+ }
2497
+ await new Promise((resolve, reject) => {
2498
+ server.on("error", reject);
2499
+ server.on("close", resolve);
2500
+ server.close();
2501
+ });
2502
+ return false;
2503
+ };
2504
+
2505
+ const basicFetch = async (url, {
2506
+ rejectUnauthorized = true,
2507
+ method = "GET",
2508
+ headers = {}
2509
+ } = {}) => {
2510
+ let requestModule;
2511
+ if (url.startsWith("http:")) {
2512
+ requestModule = await import("node:http");
2513
+ } else {
2514
+ requestModule = await import("node:https");
2515
+ }
2516
+ const {
2517
+ request
2518
+ } = requestModule;
2519
+ const urlObject = new URL(url);
2520
+ return new Promise((resolve, reject) => {
2521
+ const req = request({
2522
+ rejectUnauthorized,
2523
+ hostname: urlObject.hostname,
2524
+ port: urlObject.port,
2525
+ path: urlObject.pathname,
2526
+ method,
2527
+ headers
2528
+ });
2529
+ req.on("response", response => {
2530
+ resolve({
2531
+ status: response.statusCode,
2532
+ headers: response.headers,
2533
+ json: () => {
2534
+ req.setTimeout(0);
2535
+ req.destroy();
2536
+ return new Promise(resolve => {
2537
+ if (response.headers["content-type"] !== "application/json") {
2538
+ console.warn("not json");
2539
+ }
2540
+ let responseBody = "";
2541
+ response.setEncoding("utf8");
2542
+ response.on("data", chunk => {
2543
+ responseBody += chunk;
2544
+ });
2545
+ response.on("end", () => {
2546
+ resolve(JSON.parse(responseBody));
2547
+ });
2548
+ response.on("error", e => {
2549
+ reject(e);
2550
+ });
2551
+ });
2552
+ }
2553
+ });
2554
+ });
2555
+ req.on("error", reject);
2556
+ req.end();
2557
+ });
2558
+ };
2559
+
2404
2560
  const assertAndNormalizeWebServer = async webServer => {
2405
2561
  if (!webServer) {
2406
2562
  throw new TypeError(`webServer is required when running tests on browser(s)`);
@@ -2601,7 +2757,7 @@ const composeTwoV8Coverages = (firstV8Coverage, secondV8Coverage) => {
2601
2757
  // eslint-disable-next-line import/no-unresolved
2602
2758
  const {
2603
2759
  mergeProcessCovs
2604
- } = requireFromJsenv("@c88/v8-coverage");
2760
+ } = importWithRequire("@c88/v8-coverage");
2605
2761
  // "mergeProcessCovs" do not preserves source-map-cache during the merge
2606
2762
  // so we store sourcemap cache now
2607
2763
  const sourceMapCache = {};
@@ -2632,7 +2788,7 @@ const composeTwoFileByFileIstanbulCoverages = (firstFileByFileIstanbulCoverage,
2632
2788
  const merge = (firstIstanbulCoverage, secondIstanbulCoverage) => {
2633
2789
  const {
2634
2790
  createFileCoverage
2635
- } = requireFromJsenv("istanbul-lib-coverage");
2791
+ } = importWithRequire("istanbul-lib-coverage");
2636
2792
  const istanbulFileCoverageObject = createFileCoverage(firstIstanbulCoverage);
2637
2793
  istanbulFileCoverageObject.merge(secondIstanbulCoverage);
2638
2794
  const istanbulCoverage = istanbulFileCoverageObject.toJSON();
@@ -2645,7 +2801,7 @@ const v8CoverageToIstanbul = async (v8Coverage, {
2645
2801
  const operation = Abort.startOperation();
2646
2802
  operation.addAbortSignal(signal);
2647
2803
  try {
2648
- const v8ToIstanbul = requireFromJsenv("v8-to-istanbul");
2804
+ const v8ToIstanbul = importWithRequire("v8-to-istanbul");
2649
2805
  const sourcemapCache = v8Coverage["source-map-cache"];
2650
2806
  let istanbulCoverageComposed = null;
2651
2807
  await v8Coverage.result.reduce(async (previous, fileV8Coverage) => {
@@ -2795,7 +2951,7 @@ const babelPluginInstrument = (api, {
2795
2951
  }) => {
2796
2952
  const {
2797
2953
  programVisitor
2798
- } = requireFromJsenv("istanbul-lib-instrument");
2954
+ } = importWithRequire("istanbul-lib-instrument");
2799
2955
  const {
2800
2956
  types
2801
2957
  } = api;
@@ -2882,7 +3038,7 @@ const relativeUrlToEmptyCoverage = async (relativeUrl, {
2882
3038
  const createEmptyCoverage = relativeUrl => {
2883
3039
  const {
2884
3040
  createFileCoverage
2885
- } = requireFromJsenv("istanbul-lib-coverage");
3041
+ } = importWithRequire("istanbul-lib-coverage");
2886
3042
  return createFileCoverage(relativeUrl).toJSON();
2887
3043
  };
2888
3044
 
@@ -4288,6 +4444,35 @@ const memoize = compute => {
4288
4444
  return fnWithMemoization;
4289
4445
  };
4290
4446
 
4447
+ const WEB_URL_CONVERTER = {
4448
+ asWebUrl: (fileUrl, webServer) => {
4449
+ if (urlIsInsideOf(fileUrl, webServer.rootDirectoryUrl)) {
4450
+ return moveUrl({
4451
+ url: fileUrl,
4452
+ from: webServer.rootDirectoryUrl,
4453
+ to: `${webServer.origin}/`
4454
+ });
4455
+ }
4456
+ const fsRootUrl = ensureWindowsDriveLetter("file:///", fileUrl);
4457
+ return `${webServer.origin}/@fs/${fileUrl.slice(fsRootUrl.length)}`;
4458
+ },
4459
+ asFileUrl: (webUrl, webServer) => {
4460
+ const {
4461
+ pathname,
4462
+ search
4463
+ } = new URL(webUrl);
4464
+ if (pathname.startsWith("/@fs/")) {
4465
+ const fsRootRelativeUrl = pathname.slice("/@fs/".length);
4466
+ return `file:///${fsRootRelativeUrl}${search}`;
4467
+ }
4468
+ return moveUrl({
4469
+ url: webUrl,
4470
+ from: `${webServer.origin}/`,
4471
+ to: webServer.rootDirectoryUrl
4472
+ });
4473
+ }
4474
+ };
4475
+
4291
4476
  const initJsSupervisorMiddleware = async (page, {
4292
4477
  webServer,
4293
4478
  fileUrl,
@@ -5258,7 +5443,7 @@ const killProcessTree = async (processId, {
5258
5443
  signal,
5259
5444
  timeout = 2000
5260
5445
  }) => {
5261
- const pidtree = requireFromJsenv("pidtree");
5446
+ const pidtree = importWithRequire("pidtree");
5262
5447
  let descendantProcessIds;
5263
5448
  try {
5264
5449
  descendantProcessIds = await pidtree(processId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/test",
3
- "version": "1.1.6",
3
+ "version": "1.2.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,11 +33,11 @@
33
33
  "playwright": "1.x"
34
34
  },
35
35
  "dependencies": {
36
- "@jsenv/core": "36.0.1",
37
36
  "@jsenv/abort": "4.2.4",
38
37
  "@jsenv/ast": "4.0.0",
39
38
  "@jsenv/filesystem": "4.2.3",
40
39
  "@jsenv/log": "3.3.5",
40
+ "@jsenv/plugin-supervisor": "1.0.0",
41
41
  "@jsenv/urls": "2.0.0",
42
42
  "@jsenv/url-meta": "8.1.0",
43
43
  "@jsenv/uneval": "1.6.0",
@@ -1,9 +1,9 @@
1
- import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js";
1
+ import { importWithRequire } from "../helpers/import_with_require.js";
2
2
 
3
3
  // https://github.com/istanbuljs/babel-plugin-istanbul/blob/321740f7b25d803f881466ea819d870f7ed6a254/src/index.js
4
4
 
5
5
  export const babelPluginInstrument = (api, { useInlineSourceMaps = false }) => {
6
- const { programVisitor } = requireFromJsenv("istanbul-lib-instrument");
6
+ const { programVisitor } = importWithRequire("istanbul-lib-instrument");
7
7
  const { types } = api;
8
8
 
9
9
  return {
@@ -1,7 +1,7 @@
1
1
  import { fileURLToPath } from "node:url";
2
2
  import { readFileSync } from "node:fs";
3
3
 
4
- import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js";
4
+ import { importWithRequire } from "../helpers/import_with_require.js";
5
5
  import { istanbulCoverageMapFromCoverage } from "./istanbul_coverage_map_from_coverage.js";
6
6
 
7
7
  export const generateCoverageHtmlDirectory = async (
@@ -13,8 +13,8 @@ export const generateCoverageHtmlDirectory = async (
13
13
  coverageReportSkipFull,
14
14
  },
15
15
  ) => {
16
- const libReport = requireFromJsenv("istanbul-lib-report");
17
- const reports = requireFromJsenv("istanbul-reports");
16
+ const libReport = importWithRequire("istanbul-lib-report");
17
+ const reports = importWithRequire("istanbul-reports");
18
18
 
19
19
  const context = libReport.createContext({
20
20
  dir: fileURLToPath(rootDirectoryUrl),
@@ -1,12 +1,12 @@
1
- import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js";
1
+ import { importWithRequire } from "../helpers/import_with_require.js";
2
2
  import { istanbulCoverageMapFromCoverage } from "./istanbul_coverage_map_from_coverage.js";
3
3
 
4
4
  export const generateCoverageTextLog = (
5
5
  coverage,
6
6
  { coverageReportSkipEmpty, coverageReportSkipFull },
7
7
  ) => {
8
- const libReport = requireFromJsenv("istanbul-lib-report");
9
- const reports = requireFromJsenv("istanbul-reports");
8
+ const libReport = importWithRequire("istanbul-lib-report");
9
+ const reports = importWithRequire("istanbul-reports");
10
10
 
11
11
  const context = libReport.createContext({
12
12
  coverageMap: istanbulCoverageMapFromCoverage(coverage),
@@ -2,8 +2,8 @@ import { readFile } from "@jsenv/filesystem";
2
2
  import { resolveUrl } from "@jsenv/urls";
3
3
  import { Abort } from "@jsenv/abort";
4
4
  import { applyBabelPlugins } from "@jsenv/ast";
5
- import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js";
6
5
 
6
+ import { importWithRequire } from "../helpers/import_with_require.js";
7
7
  import { babelPluginInstrument } from "./babel_plugin_instrument.js";
8
8
 
9
9
  export const relativeUrlToEmptyCoverage = async (
@@ -47,6 +47,6 @@ export const relativeUrlToEmptyCoverage = async (
47
47
  };
48
48
 
49
49
  const createEmptyCoverage = (relativeUrl) => {
50
- const { createFileCoverage } = requireFromJsenv("istanbul-lib-coverage");
50
+ const { createFileCoverage } = importWithRequire("istanbul-lib-coverage");
51
51
  return createFileCoverage(relativeUrl).toJSON();
52
52
  };
@@ -1,5 +1,4 @@
1
- import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js";
2
-
1
+ import { importWithRequire } from "../helpers/import_with_require.js";
3
2
  export const composeTwoFileByFileIstanbulCoverages = (
4
3
  firstFileByFileIstanbulCoverage,
5
4
  secondFileByFileIstanbulCoverage,
@@ -20,7 +19,7 @@ export const composeTwoFileByFileIstanbulCoverages = (
20
19
  };
21
20
 
22
21
  const merge = (firstIstanbulCoverage, secondIstanbulCoverage) => {
23
- const { createFileCoverage } = requireFromJsenv("istanbul-lib-coverage");
22
+ const { createFileCoverage } = importWithRequire("istanbul-lib-coverage");
24
23
  const istanbulFileCoverageObject = createFileCoverage(firstIstanbulCoverage);
25
24
  istanbulFileCoverageObject.merge(secondIstanbulCoverage);
26
25
  const istanbulCoverage = istanbulFileCoverageObject.toJSON();
@@ -1,7 +1,6 @@
1
- import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js";
2
-
1
+ import { importWithRequire } from "../helpers/import_with_require.js";
3
2
  export const istanbulCoverageMapFromCoverage = (coverage) => {
4
- const { createCoverageMap } = requireFromJsenv("istanbul-lib-coverage");
3
+ const { createCoverageMap } = importWithRequire("istanbul-lib-coverage");
5
4
 
6
5
  const coverageAdjusted = {};
7
6
  Object.keys(coverage).forEach((key) => {
@@ -1,12 +1,11 @@
1
- import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js";
2
-
1
+ import { importWithRequire } from "../helpers/import_with_require.js";
3
2
  export const composeTwoV8Coverages = (firstV8Coverage, secondV8Coverage) => {
4
3
  if (secondV8Coverage.result.length === 0) {
5
4
  return firstV8Coverage;
6
5
  }
7
6
 
8
7
  // eslint-disable-next-line import/no-unresolved
9
- const { mergeProcessCovs } = requireFromJsenv("@c88/v8-coverage");
8
+ const { mergeProcessCovs } = importWithRequire("@c88/v8-coverage");
10
9
  // "mergeProcessCovs" do not preserves source-map-cache during the merge
11
10
  // so we store sourcemap cache now
12
11
  const sourceMapCache = {};
@@ -1,7 +1,7 @@
1
1
  import { urlToFileSystemPath } from "@jsenv/urls";
2
2
  import { Abort } from "@jsenv/abort";
3
- import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js";
4
3
 
4
+ import { importWithRequire } from "../helpers/import_with_require.js";
5
5
  import { composeTwoFileByFileIstanbulCoverages } from "./istanbul_coverage_composition.js";
6
6
 
7
7
  export const v8CoverageToIstanbul = async (v8Coverage, { signal }) => {
@@ -9,7 +9,7 @@ export const v8CoverageToIstanbul = async (v8Coverage, { signal }) => {
9
9
  operation.addAbortSignal(signal);
10
10
 
11
11
  try {
12
- const v8ToIstanbul = requireFromJsenv("v8-to-istanbul");
12
+ const v8ToIstanbul = importWithRequire("v8-to-istanbul");
13
13
  const sourcemapCache = v8Coverage["source-map-cache"];
14
14
  let istanbulCoverageComposed = null;
15
15
 
@@ -1,6 +1,7 @@
1
1
  import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem";
2
- import { pingServer } from "@jsenv/core/src/helpers/ping_server.js";
3
- import { basicFetch } from "@jsenv/core/src/helpers/basic_fetch.js";
2
+
3
+ import { pingServer } from "../helpers/ping_server.js";
4
+ import { basicFetch } from "../helpers/basic_fetch.js";
4
5
 
5
6
  export const assertAndNormalizeWebServer = async (webServer) => {
6
7
  if (!webServer) {
@@ -0,0 +1,53 @@
1
+ export const basicFetch = async (
2
+ url,
3
+ { rejectUnauthorized = true, method = "GET", headers = {} } = {},
4
+ ) => {
5
+ let requestModule;
6
+ if (url.startsWith("http:")) {
7
+ requestModule = await import("node:http");
8
+ } else {
9
+ requestModule = await import("node:https");
10
+ }
11
+ const { request } = requestModule;
12
+
13
+ const urlObject = new URL(url);
14
+
15
+ return new Promise((resolve, reject) => {
16
+ const req = request({
17
+ rejectUnauthorized,
18
+ hostname: urlObject.hostname,
19
+ port: urlObject.port,
20
+ path: urlObject.pathname,
21
+ method,
22
+ headers,
23
+ });
24
+ req.on("response", (response) => {
25
+ resolve({
26
+ status: response.statusCode,
27
+ headers: response.headers,
28
+ json: () => {
29
+ req.setTimeout(0);
30
+ req.destroy();
31
+ return new Promise((resolve) => {
32
+ if (response.headers["content-type"] !== "application/json") {
33
+ console.warn("not json");
34
+ }
35
+ let responseBody = "";
36
+ response.setEncoding("utf8");
37
+ response.on("data", (chunk) => {
38
+ responseBody += chunk;
39
+ });
40
+ response.on("end", () => {
41
+ resolve(JSON.parse(responseBody));
42
+ });
43
+ response.on("error", (e) => {
44
+ reject(e);
45
+ });
46
+ });
47
+ },
48
+ });
49
+ });
50
+ req.on("error", reject);
51
+ req.end();
52
+ });
53
+ };
@@ -0,0 +1,3 @@
1
+ import { createRequire } from "node:module";
2
+
3
+ export const importWithRequire = createRequire(import.meta.url);
@@ -0,0 +1,30 @@
1
+ import { createServer } from "node:net";
2
+
3
+ export const pingServer = async (url) => {
4
+ const server = createServer();
5
+ const { hostname, port } = new URL(url);
6
+
7
+ try {
8
+ await new Promise((resolve, reject) => {
9
+ server.on("error", reject);
10
+ server.on("listening", () => {
11
+ resolve();
12
+ });
13
+ server.listen(port, hostname);
14
+ });
15
+ } catch (error) {
16
+ if (error && error.code === "EADDRINUSE") {
17
+ return true;
18
+ }
19
+ if (error && error.code === "EACCES") {
20
+ return true;
21
+ }
22
+ throw error;
23
+ }
24
+ await new Promise((resolve, reject) => {
25
+ server.on("error", reject);
26
+ server.on("close", resolve);
27
+ server.close();
28
+ });
29
+ return false;
30
+ };
@@ -0,0 +1,28 @@
1
+ import { ensureWindowsDriveLetter } from "@jsenv/filesystem";
2
+ import { urlIsInsideOf, moveUrl } from "@jsenv/urls";
3
+
4
+ export const WEB_URL_CONVERTER = {
5
+ asWebUrl: (fileUrl, webServer) => {
6
+ if (urlIsInsideOf(fileUrl, webServer.rootDirectoryUrl)) {
7
+ return moveUrl({
8
+ url: fileUrl,
9
+ from: webServer.rootDirectoryUrl,
10
+ to: `${webServer.origin}/`,
11
+ });
12
+ }
13
+ const fsRootUrl = ensureWindowsDriveLetter("file:///", fileUrl);
14
+ return `${webServer.origin}/@fs/${fileUrl.slice(fsRootUrl.length)}`;
15
+ },
16
+ asFileUrl: (webUrl, webServer) => {
17
+ const { pathname, search } = new URL(webUrl);
18
+ if (pathname.startsWith("/@fs/")) {
19
+ const fsRootRelativeUrl = pathname.slice("/@fs/".length);
20
+ return `file:///${fsRootRelativeUrl}${search}`;
21
+ }
22
+ return moveUrl({
23
+ url: webUrl,
24
+ from: `${webServer.origin}/`,
25
+ to: webServer.rootDirectoryUrl,
26
+ });
27
+ },
28
+ };
@@ -1,8 +1,8 @@
1
1
  import { URL_META } from "@jsenv/url-meta";
2
2
  import { applyBabelPlugins } from "@jsenv/ast";
3
3
  import { SOURCEMAP, generateSourcemapDataUrl } from "@jsenv/sourcemap";
4
- import { WEB_URL_CONVERTER } from "@jsenv/core/src/helpers/web_url_converter.js";
5
4
 
5
+ import { WEB_URL_CONVERTER } from "../helpers/web_url_converter.js";
6
6
  import { babelPluginInstrument } from "../coverage/babel_plugin_instrument.js";
7
7
 
8
8
  export const initIstanbulMiddleware = async (
@@ -3,7 +3,7 @@ import { urlToExtension } from "@jsenv/urls";
3
3
  import {
4
4
  injectSupervisorIntoHTML,
5
5
  supervisorFileUrl,
6
- } from "@jsenv/core/src/plugins/supervisor/html_supervisor_injection.js";
6
+ } from "@jsenv/plugin-supervisor/src/html_supervisor_injection.js";
7
7
 
8
8
  export const initJsSupervisorMiddleware = async (
9
9
  page,
@@ -8,8 +8,8 @@ import {
8
8
  } from "@jsenv/abort";
9
9
  import { urlIsInsideOf } from "@jsenv/urls";
10
10
  import { memoize } from "@jsenv/utils/src/memoize/memoize.js";
11
- import { WEB_URL_CONVERTER } from "@jsenv/core/src/helpers/web_url_converter.js";
12
11
 
12
+ import { WEB_URL_CONVERTER } from "../helpers/web_url_converter.js";
13
13
  import { filterV8Coverage } from "../coverage/v8_coverage.js";
14
14
  import { composeTwoFileByFileIstanbulCoverages } from "../coverage/istanbul_coverage_composition.js";
15
15
  import { initJsSupervisorMiddleware } from "./middleware_js_supervisor.js";
@@ -1,11 +1,10 @@
1
- import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js";
2
-
1
+ import { importWithRequire } from "../helpers/import_with_require.js";
3
2
  // see also https://github.com/sindresorhus/execa/issues/96
4
3
  export const killProcessTree = async (
5
4
  processId,
6
5
  { signal, timeout = 2000 },
7
6
  ) => {
8
- const pidtree = requireFromJsenv("pidtree");
7
+ const pidtree = importWithRequire("pidtree");
9
8
 
10
9
  let descendantProcessIds;
11
10
  try {