@nasti-toolchain/nasti 1.6.0 → 1.6.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.
package/dist/index.cjs CHANGED
@@ -814,7 +814,7 @@ __export(build_exports, {
814
814
  async function build(inlineConfig = {}) {
815
815
  const config = await resolveConfig(inlineConfig, "build");
816
816
  const startTime = performance.now();
817
- console.log(import_picocolors.default.cyan("\n\u{1F528} nasti build") + import_picocolors.default.dim(` v${"1.6.0"}`));
817
+ console.log(import_picocolors.default.cyan("\n\u{1F528} nasti build") + import_picocolors.default.dim(` v${"1.6.2"}`));
818
818
  console.log(import_picocolors.default.dim(` root: ${config.root}`));
819
819
  console.log(import_picocolors.default.dim(` mode: ${config.mode}`));
820
820
  const outDir = import_node_path7.default.resolve(config.root, config.build.outDir);
@@ -1323,7 +1323,7 @@ async function transformRequest(url, ctx) {
1323
1323
  config.mode
1324
1324
  );
1325
1325
  code = replaceEnvInCode(code, envDefine);
1326
- code = rewriteImports(code, config);
1326
+ code = rewriteImports(code, config, filePath);
1327
1327
  const transformResult = { code };
1328
1328
  mod.transformResult = transformResult;
1329
1329
  return transformResult;
@@ -1335,6 +1335,8 @@ async function bundlePackageAsEsm(entryFile) {
1335
1335
  return esmBundleCache.get(entryFile);
1336
1336
  }
1337
1337
  async function doBundlePackage(entryFile) {
1338
+ const shim = await tryGenerateSubpathShim(entryFile);
1339
+ if (shim != null) return shim;
1338
1340
  const { rolldown: rolldown4 } = await import("rolldown");
1339
1341
  const bundle = await rolldown4({
1340
1342
  input: entryFile,
@@ -1364,6 +1366,103 @@ async function doBundlePackage(entryFile) {
1364
1366
  }
1365
1367
  return code;
1366
1368
  }
1369
+ async function tryGenerateSubpathShim(entryFile) {
1370
+ const NM = `${import_node_path9.default.sep}node_modules${import_node_path9.default.sep}`;
1371
+ if (!entryFile.includes(NM)) return null;
1372
+ let pkgDir = null;
1373
+ let pkgName = null;
1374
+ let dir = import_node_path9.default.dirname(entryFile);
1375
+ while (true) {
1376
+ const pkgJsonPath = import_node_path9.default.join(dir, "package.json");
1377
+ if (import_node_fs8.default.existsSync(pkgJsonPath)) {
1378
+ try {
1379
+ const pkg = JSON.parse(import_node_fs8.default.readFileSync(pkgJsonPath, "utf-8"));
1380
+ if (typeof pkg?.name === "string" && pkg.name) {
1381
+ pkgDir = dir;
1382
+ pkgName = pkg.name;
1383
+ break;
1384
+ }
1385
+ } catch {
1386
+ }
1387
+ }
1388
+ const parent = import_node_path9.default.dirname(dir);
1389
+ if (parent === dir) return null;
1390
+ dir = parent;
1391
+ if (!dir.includes(NM)) return null;
1392
+ }
1393
+ if (!pkgDir || !pkgName) return null;
1394
+ const entryExt = import_node_path9.default.extname(entryFile);
1395
+ const mainEntry = pickMainEntryByExtension(pkgDir, entryExt);
1396
+ if (!mainEntry) return null;
1397
+ if (import_node_path9.default.resolve(mainEntry) === import_node_path9.default.resolve(entryFile)) return null;
1398
+ let mainNs;
1399
+ let subNs;
1400
+ try {
1401
+ mainNs = await import((0, import_node_url2.pathToFileURL)(mainEntry).href);
1402
+ subNs = await import((0, import_node_url2.pathToFileURL)(entryFile).href);
1403
+ } catch {
1404
+ return null;
1405
+ }
1406
+ if (!mainNs || typeof mainNs !== "object") return null;
1407
+ if (!subNs || typeof subNs !== "object") return null;
1408
+ const subKeys = Object.keys(subNs).filter(
1409
+ (k) => k !== "__esModule" && k !== "default" && VALID_IDENT.test(k)
1410
+ );
1411
+ if (subKeys.length === 0) return null;
1412
+ for (const k of subKeys) {
1413
+ if (!(k in mainNs)) return null;
1414
+ if (mainNs[k] !== subNs[k]) return null;
1415
+ }
1416
+ if ("default" in subNs) {
1417
+ if (!("default" in mainNs)) return null;
1418
+ if (mainNs["default"] !== subNs["default"]) return null;
1419
+ }
1420
+ const lines = [
1421
+ `// Nasti subpath shim \u2192 ${pkgName} (avoid duplicate bundling)`,
1422
+ `import * as __pkg from "/@modules/${pkgName}";`
1423
+ ];
1424
+ for (const k of subKeys) {
1425
+ lines.push(`export const ${k} = __pkg[${JSON.stringify(k)}];`);
1426
+ }
1427
+ if ("default" in subNs) {
1428
+ lines.push(`export default ("default" in __pkg ? __pkg["default"] : __pkg);`);
1429
+ }
1430
+ return lines.join("\n") + "\n";
1431
+ }
1432
+ function pickMainEntryByExtension(pkgDir, preferredExt) {
1433
+ const pkgJsonPath = import_node_path9.default.join(pkgDir, "package.json");
1434
+ let pkg;
1435
+ try {
1436
+ pkg = JSON.parse(import_node_fs8.default.readFileSync(pkgJsonPath, "utf-8"));
1437
+ } catch {
1438
+ return null;
1439
+ }
1440
+ const candidates = [];
1441
+ const collectFromExportObject = (obj) => {
1442
+ if (!obj || typeof obj !== "object") return;
1443
+ for (const cond of ["import", "module", "default", "require", "node"]) {
1444
+ const v = obj[cond];
1445
+ if (typeof v === "string") candidates.push(v);
1446
+ else if (v && typeof v === "object") collectFromExportObject(v);
1447
+ }
1448
+ };
1449
+ const dot = pkg?.exports?.["."];
1450
+ if (typeof dot === "string") candidates.push(dot);
1451
+ else if (dot && typeof dot === "object") collectFromExportObject(dot);
1452
+ if (typeof pkg.module === "string") candidates.push(pkg.module);
1453
+ if (typeof pkg.main === "string") candidates.push(pkg.main);
1454
+ for (const cand of candidates) {
1455
+ if (import_node_path9.default.extname(cand) === preferredExt) {
1456
+ const full = import_node_path9.default.resolve(pkgDir, cand);
1457
+ if (import_node_fs8.default.existsSync(full)) return full;
1458
+ }
1459
+ }
1460
+ for (const cand of candidates) {
1461
+ const full = import_node_path9.default.resolve(pkgDir, cand);
1462
+ if (import_node_fs8.default.existsSync(full)) return full;
1463
+ }
1464
+ return null;
1465
+ }
1367
1466
  function rewriteExternalRequires(code) {
1368
1467
  const pkgs = /* @__PURE__ */ new Set();
1369
1468
  const re = /__require\(["']([^"']+)["']\)/g;
@@ -1405,26 +1504,73 @@ async function injectCjsNamedExports(code, entryFile) {
1405
1504
  return code;
1406
1505
  }
1407
1506
  }
1408
- function rewriteImports(code, _config) {
1409
- return code.replace(
1410
- /\bfrom\s+(['"])([^'"./][^'"]*)\1/g,
1411
- (match, quote, specifier) => {
1412
- return `from ${quote}/@modules/${specifier}${quote}`;
1507
+ function rewriteImports(code, config, filePath) {
1508
+ const root = config.root;
1509
+ const fileDir = import_node_path9.default.dirname(filePath);
1510
+ const aliasEntries = Object.entries(config.resolve.alias).sort(
1511
+ ([a], [b]) => b.length - a.length
1512
+ );
1513
+ const toRootUrl = (abs) => "/" + import_node_path9.default.relative(root, abs).replace(/\\/g, "/");
1514
+ const transformSpec = (spec) => {
1515
+ const suffixMatch = spec.match(/[?#].*$/);
1516
+ const suffix = suffixMatch ? suffixMatch[0] : "";
1517
+ const baseSpec = suffix ? spec.slice(0, -suffix.length) : spec;
1518
+ for (const [key, value] of aliasEntries) {
1519
+ if (baseSpec === key || baseSpec.startsWith(key + "/")) {
1520
+ const aliasBase = resolveAliasTarget(value, root);
1521
+ const sub = baseSpec.slice(key.length).replace(/^\//, "");
1522
+ const target = sub ? import_node_path9.default.join(aliasBase, sub) : aliasBase;
1523
+ const resolved = tryResolveDiskPath(target);
1524
+ return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
1525
+ }
1413
1526
  }
1414
- ).replace(
1415
- // 处理纯副作用导入: import 'bare-specifier'
1416
- /\bimport\s+(['"])([^'"./][^'"]*)\1/g,
1417
- (match, quote, specifier) => {
1418
- return `import ${quote}/@modules/${specifier}${quote}`;
1527
+ if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
1528
+ const target = import_node_path9.default.resolve(fileDir, baseSpec);
1529
+ const resolved = tryResolveDiskPath(target);
1530
+ return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
1419
1531
  }
1420
- ).replace(
1421
- // 处理动态导入: import('bare-specifier')
1422
- /\bimport\s*\(\s*(['"])([^'"./][^'"]*)\1\s*\)/g,
1423
- (match, quote, specifier) => {
1424
- return `import(${quote}/@modules/${specifier}${quote})`;
1532
+ if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
1533
+ const target = import_node_path9.default.join(root, baseSpec.replace(/^\//, ""));
1534
+ const resolved = tryResolveDiskPath(target);
1535
+ return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
1425
1536
  }
1537
+ if (baseSpec.startsWith("/")) return spec;
1538
+ return `/@modules/${spec}`;
1539
+ };
1540
+ return code.replace(
1541
+ /\bfrom\s+(['"])([^'"]+)\1/g,
1542
+ (_m, q, s) => `from ${q}${transformSpec(s)}${q}`
1543
+ ).replace(
1544
+ /\bimport\s+(['"])([^'"]+)\1/g,
1545
+ (_m, q, s) => `import ${q}${transformSpec(s)}${q}`
1546
+ ).replace(
1547
+ /\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g,
1548
+ (_m, q, s) => `import(${q}${transformSpec(s)}${q})`
1426
1549
  );
1427
1550
  }
1551
+ function resolveAliasTarget(value, root) {
1552
+ if (import_node_path9.default.isAbsolute(value) && import_node_fs8.default.existsSync(value)) return value;
1553
+ if (value.startsWith("/")) return import_node_path9.default.join(root, value.slice(1));
1554
+ return import_node_path9.default.resolve(root, value);
1555
+ }
1556
+ function tryResolveDiskPath(target) {
1557
+ if (import_node_fs8.default.existsSync(target) && import_node_fs8.default.statSync(target).isFile()) return target;
1558
+ for (const ext of RESOLVE_EXTENSIONS) {
1559
+ const withExt = target + ext;
1560
+ if (import_node_fs8.default.existsSync(withExt) && import_node_fs8.default.statSync(withExt).isFile()) return withExt;
1561
+ }
1562
+ if (import_node_fs8.default.existsSync(target) && import_node_fs8.default.statSync(target).isDirectory()) {
1563
+ for (const ext of RESOLVE_EXTENSIONS) {
1564
+ const idx = import_node_path9.default.join(target, "index" + ext);
1565
+ if (import_node_fs8.default.existsSync(idx) && import_node_fs8.default.statSync(idx).isFile()) return idx;
1566
+ }
1567
+ }
1568
+ return null;
1569
+ }
1570
+ function isUnderRoot(abs, root) {
1571
+ const rel = import_node_path9.default.relative(root, abs);
1572
+ return !!rel && !rel.startsWith("..") && !import_node_path9.default.isAbsolute(rel);
1573
+ }
1428
1574
  function resolveNodeModule(root, moduleName) {
1429
1575
  let pkgName;
1430
1576
  let subpath;
@@ -1826,7 +1972,7 @@ async function createServer(inlineConfig = {}) {
1826
1972
  const localUrl = `http://localhost:${actualPort}`;
1827
1973
  const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
1828
1974
  console.log();
1829
- console.log(import_picocolors3.default.cyan(" nasti dev server") + import_picocolors3.default.dim(` v${"1.6.0"}`));
1975
+ console.log(import_picocolors3.default.cyan(" nasti dev server") + import_picocolors3.default.dim(` v${"1.6.2"}`));
1830
1976
  console.log();
1831
1977
  console.log(` ${import_picocolors3.default.green(">")} Local: ${import_picocolors3.default.cyan(localUrl)}`);
1832
1978
  if (networkUrl) {
@@ -1970,7 +2116,7 @@ async function buildElectron(inlineConfig = {}) {
1970
2116
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
1971
2117
  const startTime = performance.now();
1972
2118
  assertElectronVersion(config);
1973
- console.log(import_picocolors2.default.cyan("\n\u26A1 nasti build (electron)") + import_picocolors2.default.dim(` v${"1.6.0"}`));
2119
+ console.log(import_picocolors2.default.cyan("\n\u26A1 nasti build (electron)") + import_picocolors2.default.dim(` v${"1.6.2"}`));
1974
2120
  console.log(import_picocolors2.default.dim(` root: ${config.root}`));
1975
2121
  console.log(import_picocolors2.default.dim(` mode: ${config.mode}`));
1976
2122
  console.log(import_picocolors2.default.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
@@ -2117,7 +2263,7 @@ async function startElectronDev(inlineConfig = {}) {
2117
2263
  const { noSpawn, ...rest } = inlineConfig;
2118
2264
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
2119
2265
  warnElectronVersion(config);
2120
- console.log(import_picocolors4.default.cyan("\n\u26A1 nasti electron dev") + import_picocolors4.default.dim(` v${"1.6.0"}`));
2266
+ console.log(import_picocolors4.default.cyan("\n\u26A1 nasti electron dev") + import_picocolors4.default.dim(` v${"1.6.2"}`));
2121
2267
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
2122
2268
  const server = await createServer2({ ...rest, target: "electron" });
2123
2269
  await server.listen();