@jsenv/plugin-supervisor 1.5.26 → 1.5.28

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.
@@ -3,8 +3,9 @@ import process$1 from "node:process";
3
3
  import os from "node:os";
4
4
  import tty from "node:tty";
5
5
  import "string-width";
6
- import { fileURLToPath } from "node:url";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import { createRequire } from "node:module";
8
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
8
9
 
9
10
  // From: https://github.com/sindresorhus/has-flag/blob/main/index.js
10
11
  /// function hasFlag(flag, argv = globalThis.Deno?.args ?? process.argv) {
@@ -454,6 +455,38 @@ isBrowser ? () => {
454
455
  throw new Error('`process.cwd()` only works in Node.js, not the browser.');
455
456
  } : process$1.cwd;
456
457
 
458
+ // normalize url search params:
459
+ // Using URLSearchParams to alter the url search params
460
+ // can result into "file:///file.css?css_module"
461
+ // becoming "file:///file.css?css_module="
462
+ // we want to get rid of the "=" and consider it's the same url
463
+ const normalizeUrl = url => {
464
+ if (url.includes("?")) {
465
+ // disable on data urls (would mess up base64 encoding)
466
+ if (url.startsWith("data:")) {
467
+ return url;
468
+ }
469
+ return url.replace(/[=](?=&|$)/g, "");
470
+ }
471
+ return url;
472
+ };
473
+ const injectQueryParams = (url, params) => {
474
+ const urlObject = new URL(url);
475
+ const {
476
+ searchParams
477
+ } = urlObject;
478
+ Object.keys(params).forEach(key => {
479
+ const value = params[key];
480
+ if (value === undefined) {
481
+ searchParams.delete(key);
482
+ } else {
483
+ searchParams.set(key, value);
484
+ }
485
+ });
486
+ const urlWithParams = urlObject.href;
487
+ return normalizeUrl(urlWithParams);
488
+ };
489
+
457
490
  const getCommonPathname = (pathname, otherPathname) => {
458
491
  if (pathname === otherPathname) {
459
492
  return pathname;
@@ -1184,6 +1217,843 @@ const generateCodeToSuperviseScriptWithSrc = ({
1184
1217
  return "window.__supervisor__.superviseScript(".concat(srcEncoded, ");");
1185
1218
  };
1186
1219
 
1220
+ // https://nodejs.org/api/packages.html#resolving-user-conditions
1221
+ const readCustomConditionsFromProcessArgs = () => {
1222
+ const packageConditions = [];
1223
+ process.execArgv.forEach(arg => {
1224
+ if (arg.includes("-C=")) {
1225
+ const packageCondition = arg.slice(0, "-C=".length);
1226
+ packageConditions.push(packageCondition);
1227
+ }
1228
+ if (arg.includes("--conditions=")) {
1229
+ const packageCondition = arg.slice("--conditions=".length);
1230
+ packageConditions.push(packageCondition);
1231
+ }
1232
+ });
1233
+ return packageConditions;
1234
+ };
1235
+
1236
+ const asDirectoryUrl = url => {
1237
+ const {
1238
+ pathname
1239
+ } = new URL(url);
1240
+ if (pathname.endsWith("/")) {
1241
+ return url;
1242
+ }
1243
+ return new URL("./", url).href;
1244
+ };
1245
+ const getParentUrl = url => {
1246
+ if (url.startsWith("file://")) {
1247
+ // With node.js new URL('../', 'file:///C:/').href
1248
+ // returns "file:///C:/" instead of "file:///"
1249
+ const resource = url.slice("file://".length);
1250
+ const slashLastIndex = resource.lastIndexOf("/");
1251
+ if (slashLastIndex === -1) {
1252
+ return url;
1253
+ }
1254
+ const lastCharIndex = resource.length - 1;
1255
+ if (slashLastIndex === lastCharIndex) {
1256
+ const slashBeforeLastIndex = resource.lastIndexOf("/", slashLastIndex - 1);
1257
+ if (slashBeforeLastIndex === -1) {
1258
+ return url;
1259
+ }
1260
+ return "file://".concat(resource.slice(0, slashBeforeLastIndex + 1));
1261
+ }
1262
+ return "file://".concat(resource.slice(0, slashLastIndex + 1));
1263
+ }
1264
+ return new URL(url.endsWith("/") ? "../" : "./", url).href;
1265
+ };
1266
+ const isValidUrl = url => {
1267
+ try {
1268
+ // eslint-disable-next-line no-new
1269
+ new URL(url);
1270
+ return true;
1271
+ } catch (_unused) {
1272
+ return false;
1273
+ }
1274
+ };
1275
+
1276
+ const defaultLookupPackageScope = url => {
1277
+ let scopeUrl = asDirectoryUrl(url);
1278
+ while (scopeUrl !== "file:///") {
1279
+ if (scopeUrl.endsWith("node_modules/")) {
1280
+ return null;
1281
+ }
1282
+ const packageJsonUrlObject = new URL("package.json", scopeUrl);
1283
+ if (existsSync(packageJsonUrlObject)) {
1284
+ return scopeUrl;
1285
+ }
1286
+ scopeUrl = getParentUrl(scopeUrl);
1287
+ }
1288
+ return null;
1289
+ };
1290
+
1291
+ const defaultReadPackageJson = packageUrl => {
1292
+ const packageJsonUrl = new URL("package.json", packageUrl);
1293
+ const buffer = readFileSync(packageJsonUrl);
1294
+ const string = String(buffer);
1295
+ try {
1296
+ return JSON.parse(string);
1297
+ } catch (_unused) {
1298
+ throw new Error("Invalid package configuration");
1299
+ }
1300
+ };
1301
+
1302
+ // https://github.com/nodejs/node/blob/0367b5c35ea0f98b323175a4aaa8e651af7a91e7/tools/node_modules/eslint/node_modules/%40babel/core/lib/vendor/import-meta-resolve.js#L2473
1303
+ const createInvalidModuleSpecifierError = (reason, specifier, {
1304
+ parentUrl
1305
+ }) => {
1306
+ const error = new Error("Invalid module \"".concat(specifier, "\" ").concat(reason, " imported from ").concat(fileURLToPath(parentUrl)));
1307
+ error.code = "INVALID_MODULE_SPECIFIER";
1308
+ return error;
1309
+ };
1310
+ const createInvalidPackageTargetError = (reason, target, {
1311
+ parentUrl,
1312
+ packageDirectoryUrl,
1313
+ key,
1314
+ isImport
1315
+ }) => {
1316
+ let message;
1317
+ if (key === ".") {
1318
+ message = "Invalid \"exports\" main target defined in ".concat(fileURLToPath(packageDirectoryUrl), "package.json imported from ").concat(fileURLToPath(parentUrl), "; ").concat(reason);
1319
+ } else {
1320
+ message = "Invalid \"".concat(isImport ? "imports" : "exports", "\" target ").concat(JSON.stringify(target), " defined for \"").concat(key, "\" in ").concat(fileURLToPath(packageDirectoryUrl), "package.json imported from ").concat(fileURLToPath(parentUrl), "; ").concat(reason);
1321
+ }
1322
+ const error = new Error(message);
1323
+ error.code = "INVALID_PACKAGE_TARGET";
1324
+ return error;
1325
+ };
1326
+ const createPackagePathNotExportedError = (subpath, {
1327
+ parentUrl,
1328
+ packageDirectoryUrl
1329
+ }) => {
1330
+ let message;
1331
+ if (subpath === ".") {
1332
+ message = "No \"exports\" main defined in ".concat(fileURLToPath(packageDirectoryUrl), "package.json imported from ").concat(fileURLToPath(parentUrl));
1333
+ } else {
1334
+ message = "Package subpath \"".concat(subpath, "\" is not defined by \"exports\" in ").concat(fileURLToPath(packageDirectoryUrl), "package.json imported from ").concat(fileURLToPath(parentUrl));
1335
+ }
1336
+ const error = new Error(message);
1337
+ error.code = "PACKAGE_PATH_NOT_EXPORTED";
1338
+ return error;
1339
+ };
1340
+ const createModuleNotFoundError = (specifier, {
1341
+ parentUrl
1342
+ }) => {
1343
+ const error = new Error("Cannot find \"".concat(specifier, "\" imported from ").concat(fileURLToPath(parentUrl)));
1344
+ error.code = "MODULE_NOT_FOUND";
1345
+ return error;
1346
+ };
1347
+ const createPackageImportNotDefinedError = (specifier, {
1348
+ parentUrl,
1349
+ packageDirectoryUrl
1350
+ }) => {
1351
+ const error = new Error("Package import specifier \"".concat(specifier, "\" is not defined in ").concat(fileURLToPath(packageDirectoryUrl), "package.json imported from ").concat(fileURLToPath(parentUrl)));
1352
+ error.code = "PACKAGE_IMPORT_NOT_DEFINED";
1353
+ return error;
1354
+ };
1355
+
1356
+ const isSpecifierForNodeBuiltin = specifier => {
1357
+ return specifier.startsWith("node:") || NODE_BUILTIN_MODULE_SPECIFIERS.includes(specifier);
1358
+ };
1359
+ const NODE_BUILTIN_MODULE_SPECIFIERS = ["assert", "assert/strict", "async_hooks", "buffer_ieee754", "buffer", "child_process", "cluster", "console", "constants", "crypto", "_debugger", "dgram", "dns", "domain", "events", "freelist", "fs", "fs/promises", "_http_agent", "_http_client", "_http_common", "_http_incoming", "_http_outgoing", "_http_server", "http", "http2", "https", "inspector", "_linklist", "module", "net", "node-inspect/lib/_inspect", "node-inspect/lib/internal/inspect_client", "node-inspect/lib/internal/inspect_repl", "os", "path", "perf_hooks", "process", "punycode", "querystring", "readline", "repl", "smalloc", "_stream_duplex", "_stream_transform", "_stream_wrap", "_stream_passthrough", "_stream_readable", "_stream_writable", "stream", "stream/promises", "string_decoder", "sys", "timers", "_tls_common", "_tls_legacy", "_tls_wrap", "tls", "trace_events", "tty", "url", "util", "v8/tools/arguments", "v8/tools/codemap", "v8/tools/consarray", "v8/tools/csvparser", "v8/tools/logreader", "v8/tools/profile_view", "v8/tools/splaytree", "v8", "vm", "worker_threads", "zlib",
1360
+ // global is special
1361
+ "global"];
1362
+
1363
+ /*
1364
+ * https://nodejs.org/api/esm.html#resolver-algorithm-specification
1365
+ * https://github.com/nodejs/node/blob/0367b5c35ea0f98b323175a4aaa8e651af7a91e7/lib/internal/modules/esm/resolve.js#L1
1366
+ * deviations from the spec:
1367
+ * - take into account "browser", "module" and "jsnext"
1368
+ * - the check for isDirectory -> throw is delayed is descoped to the caller
1369
+ * - the call to real path ->
1370
+ * delayed to the caller so that we can decide to
1371
+ * maintain symlink as facade url when it's outside project directory
1372
+ * or use the real path when inside
1373
+ */
1374
+ const applyNodeEsmResolution = ({
1375
+ specifier,
1376
+ parentUrl,
1377
+ conditions = [...readCustomConditionsFromProcessArgs(), "node", "import"],
1378
+ lookupPackageScope = defaultLookupPackageScope,
1379
+ readPackageJson = defaultReadPackageJson,
1380
+ preservesSymlink = false
1381
+ }) => {
1382
+ const resolution = applyPackageSpecifierResolution(specifier, {
1383
+ parentUrl: String(parentUrl),
1384
+ conditions,
1385
+ lookupPackageScope,
1386
+ readPackageJson,
1387
+ preservesSymlink
1388
+ });
1389
+ const {
1390
+ url
1391
+ } = resolution;
1392
+ if (url.startsWith("file:")) {
1393
+ if (url.includes("%2F") || url.includes("%5C")) {
1394
+ throw createInvalidModuleSpecifierError("must not include encoded \"/\" or \"\\\" characters", specifier, {
1395
+ parentUrl
1396
+ });
1397
+ }
1398
+ return resolution;
1399
+ }
1400
+ return resolution;
1401
+ };
1402
+ const applyPackageSpecifierResolution = (specifier, resolutionContext) => {
1403
+ const {
1404
+ parentUrl
1405
+ } = resolutionContext;
1406
+ // relative specifier
1407
+ if (specifier[0] === "/" || specifier.startsWith("./") || specifier.startsWith("../")) {
1408
+ if (specifier[0] !== "/") {
1409
+ const browserFieldResolution = applyBrowserFieldResolution(specifier, resolutionContext);
1410
+ if (browserFieldResolution) {
1411
+ return browserFieldResolution;
1412
+ }
1413
+ }
1414
+ return {
1415
+ type: "relative_specifier",
1416
+ url: new URL(specifier, parentUrl).href
1417
+ };
1418
+ }
1419
+ if (specifier[0] === "#") {
1420
+ return applyPackageImportsResolution(specifier, resolutionContext);
1421
+ }
1422
+ try {
1423
+ const urlObject = new URL(specifier);
1424
+ if (specifier.startsWith("node:")) {
1425
+ return {
1426
+ type: "node_builtin_specifier",
1427
+ url: specifier
1428
+ };
1429
+ }
1430
+ return {
1431
+ type: "absolute_specifier",
1432
+ url: urlObject.href
1433
+ };
1434
+ } catch (_unused) {
1435
+ // bare specifier
1436
+ const browserFieldResolution = applyBrowserFieldResolution(specifier, resolutionContext);
1437
+ if (browserFieldResolution) {
1438
+ return browserFieldResolution;
1439
+ }
1440
+ const packageResolution = applyPackageResolve(specifier, resolutionContext);
1441
+ const search = new URL(specifier, "file:///").search;
1442
+ if (search && !new URL(packageResolution.url).search) {
1443
+ packageResolution.url = "".concat(packageResolution.url).concat(search);
1444
+ }
1445
+ return packageResolution;
1446
+ }
1447
+ };
1448
+ const applyBrowserFieldResolution = (specifier, resolutionContext) => {
1449
+ const {
1450
+ parentUrl,
1451
+ conditions,
1452
+ lookupPackageScope,
1453
+ readPackageJson
1454
+ } = resolutionContext;
1455
+ const browserCondition = conditions.includes("browser");
1456
+ if (!browserCondition) {
1457
+ return null;
1458
+ }
1459
+ const packageDirectoryUrl = lookupPackageScope(parentUrl);
1460
+ if (!packageDirectoryUrl) {
1461
+ return null;
1462
+ }
1463
+ const packageJson = readPackageJson(packageDirectoryUrl);
1464
+ if (!packageJson) {
1465
+ return null;
1466
+ }
1467
+ const {
1468
+ browser
1469
+ } = packageJson;
1470
+ if (!browser) {
1471
+ return null;
1472
+ }
1473
+ if (typeof browser !== "object") {
1474
+ return null;
1475
+ }
1476
+ let url;
1477
+ if (specifier.startsWith(".")) {
1478
+ const specifierUrl = new URL(specifier, parentUrl).href;
1479
+ const specifierRelativeUrl = specifierUrl.slice(packageDirectoryUrl.length);
1480
+ const secifierRelativeNotation = "./".concat(specifierRelativeUrl);
1481
+ const browserMapping = browser[secifierRelativeNotation];
1482
+ if (typeof browserMapping === "string") {
1483
+ url = new URL(browserMapping, packageDirectoryUrl).href;
1484
+ } else if (browserMapping === false) {
1485
+ url = "file:///@ignore/".concat(specifierUrl.slice("file:///"));
1486
+ }
1487
+ } else {
1488
+ const browserMapping = browser[specifier];
1489
+ if (typeof browserMapping === "string") {
1490
+ url = new URL(browserMapping, packageDirectoryUrl).href;
1491
+ } else if (browserMapping === false) {
1492
+ url = "file:///@ignore/".concat(specifier);
1493
+ }
1494
+ }
1495
+ if (url) {
1496
+ return {
1497
+ type: "field:browser",
1498
+ packageDirectoryUrl,
1499
+ packageJson,
1500
+ url
1501
+ };
1502
+ }
1503
+ return null;
1504
+ };
1505
+ const applyPackageImportsResolution = (internalSpecifier, resolutionContext) => {
1506
+ const {
1507
+ parentUrl,
1508
+ lookupPackageScope,
1509
+ readPackageJson
1510
+ } = resolutionContext;
1511
+ if (internalSpecifier === "#" || internalSpecifier.startsWith("#/")) {
1512
+ throw createInvalidModuleSpecifierError("not a valid internal imports specifier name", internalSpecifier, resolutionContext);
1513
+ }
1514
+ const packageDirectoryUrl = lookupPackageScope(parentUrl);
1515
+ if (packageDirectoryUrl !== null) {
1516
+ const packageJson = readPackageJson(packageDirectoryUrl);
1517
+ const {
1518
+ imports
1519
+ } = packageJson;
1520
+ if (imports !== null && typeof imports === "object") {
1521
+ const resolved = applyPackageImportsExportsResolution(internalSpecifier, {
1522
+ ...resolutionContext,
1523
+ packageDirectoryUrl,
1524
+ packageJson,
1525
+ isImport: true
1526
+ });
1527
+ if (resolved) {
1528
+ return resolved;
1529
+ }
1530
+ }
1531
+ }
1532
+ throw createPackageImportNotDefinedError(internalSpecifier, {
1533
+ ...resolutionContext,
1534
+ packageDirectoryUrl
1535
+ });
1536
+ };
1537
+ const applyPackageResolve = (packageSpecifier, resolutionContext) => {
1538
+ const {
1539
+ parentUrl,
1540
+ conditions,
1541
+ readPackageJson,
1542
+ preservesSymlink
1543
+ } = resolutionContext;
1544
+ if (packageSpecifier === "") {
1545
+ throw new Error("invalid module specifier");
1546
+ }
1547
+ if (conditions.includes("node") && isSpecifierForNodeBuiltin(packageSpecifier)) {
1548
+ return {
1549
+ type: "node_builtin_specifier",
1550
+ url: "node:".concat(packageSpecifier)
1551
+ };
1552
+ }
1553
+ let {
1554
+ packageName,
1555
+ packageSubpath
1556
+ } = parsePackageSpecifier(packageSpecifier);
1557
+ if (packageName[0] === "." || packageName.includes("\\") || packageName.includes("%")) {
1558
+ throw createInvalidModuleSpecifierError("is not a valid package name", packageName, resolutionContext);
1559
+ }
1560
+ if (packageSubpath.endsWith("/")) {
1561
+ throw new Error("invalid module specifier");
1562
+ }
1563
+ const questionCharIndex = packageName.indexOf("?");
1564
+ if (questionCharIndex > -1) {
1565
+ packageName = packageName.slice(0, questionCharIndex);
1566
+ }
1567
+ const selfResolution = applyPackageSelfResolution(packageSubpath, {
1568
+ ...resolutionContext,
1569
+ packageName
1570
+ });
1571
+ if (selfResolution) {
1572
+ return selfResolution;
1573
+ }
1574
+ let currentUrl = parentUrl;
1575
+ while (currentUrl !== "file:///") {
1576
+ const packageDirectoryFacadeUrl = new URL("node_modules/".concat(packageName, "/"), currentUrl).href;
1577
+ if (!existsSync(new URL(packageDirectoryFacadeUrl))) {
1578
+ currentUrl = getParentUrl(currentUrl);
1579
+ continue;
1580
+ }
1581
+ const packageDirectoryUrl = preservesSymlink ? packageDirectoryFacadeUrl : resolvePackageSymlink(packageDirectoryFacadeUrl);
1582
+ const packageJson = readPackageJson(packageDirectoryUrl);
1583
+ if (packageJson !== null) {
1584
+ const {
1585
+ exports
1586
+ } = packageJson;
1587
+ if (exports !== null && exports !== undefined) {
1588
+ return applyPackageExportsResolution(packageSubpath, {
1589
+ ...resolutionContext,
1590
+ packageDirectoryUrl,
1591
+ packageJson,
1592
+ exports
1593
+ });
1594
+ }
1595
+ }
1596
+ return applyLegacySubpathResolution(packageSubpath, {
1597
+ ...resolutionContext,
1598
+ packageDirectoryUrl,
1599
+ packageJson
1600
+ });
1601
+ }
1602
+ throw createModuleNotFoundError(packageName, resolutionContext);
1603
+ };
1604
+ const applyPackageSelfResolution = (packageSubpath, resolutionContext) => {
1605
+ const {
1606
+ parentUrl,
1607
+ packageName,
1608
+ lookupPackageScope,
1609
+ readPackageJson
1610
+ } = resolutionContext;
1611
+ const packageDirectoryUrl = lookupPackageScope(parentUrl);
1612
+ if (!packageDirectoryUrl) {
1613
+ return undefined;
1614
+ }
1615
+ const packageJson = readPackageJson(packageDirectoryUrl);
1616
+ if (!packageJson) {
1617
+ return undefined;
1618
+ }
1619
+ if (packageJson.name !== packageName) {
1620
+ return undefined;
1621
+ }
1622
+ const {
1623
+ exports
1624
+ } = packageJson;
1625
+ if (!exports) {
1626
+ const subpathResolution = applyLegacySubpathResolution(packageSubpath, {
1627
+ ...resolutionContext,
1628
+ packageDirectoryUrl,
1629
+ packageJson
1630
+ });
1631
+ if (subpathResolution && subpathResolution.type !== "subpath") {
1632
+ return subpathResolution;
1633
+ }
1634
+ return undefined;
1635
+ }
1636
+ return applyPackageExportsResolution(packageSubpath, {
1637
+ ...resolutionContext,
1638
+ packageDirectoryUrl,
1639
+ packageJson
1640
+ });
1641
+ };
1642
+
1643
+ // https://github.com/nodejs/node/blob/0367b5c35ea0f98b323175a4aaa8e651af7a91e7/lib/internal/modules/esm/resolve.js#L642
1644
+ const applyPackageExportsResolution = (packageSubpath, resolutionContext) => {
1645
+ if (packageSubpath === ".") {
1646
+ const mainExport = applyMainExportResolution(resolutionContext);
1647
+ if (!mainExport) {
1648
+ throw createPackagePathNotExportedError(packageSubpath, resolutionContext);
1649
+ }
1650
+ const resolved = applyPackageTargetResolution(mainExport, {
1651
+ ...resolutionContext,
1652
+ key: "."
1653
+ });
1654
+ if (resolved) {
1655
+ return resolved;
1656
+ }
1657
+ throw createPackagePathNotExportedError(packageSubpath, resolutionContext);
1658
+ }
1659
+ const packageExportsInfo = readExports(resolutionContext);
1660
+ if (packageExportsInfo.type === "object" && packageExportsInfo.allKeysAreRelative) {
1661
+ const resolved = applyPackageImportsExportsResolution(packageSubpath, {
1662
+ ...resolutionContext,
1663
+ isImport: false
1664
+ });
1665
+ if (resolved) {
1666
+ return resolved;
1667
+ }
1668
+ }
1669
+ throw createPackagePathNotExportedError(packageSubpath, resolutionContext);
1670
+ };
1671
+ const applyPackageImportsExportsResolution = (matchKey, resolutionContext) => {
1672
+ const {
1673
+ packageJson,
1674
+ isImport
1675
+ } = resolutionContext;
1676
+ const matchObject = isImport ? packageJson.imports : packageJson.exports;
1677
+ if (!matchKey.includes("*") && matchObject.hasOwnProperty(matchKey)) {
1678
+ const target = matchObject[matchKey];
1679
+ return applyPackageTargetResolution(target, {
1680
+ ...resolutionContext,
1681
+ key: matchKey,
1682
+ isImport
1683
+ });
1684
+ }
1685
+ const expansionKeys = Object.keys(matchObject).filter(key => key.split("*").length === 2).sort(comparePatternKeys);
1686
+ for (const expansionKey of expansionKeys) {
1687
+ const [patternBase, patternTrailer] = expansionKey.split("*");
1688
+ if (matchKey === patternBase) continue;
1689
+ if (!matchKey.startsWith(patternBase)) continue;
1690
+ if (patternTrailer.length > 0) {
1691
+ if (!matchKey.endsWith(patternTrailer)) continue;
1692
+ if (matchKey.length < expansionKey.length) continue;
1693
+ }
1694
+ const target = matchObject[expansionKey];
1695
+ const subpath = matchKey.slice(patternBase.length, matchKey.length - patternTrailer.length);
1696
+ return applyPackageTargetResolution(target, {
1697
+ ...resolutionContext,
1698
+ key: matchKey,
1699
+ subpath,
1700
+ pattern: true,
1701
+ isImport
1702
+ });
1703
+ }
1704
+ return null;
1705
+ };
1706
+ const applyPackageTargetResolution = (target, resolutionContext) => {
1707
+ const {
1708
+ conditions,
1709
+ packageDirectoryUrl,
1710
+ packageJson,
1711
+ key,
1712
+ subpath = "",
1713
+ pattern = false,
1714
+ isImport = false
1715
+ } = resolutionContext;
1716
+ if (typeof target === "string") {
1717
+ if (pattern === false && subpath !== "" && !target.endsWith("/")) {
1718
+ throw new Error("invalid module specifier");
1719
+ }
1720
+ if (target.startsWith("./")) {
1721
+ const targetUrl = new URL(target, packageDirectoryUrl).href;
1722
+ if (!targetUrl.startsWith(packageDirectoryUrl)) {
1723
+ throw createInvalidPackageTargetError("target must be inside package", target, resolutionContext);
1724
+ }
1725
+ return {
1726
+ type: isImport ? "field:imports" : "field:exports",
1727
+ packageDirectoryUrl,
1728
+ packageJson,
1729
+ url: pattern ? targetUrl.replaceAll("*", subpath) : new URL(subpath, targetUrl).href
1730
+ };
1731
+ }
1732
+ if (!isImport || target.startsWith("../") || isValidUrl(target)) {
1733
+ throw createInvalidPackageTargetError("target must starst with \"./\"", target, resolutionContext);
1734
+ }
1735
+ return applyPackageResolve(pattern ? target.replaceAll("*", subpath) : "".concat(target).concat(subpath), {
1736
+ ...resolutionContext,
1737
+ parentUrl: packageDirectoryUrl
1738
+ });
1739
+ }
1740
+ if (Array.isArray(target)) {
1741
+ if (target.length === 0) {
1742
+ return null;
1743
+ }
1744
+ let lastResult;
1745
+ let i = 0;
1746
+ while (i < target.length) {
1747
+ const targetValue = target[i];
1748
+ i++;
1749
+ try {
1750
+ const resolved = applyPackageTargetResolution(targetValue, {
1751
+ ...resolutionContext,
1752
+ key: "".concat(key, "[").concat(i, "]"),
1753
+ subpath,
1754
+ pattern,
1755
+ isImport
1756
+ });
1757
+ if (resolved) {
1758
+ return resolved;
1759
+ }
1760
+ lastResult = resolved;
1761
+ } catch (e) {
1762
+ if (e.code === "INVALID_PACKAGE_TARGET") {
1763
+ continue;
1764
+ }
1765
+ lastResult = e;
1766
+ }
1767
+ }
1768
+ if (lastResult) {
1769
+ throw lastResult;
1770
+ }
1771
+ return null;
1772
+ }
1773
+ if (target === null) {
1774
+ return null;
1775
+ }
1776
+ if (typeof target === "object") {
1777
+ const keys = Object.keys(target);
1778
+ for (const key of keys) {
1779
+ if (Number.isInteger(key)) {
1780
+ throw new Error("Invalid package configuration");
1781
+ }
1782
+ if (key === "default" || conditions.includes(key)) {
1783
+ const targetValue = target[key];
1784
+ const resolved = applyPackageTargetResolution(targetValue, {
1785
+ ...resolutionContext,
1786
+ key,
1787
+ subpath,
1788
+ pattern,
1789
+ isImport
1790
+ });
1791
+ if (resolved) {
1792
+ return resolved;
1793
+ }
1794
+ }
1795
+ }
1796
+ return null;
1797
+ }
1798
+ throw createInvalidPackageTargetError("target must be a string, array, object or null", target, resolutionContext);
1799
+ };
1800
+ const readExports = ({
1801
+ packageDirectoryUrl,
1802
+ packageJson
1803
+ }) => {
1804
+ const packageExports = packageJson.exports;
1805
+ if (Array.isArray(packageExports)) {
1806
+ return {
1807
+ type: "array"
1808
+ };
1809
+ }
1810
+ if (packageExports === null) {
1811
+ return {};
1812
+ }
1813
+ if (typeof packageExports === "object") {
1814
+ const keys = Object.keys(packageExports);
1815
+ const relativeKeys = [];
1816
+ const conditionalKeys = [];
1817
+ keys.forEach(availableKey => {
1818
+ if (availableKey.startsWith(".")) {
1819
+ relativeKeys.push(availableKey);
1820
+ } else {
1821
+ conditionalKeys.push(availableKey);
1822
+ }
1823
+ });
1824
+ const hasRelativeKey = relativeKeys.length > 0;
1825
+ if (hasRelativeKey && conditionalKeys.length > 0) {
1826
+ throw new Error("Invalid package configuration: cannot mix relative and conditional keys in package.exports\n--- unexpected keys ---\n".concat(conditionalKeys.map(key => "\"".concat(key, "\"")).join("\n"), "\n--- package directory url ---\n").concat(packageDirectoryUrl));
1827
+ }
1828
+ return {
1829
+ type: "object",
1830
+ hasRelativeKey,
1831
+ allKeysAreRelative: relativeKeys.length === keys.length
1832
+ };
1833
+ }
1834
+ if (typeof packageExports === "string") {
1835
+ return {
1836
+ type: "string"
1837
+ };
1838
+ }
1839
+ return {};
1840
+ };
1841
+ const parsePackageSpecifier = packageSpecifier => {
1842
+ if (packageSpecifier[0] === "@") {
1843
+ const firstSlashIndex = packageSpecifier.indexOf("/");
1844
+ if (firstSlashIndex === -1) {
1845
+ throw new Error("invalid module specifier");
1846
+ }
1847
+ const secondSlashIndex = packageSpecifier.indexOf("/", firstSlashIndex + 1);
1848
+ if (secondSlashIndex === -1) {
1849
+ return {
1850
+ packageName: packageSpecifier,
1851
+ packageSubpath: ".",
1852
+ isScoped: true
1853
+ };
1854
+ }
1855
+ const packageName = packageSpecifier.slice(0, secondSlashIndex);
1856
+ const afterSecondSlash = packageSpecifier.slice(secondSlashIndex + 1);
1857
+ const packageSubpath = "./".concat(afterSecondSlash);
1858
+ return {
1859
+ packageName,
1860
+ packageSubpath,
1861
+ isScoped: true
1862
+ };
1863
+ }
1864
+ const firstSlashIndex = packageSpecifier.indexOf("/");
1865
+ if (firstSlashIndex === -1) {
1866
+ return {
1867
+ packageName: packageSpecifier,
1868
+ packageSubpath: "."
1869
+ };
1870
+ }
1871
+ const packageName = packageSpecifier.slice(0, firstSlashIndex);
1872
+ const afterFirstSlash = packageSpecifier.slice(firstSlashIndex + 1);
1873
+ const packageSubpath = "./".concat(afterFirstSlash);
1874
+ return {
1875
+ packageName,
1876
+ packageSubpath
1877
+ };
1878
+ };
1879
+ const applyMainExportResolution = resolutionContext => {
1880
+ const {
1881
+ packageJson
1882
+ } = resolutionContext;
1883
+ const packageExportsInfo = readExports(resolutionContext);
1884
+ if (packageExportsInfo.type === "array" || packageExportsInfo.type === "string") {
1885
+ return packageJson.exports;
1886
+ }
1887
+ if (packageExportsInfo.type === "object") {
1888
+ if (packageExportsInfo.hasRelativeKey) {
1889
+ return packageJson.exports["."];
1890
+ }
1891
+ return packageJson.exports;
1892
+ }
1893
+ return undefined;
1894
+ };
1895
+ const applyLegacySubpathResolution = (packageSubpath, resolutionContext) => {
1896
+ const {
1897
+ packageDirectoryUrl,
1898
+ packageJson
1899
+ } = resolutionContext;
1900
+ if (packageSubpath === ".") {
1901
+ return applyLegacyMainResolution(packageSubpath, resolutionContext);
1902
+ }
1903
+ const browserFieldResolution = applyBrowserFieldResolution(packageSubpath, resolutionContext);
1904
+ if (browserFieldResolution) {
1905
+ return browserFieldResolution;
1906
+ }
1907
+ return {
1908
+ type: "subpath",
1909
+ packageDirectoryUrl,
1910
+ packageJson,
1911
+ url: new URL(packageSubpath, packageDirectoryUrl).href
1912
+ };
1913
+ };
1914
+ const applyLegacyMainResolution = (packageSubpath, resolutionContext) => {
1915
+ const {
1916
+ conditions,
1917
+ packageDirectoryUrl,
1918
+ packageJson
1919
+ } = resolutionContext;
1920
+ for (const condition of conditions) {
1921
+ const conditionResolver = mainLegacyResolvers[condition];
1922
+ if (!conditionResolver) {
1923
+ continue;
1924
+ }
1925
+ const resolved = conditionResolver(resolutionContext);
1926
+ if (resolved) {
1927
+ return {
1928
+ type: resolved.type,
1929
+ packageDirectoryUrl,
1930
+ packageJson,
1931
+ url: new URL(resolved.path, packageDirectoryUrl).href
1932
+ };
1933
+ }
1934
+ }
1935
+ return {
1936
+ type: "field:main",
1937
+ // the absence of "main" field
1938
+ packageDirectoryUrl,
1939
+ packageJson,
1940
+ url: new URL("index.js", packageDirectoryUrl).href
1941
+ };
1942
+ };
1943
+ const mainLegacyResolvers = {
1944
+ import: ({
1945
+ packageJson
1946
+ }) => {
1947
+ if (typeof packageJson.module === "string") {
1948
+ return {
1949
+ type: "field:module",
1950
+ path: packageJson.module
1951
+ };
1952
+ }
1953
+ if (typeof packageJson.jsnext === "string") {
1954
+ return {
1955
+ type: "field:jsnext",
1956
+ path: packageJson.jsnext
1957
+ };
1958
+ }
1959
+ if (typeof packageJson.main === "string") {
1960
+ return {
1961
+ type: "field:main",
1962
+ path: packageJson.main
1963
+ };
1964
+ }
1965
+ return null;
1966
+ },
1967
+ browser: ({
1968
+ packageDirectoryUrl,
1969
+ packageJson
1970
+ }) => {
1971
+ const browserMain = (() => {
1972
+ if (typeof packageJson.browser === "string") {
1973
+ return packageJson.browser;
1974
+ }
1975
+ if (typeof packageJson.browser === "object" && packageJson.browser !== null) {
1976
+ return packageJson.browser["."];
1977
+ }
1978
+ return "";
1979
+ })();
1980
+ if (!browserMain) {
1981
+ if (typeof packageJson.module === "string") {
1982
+ return {
1983
+ type: "field:module",
1984
+ path: packageJson.module
1985
+ };
1986
+ }
1987
+ return null;
1988
+ }
1989
+ if (typeof packageJson.module !== "string" || packageJson.module === browserMain) {
1990
+ return {
1991
+ type: "field:browser",
1992
+ path: browserMain
1993
+ };
1994
+ }
1995
+ const browserMainUrlObject = new URL(browserMain, packageDirectoryUrl);
1996
+ const content = readFileSync(browserMainUrlObject, "utf-8");
1997
+ if (/typeof exports\s*==/.test(content) && /typeof module\s*==/.test(content) || /module\.exports\s*=/.test(content)) {
1998
+ return {
1999
+ type: "field:module",
2000
+ path: packageJson.module
2001
+ };
2002
+ }
2003
+ return {
2004
+ type: "field:browser",
2005
+ path: browserMain
2006
+ };
2007
+ },
2008
+ node: ({
2009
+ packageJson
2010
+ }) => {
2011
+ if (typeof packageJson.main === "string") {
2012
+ return {
2013
+ type: "field:main",
2014
+ path: packageJson.main
2015
+ };
2016
+ }
2017
+ return null;
2018
+ }
2019
+ };
2020
+ const comparePatternKeys = (keyA, keyB) => {
2021
+ if (!keyA.endsWith("/") && !keyA.includes("*")) {
2022
+ throw new Error("Invalid package configuration");
2023
+ }
2024
+ if (!keyB.endsWith("/") && !keyB.includes("*")) {
2025
+ throw new Error("Invalid package configuration");
2026
+ }
2027
+ const aStarIndex = keyA.indexOf("*");
2028
+ const baseLengthA = aStarIndex > -1 ? aStarIndex + 1 : keyA.length;
2029
+ const bStarIndex = keyB.indexOf("*");
2030
+ const baseLengthB = bStarIndex > -1 ? bStarIndex + 1 : keyB.length;
2031
+ if (baseLengthA > baseLengthB) {
2032
+ return -1;
2033
+ }
2034
+ if (baseLengthB > baseLengthA) {
2035
+ return 1;
2036
+ }
2037
+ if (aStarIndex === -1) {
2038
+ return 1;
2039
+ }
2040
+ if (bStarIndex === -1) {
2041
+ return -1;
2042
+ }
2043
+ if (keyA.length > keyB.length) {
2044
+ return -1;
2045
+ }
2046
+ if (keyB.length > keyA.length) {
2047
+ return 1;
2048
+ }
2049
+ return 0;
2050
+ };
2051
+ const resolvePackageSymlink = packageDirectoryUrl => {
2052
+ const packageDirectoryPath = realpathSync(new URL(packageDirectoryUrl));
2053
+ const packageDirectoryResolvedUrl = pathToFileURL(packageDirectoryPath).href;
2054
+ return "".concat(packageDirectoryResolvedUrl, "/");
2055
+ };
2056
+
1187
2057
  /*
1188
2058
  * This plugin provides a way for jsenv to supervisor js execution:
1189
2059
  * - Know how many js are executed, when they are done, collect errors, etc...
@@ -1199,7 +2069,9 @@ const jsenvPluginSupervisor = ({
1199
2069
  const resolveUrlSite = urlWithLineAndColumn => {
1200
2070
  const inlineUrlMatch = urlWithLineAndColumn.match(/@L([0-9]+)C([0-9]+)-L([0-9]+)C([0-9]+)\.\w+(:([0-9]+):([0-9]+))?$/);
1201
2071
  if (inlineUrlMatch) {
1202
- const htmlUrl = urlWithLineAndColumn.slice(0, inlineUrlMatch.index);
2072
+ const htmlUrl = injectQueryParams(urlWithLineAndColumn.slice(0, inlineUrlMatch.index), {
2073
+ hot: undefined
2074
+ });
1203
2075
  const tagLineStart = parseInt(inlineUrlMatch[1]);
1204
2076
  const tagColumnStart = parseInt(inlineUrlMatch[2]);
1205
2077
  // const tagLineEnd = parseInt(inlineUrlMatch[3]);
@@ -1220,7 +2092,9 @@ const jsenvPluginSupervisor = ({
1220
2092
  if (!match) {
1221
2093
  return null;
1222
2094
  }
1223
- const file = urlWithLineAndColumn.slice(0, match.index);
2095
+ const file = injectQueryParams(urlWithLineAndColumn.slice(0, match.index), {
2096
+ hot: undefined
2097
+ });
1224
2098
  let line = parseInt(match[1]);
1225
2099
  let column = parseInt(match[2]);
1226
2100
  return {
@@ -1311,6 +2185,14 @@ const jsenvPluginSupervisor = ({
1311
2185
  body: "Missing file in url"
1312
2186
  };
1313
2187
  }
2188
+ const {
2189
+ url
2190
+ } = applyNodeEsmResolution({
2191
+ conditions: [],
2192
+ parentUrl: serveInfo.rootDirectoryUrl,
2193
+ specifier: file
2194
+ });
2195
+ file = url;
1314
2196
  const getErrorCauseInfo = () => {
1315
2197
  const urlInfo = serveInfo.kitchen.graph.getUrlInfo(file);
1316
2198
  if (!urlInfo) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/plugin-supervisor",
3
- "version": "1.5.26",
3
+ "version": "1.5.28",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -4,7 +4,9 @@
4
4
  */
5
5
 
6
6
  import { generateContentFrame } from "@jsenv/humanize";
7
+ import { applyNodeEsmResolution } from "@jsenv/node-esm-resolution";
7
8
  import { getOriginalPosition } from "@jsenv/sourcemap";
9
+ import { injectQueryParams } from "@jsenv/urls";
8
10
  import { createRequire } from "node:module";
9
11
  import { fileURLToPath } from "node:url";
10
12
  import {
@@ -24,7 +26,10 @@ export const jsenvPluginSupervisor = ({
24
26
  /@L([0-9]+)C([0-9]+)-L([0-9]+)C([0-9]+)\.\w+(:([0-9]+):([0-9]+))?$/,
25
27
  );
26
28
  if (inlineUrlMatch) {
27
- const htmlUrl = urlWithLineAndColumn.slice(0, inlineUrlMatch.index);
29
+ const htmlUrl = injectQueryParams(
30
+ urlWithLineAndColumn.slice(0, inlineUrlMatch.index),
31
+ { hot: undefined },
32
+ );
28
33
  const tagLineStart = parseInt(inlineUrlMatch[1]);
29
34
  const tagColumnStart = parseInt(inlineUrlMatch[2]);
30
35
  // const tagLineEnd = parseInt(inlineUrlMatch[3]);
@@ -52,7 +57,9 @@ export const jsenvPluginSupervisor = ({
52
57
  if (!match) {
53
58
  return null;
54
59
  }
55
- const file = urlWithLineAndColumn.slice(0, match.index);
60
+ const file = injectQueryParams(urlWithLineAndColumn.slice(0, match.index), {
61
+ hot: undefined,
62
+ });
56
63
  let line = parseInt(match[1]);
57
64
  let column = parseInt(match[2]);
58
65
  return {
@@ -141,6 +148,12 @@ export const jsenvPluginSupervisor = ({
141
148
  body: "Missing file in url",
142
149
  };
143
150
  }
151
+ const { url } = applyNodeEsmResolution({
152
+ conditions: [],
153
+ parentUrl: serveInfo.rootDirectoryUrl,
154
+ specifier: file,
155
+ });
156
+ file = url;
144
157
  const getErrorCauseInfo = () => {
145
158
  const urlInfo = serveInfo.kitchen.graph.getUrlInfo(file);
146
159
  if (!urlInfo) {