@nasti-toolchain/nasti 2.4.2 → 2.4.4

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/cli.cjs CHANGED
@@ -5,10 +5,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __glob = (map) => (path18) => {
9
- var fn = map[path18];
8
+ var __glob = (map) => (path19) => {
9
+ var fn = map[path19];
10
10
  if (fn) return fn();
11
- throw new Error("Module not found in bundle: " + path18);
11
+ throw new Error("Module not found in bundle: " + path19);
12
12
  };
13
13
  var __esm = (fn, res) => function __init() {
14
14
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -851,6 +851,24 @@ var init_module_graph = __esm({
851
851
  getModulesByFile(file) {
852
852
  return this.fileToModulesMap.get(file);
853
853
  }
854
+ /**
855
+ * Modules whose registered entry file lives under `dir` (inclusive).
856
+ * Used when a non-entry source inside a prebundled workspace package changes:
857
+ * only the package entry was registered, so getModulesByFile(changedFile)
858
+ * misses — we invalidate every /@modules entry rooted in that package.
859
+ */
860
+ getModulesWithFileUnder(dir) {
861
+ const result = /* @__PURE__ */ new Set();
862
+ const normDir = dir.replace(/\\/g, "/");
863
+ const normPrefix = normDir.endsWith("/") ? normDir : normDir + "/";
864
+ for (const [file, mods] of this.fileToModulesMap) {
865
+ const normFile = file.replace(/\\/g, "/");
866
+ if (normFile === normDir || normFile.startsWith(normPrefix)) {
867
+ for (const m of mods) result.add(m);
868
+ }
869
+ }
870
+ return result;
871
+ }
854
872
  async ensureEntryFromUrl(url) {
855
873
  const normalizedUrl = removeTimestampQuery(url);
856
874
  let mod = this.urlToModuleMap.get(normalizedUrl);
@@ -1583,6 +1601,120 @@ var init_assets = __esm({
1583
1601
  }
1584
1602
  });
1585
1603
 
1604
+ // src/server/fs-allow.ts
1605
+ function isUnderRoot(abs, root) {
1606
+ const rel = import_node_path5.default.relative(root, abs);
1607
+ return !!rel && !rel.startsWith("..") && !import_node_path5.default.isAbsolute(rel);
1608
+ }
1609
+ function discoverLinkedPackageRoots(projectRoot, maxDepth = 4) {
1610
+ const results = [];
1611
+ const seenReal = /* @__PURE__ */ new Set();
1612
+ const queued = /* @__PURE__ */ new Set([projectRoot]);
1613
+ const queue = [projectRoot];
1614
+ for (let depth = 0; depth < maxDepth && queue.length > 0; depth++) {
1615
+ const levelCount = queue.length;
1616
+ for (let i = 0; i < levelCount; i++) {
1617
+ const dir = queue.shift();
1618
+ const nm = import_node_path5.default.join(dir, "node_modules");
1619
+ let entries;
1620
+ try {
1621
+ entries = import_node_fs5.default.readdirSync(nm, { withFileTypes: true });
1622
+ } catch {
1623
+ continue;
1624
+ }
1625
+ for (const ent of entries) {
1626
+ if (ent.name.startsWith(".") || ent.name === "node_modules") continue;
1627
+ const pkgNames = ent.name.startsWith("@") ? listScopedPackages(nm, ent.name) : [ent.name];
1628
+ for (const pkgName of pkgNames) {
1629
+ const pkgPath = import_node_path5.default.join(nm, pkgName);
1630
+ let real;
1631
+ try {
1632
+ real = import_node_fs5.default.realpathSync(pkgPath);
1633
+ } catch {
1634
+ continue;
1635
+ }
1636
+ if (seenReal.has(real)) continue;
1637
+ seenReal.add(real);
1638
+ if (!queued.has(real)) {
1639
+ queued.add(real);
1640
+ queue.push(real);
1641
+ }
1642
+ if (real !== projectRoot && !isUnderRoot(real, projectRoot) && !real.includes(NM)) {
1643
+ results.push(real);
1644
+ }
1645
+ }
1646
+ }
1647
+ }
1648
+ }
1649
+ return results;
1650
+ }
1651
+ function listScopedPackages(nm, scope) {
1652
+ try {
1653
+ return import_node_fs5.default.readdirSync(import_node_path5.default.join(nm, scope)).filter((name) => !name.startsWith(".")).map((name) => import_node_path5.default.join(scope, name));
1654
+ } catch {
1655
+ return [];
1656
+ }
1657
+ }
1658
+ function getLinkedPackageRoots(projectRoot) {
1659
+ let mtimeMs = 0;
1660
+ try {
1661
+ mtimeMs = import_node_fs5.default.statSync(import_node_path5.default.join(projectRoot, "node_modules")).mtimeMs;
1662
+ } catch {
1663
+ mtimeMs = 0;
1664
+ }
1665
+ const cached2 = linkedRootsCache.get(projectRoot);
1666
+ if (cached2 && cached2.mtimeMs === mtimeMs) {
1667
+ return cached2.roots;
1668
+ }
1669
+ const roots = discoverLinkedPackageRoots(projectRoot);
1670
+ linkedRootsCache.set(projectRoot, { roots, mtimeMs });
1671
+ return roots;
1672
+ }
1673
+ function clearLinkedPackageRootsCache() {
1674
+ linkedRootsCache.clear();
1675
+ }
1676
+ function isAllowedDevModulePath(realId, projectRoot) {
1677
+ if (realId === projectRoot || isUnderRoot(realId, projectRoot)) return true;
1678
+ for (const pkgRoot of getLinkedPackageRoots(projectRoot)) {
1679
+ if (realId === pkgRoot || realId.startsWith(pkgRoot + import_node_path5.default.sep)) return true;
1680
+ }
1681
+ let dir = projectRoot;
1682
+ for (; ; ) {
1683
+ const nm = import_node_path5.default.join(dir, "node_modules");
1684
+ if (realId === nm || realId.startsWith(nm + import_node_path5.default.sep)) return true;
1685
+ const parent = import_node_path5.default.dirname(dir);
1686
+ if (parent === dir) break;
1687
+ dir = parent;
1688
+ }
1689
+ return false;
1690
+ }
1691
+ function findNearestPackageRoot(file) {
1692
+ let dir = import_node_path5.default.dirname(file);
1693
+ for (; ; ) {
1694
+ const pkgJson = import_node_path5.default.join(dir, "package.json");
1695
+ if (import_node_fs5.default.existsSync(pkgJson)) {
1696
+ try {
1697
+ const pkg = JSON.parse(import_node_fs5.default.readFileSync(pkgJson, "utf-8"));
1698
+ if (typeof pkg?.name === "string" && pkg.name) return dir;
1699
+ } catch {
1700
+ }
1701
+ }
1702
+ const parent = import_node_path5.default.dirname(dir);
1703
+ if (parent === dir) return null;
1704
+ dir = parent;
1705
+ }
1706
+ }
1707
+ var import_node_fs5, import_node_path5, NM, linkedRootsCache;
1708
+ var init_fs_allow = __esm({
1709
+ "src/server/fs-allow.ts"() {
1710
+ "use strict";
1711
+ import_node_fs5 = __toESM(require("fs"), 1);
1712
+ import_node_path5 = __toESM(require("path"), 1);
1713
+ NM = `${import_node_path5.default.sep}node_modules${import_node_path5.default.sep}`;
1714
+ linkedRootsCache = /* @__PURE__ */ new Map();
1715
+ }
1716
+ });
1717
+
1586
1718
  // src/server/middleware.ts
1587
1719
  function getReactRefreshRuntimeEsm(includeBoundaryHelpers = false) {
1588
1720
  if (__refreshRuntimeCache) {
@@ -1591,10 +1723,10 @@ function getReactRefreshRuntimeEsm(includeBoundaryHelpers = false) {
1591
1723
  let cjsPath;
1592
1724
  try {
1593
1725
  const pkgPath = __require.resolve("react-refresh/package.json");
1594
- cjsPath = import_node_path5.default.join(import_node_path5.default.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
1726
+ cjsPath = import_node_path6.default.join(import_node_path6.default.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
1595
1727
  } catch (err) {
1596
- cjsPath = import_node_path5.default.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
1597
- if (!import_node_fs5.default.existsSync(cjsPath)) {
1728
+ cjsPath = import_node_path6.default.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
1729
+ if (!import_node_fs6.default.existsSync(cjsPath)) {
1598
1730
  const origMsg = err instanceof Error ? err.message : String(err);
1599
1731
  throw new Error(
1600
1732
  `[nasti] Missing dependency "react-refresh". Install it with: npm install react-refresh
@@ -1602,7 +1734,7 @@ Original resolve error: ${origMsg}`
1602
1734
  );
1603
1735
  }
1604
1736
  }
1605
- const cjsSource = import_node_fs5.default.readFileSync(cjsPath, "utf-8");
1737
+ const cjsSource = import_node_fs6.default.readFileSync(cjsPath, "utf-8");
1606
1738
  __refreshRuntimeCache = `// Wrapped react-refresh runtime -> ESM
1607
1739
  const exports = {};
1608
1740
  const module = { exports };
@@ -1773,8 +1905,8 @@ async function transformRequest(url, ctx) {
1773
1905
  let realIdValid = false;
1774
1906
  try {
1775
1907
  if (idParam) {
1776
- realId = import_node_fs5.default.realpathSync(idParam);
1777
- realIdValid = import_node_fs5.default.statSync(realId).isFile() && (realId.includes(`${import_node_path5.default.sep}node_modules${import_node_path5.default.sep}`) || isUnderRoot(realId, config.root));
1908
+ realId = import_node_fs6.default.realpathSync(idParam);
1909
+ realIdValid = import_node_fs6.default.statSync(realId).isFile() && isAllowedDevModulePath(realId, config.root);
1778
1910
  }
1779
1911
  } catch {
1780
1912
  realId = null;
@@ -1841,7 +1973,7 @@ async function transformRequest(url, ctx) {
1841
1973
  }
1842
1974
  }
1843
1975
  const filePath = resolveUrlToFile(url, config.root);
1844
- if (!filePath || !import_node_fs5.default.existsSync(filePath)) return null;
1976
+ if (!filePath || !import_node_fs6.default.existsSync(filePath)) return null;
1845
1977
  const mod = await moduleGraph.ensureEntryFromUrl(url);
1846
1978
  moduleGraph.registerModule(mod, filePath);
1847
1979
  const transformVersion = mod.invalidationVersion;
@@ -1852,7 +1984,7 @@ async function transformRequest(url, ctx) {
1852
1984
  return transformResult2;
1853
1985
  }
1854
1986
  const loaded = await pluginContainer.load(filePath);
1855
- let code = loaded == null ? import_node_fs5.default.readFileSync(filePath, "utf-8") : typeof loaded === "string" ? loaded : loaded.code;
1987
+ let code = loaded == null ? import_node_fs6.default.readFileSync(filePath, "utf-8") : typeof loaded === "string" ? loaded : loaded.code;
1856
1988
  let map = loaded && typeof loaded !== "string" ? loaded.map : void 0;
1857
1989
  const pluginResult = await pluginContainer.transform(code, filePath);
1858
1990
  if (pluginResult) {
@@ -1910,7 +2042,7 @@ async function loadVirtualModule(spec, ctx) {
1910
2042
  const resolved = await pluginContainer.resolveId(spec);
1911
2043
  if (resolved == null) return null;
1912
2044
  const resolvedId = typeof resolved === "string" ? resolved : resolved.id;
1913
- const looksVirtual = resolvedId.startsWith("\0") || !import_node_fs5.default.existsSync(resolvedId);
2045
+ const looksVirtual = resolvedId.startsWith("\0") || !import_node_fs6.default.existsSync(resolvedId);
1914
2046
  if (!looksVirtual) return null;
1915
2047
  const loadResult = await pluginContainer.load(resolvedId);
1916
2048
  if (loadResult == null) return null;
@@ -1924,7 +2056,7 @@ async function loadVirtualModule(spec, ctx) {
1924
2056
  config.mode,
1925
2057
  ssrDefineOverrides(ctx.environment?.consumer ?? "client")
1926
2058
  ));
1927
- const anchor = import_node_path5.default.join(config.root, "__nasti_virtual__.ts");
2059
+ const anchor = import_node_path6.default.join(config.root, "__nasti_virtual__.ts");
1928
2060
  code = rewriteImports(code, config, anchor);
1929
2061
  return { id: resolvedId, result: { code } };
1930
2062
  }
@@ -1950,7 +2082,7 @@ async function doBundlePackage(entryFile, root) {
1950
2082
  await bundle2.close();
1951
2083
  let code = result.output[0].code;
1952
2084
  code = code.replace(/process\.env\.NODE_ENV/g, '"development"');
1953
- const externalBaseDir = import_node_path5.default.dirname(entryFile);
2085
+ const externalBaseDir = import_node_path6.default.dirname(entryFile);
1954
2086
  code = code.replace(
1955
2087
  /^(import\b[^;'"]*?\bfrom\s+)(['"])([^'"./][^'"]*)(\2)/gm,
1956
2088
  (_, prefix, q, spec) => `${prefix}${q}${externalSpecToModuleUrl(spec, externalBaseDir, root)}${q}`
@@ -1968,16 +2100,16 @@ async function doBundlePackage(entryFile, root) {
1968
2100
  return code;
1969
2101
  }
1970
2102
  async function tryGenerateSubpathShim(entryFile, root) {
1971
- const NM = `${import_node_path5.default.sep}node_modules${import_node_path5.default.sep}`;
1972
- if (!entryFile.includes(NM)) return null;
2103
+ const NM2 = `${import_node_path6.default.sep}node_modules${import_node_path6.default.sep}`;
2104
+ if (!entryFile.includes(NM2)) return null;
1973
2105
  let pkgDir = null;
1974
2106
  let pkgName = null;
1975
- let dir = import_node_path5.default.dirname(entryFile);
2107
+ let dir = import_node_path6.default.dirname(entryFile);
1976
2108
  while (true) {
1977
- const pkgJsonPath = import_node_path5.default.join(dir, "package.json");
1978
- if (import_node_fs5.default.existsSync(pkgJsonPath)) {
2109
+ const pkgJsonPath = import_node_path6.default.join(dir, "package.json");
2110
+ if (import_node_fs6.default.existsSync(pkgJsonPath)) {
1979
2111
  try {
1980
- const pkg = JSON.parse(import_node_fs5.default.readFileSync(pkgJsonPath, "utf-8"));
2112
+ const pkg = JSON.parse(import_node_fs6.default.readFileSync(pkgJsonPath, "utf-8"));
1981
2113
  if (typeof pkg?.name === "string" && pkg.name) {
1982
2114
  pkgDir = dir;
1983
2115
  pkgName = pkg.name;
@@ -1986,16 +2118,16 @@ async function tryGenerateSubpathShim(entryFile, root) {
1986
2118
  } catch {
1987
2119
  }
1988
2120
  }
1989
- const parent = import_node_path5.default.dirname(dir);
2121
+ const parent = import_node_path6.default.dirname(dir);
1990
2122
  if (parent === dir) return null;
1991
2123
  dir = parent;
1992
- if (!dir.includes(NM)) return null;
2124
+ if (!dir.includes(NM2)) return null;
1993
2125
  }
1994
2126
  if (!pkgDir || !pkgName) return null;
1995
- const entryExt = import_node_path5.default.extname(entryFile);
2127
+ const entryExt = import_node_path6.default.extname(entryFile);
1996
2128
  const mainEntry = pickMainEntryByExtension(pkgDir, entryExt);
1997
2129
  if (!mainEntry) return null;
1998
- if (import_node_path5.default.resolve(mainEntry) === import_node_path5.default.resolve(entryFile)) return null;
2130
+ if (import_node_path6.default.resolve(mainEntry) === import_node_path6.default.resolve(entryFile)) return null;
1999
2131
  let mainNs;
2000
2132
  let subNs;
2001
2133
  try {
@@ -2019,7 +2151,7 @@ async function tryGenerateSubpathShim(entryFile, root) {
2019
2151
  if (mainNs["default"] !== subNs["default"]) return null;
2020
2152
  }
2021
2153
  const rootMain = resolveNodeModule(root, pkgName);
2022
- const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir + import_node_path5.default.sep) ? `/@modules/${pkgName}` : `/@modules/${pkgName}?id=${encodeURIComponent(mainEntry)}`;
2154
+ const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir + import_node_path6.default.sep) ? `/@modules/${pkgName}` : `/@modules/${pkgName}?id=${encodeURIComponent(mainEntry)}`;
2023
2155
  const lines = [
2024
2156
  `// Nasti subpath shim \u2192 ${pkgName} (avoid duplicate bundling)`,
2025
2157
  `import * as __pkg from "${mainEntryUrl}";`
@@ -2033,10 +2165,10 @@ async function tryGenerateSubpathShim(entryFile, root) {
2033
2165
  return lines.join("\n") + "\n";
2034
2166
  }
2035
2167
  function pickMainEntryByExtension(pkgDir, preferredExt) {
2036
- const pkgJsonPath = import_node_path5.default.join(pkgDir, "package.json");
2168
+ const pkgJsonPath = import_node_path6.default.join(pkgDir, "package.json");
2037
2169
  let pkg;
2038
2170
  try {
2039
- pkg = JSON.parse(import_node_fs5.default.readFileSync(pkgJsonPath, "utf-8"));
2171
+ pkg = JSON.parse(import_node_fs6.default.readFileSync(pkgJsonPath, "utf-8"));
2040
2172
  } catch {
2041
2173
  return null;
2042
2174
  }
@@ -2055,14 +2187,14 @@ function pickMainEntryByExtension(pkgDir, preferredExt) {
2055
2187
  if (typeof pkg.module === "string") candidates.push(pkg.module);
2056
2188
  if (typeof pkg.main === "string") candidates.push(pkg.main);
2057
2189
  for (const cand of candidates) {
2058
- if (import_node_path5.default.extname(cand) === preferredExt) {
2059
- const full = import_node_path5.default.resolve(pkgDir, cand);
2060
- if (import_node_fs5.default.existsSync(full)) return full;
2190
+ if (import_node_path6.default.extname(cand) === preferredExt) {
2191
+ const full = import_node_path6.default.resolve(pkgDir, cand);
2192
+ if (import_node_fs6.default.existsSync(full)) return full;
2061
2193
  }
2062
2194
  }
2063
2195
  for (const cand of candidates) {
2064
- const full = import_node_path5.default.resolve(pkgDir, cand);
2065
- if (import_node_fs5.default.existsSync(full)) return full;
2196
+ const full = import_node_path6.default.resolve(pkgDir, cand);
2197
+ if (import_node_fs6.default.existsSync(full)) return full;
2066
2198
  }
2067
2199
  return null;
2068
2200
  }
@@ -2087,8 +2219,8 @@ function rewriteExternalRequires(code, baseDir, root) {
2087
2219
  }
2088
2220
  async function injectCjsNamedExports(code, entryFile) {
2089
2221
  try {
2090
- const { createRequire: createRequire6 } = await import("module");
2091
- const req = createRequire6(entryFile);
2222
+ const { createRequire: createRequire7 } = await import("module");
2223
+ const req = createRequire7(entryFile);
2092
2224
  const cjsExports = req(entryFile);
2093
2225
  if (!cjsExports || typeof cjsExports !== "object" && typeof cjsExports !== "function" || Array.isArray(cjsExports)) return code;
2094
2226
  const namedKeys = Object.keys(cjsExports).filter(
@@ -2129,11 +2261,22 @@ function rewriteImports(code, config, filePath, importedUrls, moduleGraph) {
2129
2261
  }
2130
2262
  function createModuleSpecifierResolver(config, filePath) {
2131
2263
  const root = config.root;
2132
- const fileDir = import_node_path5.default.dirname(filePath);
2264
+ const fileDir = import_node_path6.default.dirname(filePath);
2133
2265
  const aliasEntries = Object.entries(config.resolve.alias).sort(
2134
2266
  ([a], [b]) => b.length - a.length
2135
2267
  );
2136
- const toRootUrl = (abs) => "/" + import_node_path5.default.relative(root, abs).replace(/\\/g, "/");
2268
+ const toServableUrl = (abs) => {
2269
+ if (isUnderRoot(abs, root)) {
2270
+ return "/" + import_node_path6.default.relative(root, abs).replace(/\\/g, "/");
2271
+ }
2272
+ for (const pkgRoot of getLinkedPackageRoots(root)) {
2273
+ if (abs === pkgRoot || abs.startsWith(pkgRoot + import_node_path6.default.sep)) {
2274
+ const normalized = abs.replace(/\\/g, "/");
2275
+ return "/@fs/" + (normalized.startsWith("/") ? normalized.slice(1) : normalized);
2276
+ }
2277
+ }
2278
+ return null;
2279
+ };
2137
2280
  return (specifier) => {
2138
2281
  const suffixMatch = specifier.match(/[?#].*$/);
2139
2282
  const suffix = suffixMatch ? suffixMatch[0] : "";
@@ -2142,18 +2285,21 @@ function createModuleSpecifierResolver(config, filePath) {
2142
2285
  if (baseSpec === key || baseSpec.startsWith(key + "/")) {
2143
2286
  const aliasBase = resolveAliasTarget(value, root);
2144
2287
  const sub = baseSpec.slice(key.length).replace(/^\//, "");
2145
- const target = sub ? import_node_path5.default.join(aliasBase, sub) : aliasBase;
2288
+ const target = sub ? import_node_path6.default.join(aliasBase, sub) : aliasBase;
2146
2289
  const resolved = tryResolveDiskPath(target);
2147
- return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
2290
+ const url = resolved ? toServableUrl(resolved) : null;
2291
+ return url ? url + suffix : specifier;
2148
2292
  }
2149
2293
  }
2150
2294
  if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
2151
- const resolved = tryResolveDiskPath(import_node_path5.default.resolve(fileDir, baseSpec));
2152
- return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
2295
+ const resolved = tryResolveDiskPath(import_node_path6.default.resolve(fileDir, baseSpec));
2296
+ const url = resolved ? toServableUrl(resolved) : null;
2297
+ return url ? url + suffix : specifier;
2153
2298
  }
2154
2299
  if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
2155
- const resolved = tryResolveDiskPath(import_node_path5.default.join(root, baseSpec.replace(/^\//, "")));
2156
- return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
2300
+ const resolved = tryResolveDiskPath(import_node_path6.default.join(root, baseSpec.replace(/^\//, "")));
2301
+ const url = resolved ? toServableUrl(resolved) : null;
2302
+ return url ? url + suffix : specifier;
2157
2303
  }
2158
2304
  if (baseSpec.startsWith("/")) return specifier;
2159
2305
  return `/@modules/${specifier}`;
@@ -2306,28 +2452,24 @@ function maskStringsAndComments(code) {
2306
2452
  return masked.join("");
2307
2453
  }
2308
2454
  function resolveAliasTarget(value, root) {
2309
- if (import_node_path5.default.isAbsolute(value) && import_node_fs5.default.existsSync(value)) return value;
2310
- if (value.startsWith("/")) return import_node_path5.default.join(root, value.slice(1));
2311
- return import_node_path5.default.resolve(root, value);
2455
+ if (import_node_path6.default.isAbsolute(value) && import_node_fs6.default.existsSync(value)) return value;
2456
+ if (value.startsWith("/")) return import_node_path6.default.join(root, value.slice(1));
2457
+ return import_node_path6.default.resolve(root, value);
2312
2458
  }
2313
2459
  function tryResolveDiskPath(target) {
2314
- if (import_node_fs5.default.existsSync(target) && import_node_fs5.default.statSync(target).isFile()) return target;
2460
+ if (import_node_fs6.default.existsSync(target) && import_node_fs6.default.statSync(target).isFile()) return target;
2315
2461
  for (const ext of RESOLVE_EXTENSIONS) {
2316
2462
  const withExt = target + ext;
2317
- if (import_node_fs5.default.existsSync(withExt) && import_node_fs5.default.statSync(withExt).isFile()) return withExt;
2463
+ if (import_node_fs6.default.existsSync(withExt) && import_node_fs6.default.statSync(withExt).isFile()) return withExt;
2318
2464
  }
2319
- if (import_node_fs5.default.existsSync(target) && import_node_fs5.default.statSync(target).isDirectory()) {
2465
+ if (import_node_fs6.default.existsSync(target) && import_node_fs6.default.statSync(target).isDirectory()) {
2320
2466
  for (const ext of RESOLVE_EXTENSIONS) {
2321
- const idx = import_node_path5.default.join(target, "index" + ext);
2322
- if (import_node_fs5.default.existsSync(idx) && import_node_fs5.default.statSync(idx).isFile()) return idx;
2467
+ const idx = import_node_path6.default.join(target, "index" + ext);
2468
+ if (import_node_fs6.default.existsSync(idx) && import_node_fs6.default.statSync(idx).isFile()) return idx;
2323
2469
  }
2324
2470
  }
2325
2471
  return null;
2326
2472
  }
2327
- function isUnderRoot(abs, root) {
2328
- const rel = import_node_path5.default.relative(root, abs);
2329
- return !!rel && !rel.startsWith("..") && !import_node_path5.default.isAbsolute(rel);
2330
- }
2331
2473
  function appendTimestampQuery(url, timestamp) {
2332
2474
  const hashIndex = url.indexOf("#");
2333
2475
  const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
@@ -2345,7 +2487,7 @@ function resolveNodeModule(baseDir, moduleName) {
2345
2487
  const resolved = resolveNodeModuleEntry(baseDir, moduleName);
2346
2488
  if (!resolved) return null;
2347
2489
  try {
2348
- return import_node_fs5.default.realpathSync(resolved);
2490
+ return import_node_fs6.default.realpathSync(resolved);
2349
2491
  } catch {
2350
2492
  return resolved;
2351
2493
  }
@@ -2365,21 +2507,21 @@ function resolveNodeModuleEntry(root, moduleName) {
2365
2507
  let pkgDir = null;
2366
2508
  let dir = root;
2367
2509
  for (; ; ) {
2368
- const candidate = import_node_path5.default.join(dir, "node_modules", pkgName);
2369
- if (import_node_fs5.default.existsSync(candidate)) {
2510
+ const candidate = import_node_path6.default.join(dir, "node_modules", pkgName);
2511
+ if (import_node_fs6.default.existsSync(candidate)) {
2370
2512
  pkgDir = candidate;
2371
2513
  break;
2372
2514
  }
2373
- const parent = import_node_path5.default.dirname(dir);
2515
+ const parent = import_node_path6.default.dirname(dir);
2374
2516
  if (parent === dir) break;
2375
2517
  dir = parent;
2376
2518
  }
2377
2519
  if (!pkgDir) return null;
2378
- const pkgJsonPath = import_node_path5.default.join(pkgDir, "package.json");
2379
- if (!import_node_fs5.default.existsSync(pkgJsonPath)) return null;
2520
+ const pkgJsonPath = import_node_path6.default.join(pkgDir, "package.json");
2521
+ if (!import_node_fs6.default.existsSync(pkgJsonPath)) return null;
2380
2522
  let pkg;
2381
2523
  try {
2382
- pkg = JSON.parse(import_node_fs5.default.readFileSync(pkgJsonPath, "utf-8"));
2524
+ pkg = JSON.parse(import_node_fs6.default.readFileSync(pkgJsonPath, "utf-8"));
2383
2525
  } catch {
2384
2526
  return null;
2385
2527
  }
@@ -2392,32 +2534,32 @@ function resolveNodeModuleEntry(root, moduleName) {
2392
2534
  const subDirs = [""];
2393
2535
  for (const field of ["module", "main"]) {
2394
2536
  if (typeof pkg[field] === "string") {
2395
- const dir2 = import_node_path5.default.dirname(pkg[field]);
2537
+ const dir2 = import_node_path6.default.dirname(pkg[field]);
2396
2538
  if (dir2 && dir2 !== "." && !subDirs.includes(dir2)) subDirs.push(dir2);
2397
2539
  }
2398
2540
  }
2399
2541
  for (const dir2 of subDirs) {
2400
- const direct = import_node_path5.default.join(pkgDir, dir2, subpath);
2401
- if (import_node_fs5.default.existsSync(direct) && import_node_fs5.default.statSync(direct).isFile()) return direct;
2542
+ const direct = import_node_path6.default.join(pkgDir, dir2, subpath);
2543
+ if (import_node_fs6.default.existsSync(direct) && import_node_fs6.default.statSync(direct).isFile()) return direct;
2402
2544
  for (const ext of RESOLVE_EXTENSIONS) {
2403
- if (import_node_fs5.default.existsSync(direct + ext)) return direct + ext;
2545
+ if (import_node_fs6.default.existsSync(direct + ext)) return direct + ext;
2404
2546
  }
2405
2547
  }
2406
2548
  return null;
2407
2549
  }
2408
2550
  for (const field of ["module", "jsnext:main", "jsnext", "main"]) {
2409
2551
  if (typeof pkg[field] === "string") {
2410
- const entry = import_node_path5.default.join(pkgDir, pkg[field]);
2411
- if (import_node_fs5.default.existsSync(entry)) return entry;
2552
+ const entry = import_node_path6.default.join(pkgDir, pkg[field]);
2553
+ if (import_node_fs6.default.existsSync(entry)) return entry;
2412
2554
  }
2413
2555
  }
2414
- const indexFallback = import_node_path5.default.join(pkgDir, "index.js");
2415
- if (import_node_fs5.default.existsSync(indexFallback)) return indexFallback;
2556
+ const indexFallback = import_node_path6.default.join(pkgDir, "index.js");
2557
+ if (import_node_fs6.default.existsSync(indexFallback)) return indexFallback;
2416
2558
  return null;
2417
2559
  }
2418
2560
  function resolvePackageExports(exports2, key, pkgDir) {
2419
2561
  if (typeof exports2 === "string") {
2420
- return key === "." ? import_node_path5.default.join(pkgDir, exports2) : null;
2562
+ return key === "." ? import_node_path6.default.join(pkgDir, exports2) : null;
2421
2563
  }
2422
2564
  const entry = exports2[key];
2423
2565
  if (entry === void 0) {
@@ -2429,7 +2571,7 @@ function resolvePackageExports(exports2, key, pkgDir) {
2429
2571
  return resolveExportValue(entry, pkgDir);
2430
2572
  }
2431
2573
  function resolveExportValue(value, pkgDir) {
2432
- if (typeof value === "string") return import_node_path5.default.join(pkgDir, value);
2574
+ if (typeof value === "string") return import_node_path6.default.join(pkgDir, value);
2433
2575
  if (Array.isArray(value)) {
2434
2576
  for (const item of value) {
2435
2577
  const r = resolveExportValue(item, pkgDir);
@@ -2448,35 +2590,54 @@ function resolveExportValue(value, pkgDir) {
2448
2590
  return null;
2449
2591
  }
2450
2592
  function resolveUrlToFile(url, root) {
2451
- const cleanUrl = url.split("?")[0];
2593
+ const cleanUrl = url.split(/[?#]/)[0];
2452
2594
  if (cleanUrl.startsWith("/@modules/")) {
2453
2595
  const moduleName = cleanUrl.slice("/@modules/".length);
2454
2596
  return resolveNodeModule(root, moduleName);
2455
2597
  }
2456
- const filePath = import_node_path5.default.resolve(root, cleanUrl.replace(/^\//, ""));
2457
- if (import_node_fs5.default.existsSync(filePath) && import_node_fs5.default.statSync(filePath).isFile()) {
2598
+ if (cleanUrl.startsWith("/@fs/")) {
2599
+ let abs = cleanUrl.slice("/@fs/".length);
2600
+ if (process.platform === "win32") {
2601
+ abs = abs.replace(/\//g, import_node_path6.default.sep);
2602
+ } else if (!abs.startsWith("/")) {
2603
+ abs = "/" + abs;
2604
+ }
2605
+ try {
2606
+ const real = import_node_fs6.default.realpathSync(abs);
2607
+ if (import_node_fs6.default.statSync(real).isFile() && isAllowedDevModulePath(real, root)) return real;
2608
+ } catch {
2609
+ return null;
2610
+ }
2611
+ return null;
2612
+ }
2613
+ const filePath = import_node_path6.default.resolve(root, cleanUrl.replace(/^\//, ""));
2614
+ if (import_node_fs6.default.existsSync(filePath) && import_node_fs6.default.statSync(filePath).isFile()) {
2458
2615
  return filePath;
2459
2616
  }
2460
2617
  for (const ext of RESOLVE_EXTENSIONS) {
2461
2618
  const withExt = filePath + ext;
2462
- if (import_node_fs5.default.existsSync(withExt)) return withExt;
2619
+ if (import_node_fs6.default.existsSync(withExt)) return withExt;
2463
2620
  }
2464
2621
  for (const ext of RESOLVE_EXTENSIONS) {
2465
- const indexFile = import_node_path5.default.join(filePath, "index" + ext);
2466
- if (import_node_fs5.default.existsSync(indexFile)) return indexFile;
2622
+ const indexFile = import_node_path6.default.join(filePath, "index" + ext);
2623
+ if (import_node_fs6.default.existsSync(indexFile)) return indexFile;
2467
2624
  }
2468
2625
  return null;
2469
2626
  }
2470
2627
  function isModuleRequest(url, destination) {
2471
- const cleanUrl = url.split("?")[0];
2628
+ const cleanUrl = url.split(/[?#]/)[0];
2472
2629
  if (/\.(ts|tsx|jsx|js|mjs|vue|css|json)$/.test(cleanUrl)) return true;
2473
2630
  if (cleanUrl.startsWith("/@modules/")) return true;
2631
+ if (cleanUrl.startsWith("/@fs/")) return true;
2474
2632
  if (isAssetFile(cleanUrl)) {
2475
- const query = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
2633
+ const qIdx = url.indexOf("?");
2634
+ const hIdx = url.indexOf("#");
2635
+ const queryEnd = hIdx === -1 ? url.length : hIdx;
2636
+ const query = qIdx === -1 || qIdx > queryEnd ? "" : url.slice(qIdx + 1, queryEnd);
2476
2637
  const isExplicitAssetModule = /(?:^|&)(?:url|raw)(?:&|$)/.test(query);
2477
2638
  return isExplicitAssetModule || destination === "script";
2478
2639
  }
2479
- if (!import_node_path5.default.extname(cleanUrl)) return true;
2640
+ if (!import_node_path6.default.extname(cleanUrl)) return true;
2480
2641
  return false;
2481
2642
  }
2482
2643
  function getHmrClientCode() {
@@ -2706,12 +2867,12 @@ function clearCustomListeners(ownerPath) {
2706
2867
  }
2707
2868
  `;
2708
2869
  }
2709
- var import_node_path5, import_node_fs5, import_node_module, import_node_url2, import_picocolors3, import_meta, __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_BOUNDARY_HELPERS, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
2870
+ var import_node_path6, import_node_fs6, import_node_module, import_node_url2, import_picocolors3, import_meta, __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_BOUNDARY_HELPERS, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
2710
2871
  var init_middleware = __esm({
2711
2872
  "src/server/middleware.ts"() {
2712
2873
  "use strict";
2713
- import_node_path5 = __toESM(require("path"), 1);
2714
- import_node_fs5 = __toESM(require("fs"), 1);
2874
+ import_node_path6 = __toESM(require("path"), 1);
2875
+ import_node_fs6 = __toESM(require("fs"), 1);
2715
2876
  import_node_module = require("module");
2716
2877
  import_node_url2 = require("url");
2717
2878
  import_picocolors3 = __toESM(require("picocolors"), 1);
@@ -2720,8 +2881,9 @@ var init_middleware = __esm({
2720
2881
  init_env();
2721
2882
  init_url();
2722
2883
  init_assets();
2884
+ init_fs_allow();
2723
2885
  import_meta = {};
2724
- __dirname_esm = import_node_path5.default.dirname((0, import_node_url2.fileURLToPath)(import_meta.url));
2886
+ __dirname_esm = import_node_path6.default.dirname((0, import_node_url2.fileURLToPath)(import_meta.url));
2725
2887
  __require = (0, import_node_module.createRequire)(import_meta.url);
2726
2888
  __refreshRuntimeCache = null;
2727
2889
  REACT_REFRESH_BOUNDARY_HELPERS = `
@@ -2810,9 +2972,26 @@ async function handleFileChange(file, server, environmentName = "client", timest
2810
2972
  }
2811
2973
  const moduleGraph = environment.moduleGraph;
2812
2974
  const logger = config.logger;
2813
- const relativePath = "/" + import_node_path6.default.relative(config.root, file);
2814
- const shortFile = import_node_path6.default.relative(config.root, file);
2815
- const mods = moduleGraph.getModulesByFile(file);
2975
+ const relativePath = "/" + import_node_path7.default.relative(config.root, file);
2976
+ const shortFile = import_node_path7.default.relative(config.root, file);
2977
+ let mods = moduleGraph.getModulesByFile(file);
2978
+ if (!mods || mods.size === 0) {
2979
+ try {
2980
+ const real = import_node_fs7.default.realpathSync(file);
2981
+ if (real !== file) mods = moduleGraph.getModulesByFile(real);
2982
+ if (mods && mods.size > 0) file = real;
2983
+ } catch {
2984
+ }
2985
+ }
2986
+ if (!mods || mods.size === 0) {
2987
+ const packageRoot = findNearestPackageRoot(file);
2988
+ if (packageRoot && getLinkedPackageRoots(config.root).some(
2989
+ (r) => packageRoot === r || packageRoot.startsWith(r + import_node_path7.default.sep)
2990
+ )) {
2991
+ const under = moduleGraph.getModulesWithFileUnder(packageRoot);
2992
+ if (under.size > 0) mods = under;
2993
+ }
2994
+ }
2816
2995
  if (!mods || mods.size === 0) {
2817
2996
  return null;
2818
2997
  }
@@ -2827,7 +3006,7 @@ async function handleFileChange(file, server, environmentName = "client", timest
2827
3006
  file,
2828
3007
  timestamp,
2829
3008
  modules: [mod],
2830
- read: () => import_node_fs6.default.readFileSync(file, "utf-8"),
3009
+ read: () => import_node_fs7.default.readFileSync(file, "utf-8"),
2831
3010
  server,
2832
3011
  environment
2833
3012
  };
@@ -2888,20 +3067,21 @@ async function handleFileChange(file, server, environmentName = "client", timest
2888
3067
  fullReload
2889
3068
  };
2890
3069
  }
2891
- var import_node_path6, import_node_fs6, import_picocolors4;
3070
+ var import_node_path7, import_node_fs7, import_picocolors4;
2892
3071
  var init_hmr = __esm({
2893
3072
  "src/server/hmr.ts"() {
2894
3073
  "use strict";
2895
- import_node_path6 = __toESM(require("path"), 1);
2896
- import_node_fs6 = __toESM(require("fs"), 1);
3074
+ import_node_path7 = __toESM(require("path"), 1);
3075
+ import_node_fs7 = __toESM(require("fs"), 1);
2897
3076
  import_picocolors4 = __toESM(require("picocolors"), 1);
3077
+ init_fs_allow();
2898
3078
  }
2899
3079
  });
2900
3080
 
2901
3081
  // src/plugins/resolve.ts
2902
3082
  function resolvePlugin(config) {
2903
3083
  const { alias, extensions } = config.resolve;
2904
- const require2 = (0, import_node_module2.createRequire)(import_node_path7.default.resolve(config.root, "package.json"));
3084
+ const require2 = (0, import_node_module2.createRequire)(import_node_path8.default.resolve(config.root, "package.json"));
2905
3085
  const aliasEntries = Object.entries(alias).sort(
2906
3086
  ([a], [b]) => b.length - a.length
2907
3087
  );
@@ -2909,10 +3089,10 @@ function resolvePlugin(config) {
2909
3089
  if (config.framework === "vue") {
2910
3090
  try {
2911
3091
  const vuePkgJson = require2.resolve("vue/package.json", { paths: [config.root] });
2912
- const vueDir = import_node_path7.default.dirname(vuePkgJson);
2913
- const mod = JSON.parse(import_node_fs7.default.readFileSync(vuePkgJson, "utf-8")).module;
2914
- const entry = import_node_path7.default.join(vueDir, mod ?? "dist/vue.runtime.esm-bundler.js");
2915
- if (import_node_fs7.default.existsSync(entry)) vueRuntimeEntry = entry;
3092
+ const vueDir = import_node_path8.default.dirname(vuePkgJson);
3093
+ const mod = JSON.parse(import_node_fs8.default.readFileSync(vuePkgJson, "utf-8")).module;
3094
+ const entry = import_node_path8.default.join(vueDir, mod ?? "dist/vue.runtime.esm-bundler.js");
3095
+ if (import_node_fs8.default.existsSync(entry)) vueRuntimeEntry = entry;
2916
3096
  } catch {
2917
3097
  }
2918
3098
  }
@@ -2924,24 +3104,24 @@ function resolvePlugin(config) {
2924
3104
  if (source === key || source.startsWith(key + "/")) {
2925
3105
  const aliasBase = resolveAliasTarget2(value, config.root);
2926
3106
  const sub = source.slice(key.length).replace(/^\//, "");
2927
- const target = sub ? import_node_path7.default.join(aliasBase, sub) : aliasBase;
3107
+ const target = sub ? import_node_path8.default.join(aliasBase, sub) : aliasBase;
2928
3108
  const resolved = tryResolveFile(target, extensions);
2929
3109
  if (resolved) return resolved;
2930
3110
  break;
2931
3111
  }
2932
3112
  }
2933
3113
  if (source.startsWith("/") && !source.startsWith("//")) {
2934
- const rootRelative = import_node_path7.default.join(config.root, source.slice(1));
3114
+ const rootRelative = import_node_path8.default.join(config.root, source.slice(1));
2935
3115
  const resolved = tryResolveFile(rootRelative, extensions);
2936
3116
  if (resolved) return resolved;
2937
3117
  }
2938
- if (import_node_path7.default.isAbsolute(source) && import_node_fs7.default.existsSync(source)) {
3118
+ if (import_node_path8.default.isAbsolute(source) && import_node_fs8.default.existsSync(source)) {
2939
3119
  const resolved = tryResolveFile(source, extensions);
2940
3120
  if (resolved) return resolved;
2941
3121
  }
2942
3122
  if (source.startsWith(".")) {
2943
- const dir = importer ? import_node_path7.default.dirname(importer) : config.root;
2944
- const absolute = import_node_path7.default.resolve(dir, source);
3123
+ const dir = importer ? import_node_path8.default.dirname(importer) : config.root;
3124
+ const absolute = import_node_path8.default.resolve(dir, source);
2945
3125
  const resolved = tryResolveFile(absolute, extensions);
2946
3126
  if (resolved) return resolved;
2947
3127
  }
@@ -2950,7 +3130,7 @@ function resolvePlugin(config) {
2950
3130
  if (config.command === "build") return null;
2951
3131
  try {
2952
3132
  const resolved = require2.resolve(source, {
2953
- paths: [importer ? import_node_path7.default.dirname(importer) : config.root]
3133
+ paths: [importer ? import_node_path8.default.dirname(importer) : config.root]
2954
3134
  });
2955
3135
  return resolved;
2956
3136
  } catch {
@@ -2961,9 +3141,9 @@ function resolvePlugin(config) {
2961
3141
  },
2962
3142
  load(id) {
2963
3143
  if (id.startsWith("\0")) return null;
2964
- if (!import_node_fs7.default.existsSync(id)) return null;
3144
+ if (!import_node_fs8.default.existsSync(id)) return null;
2965
3145
  if (id.endsWith(".json")) {
2966
- const content = import_node_fs7.default.readFileSync(id, "utf-8");
3146
+ const content = import_node_fs8.default.readFileSync(id, "utf-8");
2967
3147
  return `export default ${content}`;
2968
3148
  }
2969
3149
  return null;
@@ -2971,36 +3151,36 @@ function resolvePlugin(config) {
2971
3151
  };
2972
3152
  }
2973
3153
  function resolveAliasTarget2(value, root) {
2974
- if (import_node_path7.default.isAbsolute(value) && import_node_fs7.default.existsSync(value)) return value;
2975
- if (value.startsWith("/")) return import_node_path7.default.join(root, value.slice(1));
2976
- return import_node_path7.default.resolve(root, value);
3154
+ if (import_node_path8.default.isAbsolute(value) && import_node_fs8.default.existsSync(value)) return value;
3155
+ if (value.startsWith("/")) return import_node_path8.default.join(root, value.slice(1));
3156
+ return import_node_path8.default.resolve(root, value);
2977
3157
  }
2978
3158
  function tryResolveFile(file, extensions) {
2979
- if (import_node_fs7.default.existsSync(file) && import_node_fs7.default.statSync(file).isFile()) {
3159
+ if (import_node_fs8.default.existsSync(file) && import_node_fs8.default.statSync(file).isFile()) {
2980
3160
  return file;
2981
3161
  }
2982
3162
  for (const ext of extensions) {
2983
3163
  const withExt = file + ext;
2984
- if (import_node_fs7.default.existsSync(withExt) && import_node_fs7.default.statSync(withExt).isFile()) {
3164
+ if (import_node_fs8.default.existsSync(withExt) && import_node_fs8.default.statSync(withExt).isFile()) {
2985
3165
  return withExt;
2986
3166
  }
2987
3167
  }
2988
- if (import_node_fs7.default.existsSync(file) && import_node_fs7.default.statSync(file).isDirectory()) {
3168
+ if (import_node_fs8.default.existsSync(file) && import_node_fs8.default.statSync(file).isDirectory()) {
2989
3169
  for (const ext of extensions) {
2990
- const indexFile = import_node_path7.default.join(file, "index" + ext);
2991
- if (import_node_fs7.default.existsSync(indexFile)) {
3170
+ const indexFile = import_node_path8.default.join(file, "index" + ext);
3171
+ if (import_node_fs8.default.existsSync(indexFile)) {
2992
3172
  return indexFile;
2993
3173
  }
2994
3174
  }
2995
3175
  }
2996
3176
  return null;
2997
3177
  }
2998
- var import_node_path7, import_node_fs7, import_node_module2;
3178
+ var import_node_path8, import_node_fs8, import_node_module2;
2999
3179
  var init_resolve = __esm({
3000
3180
  "src/plugins/resolve.ts"() {
3001
3181
  "use strict";
3002
- import_node_path7 = __toESM(require("path"), 1);
3003
- import_node_fs7 = __toESM(require("fs"), 1);
3182
+ import_node_path8 = __toESM(require("path"), 1);
3183
+ import_node_fs8 = __toESM(require("fs"), 1);
3004
3184
  import_node_module2 = require("module");
3005
3185
  }
3006
3186
  });
@@ -3040,27 +3220,27 @@ var require_process = __commonJS({
3040
3220
  var require_filesystem = __commonJS({
3041
3221
  "node_modules/detect-libc/lib/filesystem.js"(exports2, module2) {
3042
3222
  "use strict";
3043
- var fs13 = require("fs");
3223
+ var fs14 = require("fs");
3044
3224
  var LDD_PATH = "/usr/bin/ldd";
3045
3225
  var SELF_PATH = "/proc/self/exe";
3046
3226
  var MAX_LENGTH = 2048;
3047
- var readFileSync = (path18) => {
3048
- const fd = fs13.openSync(path18, "r");
3227
+ var readFileSync = (path19) => {
3228
+ const fd = fs14.openSync(path19, "r");
3049
3229
  const buffer = Buffer.alloc(MAX_LENGTH);
3050
- const bytesRead = fs13.readSync(fd, buffer, 0, MAX_LENGTH, 0);
3051
- fs13.close(fd, () => {
3230
+ const bytesRead = fs14.readSync(fd, buffer, 0, MAX_LENGTH, 0);
3231
+ fs14.close(fd, () => {
3052
3232
  });
3053
3233
  return buffer.subarray(0, bytesRead);
3054
3234
  };
3055
- var readFile = (path18) => new Promise((resolve, reject) => {
3056
- fs13.open(path18, "r", (err, fd) => {
3235
+ var readFile = (path19) => new Promise((resolve, reject) => {
3236
+ fs14.open(path19, "r", (err, fd) => {
3057
3237
  if (err) {
3058
3238
  reject(err);
3059
3239
  } else {
3060
3240
  const buffer = Buffer.alloc(MAX_LENGTH);
3061
- fs13.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
3241
+ fs14.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
3062
3242
  resolve(buffer.subarray(0, bytesRead));
3063
- fs13.close(fd, () => {
3243
+ fs14.close(fd, () => {
3064
3244
  });
3065
3245
  });
3066
3246
  }
@@ -3172,11 +3352,11 @@ var require_detect_libc = __commonJS({
3172
3352
  }
3173
3353
  return null;
3174
3354
  };
3175
- var familyFromInterpreterPath = (path18) => {
3176
- if (path18) {
3177
- if (path18.includes("/ld-musl-")) {
3355
+ var familyFromInterpreterPath = (path19) => {
3356
+ if (path19) {
3357
+ if (path19.includes("/ld-musl-")) {
3178
3358
  return MUSL;
3179
- } else if (path18.includes("/ld-linux-")) {
3359
+ } else if (path19.includes("/ld-linux-")) {
3180
3360
  return GLIBC;
3181
3361
  }
3182
3362
  }
@@ -3223,8 +3403,8 @@ var require_detect_libc = __commonJS({
3223
3403
  cachedFamilyInterpreter = null;
3224
3404
  try {
3225
3405
  const selfContent = await readFile(SELF_PATH);
3226
- const path18 = interpreterPath(selfContent);
3227
- cachedFamilyInterpreter = familyFromInterpreterPath(path18);
3406
+ const path19 = interpreterPath(selfContent);
3407
+ cachedFamilyInterpreter = familyFromInterpreterPath(path19);
3228
3408
  } catch (e) {
3229
3409
  }
3230
3410
  return cachedFamilyInterpreter;
@@ -3236,8 +3416,8 @@ var require_detect_libc = __commonJS({
3236
3416
  cachedFamilyInterpreter = null;
3237
3417
  try {
3238
3418
  const selfContent = readFileSync(SELF_PATH);
3239
- const path18 = interpreterPath(selfContent);
3240
- cachedFamilyInterpreter = familyFromInterpreterPath(path18);
3419
+ const path19 = interpreterPath(selfContent);
3420
+ cachedFamilyInterpreter = familyFromInterpreterPath(path19);
3241
3421
  } catch (e) {
3242
3422
  }
3243
3423
  return cachedFamilyInterpreter;
@@ -3963,7 +4143,7 @@ function hasTailwindDirectives(css) {
3963
4143
  }
3964
4144
  async function loadTailwind(projectRoot) {
3965
4145
  if (cached && cachedRoot === projectRoot) return cached;
3966
- const req = (0, import_node_module3.createRequire)(import_node_path8.default.join(projectRoot, "package.json"));
4146
+ const req = (0, import_node_module3.createRequire)(import_node_path9.default.join(projectRoot, "package.json"));
3967
4147
  let nodePath;
3968
4148
  let oxidePath;
3969
4149
  try {
@@ -3984,7 +4164,7 @@ async function compileTailwind(css, fromFile, projectRoot) {
3984
4164
  const { node, oxide } = await loadTailwind(projectRoot);
3985
4165
  const dependencies = [];
3986
4166
  const compiler2 = await node.compile(css, {
3987
- base: import_node_path8.default.dirname(fromFile),
4167
+ base: import_node_path9.default.dirname(fromFile),
3988
4168
  from: fromFile,
3989
4169
  onDependency: (p) => dependencies.push(p)
3990
4170
  });
@@ -3995,11 +4175,11 @@ async function compileTailwind(css, fromFile, projectRoot) {
3995
4175
  dependencies: [...dependencies, ...scanner.files]
3996
4176
  };
3997
4177
  }
3998
- var import_node_path8, import_node_module3, import_node_url3, TAILWIND_DIRECTIVE_RE, cached, cachedRoot;
4178
+ var import_node_path9, import_node_module3, import_node_url3, TAILWIND_DIRECTIVE_RE, cached, cachedRoot;
3999
4179
  var init_tailwind = __esm({
4000
4180
  "src/plugins/tailwind.ts"() {
4001
4181
  "use strict";
4002
- import_node_path8 = __toESM(require("path"), 1);
4182
+ import_node_path9 = __toESM(require("path"), 1);
4003
4183
  import_node_module3 = require("module");
4004
4184
  import_node_url3 = require("url");
4005
4185
  TAILWIND_DIRECTIVE_RE = /@(?:import\s+["']tailwindcss(?:\b|\/)|tailwind\b|theme\b|apply\b|plugin\b|source\b|utility\b|variant\b|custom-variant\b|reference\b)/;
@@ -4131,16 +4311,16 @@ function rewriteCssUrls(css, from, root) {
4131
4311
  if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
4132
4312
  return match;
4133
4313
  }
4134
- const resolved = import_node_path9.default.resolve(import_node_path9.default.dirname(from), url);
4135
- const relative = "/" + import_node_path9.default.relative(root, resolved).replace(/\\/g, "/");
4314
+ const resolved = import_node_path10.default.resolve(import_node_path10.default.dirname(from), url);
4315
+ const relative = "/" + import_node_path10.default.relative(root, resolved).replace(/\\/g, "/");
4136
4316
  return `url(${relative})`;
4137
4317
  });
4138
4318
  }
4139
- var import_node_path9, import_source_map_js;
4319
+ var import_node_path10, import_source_map_js;
4140
4320
  var init_css = __esm({
4141
4321
  "src/plugins/css.ts"() {
4142
4322
  "use strict";
4143
- import_node_path9 = __toESM(require("path"), 1);
4323
+ import_node_path10 = __toESM(require("path"), 1);
4144
4324
  import_source_map_js = require("source-map-js");
4145
4325
  init_css_engine();
4146
4326
  init_tailwind();
@@ -4259,8 +4439,8 @@ function vuePlugin(config, environmentName = "client") {
4259
4439
  let cached2 = descriptorCache.get(filePath);
4260
4440
  if (!cached2) {
4261
4441
  try {
4262
- const fs13 = await import("fs");
4263
- const rawSource = fs13.readFileSync(filePath, "utf-8");
4442
+ const fs14 = await import("fs");
4443
+ const rawSource = fs14.readFileSync(filePath, "utf-8");
4264
4444
  const transformedSfc = await applySourceTransform(
4265
4445
  vueOptions.transformSfc,
4266
4446
  rawSource,
@@ -4349,8 +4529,10 @@ function vuePlugin(config, environmentName = "client") {
4349
4529
  });
4350
4530
  const scopeId = hashId(id);
4351
4531
  const wantsSourceMap = !!config.build.sourcemap || transformedSfc.map != null;
4532
+ const vapor = resolveVaporMode(descriptor, vueOptions, sfc, config);
4352
4533
  let scriptCode = "";
4353
4534
  let scriptMap;
4535
+ let scriptBindings;
4354
4536
  if (descriptor.script || descriptor.scriptSetup) {
4355
4537
  const inlineTemplate = vueOptions.script?.inlineTemplate !== false;
4356
4538
  const compiled = sfc.compileScript(descriptor, {
@@ -4362,9 +4544,11 @@ function vuePlugin(config, environmentName = "client") {
4362
4544
  // 让 compileScript 产出 `const __sfc__ = ...`(而非默认的 `export default {...}`)。
4363
4545
  // 否则下方追加的 `__sfc__.render` / `__sfc__.__scopeId` / HMR 记录会引用一个
4364
4546
  // 不存在的 `__sfc__`,并与 compileScript 自带的 `export default` 形成双重默认导出。
4365
- genDefaultAs: "__sfc__"
4547
+ genDefaultAs: "__sfc__",
4548
+ vapor
4366
4549
  });
4367
4550
  scriptCode = compiled.content;
4551
+ scriptBindings = compiled.bindings;
4368
4552
  scriptMap = composeSourceMapChain(
4369
4553
  [compiled.map, transformedSfc.map],
4370
4554
  { filename: id, environmentName, type: "sfc" }
@@ -4378,7 +4562,9 @@ function vuePlugin(config, environmentName = "client") {
4378
4562
  }
4379
4563
  let templateCode = "";
4380
4564
  let templateMap;
4565
+ let templateMultiRoot;
4381
4566
  const scriptSetupIsInline = !!descriptor.scriptSetup && vueOptions.script?.inlineTemplate !== false;
4567
+ const isTemplateOnlyVapor = vapor && !descriptor.script && !descriptor.scriptSetup;
4382
4568
  if (descriptor.template && !scriptSetupIsInline) {
4383
4569
  const transformedTemplate = await applySourceTransform(
4384
4570
  vueOptions.transformTemplate,
@@ -4400,12 +4586,16 @@ function vuePlugin(config, environmentName = "client") {
4400
4586
  filename: id,
4401
4587
  id: scopeId,
4402
4588
  inMap: templateInputMap,
4589
+ vapor,
4403
4590
  compilerOptions: {
4404
4591
  ...customCompilerOptions,
4592
+ // Vapor 在 bindingMetadata 缺失时需要空对象(与 Vite / compiler-sfc 一致)
4593
+ bindingMetadata: customCompilerOptions.bindingMetadata ?? scriptBindings ?? (vapor ? {} : void 0),
4405
4594
  scopeId: `data-v-${scopeId}`
4406
4595
  }
4407
4596
  });
4408
4597
  templateCode = compiled.code;
4598
+ templateMultiRoot = compiled.multiRoot;
4409
4599
  if (wantsSourceMap || transformedTemplate.map != null) {
4410
4600
  templateMap = compiled.map;
4411
4601
  }
@@ -4443,12 +4633,20 @@ function vuePlugin(config, environmentName = "client") {
4443
4633
  outputNode.add(fragment);
4444
4634
  }
4445
4635
  };
4446
- append(scriptCode || "const __sfc__ = {}", scriptMap);
4636
+ append(
4637
+ scriptCode || (vapor ? "const __sfc__ = { __vapor: true }" : "const __sfc__ = {}"),
4638
+ scriptMap
4639
+ );
4447
4640
  if (templateCode) {
4448
4641
  append("\n");
4449
4642
  append(templateCode, templateMap);
4450
4643
  append("\n");
4451
4644
  append("\n__sfc__.render = render\n");
4645
+ if (isTemplateOnlyVapor && templateMultiRoot !== void 0) {
4646
+ append(`
4647
+ __sfc__.__multiRoot = ${JSON.stringify(templateMultiRoot)}
4648
+ `);
4649
+ }
4452
4650
  }
4453
4651
  if (descriptor.styles.length > 0) {
4454
4652
  for (let i = 0; i < descriptor.styles.length; i++) {
@@ -4457,6 +4655,16 @@ import "${id}?vue&type=style&index=${i}&lang.css"
4457
4655
  `);
4458
4656
  }
4459
4657
  }
4658
+ if (vapor) {
4659
+ append(
4660
+ `
4661
+ if (!globalThis.__NASTI_VAPOR_BETA_WARNED__) {
4662
+ globalThis.__NASTI_VAPOR_BETA_WARNED__ = true
4663
+ console.warn(${JSON.stringify(VAPOR_BETA_WARNING)})
4664
+ }
4665
+ `
4666
+ );
4667
+ }
4460
4668
  append(`
4461
4669
  __sfc__.__scopeId = "data-v-${scopeId}"
4462
4670
  `);
@@ -4516,6 +4724,32 @@ if (import.meta.hot) {
4516
4724
  }
4517
4725
  };
4518
4726
  }
4727
+ function resolveVaporMode(descriptor, vueOptions, sfc, config) {
4728
+ const requested = !!descriptor.vapor || !!vueOptions.features?.vapor && canForceVaporMode(descriptor);
4729
+ if (!requested) return false;
4730
+ if (!supportsVaporCompiler(sfc)) {
4731
+ config.logger.warnOnce(
4732
+ "[nasti:vue] Vapor Mode requires @vue/compiler-sfc >= 3.6. Install it: npm install @vue/compiler-sfc@^3.6.0-0"
4733
+ );
4734
+ return false;
4735
+ }
4736
+ config.logger.warnOnce(VAPOR_BETA_WARNING);
4737
+ return true;
4738
+ }
4739
+ function canForceVaporMode(descriptor) {
4740
+ if (typeof descriptor.filename === "string" && descriptor.filename.endsWith(".vue")) {
4741
+ if (descriptor.script && !descriptor.scriptSetup) return false;
4742
+ return !!(descriptor.scriptSetup || descriptor.template);
4743
+ }
4744
+ return true;
4745
+ }
4746
+ function supportsVaporCompiler(sfc) {
4747
+ const version = sfc.version;
4748
+ if (!version) return false;
4749
+ const [major, minor] = version.split(".").map((part) => Number.parseInt(part, 10));
4750
+ if (!Number.isFinite(major) || !Number.isFinite(minor)) return false;
4751
+ return major > 3 || major === 3 && minor >= 6;
4752
+ }
4519
4753
  async function applySourceTransform(transform2, source, context) {
4520
4754
  if (!transform2) return { code: source };
4521
4755
  const result = await transform2(source, context);
@@ -4576,7 +4810,7 @@ function warnUnchainableMap(context, reason) {
4576
4810
  function hashId(filename) {
4577
4811
  return import_node_crypto2.default.createHash("sha256").update(filename).digest("hex").slice(0, 8);
4578
4812
  }
4579
- var import_node_crypto2, import_source_map_js2, VUE_FILE_RE, VUE_QUERY_RE, debug3, compiler;
4813
+ var import_node_crypto2, import_source_map_js2, VUE_FILE_RE, VUE_QUERY_RE, debug3, VAPOR_BETA_WARNING, compiler;
4580
4814
  var init_vue = __esm({
4581
4815
  "src/plugins/vue.ts"() {
4582
4816
  "use strict";
@@ -4587,6 +4821,7 @@ var init_vue = __esm({
4587
4821
  VUE_FILE_RE = /\.vue$/;
4588
4822
  VUE_QUERY_RE = /\.vue\?vue&type=(script|template|style)(&index=\d+)?(&lang[.=]\w+)?/;
4589
4823
  debug3 = createDebugger("nasti:vue");
4824
+ VAPOR_BETA_WARNING = "Vapor Mode is a beta feature; Zixiao Labs and the Vue team do not provide guarantees against crashes in production environments, and it is not suitable for server-side rendering environments.";
4590
4825
  compiler = null;
4591
4826
  }
4592
4827
  });
@@ -4643,12 +4878,12 @@ function createModuleRunner(environment) {
4643
4878
  }
4644
4879
  return new NastiModuleRunner(environment);
4645
4880
  }
4646
- var import_node_path10, import_node_fs8, import_node_module4, import_node_url4, debug4, NODE_BUILTINS, NastiModuleRunner, AsyncFunction;
4881
+ var import_node_path11, import_node_fs9, import_node_module4, import_node_url4, debug4, NODE_BUILTINS, NastiModuleRunner, AsyncFunction;
4647
4882
  var init_runnable_environment = __esm({
4648
4883
  "src/server/runnable-environment.ts"() {
4649
4884
  "use strict";
4650
- import_node_path10 = __toESM(require("path"), 1);
4651
- import_node_fs8 = __toESM(require("fs"), 1);
4885
+ import_node_path11 = __toESM(require("path"), 1);
4886
+ import_node_fs9 = __toESM(require("fs"), 1);
4652
4887
  import_node_module4 = require("module");
4653
4888
  import_node_url4 = require("url");
4654
4889
  init_transformer();
@@ -4670,7 +4905,7 @@ var init_runnable_environment = __esm({
4670
4905
  this.config.mode,
4671
4906
  ssrDefineOverrides(environment.consumer)
4672
4907
  );
4673
- this.require = (0, import_node_module4.createRequire)(import_node_path10.default.join(this.config.root, "package.json"));
4908
+ this.require = (0, import_node_module4.createRequire)(import_node_path11.default.join(this.config.root, "package.json"));
4674
4909
  const handlers = {
4675
4910
  fetchModule: async (id, importer) => this.fetchModule(id, importer),
4676
4911
  getBuiltins: () => [/^node:/, ...import_node_module4.builtinModules]
@@ -4694,9 +4929,9 @@ var init_runnable_environment = __esm({
4694
4929
  this.cache.clear();
4695
4930
  }
4696
4931
  resolveToId(rawUrl) {
4697
- if (import_node_path10.default.isAbsolute(rawUrl) && import_node_fs8.default.existsSync(rawUrl.split("?")[0])) return rawUrl;
4932
+ if (import_node_path11.default.isAbsolute(rawUrl) && import_node_fs9.default.existsSync(rawUrl.split("?")[0])) return rawUrl;
4698
4933
  const clean = rawUrl.replace(/^\//, "");
4699
- return import_node_path10.default.resolve(this.config.root, clean);
4934
+ return import_node_path11.default.resolve(this.config.root, clean);
4700
4935
  }
4701
4936
  /**
4702
4937
  * fetchModule(invoke 契约方法):环境管线产出 runner 可执行代码。
@@ -4705,14 +4940,14 @@ var init_runnable_environment = __esm({
4705
4940
  */
4706
4941
  async fetchModule(id, importer) {
4707
4942
  if (NODE_BUILTINS.has(id)) return { externalize: id };
4708
- if (!id.startsWith(".") && !import_node_path10.default.isAbsolute(id) && !id.startsWith("\0")) {
4943
+ if (!id.startsWith(".") && !import_node_path11.default.isAbsolute(id) && !id.startsWith("\0")) {
4709
4944
  return { externalize: id };
4710
4945
  }
4711
4946
  const container = this.environment.pluginContainer;
4712
4947
  let resolvedId = id;
4713
4948
  if (id.startsWith(".") && importer) {
4714
4949
  const resolved = await container.resolveId(id, importer);
4715
- resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id : import_node_path10.default.resolve(import_node_path10.default.dirname(importer.split("?")[0]), id);
4950
+ resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id : import_node_path11.default.resolve(import_node_path11.default.dirname(importer.split("?")[0]), id);
4716
4951
  }
4717
4952
  resolvedId = this.completeExtension(resolvedId);
4718
4953
  const cleanId = resolvedId.split("?")[0];
@@ -4720,8 +4955,8 @@ var init_runnable_environment = __esm({
4720
4955
  const loaded = await container.load(resolvedId);
4721
4956
  if (loaded != null) {
4722
4957
  code = typeof loaded === "string" ? loaded : loaded.code;
4723
- } else if (import_node_fs8.default.existsSync(cleanId)) {
4724
- code = import_node_fs8.default.readFileSync(cleanId, "utf-8");
4958
+ } else if (import_node_fs9.default.existsSync(cleanId)) {
4959
+ code = import_node_fs9.default.readFileSync(cleanId, "utf-8");
4725
4960
  } else {
4726
4961
  throw new Error(`[nasti:ssr] cannot load module: ${resolvedId}`);
4727
4962
  }
@@ -4755,19 +4990,19 @@ var init_runnable_environment = __esm({
4755
4990
  completeExtension(id) {
4756
4991
  const clean = id.split("?")[0];
4757
4992
  const query = id.includes("?") ? id.slice(id.indexOf("?")) : "";
4758
- if (import_node_fs8.default.existsSync(clean) && import_node_fs8.default.statSync(clean).isFile()) return id;
4993
+ if (import_node_fs9.default.existsSync(clean) && import_node_fs9.default.statSync(clean).isFile()) return id;
4759
4994
  const jsMatch = clean.match(/^(.*)\.([mc]?)jsx?$/);
4760
4995
  if (jsMatch) {
4761
4996
  for (const tsExt of [`.${jsMatch[2]}ts`, `.${jsMatch[2]}tsx`]) {
4762
- if (import_node_fs8.default.existsSync(jsMatch[1] + tsExt)) return jsMatch[1] + tsExt + query;
4997
+ if (import_node_fs9.default.existsSync(jsMatch[1] + tsExt)) return jsMatch[1] + tsExt + query;
4763
4998
  }
4764
4999
  }
4765
5000
  for (const ext of this.config.resolve.extensions) {
4766
- if (import_node_fs8.default.existsSync(clean + ext)) return clean + ext + query;
5001
+ if (import_node_fs9.default.existsSync(clean + ext)) return clean + ext + query;
4767
5002
  }
4768
5003
  for (const ext of this.config.resolve.extensions) {
4769
- const indexPath = import_node_path10.default.join(clean, `index${ext}`);
4770
- if (import_node_fs8.default.existsSync(indexPath)) return indexPath;
5004
+ const indexPath = import_node_path11.default.join(clean, `index${ext}`);
5005
+ if (import_node_fs9.default.existsSync(indexPath)) return indexPath;
4771
5006
  }
4772
5007
  return id;
4773
5008
  }
@@ -4794,10 +5029,10 @@ var init_runnable_environment = __esm({
4794
5029
  return;
4795
5030
  }
4796
5031
  const ssrImport = async (dep) => {
4797
- if (NODE_BUILTINS.has(dep) || !dep.startsWith(".") && !import_node_path10.default.isAbsolute(dep) && !dep.startsWith("\0")) {
5032
+ if (NODE_BUILTINS.has(dep) || !dep.startsWith(".") && !import_node_path11.default.isAbsolute(dep) && !dep.startsWith("\0")) {
4798
5033
  return this.importExternal(dep);
4799
5034
  }
4800
- const depId = dep.startsWith(".") ? this.completeExtension(import_node_path10.default.resolve(import_node_path10.default.dirname(fetched.id.split("?")[0]), dep)) : this.completeExtension(dep);
5035
+ const depId = dep.startsWith(".") ? this.completeExtension(import_node_path11.default.resolve(import_node_path11.default.dirname(fetched.id.split("?")[0]), dep)) : this.completeExtension(dep);
4801
5036
  return this.instantiate(depId);
4802
5037
  };
4803
5038
  const ssrExportAll = (sourceModule) => {
@@ -4829,7 +5064,7 @@ var init_runnable_environment = __esm({
4829
5064
  }
4830
5065
  async importExternal(spec) {
4831
5066
  try {
4832
- return await (spec.startsWith("node:") || !import_node_path10.default.isAbsolute(spec) ? import(this.resolveExternalSpecifier(spec)) : import((0, import_node_url4.pathToFileURL)(spec).href));
5067
+ return await (spec.startsWith("node:") || !import_node_path11.default.isAbsolute(spec) ? import(this.resolveExternalSpecifier(spec)) : import((0, import_node_url4.pathToFileURL)(spec).href));
4833
5068
  } catch (err) {
4834
5069
  throw new Error(`[nasti:ssr] failed to import external "${spec}": ${err.message}`);
4835
5070
  }
@@ -4889,7 +5124,7 @@ function reportBuildOutput(output, config, logger) {
4889
5124
  if (compressed && content != null) {
4890
5125
  gzip = (0, import_node_zlib.gzipSync)(typeof content === "string" ? Buffer.from(content) : content).byteLength;
4891
5126
  }
4892
- const ext = import_node_path11.default.extname(file.fileName);
5127
+ const ext = import_node_path12.default.extname(file.fileName);
4893
5128
  const group = file.type === "chunk" ? "js" : ext === ".css" ? "css" : "assets";
4894
5129
  entries.push({ name: file.fileName, size, gzip, group });
4895
5130
  }
@@ -4923,11 +5158,11 @@ function warnLargeChunks(output, config, logger) {
4923
5158
  )
4924
5159
  );
4925
5160
  }
4926
- var import_node_path11, import_node_zlib, import_picocolors5, debug5, numberFormatter;
5161
+ var import_node_path12, import_node_zlib, import_picocolors5, debug5, numberFormatter;
4927
5162
  var init_reporter = __esm({
4928
5163
  "src/build/reporter.ts"() {
4929
5164
  "use strict";
4930
- import_node_path11 = __toESM(require("path"), 1);
5165
+ import_node_path12 = __toESM(require("path"), 1);
4931
5166
  import_node_zlib = require("zlib");
4932
5167
  import_picocolors5 = __toESM(require("picocolors"), 1);
4933
5168
  init_debug();
@@ -4943,7 +5178,7 @@ var init_reporter = __esm({
4943
5178
  function createBuildAppContext(config, results) {
4944
5179
  const output = [];
4945
5180
  const emitted = /* @__PURE__ */ new Set();
4946
- const outDir = import_node_path12.default.resolve(config.root, config.build.outDir);
5181
+ const outDir = import_node_path13.default.resolve(config.root, config.build.outDir);
4947
5182
  let environmentArtifacts;
4948
5183
  return {
4949
5184
  config,
@@ -4999,14 +5234,14 @@ function createBuildAppContext(config, results) {
4999
5234
  if (environmentArtifacts.has(collisionKey)) {
5000
5235
  throw new Error(`[nasti] app artifact conflicts with environment output: ${fileName}`);
5001
5236
  }
5002
- const target = import_node_path12.default.resolve(outDir, ...fileName.split("/"));
5003
- const relative = import_node_path12.default.relative(outDir, target);
5004
- if (relative.startsWith("..") || import_node_path12.default.isAbsolute(relative)) {
5237
+ const target = import_node_path13.default.resolve(outDir, ...fileName.split("/"));
5238
+ const relative = import_node_path13.default.relative(outDir, target);
5239
+ if (relative.startsWith("..") || import_node_path13.default.isAbsolute(relative)) {
5005
5240
  throw new Error(`[nasti] app artifact must stay inside build.outDir: ${file.fileName}`);
5006
5241
  }
5007
5242
  assertNoSymlinkComponents(outDir, fileName);
5008
- import_node_fs9.default.mkdirSync(import_node_path12.default.dirname(target), { recursive: true });
5009
- import_node_fs9.default.writeFileSync(target, file.source);
5243
+ import_node_fs10.default.mkdirSync(import_node_path13.default.dirname(target), { recursive: true });
5244
+ import_node_fs10.default.writeFileSync(target, file.source);
5010
5245
  const artifact = {
5011
5246
  ...file,
5012
5247
  fileName,
@@ -5022,10 +5257,10 @@ function joinPublicPath(base, fileName) {
5022
5257
  return `${base.endsWith("/") ? base : `${base}/`}${fileName.replace(/^\//, "")}`;
5023
5258
  }
5024
5259
  function normalizeEnvironmentFileName(fileName) {
5025
- return import_node_path12.default.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
5260
+ return import_node_path13.default.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
5026
5261
  }
5027
5262
  function isInvalidEnvironmentFileName(fileName) {
5028
- return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || import_node_path12.default.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
5263
+ return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || import_node_path13.default.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
5029
5264
  }
5030
5265
  function normalizeAppFileName(fileName) {
5031
5266
  const normalized = normalizeEnvironmentFileName(fileName);
@@ -5042,14 +5277,14 @@ function collectEnvironmentArtifacts(config, results, appOutDir) {
5042
5277
  for (const [environmentName, result] of Object.entries(results)) {
5043
5278
  const environment = config.environments[environmentName];
5044
5279
  if (!environment) continue;
5045
- const environmentOutDir = import_node_path12.default.resolve(config.root, environment.build.outDir);
5280
+ const environmentOutDir = import_node_path13.default.resolve(config.root, environment.build.outDir);
5046
5281
  for (const artifact of result.output) {
5047
- const artifactPath = import_node_path12.default.resolve(
5282
+ const artifactPath = import_node_path13.default.resolve(
5048
5283
  environmentOutDir,
5049
5284
  ...normalizeEnvironmentFileName(artifact.fileName).split("/")
5050
5285
  );
5051
- const relative = import_node_path12.default.relative(appOutDir, artifactPath);
5052
- if (!relative.startsWith("..") && !import_node_path12.default.isAbsolute(relative)) {
5286
+ const relative = import_node_path13.default.relative(appOutDir, artifactPath);
5287
+ if (!relative.startsWith("..") && !import_node_path13.default.isAbsolute(relative)) {
5053
5288
  occupied.add(artifactCollisionKey(relative));
5054
5289
  }
5055
5290
  }
@@ -5059,10 +5294,10 @@ function collectEnvironmentArtifacts(config, results, appOutDir) {
5059
5294
  function assertNoSymlinkComponents(outDir, fileName) {
5060
5295
  let current = outDir;
5061
5296
  for (const segment of fileName.split("/")) {
5062
- current = import_node_path12.default.join(current, segment);
5297
+ current = import_node_path13.default.join(current, segment);
5063
5298
  let stats;
5064
5299
  try {
5065
- stats = import_node_fs9.default.lstatSync(current);
5300
+ stats = import_node_fs10.default.lstatSync(current);
5066
5301
  } catch (error) {
5067
5302
  if (error.code === "ENOENT") continue;
5068
5303
  throw error;
@@ -5080,12 +5315,12 @@ function inferEnvironmentEntries(output) {
5080
5315
  }
5081
5316
  return Object.keys(entries).length > 0 ? entries : void 0;
5082
5317
  }
5083
- var import_node_fs9, import_node_path12;
5318
+ var import_node_fs10, import_node_path13;
5084
5319
  var init_build_app_context = __esm({
5085
5320
  "src/core/build-app-context.ts"() {
5086
5321
  "use strict";
5087
- import_node_fs9 = __toESM(require("fs"), 1);
5088
- import_node_path12 = __toESM(require("path"), 1);
5322
+ import_node_fs10 = __toESM(require("fs"), 1);
5323
+ import_node_path13 = __toESM(require("path"), 1);
5089
5324
  }
5090
5325
  });
5091
5326
 
@@ -5102,7 +5337,7 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
5102
5337
  const config = environment.config;
5103
5338
  const envOptions = environment.options;
5104
5339
  const isServer = environment.consumer === "server";
5105
- const outDir = import_node_path13.default.resolve(config.root, envOptions.build.outDir);
5340
+ const outDir = import_node_path14.default.resolve(config.root, envOptions.build.outDir);
5106
5341
  const assetsDir = envOptions.build.assetsDir;
5107
5342
  const {
5108
5343
  output: userOutput,
@@ -5142,7 +5377,7 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
5142
5377
  // 相对/绝对/虚拟模块照常打包。需要内联依赖时经 rolldownOptions.external 覆盖。
5143
5378
  external: restInputOptions.external ?? ((id) => {
5144
5379
  if (NODE_BUILTINS2.has(id)) return true;
5145
- return !id.startsWith(".") && !import_node_path13.default.isAbsolute(id) && !id.startsWith("\0");
5380
+ return !id.startsWith(".") && !import_node_path14.default.isAbsolute(id) && !id.startsWith("\0");
5146
5381
  })
5147
5382
  } : {}
5148
5383
  };
@@ -5299,11 +5534,11 @@ function prepareBuildOutputDirectories(config, buildableNames) {
5299
5534
  const protectedPaths = /* @__PURE__ */ new Set();
5300
5535
  const clientIsBuilt = buildableNames.includes("client");
5301
5536
  if (!clientIsBuilt && config.build.emptyOutDir) {
5302
- directories.add(import_node_path13.default.resolve(config.root, config.build.outDir));
5537
+ directories.add(import_node_path14.default.resolve(config.root, config.build.outDir));
5303
5538
  }
5304
5539
  for (const name of buildableNames) {
5305
5540
  const environment = config.environments[name];
5306
- const outDir = import_node_path13.default.resolve(config.root, environment.build.outDir);
5541
+ const outDir = import_node_path14.default.resolve(config.root, environment.build.outDir);
5307
5542
  if (!environment.build.emptyOutDir) {
5308
5543
  protectedPaths.add(outDir);
5309
5544
  continue;
@@ -5311,8 +5546,8 @@ function prepareBuildOutputDirectories(config, buildableNames) {
5311
5546
  if (!environment.driver) directories.add(outDir);
5312
5547
  }
5313
5548
  const containsPath = (parent, child) => {
5314
- const relative = import_node_path13.default.relative(parent, child);
5315
- return relative === "" || !relative.startsWith("..") && !import_node_path13.default.isAbsolute(relative);
5549
+ const relative = import_node_path14.default.relative(parent, child);
5550
+ return relative === "" || !relative.startsWith("..") && !import_node_path14.default.isAbsolute(relative);
5316
5551
  };
5317
5552
  const roots = [...directories].filter(
5318
5553
  (directory) => ![...protectedPaths].some((protectedPath) => containsPath(directory, protectedPath))
@@ -5320,7 +5555,7 @@ function prepareBuildOutputDirectories(config, buildableNames) {
5320
5555
  (directory, index2, all) => !all.slice(0, index2).some((parent) => containsPath(parent, directory))
5321
5556
  );
5322
5557
  for (const directory of roots) {
5323
- if (import_node_fs10.default.existsSync(directory)) import_node_fs10.default.rmSync(directory, { recursive: true, force: true });
5558
+ if (import_node_fs11.default.existsSync(directory)) import_node_fs11.default.rmSync(directory, { recursive: true, force: true });
5324
5559
  }
5325
5560
  }
5326
5561
  function assertDriverBuildResult(environment, result) {
@@ -5339,7 +5574,7 @@ function resolveClientEntries(config, html) {
5339
5574
  if (configuredEntries.length > 0) return configuredEntries;
5340
5575
  const entryPoints = [];
5341
5576
  const htmlFile = config.environments.client?.html;
5342
- const htmlDir = htmlFile ? import_node_path13.default.dirname(htmlFile) : config.root;
5577
+ const htmlDir = htmlFile ? import_node_path14.default.dirname(htmlFile) : config.root;
5343
5578
  if (html) {
5344
5579
  const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
5345
5580
  for (const match of scriptMatches) {
@@ -5347,7 +5582,7 @@ function resolveClientEntries(config, html) {
5347
5582
  if (src && !src.startsWith("http")) {
5348
5583
  const cleanSrc = src.split(/[?#]/, 1)[0];
5349
5584
  entryPoints.push(
5350
- cleanSrc.startsWith("/") ? import_node_path13.default.resolve(config.root, cleanSrc.replace(/^\//, "")) : import_node_path13.default.resolve(htmlDir, cleanSrc)
5585
+ cleanSrc.startsWith("/") ? import_node_path14.default.resolve(config.root, cleanSrc.replace(/^\//, "")) : import_node_path14.default.resolve(htmlDir, cleanSrc)
5351
5586
  );
5352
5587
  }
5353
5588
  }
@@ -5355,8 +5590,8 @@ function resolveClientEntries(config, html) {
5355
5590
  if (entryPoints.length === 0) {
5356
5591
  const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
5357
5592
  for (const entry of fallbackEntries) {
5358
- const fullPath = import_node_path13.default.resolve(config.root, entry);
5359
- if (import_node_fs10.default.existsSync(fullPath)) {
5593
+ const fullPath = import_node_path14.default.resolve(config.root, entry);
5594
+ if (import_node_fs11.default.existsSync(fullPath)) {
5360
5595
  entryPoints.push(fullPath);
5361
5596
  break;
5362
5597
  }
@@ -5385,7 +5620,7 @@ async function build(inlineConfig = {}) {
5385
5620
  const startTime = performance.now();
5386
5621
  logger.info(
5387
5622
  import_picocolors6.default.cyan(`
5388
- nasti v${"2.4.2"} `) + import_picocolors6.default.green(`building for ${config.mode}...`)
5623
+ nasti v${"2.4.4"} `) + import_picocolors6.default.green(`building for ${config.mode}...`)
5389
5624
  );
5390
5625
  debug6?.(`root: ${config.root}`);
5391
5626
  const buildableNames = Object.keys(config.environments).filter((name) => {
@@ -5460,7 +5695,7 @@ nasti v${"2.4.2"} `) + import_picocolors6.default.green(`building for ${config.m
5460
5695
  }
5461
5696
  async function buildClientEnvironment(config) {
5462
5697
  const logger = config.logger;
5463
- const outDir = import_node_path13.default.resolve(config.root, config.build.outDir);
5698
+ const outDir = import_node_path14.default.resolve(config.root, config.build.outDir);
5464
5699
  const cssEngine = createCssEngine();
5465
5700
  const pluginList = resolvePluginList(config, config.plugins, {
5466
5701
  cssEngine,
@@ -5483,8 +5718,8 @@ async function buildClientEnvironment(config) {
5483
5718
  assertDriverBuildResult(clientEnv, result);
5484
5719
  return { environment: clientEnv, result: finalizeEnvironmentResult(clientEnv, result) };
5485
5720
  }
5486
- import_node_fs10.default.mkdirSync(outDir, { recursive: true });
5487
- const htmlFile = config.environments.client.html ?? import_node_path13.default.resolve(config.root, "index.html");
5721
+ import_node_fs11.default.mkdirSync(outDir, { recursive: true });
5722
+ const htmlFile = config.environments.client.html ?? import_node_path14.default.resolve(config.root, "index.html");
5488
5723
  const html = await readHtmlFile(config.root, htmlFile);
5489
5724
  const entryPoints = resolveClientEntries(config, html);
5490
5725
  if (entryPoints.length === 0) {
@@ -5534,7 +5769,7 @@ async function buildClientEnvironment(config) {
5534
5769
  );
5535
5770
  }
5536
5771
  }
5537
- import_node_fs10.default.writeFileSync(import_node_path13.default.resolve(outDir, "index.html"), processedHtml);
5772
+ import_node_fs11.default.writeFileSync(import_node_path14.default.resolve(outDir, "index.html"), processedHtml);
5538
5773
  }
5539
5774
  if (!nativeReporter && config.logLevel !== "silent") {
5540
5775
  reportBuildOutput(output, config, logger);
@@ -5588,7 +5823,7 @@ async function buildServerEnvironment(config, name) {
5588
5823
  }
5589
5824
  }
5590
5825
  for (const entry of envOptions.entry) {
5591
- if (!import_node_fs10.default.existsSync(entry)) {
5826
+ if (!import_node_fs11.default.existsSync(entry)) {
5592
5827
  await environment.close();
5593
5828
  throw new Error(`[nasti] environment "${name}" entry not found: ${entry}`);
5594
5829
  }
@@ -5602,13 +5837,13 @@ async function buildServerEnvironment(config, name) {
5602
5837
  envOptions.entry,
5603
5838
  rolldownPlugins
5604
5839
  );
5605
- import_node_fs10.default.mkdirSync(outDir, { recursive: true });
5840
+ import_node_fs11.default.mkdirSync(outDir, { recursive: true });
5606
5841
  const bundle2 = await (0, import_rolldown.rolldown)(inputOptions);
5607
5842
  const { output } = await bundle2.write(outputOptions);
5608
5843
  await bundle2.close();
5609
5844
  if (cssEngine) environment.setBuildMetadata({ css: getCssMetadata(cssEngine) });
5610
5845
  logger.info(
5611
- import_picocolors6.default.dim(` [${name}] `) + output.map((o) => import_node_path13.default.join(envOptions.build.outDir, o.fileName)).join(import_picocolors6.default.dim(", "))
5846
+ import_picocolors6.default.dim(` [${name}] `) + output.map((o) => import_node_path14.default.join(envOptions.build.outDir, o.fileName)).join(import_picocolors6.default.dim(", "))
5612
5847
  );
5613
5848
  return {
5614
5849
  environment,
@@ -5640,9 +5875,9 @@ function escapeRegExp(string) {
5640
5875
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5641
5876
  }
5642
5877
  function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, urlPrefix) {
5643
- const rootRelative = import_node_path13.default.relative(config.root, facadeModuleId).split(import_node_path13.default.sep).join("/");
5644
- const resolvedHtmlFile = import_node_path13.default.resolve(config.root, htmlFile);
5645
- const htmlRelative = import_node_path13.default.relative(import_node_path13.default.dirname(resolvedHtmlFile), facadeModuleId).split(import_node_path13.default.sep).join("/");
5878
+ const rootRelative = import_node_path14.default.relative(config.root, facadeModuleId).split(import_node_path14.default.sep).join("/");
5879
+ const resolvedHtmlFile = import_node_path14.default.resolve(config.root, htmlFile);
5880
+ const htmlRelative = import_node_path14.default.relative(import_node_path14.default.dirname(resolvedHtmlFile), facadeModuleId).split(import_node_path14.default.sep).join("/");
5646
5881
  const candidates = /* @__PURE__ */ new Set([
5647
5882
  rootRelative,
5648
5883
  `/${rootRelative}`,
@@ -5658,12 +5893,12 @@ function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, ur
5658
5893
  }
5659
5894
  return processed;
5660
5895
  }
5661
- var import_node_path13, import_node_fs10, import_node_module5, import_rolldown, import_picocolors6, debug6, NODE_BUILTINS2;
5896
+ var import_node_path14, import_node_fs11, import_node_module5, import_rolldown, import_picocolors6, debug6, NODE_BUILTINS2;
5662
5897
  var init_build = __esm({
5663
5898
  "src/build/index.ts"() {
5664
5899
  "use strict";
5665
- import_node_path13 = __toESM(require("path"), 1);
5666
- import_node_fs10 = __toESM(require("fs"), 1);
5900
+ import_node_path14 = __toESM(require("path"), 1);
5901
+ import_node_fs11 = __toESM(require("fs"), 1);
5667
5902
  import_node_module5 = require("module");
5668
5903
  import_rolldown = require("rolldown");
5669
5904
  init_config();
@@ -5769,7 +6004,7 @@ async function createBundledDevServer(opts) {
5769
6004
  }
5770
6005
  const url = `/${patchPath}`;
5771
6006
  logger.info(
5772
- import_picocolors7.default.green("hmr update ") + import_picocolors7.default.dim(changedFiles.map((f) => import_node_path14.default.relative(config.root, f)).join(", ")),
6007
+ import_picocolors7.default.green("hmr update ") + import_picocolors7.default.dim(changedFiles.map((f) => import_node_path15.default.relative(config.root, f)).join(", ")),
5773
6008
  { timestamp: true }
5774
6009
  );
5775
6010
  sendTo(clientId, { type: "hmr:update", path: url, url });
@@ -5924,7 +6159,7 @@ async function createBundledDevServer(opts) {
5924
6159
  return;
5925
6160
  }
5926
6161
  res.setHeader("ETag", hit.etag);
5927
- res.setHeader("Content-Type", MIME_TYPES[import_node_path14.default.extname(fileName)] ?? "application/octet-stream");
6162
+ res.setHeader("Content-Type", MIME_TYPES[import_node_path15.default.extname(fileName)] ?? "application/octet-stream");
5928
6163
  res.setHeader("Cache-Control", "no-cache");
5929
6164
  res.once("finish", () => {
5930
6165
  void engine.notifyPayloadDelivered(fileName).catch(
@@ -5965,7 +6200,7 @@ function stripCatchAllLoad(plugins) {
5965
6200
  );
5966
6201
  }
5967
6202
  function createReactRefreshRuntimePlugin(entryPoints) {
5968
- const entryIds = new Set(entryPoints.map((p) => import_node_path14.default.resolve(p)));
6203
+ const entryIds = new Set(entryPoints.map((p) => import_node_path15.default.resolve(p)));
5969
6204
  return {
5970
6205
  name: "nasti:bundled-react-refresh",
5971
6206
  resolveId(source) {
@@ -5983,7 +6218,7 @@ function createReactRefreshRuntimePlugin(entryPoints) {
5983
6218
  return null;
5984
6219
  },
5985
6220
  transform(code, id) {
5986
- if (!entryIds.has(import_node_path14.default.resolve(id.split("?")[0]))) return null;
6221
+ if (!entryIds.has(import_node_path15.default.resolve(id.split("?")[0]))) return null;
5987
6222
  return { code: `import ${JSON.stringify(PREAMBLE_SPEC)};
5988
6223
  ${code}`, map: null };
5989
6224
  }
@@ -6030,11 +6265,11 @@ async function renderBundledIndexHtml(html, config, entryFileNames) {
6030
6265
  }
6031
6266
  return processed;
6032
6267
  }
6033
- var import_node_path14, import_node_crypto3, import_ws2, import_picocolors7, debug7, MIME_TYPES, MemoryFiles, PREAMBLE_SPEC, RESOLVED_PREAMBLE_ID, REFRESH_RUNTIME_URL, BUNDLED_PREAMBLE_CODE, WRAPPER_RUNTIME_HELPERS;
6268
+ var import_node_path15, import_node_crypto3, import_ws2, import_picocolors7, debug7, MIME_TYPES, MemoryFiles, PREAMBLE_SPEC, RESOLVED_PREAMBLE_ID, REFRESH_RUNTIME_URL, BUNDLED_PREAMBLE_CODE, WRAPPER_RUNTIME_HELPERS;
6034
6269
  var init_dev_engine = __esm({
6035
6270
  "src/server/bundled/dev-engine.ts"() {
6036
6271
  "use strict";
6037
- import_node_path14 = __toESM(require("path"), 1);
6272
+ import_node_path15 = __toESM(require("path"), 1);
6038
6273
  import_node_crypto3 = __toESM(require("crypto"), 1);
6039
6274
  import_ws2 = require("ws");
6040
6275
  import_picocolors7 = __toESM(require("picocolors"), 1);
@@ -6244,20 +6479,39 @@ async function createServer(inlineConfig = {}) {
6244
6479
  app.use(bundledServer.middleware);
6245
6480
  }
6246
6481
  const ignoredSegments = /* @__PURE__ */ new Set(["node_modules", ".git", ".nasti"]);
6247
- const outDirAbs = import_node_path15.default.resolve(config.root, config.build.outDir);
6248
- const watcher = (0, import_chokidar.watch)(config.root, {
6482
+ const outDirAbs = import_node_path16.default.resolve(config.root, config.build.outDir);
6483
+ const linkedPackageRoots = getLinkedPackageRoots(config.root).filter(
6484
+ (r) => r !== config.root && !isUnderRoot(config.root, r)
6485
+ );
6486
+ const watchTargets = [config.root, ...linkedPackageRoots];
6487
+ const watcher = (0, import_chokidar.watch)(watchTargets, {
6249
6488
  ignored: (filePath) => {
6250
- if (filePath === config.root) return false;
6251
- if (filePath === outDirAbs || filePath.startsWith(outDirAbs + import_node_path15.default.sep)) return true;
6252
- const rel = import_node_path15.default.relative(config.root, filePath);
6253
- if (!rel || rel.startsWith("..") || import_node_path15.default.isAbsolute(rel)) return false;
6254
- for (const seg of rel.split(import_node_path15.default.sep)) {
6255
- if (ignoredSegments.has(seg)) return true;
6489
+ if (filePath === outDirAbs || filePath.startsWith(outDirAbs + import_node_path16.default.sep)) return true;
6490
+ for (const watchRoot of watchTargets) {
6491
+ if (filePath === watchRoot) return false;
6492
+ const rel = import_node_path16.default.relative(watchRoot, filePath);
6493
+ if (!rel || rel.startsWith("..") || import_node_path16.default.isAbsolute(rel)) continue;
6494
+ for (const seg of rel.split(import_node_path16.default.sep)) {
6495
+ if (ignoredSegments.has(seg)) return true;
6496
+ }
6497
+ return false;
6256
6498
  }
6257
6499
  return false;
6258
6500
  },
6259
6501
  ignoreInitial: true
6260
6502
  });
6503
+ await new Promise((resolve, reject) => {
6504
+ const onReady = () => {
6505
+ watcher.off("error", onError);
6506
+ resolve();
6507
+ };
6508
+ const onError = (err) => {
6509
+ watcher.off("ready", onReady);
6510
+ reject(err);
6511
+ };
6512
+ watcher.once("ready", onReady);
6513
+ watcher.once("error", onError);
6514
+ });
6261
6515
  let server;
6262
6516
  const environmentServices = {};
6263
6517
  let environmentDriversStarted = false;
@@ -6369,16 +6623,25 @@ async function createServer(inlineConfig = {}) {
6369
6623
  });
6370
6624
  };
6371
6625
  watcher.on("change", (file) => {
6626
+ if (file.includes(`${import_node_path16.default.sep}node_modules${import_node_path16.default.sep}`) || file.endsWith(`${import_node_path16.default.sep}node_modules`)) {
6627
+ clearLinkedPackageRootsCache();
6628
+ }
6372
6629
  ssrRunner?.invalidateFile(file);
6373
6630
  queueClientEnvironmentUpdate(file);
6374
6631
  notifyEnvironmentDrivers(file, "change");
6375
6632
  });
6376
6633
  watcher.on("add", (file) => {
6634
+ if (file.includes(`${import_node_path16.default.sep}node_modules${import_node_path16.default.sep}`) || file.endsWith(`${import_node_path16.default.sep}node_modules`)) {
6635
+ clearLinkedPackageRootsCache();
6636
+ }
6377
6637
  ssrRunner?.invalidateFile(file);
6378
6638
  queueClientEnvironmentUpdate(file);
6379
6639
  notifyEnvironmentDrivers(file, "add");
6380
6640
  });
6381
6641
  watcher.on("unlink", (file) => {
6642
+ if (file.includes(`${import_node_path16.default.sep}node_modules${import_node_path16.default.sep}`) || file.endsWith(`${import_node_path16.default.sep}node_modules`)) {
6643
+ clearLinkedPackageRootsCache();
6644
+ }
6382
6645
  ssrRunner?.invalidateFile(file);
6383
6646
  notifyEnvironmentDrivers(file, "unlink");
6384
6647
  });
@@ -6408,7 +6671,7 @@ async function createServer(inlineConfig = {}) {
6408
6671
  const readyIn = Math.ceil(performance.now() - startTime);
6409
6672
  logger.info(
6410
6673
  `
6411
- ${import_picocolors8.default.cyan(import_picocolors8.default.bold("NASTI"))} ${import_picocolors8.default.cyan(`v${"2.4.2"}`)} ${import_picocolors8.default.dim("ready in")} ${import_picocolors8.default.bold(readyIn)} ${import_picocolors8.default.dim("ms")}
6674
+ ${import_picocolors8.default.cyan(import_picocolors8.default.bold("NASTI"))} ${import_picocolors8.default.cyan(`v${"2.4.4"}`)} ${import_picocolors8.default.dim("ready in")} ${import_picocolors8.default.bold(readyIn)} ${import_picocolors8.default.dim("ms")}
6412
6675
  `
6413
6676
  );
6414
6677
  printServerUrls(
@@ -6505,7 +6768,7 @@ async function createServer(inlineConfig = {}) {
6505
6768
  throw error;
6506
6769
  }
6507
6770
  app.use(transformMiddleware(transformContexts.get("client")));
6508
- const publicDir = import_node_path15.default.resolve(config.root, "public");
6771
+ const publicDir = import_node_path16.default.resolve(config.root, "public");
6509
6772
  app.use((0, import_sirv.default)(publicDir, { dev: true, etag: true }));
6510
6773
  app.use((0, import_sirv.default)(config.root, { dev: true, etag: true }));
6511
6774
  const postMiddlewares = [];
@@ -6531,12 +6794,12 @@ function getNetworkAddress() {
6531
6794
  }
6532
6795
  return "localhost";
6533
6796
  }
6534
- var import_node_http, import_node_path15, import_node_os, import_connect, import_sirv, import_chokidar, import_picocolors8;
6797
+ var import_node_http, import_node_path16, import_node_os, import_connect, import_sirv, import_chokidar, import_picocolors8;
6535
6798
  var init_server = __esm({
6536
6799
  "src/server/index.ts"() {
6537
6800
  "use strict";
6538
6801
  import_node_http = __toESM(require("http"), 1);
6539
- import_node_path15 = __toESM(require("path"), 1);
6802
+ import_node_path16 = __toESM(require("path"), 1);
6540
6803
  import_node_os = __toESM(require("os"), 1);
6541
6804
  import_connect = __toESM(require("connect"), 1);
6542
6805
  import_sirv = __toESM(require("sirv"), 1);
@@ -6552,6 +6815,7 @@ var init_server = __esm({
6552
6815
  init_builtins();
6553
6816
  init_plugin_api();
6554
6817
  init_env();
6818
+ init_fs_allow();
6555
6819
  }
6556
6820
  });
6557
6821
 
@@ -6606,16 +6870,16 @@ async function buildElectron(inlineConfig = {}) {
6606
6870
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
6607
6871
  const startTime = performance.now();
6608
6872
  assertElectronVersion(config);
6609
- console.log(import_picocolors9.default.cyan("\n\u26A1 nasti build (electron)") + import_picocolors9.default.dim(` v${"2.4.2"}`));
6873
+ console.log(import_picocolors9.default.cyan("\n\u26A1 nasti build (electron)") + import_picocolors9.default.dim(` v${"2.4.4"}`));
6610
6874
  console.log(import_picocolors9.default.dim(` root: ${config.root}`));
6611
6875
  console.log(import_picocolors9.default.dim(` mode: ${config.mode}`));
6612
6876
  console.log(import_picocolors9.default.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
6613
- const outDir = import_node_path16.default.resolve(config.root, config.build.outDir);
6614
- if (config.build.emptyOutDir && import_node_fs11.default.existsSync(outDir)) {
6615
- import_node_fs11.default.rmSync(outDir, { recursive: true, force: true });
6877
+ const outDir = import_node_path17.default.resolve(config.root, config.build.outDir);
6878
+ if (config.build.emptyOutDir && import_node_fs12.default.existsSync(outDir)) {
6879
+ import_node_fs12.default.rmSync(outDir, { recursive: true, force: true });
6616
6880
  }
6617
- import_node_fs11.default.mkdirSync(outDir, { recursive: true });
6618
- const rendererOutDir = import_node_path16.default.join(outDir, "renderer");
6881
+ import_node_fs12.default.mkdirSync(outDir, { recursive: true });
6882
+ const rendererOutDir = import_node_path17.default.join(outDir, "renderer");
6619
6883
  const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
6620
6884
  await build2(createElectronRendererConfig(config, inlineConfig, {
6621
6885
  build: {
@@ -6624,8 +6888,8 @@ async function buildElectron(inlineConfig = {}) {
6624
6888
  emptyOutDir: false
6625
6889
  }
6626
6890
  }));
6627
- const mainEntry = import_node_path16.default.resolve(config.root, config.electron.main);
6628
- if (!import_node_fs11.default.existsSync(mainEntry)) {
6891
+ const mainEntry = import_node_path17.default.resolve(config.root, config.electron.main);
6892
+ if (!import_node_fs12.default.existsSync(mainEntry)) {
6629
6893
  throw new Error(
6630
6894
  `Electron main entry not found: ${config.electron.main}
6631
6895
  \u5728 nasti.config.ts \u7684 electron.main \u6307\u5B9A\u4E3B\u8FDB\u7A0B\u5165\u53E3\u6587\u4EF6\u3002`
@@ -6639,11 +6903,11 @@ async function buildElectron(inlineConfig = {}) {
6639
6903
  const preloadEntries = normalizePreload(config.electron.preload, config.root);
6640
6904
  const preloadFiles = [];
6641
6905
  for (const entry of preloadEntries) {
6642
- if (!import_node_fs11.default.existsSync(entry)) {
6906
+ if (!import_node_fs12.default.existsSync(entry)) {
6643
6907
  console.warn(import_picocolors9.default.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
6644
6908
  continue;
6645
6909
  }
6646
- const base = import_node_path16.default.basename(entry).replace(/\.[^.]+$/, "");
6910
+ const base = import_node_path17.default.basename(entry).replace(/\.[^.]+$/, "");
6647
6911
  const out = outFileName(outDir, base, config.electron.preloadFormat);
6648
6912
  await bundleNode(config, entry, {
6649
6913
  outFile: out,
@@ -6655,10 +6919,10 @@ async function buildElectron(inlineConfig = {}) {
6655
6919
  const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
6656
6920
  console.log(import_picocolors9.default.green(`
6657
6921
  \u2713 Electron build complete in ${elapsed}s`));
6658
- console.log(import_picocolors9.default.dim(` renderer: ${import_node_path16.default.relative(config.root, rendererOutDir)}/`));
6659
- console.log(import_picocolors9.default.dim(` main: ${import_node_path16.default.relative(config.root, mainFile)}`));
6922
+ console.log(import_picocolors9.default.dim(` renderer: ${import_node_path17.default.relative(config.root, rendererOutDir)}/`));
6923
+ console.log(import_picocolors9.default.dim(` main: ${import_node_path17.default.relative(config.root, mainFile)}`));
6660
6924
  for (const pf of preloadFiles) {
6661
- console.log(import_picocolors9.default.dim(` preload: ${import_node_path16.default.relative(config.root, pf)}`));
6925
+ console.log(import_picocolors9.default.dim(` preload: ${import_node_path17.default.relative(config.root, pf)}`));
6662
6926
  }
6663
6927
  console.log();
6664
6928
  return { rendererOutDir, mainFile, preloadFiles };
@@ -6696,7 +6960,7 @@ async function bundleNode(config, entry, opts) {
6696
6960
  },
6697
6961
  plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
6698
6962
  });
6699
- import_node_fs11.default.mkdirSync(import_node_path16.default.dirname(opts.outFile), { recursive: true });
6963
+ import_node_fs12.default.mkdirSync(import_node_path17.default.dirname(opts.outFile), { recursive: true });
6700
6964
  await bundle2.write({
6701
6965
  sourcemap: !!config.build.sourcemap,
6702
6966
  minify: !!config.build.minify,
@@ -6707,7 +6971,7 @@ async function bundleNode(config, entry, opts) {
6707
6971
  codeSplitting: false
6708
6972
  });
6709
6973
  await bundle2.close();
6710
- console.log(import_picocolors9.default.dim(` \u2713 ${opts.label} \u2192 ${import_node_path16.default.relative(config.root, opts.outFile)}`));
6974
+ console.log(import_picocolors9.default.dim(` \u2713 ${opts.label} \u2192 ${import_node_path17.default.relative(config.root, opts.outFile)}`));
6711
6975
  return opts.outFile;
6712
6976
  }
6713
6977
  function createElectronRendererConfig(config, inlineConfig = {}, overrides = {}) {
@@ -6731,11 +6995,11 @@ function createElectronRendererConfig(config, inlineConfig = {}, overrides = {})
6731
6995
  }
6732
6996
  function outFileName(outDir, base, format) {
6733
6997
  const ext = format === "cjs" ? ".cjs" : ".mjs";
6734
- return import_node_path16.default.join(outDir, base + ext);
6998
+ return import_node_path17.default.join(outDir, base + ext);
6735
6999
  }
6736
7000
  function normalizePreload(preload, root) {
6737
7001
  const list = Array.isArray(preload) ? preload : preload ? [preload] : [];
6738
- return list.map((p) => import_node_path16.default.resolve(root, p));
7002
+ return list.map((p) => import_node_path17.default.resolve(root, p));
6739
7003
  }
6740
7004
  function assertElectronVersion(config) {
6741
7005
  const min = config.electron.minVersion;
@@ -6750,21 +7014,30 @@ function assertElectronVersion(config) {
6750
7014
  }
6751
7015
  function detectInstalledElectron(root) {
6752
7016
  try {
6753
- const pkgPath = import_node_path16.default.resolve(root, "node_modules/electron/package.json");
6754
- if (!import_node_fs11.default.existsSync(pkgPath)) return null;
6755
- const pkg = JSON.parse(import_node_fs11.default.readFileSync(pkgPath, "utf-8"));
7017
+ const require2 = (0, import_node_module7.createRequire)(import_node_path17.default.resolve(root, "package.json"));
7018
+ const pkgPath = require2.resolve("electron/package.json");
7019
+ const pkg = JSON.parse(import_node_fs12.default.readFileSync(pkgPath, "utf-8"));
6756
7020
  const major = parseInt(String(pkg.version).split(".")[0], 10);
6757
7021
  return Number.isFinite(major) ? major : null;
6758
7022
  } catch {
6759
- return null;
7023
+ try {
7024
+ const pkgPath = import_node_path17.default.resolve(root, "node_modules/electron/package.json");
7025
+ if (!import_node_fs12.default.existsSync(pkgPath)) return null;
7026
+ const pkg = JSON.parse(import_node_fs12.default.readFileSync(pkgPath, "utf-8"));
7027
+ const major = parseInt(String(pkg.version).split(".")[0], 10);
7028
+ return Number.isFinite(major) ? major : null;
7029
+ } catch {
7030
+ return null;
7031
+ }
6760
7032
  }
6761
7033
  }
6762
- var import_node_path16, import_node_fs11, import_rolldown2, import_picocolors9;
7034
+ var import_node_path17, import_node_fs12, import_node_module7, import_rolldown2, import_picocolors9;
6763
7035
  var init_electron2 = __esm({
6764
7036
  "src/build/electron.ts"() {
6765
7037
  "use strict";
6766
- import_node_path16 = __toESM(require("path"), 1);
6767
- import_node_fs11 = __toESM(require("fs"), 1);
7038
+ import_node_path17 = __toESM(require("path"), 1);
7039
+ import_node_fs12 = __toESM(require("fs"), 1);
7040
+ import_node_module7 = require("module");
6768
7041
  import_rolldown2 = require("rolldown");
6769
7042
  import_picocolors9 = __toESM(require("picocolors"), 1);
6770
7043
  init_config();
@@ -6785,7 +7058,7 @@ async function startElectronDev(inlineConfig = {}) {
6785
7058
  const { noSpawn, ...rest } = inlineConfig;
6786
7059
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
6787
7060
  warnElectronVersion(config);
6788
- console.log(import_picocolors10.default.cyan("\n\u26A1 nasti electron dev") + import_picocolors10.default.dim(` v${"2.4.2"}`));
7061
+ console.log(import_picocolors10.default.cyan("\n\u26A1 nasti electron dev") + import_picocolors10.default.dim(` v${"2.4.4"}`));
6789
7062
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
6790
7063
  const server = await createServer2({
6791
7064
  ...rest,
@@ -6795,11 +7068,11 @@ async function startElectronDev(inlineConfig = {}) {
6795
7068
  await server.listen();
6796
7069
  const devUrl = `http://localhost:${server.config.server.port}` + electronRendererDevPath(config.electron.renderer);
6797
7070
  console.log(import_picocolors10.default.dim(` renderer: ${devUrl}`));
6798
- const stageDir = import_node_path17.default.resolve(config.root, ".nasti");
6799
- import_node_fs12.default.mkdirSync(stageDir, { recursive: true });
6800
- const mainEntry = import_node_path17.default.resolve(config.root, config.electron.main);
7071
+ const stageDir = import_node_path18.default.resolve(config.root, ".nasti");
7072
+ import_node_fs13.default.mkdirSync(stageDir, { recursive: true });
7073
+ const mainEntry = import_node_path18.default.resolve(config.root, config.electron.main);
6801
7074
  const preloadEntries = normalizePreload(config.electron.preload, config.root);
6802
- const builtMainFile = import_node_path17.default.join(stageDir, "main" + extFor(config.electron.mainFormat));
7075
+ const builtMainFile = import_node_path18.default.join(stageDir, "main" + extFor(config.electron.mainFormat));
6803
7076
  const builtPreloadFiles = [];
6804
7077
  const compileAll = async () => {
6805
7078
  await compileNode(config, mainEntry, {
@@ -6809,9 +7082,9 @@ async function startElectronDev(inlineConfig = {}) {
6809
7082
  });
6810
7083
  builtPreloadFiles.length = 0;
6811
7084
  for (const entry of preloadEntries) {
6812
- if (!import_node_fs12.default.existsSync(entry)) continue;
6813
- const base = import_node_path17.default.basename(entry).replace(/\.[^.]+$/, "");
6814
- const out = import_node_path17.default.join(stageDir, base + extFor(config.electron.preloadFormat));
7085
+ if (!import_node_fs13.default.existsSync(entry)) continue;
7086
+ const base = import_node_path18.default.basename(entry).replace(/\.[^.]+$/, "");
7087
+ const out = import_node_path18.default.join(stageDir, base + extFor(config.electron.preloadFormat));
6815
7088
  await compileNode(config, entry, {
6816
7089
  outFile: out,
6817
7090
  format: config.electron.preloadFormat,
@@ -6850,7 +7123,7 @@ async function startElectronDev(inlineConfig = {}) {
6850
7123
  };
6851
7124
  spawnElectron();
6852
7125
  if (config.electron.autoRestart) {
6853
- const watchTargets = [mainEntry, ...preloadEntries].filter(import_node_fs12.default.existsSync);
7126
+ const watchTargets = [mainEntry, ...preloadEntries].filter(import_node_fs13.default.existsSync);
6854
7127
  const watcher = import_chokidar2.default.watch(watchTargets, { ignoreInitial: true });
6855
7128
  let restarting = null;
6856
7129
  let pending = false;
@@ -6930,7 +7203,7 @@ async function compileNode(config, entry, opts) {
6930
7203
  platform: "node",
6931
7204
  plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
6932
7205
  });
6933
- import_node_fs12.default.mkdirSync(import_node_path17.default.dirname(opts.outFile), { recursive: true });
7206
+ import_node_fs13.default.mkdirSync(import_node_path18.default.dirname(opts.outFile), { recursive: true });
6934
7207
  await bundle2.write({
6935
7208
  file: opts.outFile,
6936
7209
  format: opts.format === "cjs" ? "cjs" : "esm",
@@ -6943,18 +7216,18 @@ async function compileNode(config, entry, opts) {
6943
7216
  await bundle2.close();
6944
7217
  }
6945
7218
  function electronRendererDevPath(renderer) {
6946
- const normalized = renderer.split(import_node_path17.default.sep).join("/").replace(/^\.?\//, "");
7219
+ const normalized = renderer.split(import_node_path18.default.sep).join("/").replace(/^\.?\//, "");
6947
7220
  return normalized === "index.html" ? "/" : `/${normalized}`;
6948
7221
  }
6949
7222
  function resolveElectronBinary(config) {
6950
- if (config.electron.electronPath && import_node_fs12.default.existsSync(config.electron.electronPath)) {
7223
+ if (config.electron.electronPath && import_node_fs13.default.existsSync(config.electron.electronPath)) {
6951
7224
  return config.electron.electronPath;
6952
7225
  }
6953
7226
  try {
6954
- const require2 = (0, import_node_module7.createRequire)(import_node_path17.default.resolve(config.root, "package.json"));
7227
+ const require2 = (0, import_node_module8.createRequire)(import_node_path18.default.resolve(config.root, "package.json"));
6955
7228
  const pathFile = require2.resolve("electron");
6956
7229
  const electronModule = require2(pathFile);
6957
- if (typeof electronModule === "string" && import_node_fs12.default.existsSync(electronModule)) {
7230
+ if (typeof electronModule === "string" && import_node_fs13.default.existsSync(electronModule)) {
6958
7231
  return electronModule;
6959
7232
  }
6960
7233
  } catch {
@@ -6979,13 +7252,13 @@ function warnElectronVersion(config) {
6979
7252
  );
6980
7253
  }
6981
7254
  }
6982
- var import_node_path17, import_node_fs12, import_node_module7, import_node_child_process, import_chokidar2, import_picocolors10, import_rolldown3;
7255
+ var import_node_path18, import_node_fs13, import_node_module8, import_node_child_process, import_chokidar2, import_picocolors10, import_rolldown3;
6983
7256
  var init_electron_dev = __esm({
6984
7257
  "src/server/electron-dev.ts"() {
6985
7258
  "use strict";
6986
- import_node_path17 = __toESM(require("path"), 1);
6987
- import_node_fs12 = __toESM(require("fs"), 1);
6988
- import_node_module7 = require("module");
7259
+ import_node_path18 = __toESM(require("path"), 1);
7260
+ import_node_fs13 = __toESM(require("fs"), 1);
7261
+ import_node_module8 = require("module");
6989
7262
  import_node_child_process = require("child_process");
6990
7263
  import_chokidar2 = __toESM(require("chokidar"), 1);
6991
7264
  import_picocolors10 = __toESM(require("picocolors"), 1);
@@ -7137,20 +7410,20 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
7137
7410
  const logger = createCliLogger(options);
7138
7411
  try {
7139
7412
  const http2 = await import("http");
7140
- const path18 = await import("path");
7413
+ const path19 = await import("path");
7141
7414
  const os2 = await import("os");
7142
7415
  const sirv2 = (await import("sirv")).default;
7143
7416
  const connect2 = (await import("connect")).default;
7144
7417
  const { printServerUrls: printServerUrls2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
7145
- const resolvedRoot = path18.resolve(root ?? ".");
7146
- const outDir = path18.resolve(resolvedRoot, options.outDir);
7418
+ const resolvedRoot = path19.resolve(root ?? ".");
7419
+ const outDir = path19.resolve(resolvedRoot, options.outDir);
7147
7420
  const app = connect2();
7148
7421
  app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
7149
7422
  const port = options.port;
7150
7423
  const host = options.host === true ? "0.0.0.0" : options.host ?? "localhost";
7151
7424
  http2.createServer(app).listen(port, host, () => {
7152
7425
  logger.info(`
7153
- ${import_picocolors11.default.cyan(import_picocolors11.default.bold("NASTI"))} ${import_picocolors11.default.cyan(`v${"2.4.2"}`)} ${import_picocolors11.default.dim("preview")}
7426
+ ${import_picocolors11.default.cyan(import_picocolors11.default.bold("NASTI"))} ${import_picocolors11.default.cyan(`v${"2.4.4"}`)} ${import_picocolors11.default.dim("preview")}
7154
7427
  `);
7155
7428
  printServerUrls2(
7156
7429
  {
@@ -7167,6 +7440,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
7167
7440
  }
7168
7441
  });
7169
7442
  cli.help();
7170
- cli.version("2.4.2");
7443
+ cli.version("2.4.4");
7171
7444
  cli.parse();
7172
7445
  //# sourceMappingURL=cli.cjs.map