@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.js CHANGED
@@ -793,7 +793,7 @@ import pc from "picocolors";
793
793
  async function build(inlineConfig = {}) {
794
794
  const config = await resolveConfig(inlineConfig, "build");
795
795
  const startTime = performance.now();
796
- console.log(pc.cyan("\n\u{1F528} nasti build") + pc.dim(` v${"1.6.0"}`));
796
+ console.log(pc.cyan("\n\u{1F528} nasti build") + pc.dim(` v${"1.6.2"}`));
797
797
  console.log(pc.dim(` root: ${config.root}`));
798
798
  console.log(pc.dim(` mode: ${config.mode}`));
799
799
  const outDir = path7.resolve(config.root, config.build.outDir);
@@ -1104,7 +1104,7 @@ __export(middleware_exports, {
1104
1104
  import path9 from "path";
1105
1105
  import fs8 from "fs";
1106
1106
  import { createRequire as createRequire2 } from "module";
1107
- import { fileURLToPath } from "url";
1107
+ import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "url";
1108
1108
  function getReactRefreshRuntimeEsm() {
1109
1109
  if (__refreshRuntimeCache) return __refreshRuntimeCache;
1110
1110
  let cjsPath;
@@ -1300,7 +1300,7 @@ async function transformRequest(url, ctx) {
1300
1300
  config.mode
1301
1301
  );
1302
1302
  code = replaceEnvInCode(code, envDefine);
1303
- code = rewriteImports(code, config);
1303
+ code = rewriteImports(code, config, filePath);
1304
1304
  const transformResult = { code };
1305
1305
  mod.transformResult = transformResult;
1306
1306
  return transformResult;
@@ -1312,6 +1312,8 @@ async function bundlePackageAsEsm(entryFile) {
1312
1312
  return esmBundleCache.get(entryFile);
1313
1313
  }
1314
1314
  async function doBundlePackage(entryFile) {
1315
+ const shim = await tryGenerateSubpathShim(entryFile);
1316
+ if (shim != null) return shim;
1315
1317
  const { rolldown: rolldown4 } = await import("rolldown");
1316
1318
  const bundle = await rolldown4({
1317
1319
  input: entryFile,
@@ -1341,6 +1343,103 @@ async function doBundlePackage(entryFile) {
1341
1343
  }
1342
1344
  return code;
1343
1345
  }
1346
+ async function tryGenerateSubpathShim(entryFile) {
1347
+ const NM = `${path9.sep}node_modules${path9.sep}`;
1348
+ if (!entryFile.includes(NM)) return null;
1349
+ let pkgDir = null;
1350
+ let pkgName = null;
1351
+ let dir = path9.dirname(entryFile);
1352
+ while (true) {
1353
+ const pkgJsonPath = path9.join(dir, "package.json");
1354
+ if (fs8.existsSync(pkgJsonPath)) {
1355
+ try {
1356
+ const pkg = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
1357
+ if (typeof pkg?.name === "string" && pkg.name) {
1358
+ pkgDir = dir;
1359
+ pkgName = pkg.name;
1360
+ break;
1361
+ }
1362
+ } catch {
1363
+ }
1364
+ }
1365
+ const parent = path9.dirname(dir);
1366
+ if (parent === dir) return null;
1367
+ dir = parent;
1368
+ if (!dir.includes(NM)) return null;
1369
+ }
1370
+ if (!pkgDir || !pkgName) return null;
1371
+ const entryExt = path9.extname(entryFile);
1372
+ const mainEntry = pickMainEntryByExtension(pkgDir, entryExt);
1373
+ if (!mainEntry) return null;
1374
+ if (path9.resolve(mainEntry) === path9.resolve(entryFile)) return null;
1375
+ let mainNs;
1376
+ let subNs;
1377
+ try {
1378
+ mainNs = await import(pathToFileURL2(mainEntry).href);
1379
+ subNs = await import(pathToFileURL2(entryFile).href);
1380
+ } catch {
1381
+ return null;
1382
+ }
1383
+ if (!mainNs || typeof mainNs !== "object") return null;
1384
+ if (!subNs || typeof subNs !== "object") return null;
1385
+ const subKeys = Object.keys(subNs).filter(
1386
+ (k) => k !== "__esModule" && k !== "default" && VALID_IDENT.test(k)
1387
+ );
1388
+ if (subKeys.length === 0) return null;
1389
+ for (const k of subKeys) {
1390
+ if (!(k in mainNs)) return null;
1391
+ if (mainNs[k] !== subNs[k]) return null;
1392
+ }
1393
+ if ("default" in subNs) {
1394
+ if (!("default" in mainNs)) return null;
1395
+ if (mainNs["default"] !== subNs["default"]) return null;
1396
+ }
1397
+ const lines = [
1398
+ `// Nasti subpath shim \u2192 ${pkgName} (avoid duplicate bundling)`,
1399
+ `import * as __pkg from "/@modules/${pkgName}";`
1400
+ ];
1401
+ for (const k of subKeys) {
1402
+ lines.push(`export const ${k} = __pkg[${JSON.stringify(k)}];`);
1403
+ }
1404
+ if ("default" in subNs) {
1405
+ lines.push(`export default ("default" in __pkg ? __pkg["default"] : __pkg);`);
1406
+ }
1407
+ return lines.join("\n") + "\n";
1408
+ }
1409
+ function pickMainEntryByExtension(pkgDir, preferredExt) {
1410
+ const pkgJsonPath = path9.join(pkgDir, "package.json");
1411
+ let pkg;
1412
+ try {
1413
+ pkg = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
1414
+ } catch {
1415
+ return null;
1416
+ }
1417
+ const candidates = [];
1418
+ const collectFromExportObject = (obj) => {
1419
+ if (!obj || typeof obj !== "object") return;
1420
+ for (const cond of ["import", "module", "default", "require", "node"]) {
1421
+ const v = obj[cond];
1422
+ if (typeof v === "string") candidates.push(v);
1423
+ else if (v && typeof v === "object") collectFromExportObject(v);
1424
+ }
1425
+ };
1426
+ const dot = pkg?.exports?.["."];
1427
+ if (typeof dot === "string") candidates.push(dot);
1428
+ else if (dot && typeof dot === "object") collectFromExportObject(dot);
1429
+ if (typeof pkg.module === "string") candidates.push(pkg.module);
1430
+ if (typeof pkg.main === "string") candidates.push(pkg.main);
1431
+ for (const cand of candidates) {
1432
+ if (path9.extname(cand) === preferredExt) {
1433
+ const full = path9.resolve(pkgDir, cand);
1434
+ if (fs8.existsSync(full)) return full;
1435
+ }
1436
+ }
1437
+ for (const cand of candidates) {
1438
+ const full = path9.resolve(pkgDir, cand);
1439
+ if (fs8.existsSync(full)) return full;
1440
+ }
1441
+ return null;
1442
+ }
1344
1443
  function rewriteExternalRequires(code) {
1345
1444
  const pkgs = /* @__PURE__ */ new Set();
1346
1445
  const re = /__require\(["']([^"']+)["']\)/g;
@@ -1382,26 +1481,73 @@ async function injectCjsNamedExports(code, entryFile) {
1382
1481
  return code;
1383
1482
  }
1384
1483
  }
1385
- function rewriteImports(code, _config) {
1386
- return code.replace(
1387
- /\bfrom\s+(['"])([^'"./][^'"]*)\1/g,
1388
- (match, quote, specifier) => {
1389
- return `from ${quote}/@modules/${specifier}${quote}`;
1484
+ function rewriteImports(code, config, filePath) {
1485
+ const root = config.root;
1486
+ const fileDir = path9.dirname(filePath);
1487
+ const aliasEntries = Object.entries(config.resolve.alias).sort(
1488
+ ([a], [b]) => b.length - a.length
1489
+ );
1490
+ const toRootUrl = (abs) => "/" + path9.relative(root, abs).replace(/\\/g, "/");
1491
+ const transformSpec = (spec) => {
1492
+ const suffixMatch = spec.match(/[?#].*$/);
1493
+ const suffix = suffixMatch ? suffixMatch[0] : "";
1494
+ const baseSpec = suffix ? spec.slice(0, -suffix.length) : spec;
1495
+ for (const [key, value] of aliasEntries) {
1496
+ if (baseSpec === key || baseSpec.startsWith(key + "/")) {
1497
+ const aliasBase = resolveAliasTarget(value, root);
1498
+ const sub = baseSpec.slice(key.length).replace(/^\//, "");
1499
+ const target = sub ? path9.join(aliasBase, sub) : aliasBase;
1500
+ const resolved = tryResolveDiskPath(target);
1501
+ return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
1502
+ }
1390
1503
  }
1391
- ).replace(
1392
- // 处理纯副作用导入: import 'bare-specifier'
1393
- /\bimport\s+(['"])([^'"./][^'"]*)\1/g,
1394
- (match, quote, specifier) => {
1395
- return `import ${quote}/@modules/${specifier}${quote}`;
1504
+ if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
1505
+ const target = path9.resolve(fileDir, baseSpec);
1506
+ const resolved = tryResolveDiskPath(target);
1507
+ return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
1396
1508
  }
1397
- ).replace(
1398
- // 处理动态导入: import('bare-specifier')
1399
- /\bimport\s*\(\s*(['"])([^'"./][^'"]*)\1\s*\)/g,
1400
- (match, quote, specifier) => {
1401
- return `import(${quote}/@modules/${specifier}${quote})`;
1509
+ if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
1510
+ const target = path9.join(root, baseSpec.replace(/^\//, ""));
1511
+ const resolved = tryResolveDiskPath(target);
1512
+ return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
1402
1513
  }
1514
+ if (baseSpec.startsWith("/")) return spec;
1515
+ return `/@modules/${spec}`;
1516
+ };
1517
+ return code.replace(
1518
+ /\bfrom\s+(['"])([^'"]+)\1/g,
1519
+ (_m, q, s) => `from ${q}${transformSpec(s)}${q}`
1520
+ ).replace(
1521
+ /\bimport\s+(['"])([^'"]+)\1/g,
1522
+ (_m, q, s) => `import ${q}${transformSpec(s)}${q}`
1523
+ ).replace(
1524
+ /\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g,
1525
+ (_m, q, s) => `import(${q}${transformSpec(s)}${q})`
1403
1526
  );
1404
1527
  }
1528
+ function resolveAliasTarget(value, root) {
1529
+ if (path9.isAbsolute(value) && fs8.existsSync(value)) return value;
1530
+ if (value.startsWith("/")) return path9.join(root, value.slice(1));
1531
+ return path9.resolve(root, value);
1532
+ }
1533
+ function tryResolveDiskPath(target) {
1534
+ if (fs8.existsSync(target) && fs8.statSync(target).isFile()) return target;
1535
+ for (const ext of RESOLVE_EXTENSIONS) {
1536
+ const withExt = target + ext;
1537
+ if (fs8.existsSync(withExt) && fs8.statSync(withExt).isFile()) return withExt;
1538
+ }
1539
+ if (fs8.existsSync(target) && fs8.statSync(target).isDirectory()) {
1540
+ for (const ext of RESOLVE_EXTENSIONS) {
1541
+ const idx = path9.join(target, "index" + ext);
1542
+ if (fs8.existsSync(idx) && fs8.statSync(idx).isFile()) return idx;
1543
+ }
1544
+ }
1545
+ return null;
1546
+ }
1547
+ function isUnderRoot(abs, root) {
1548
+ const rel = path9.relative(root, abs);
1549
+ return !!rel && !rel.startsWith("..") && !path9.isAbsolute(rel);
1550
+ }
1405
1551
  function resolveNodeModule(root, moduleName) {
1406
1552
  let pkgName;
1407
1553
  let subpath;
@@ -1804,7 +1950,7 @@ async function createServer(inlineConfig = {}) {
1804
1950
  const localUrl = `http://localhost:${actualPort}`;
1805
1951
  const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
1806
1952
  console.log();
1807
- console.log(pc3.cyan(" nasti dev server") + pc3.dim(` v${"1.6.0"}`));
1953
+ console.log(pc3.cyan(" nasti dev server") + pc3.dim(` v${"1.6.2"}`));
1808
1954
  console.log();
1809
1955
  console.log(` ${pc3.green(">")} Local: ${pc3.cyan(localUrl)}`);
1810
1956
  if (networkUrl) {
@@ -1928,7 +2074,7 @@ async function buildElectron(inlineConfig = {}) {
1928
2074
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
1929
2075
  const startTime = performance.now();
1930
2076
  assertElectronVersion(config);
1931
- console.log(pc2.cyan("\n\u26A1 nasti build (electron)") + pc2.dim(` v${"1.6.0"}`));
2077
+ console.log(pc2.cyan("\n\u26A1 nasti build (electron)") + pc2.dim(` v${"1.6.2"}`));
1932
2078
  console.log(pc2.dim(` root: ${config.root}`));
1933
2079
  console.log(pc2.dim(` mode: ${config.mode}`));
1934
2080
  console.log(pc2.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
@@ -2075,7 +2221,7 @@ async function startElectronDev(inlineConfig = {}) {
2075
2221
  const { noSpawn, ...rest } = inlineConfig;
2076
2222
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
2077
2223
  warnElectronVersion(config);
2078
- console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.6.0"}`));
2224
+ console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.6.2"}`));
2079
2225
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
2080
2226
  const server = await createServer2({ ...rest, target: "electron" });
2081
2227
  await server.listen();