@nasti-toolchain/nasti 2.4.3 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -10,10 +10,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
10
10
  if (typeof require !== "undefined") return require.apply(this, arguments);
11
11
  throw Error('Dynamic require of "' + x + '" is not supported');
12
12
  });
13
- var __glob = (map) => (path18) => {
14
- var fn = map[path18];
13
+ var __glob = (map) => (path19) => {
14
+ var fn = map[path19];
15
15
  if (fn) return fn();
16
- throw new Error("Module not found in bundle: " + path18);
16
+ throw new Error("Module not found in bundle: " + path19);
17
17
  };
18
18
  var __esm = (fn, res) => function __init() {
19
19
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -162,7 +162,7 @@ var init_logger = __esm({
162
162
  });
163
163
 
164
164
  // src/config/defaults.ts
165
- var defaultResolve, defaultServer, defaultBuild, defaultElectron, defaultExperimental, defaults;
165
+ var defaultResolve, defaultServer, defaultBuild, defaultElectron, defaultExperimental, defaultReact, defaults;
166
166
  var init_defaults = __esm({
167
167
  "src/config/defaults.ts"() {
168
168
  "use strict";
@@ -215,12 +215,20 @@ var init_defaults = __esm({
215
215
  defaultExperimental = {
216
216
  bundledDev: false
217
217
  };
218
+ defaultReact = {
219
+ include: /\.[tj]sx?$/,
220
+ exclude: /node_modules/,
221
+ jsxImportSource: "react",
222
+ jsxRuntime: "automatic",
223
+ compiler: false
224
+ };
218
225
  defaults = {
219
226
  root: ".",
220
227
  base: "/",
221
228
  mode: "development",
222
229
  target: "web",
223
230
  framework: "auto",
231
+ react: defaultReact,
224
232
  resolve: defaultResolve,
225
233
  server: defaultServer,
226
234
  build: defaultBuild,
@@ -445,6 +453,13 @@ async function resolveConfig(inlineConfig = {}, command) {
445
453
  mode,
446
454
  target: merged.target ?? defaults.target,
447
455
  framework: (merged.framework ?? defaults.framework) === "auto" ? detectFramework(root) : merged.framework,
456
+ react: {
457
+ include: merged.react?.include ?? defaultReact.include,
458
+ exclude: merged.react?.exclude ?? defaultReact.exclude,
459
+ jsxImportSource: merged.react?.jsxImportSource ?? defaultReact.jsxImportSource,
460
+ jsxRuntime: merged.react?.jsxRuntime ?? defaultReact.jsxRuntime,
461
+ compiler: merged.react?.compiler === true ? {} : merged.react?.compiler ?? defaultReact.compiler
462
+ },
448
463
  command,
449
464
  resolve: {
450
465
  // tsconfig paths 优先级最低:tsconfig < defaults < user config
@@ -856,6 +871,24 @@ var init_module_graph = __esm({
856
871
  getModulesByFile(file) {
857
872
  return this.fileToModulesMap.get(file);
858
873
  }
874
+ /**
875
+ * Modules whose registered entry file lives under `dir` (inclusive).
876
+ * Used when a non-entry source inside a prebundled workspace package changes:
877
+ * only the package entry was registered, so getModulesByFile(changedFile)
878
+ * misses — we invalidate every /@modules entry rooted in that package.
879
+ */
880
+ getModulesWithFileUnder(dir) {
881
+ const result = /* @__PURE__ */ new Set();
882
+ const normDir = dir.replace(/\\/g, "/");
883
+ const normPrefix = normDir.endsWith("/") ? normDir : normDir + "/";
884
+ for (const [file, mods] of this.fileToModulesMap) {
885
+ const normFile = file.replace(/\\/g, "/");
886
+ if (normFile === normDir || normFile.startsWith(normPrefix)) {
887
+ for (const m of mods) result.add(m);
888
+ }
889
+ }
890
+ return result;
891
+ }
859
892
  async ensureEntryFromUrl(url) {
860
893
  const normalizedUrl = removeTimestampQuery(url);
861
894
  let mod = this.urlToModuleMap.get(normalizedUrl);
@@ -1341,13 +1374,88 @@ ${msg}`);
1341
1374
  map: result.map ? JSON.stringify(result.map) : null
1342
1375
  };
1343
1376
  }
1344
- var JS_EXTENSIONS, TS_EXTENSIONS, JSX_EXTENSIONS;
1377
+ async function transformReactCode(filename, code, options) {
1378
+ if (!matchesReactFilter(filename, options.react.include, options.react.exclude)) {
1379
+ return null;
1380
+ }
1381
+ if (!options.react.compiler) {
1382
+ if (!shouldTransform(filename)) return null;
1383
+ return transformCode(filename, code, {
1384
+ sourcemap: options.sourcemap,
1385
+ jsxRuntime: options.react.jsxRuntime,
1386
+ jsxImportSource: options.react.jsxImportSource,
1387
+ reactRefresh: options.reactRefresh,
1388
+ target: options.target
1389
+ });
1390
+ }
1391
+ if (!shouldTransform(filename)) return null;
1392
+ const compiler2 = await loadReactCompiler();
1393
+ const compilerOptions = options.react.compiler;
1394
+ const shouldCompile = options.consumer === "client" && (compilerOptions.compilationMode === "annotation" ? /['"]use memo['"]/.test(code) : defaultReactCompilerCodeFilter.test(code));
1395
+ const result = await compiler2.transform(cleanTransformId(filename), code, {
1396
+ jsx: {
1397
+ runtime: options.react.jsxRuntime,
1398
+ development: options.development,
1399
+ importSource: options.react.jsxImportSource,
1400
+ refresh: options.consumer === "client" && !!options.reactRefresh
1401
+ },
1402
+ reactCompiler: shouldCompile ? compilerOptions : false,
1403
+ sourcemap: options.sourcemap ?? true
1404
+ });
1405
+ const diagnostics = result.errors.map(
1406
+ (error) => `${error.message}${error.codeframe ? `
1407
+ ${error.codeframe}` : ""}`
1408
+ );
1409
+ if (result.fatal) {
1410
+ throw new Error(
1411
+ diagnostics.join("\n\n") || `React Compiler transform failed for ${filename}`
1412
+ );
1413
+ }
1414
+ for (const diagnostic of diagnostics) options.onWarning?.(diagnostic);
1415
+ return {
1416
+ code: result.code,
1417
+ map: result.map ? JSON.stringify(result.map) : null
1418
+ };
1419
+ }
1420
+ function matchesReactFilter(id, include, exclude) {
1421
+ const cleanId = cleanTransformId(id);
1422
+ return matchesFilter(cleanId, include) && !matchesFilter(cleanId, exclude);
1423
+ }
1424
+ function matchesFilter(id, filter2) {
1425
+ const patterns = Array.isArray(filter2) ? filter2 : [filter2];
1426
+ return patterns.some((pattern) => {
1427
+ if (pattern instanceof RegExp) {
1428
+ pattern.lastIndex = 0;
1429
+ return pattern.test(id);
1430
+ }
1431
+ if (!pattern.includes("*")) return id.includes(pattern);
1432
+ const expression = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "\0").replace(/\*/g, "[^/]*").replace(/\0/g, ".*");
1433
+ return new RegExp(`^${expression}$`).test(id);
1434
+ });
1435
+ }
1436
+ function cleanTransformId(id) {
1437
+ return id.split(/[?#]/, 1)[0];
1438
+ }
1439
+ async function loadReactCompiler() {
1440
+ if (reactCompilerImplementation) return reactCompilerImplementation;
1441
+ try {
1442
+ reactCompilerImplementation = await import("oxc-transform-react");
1443
+ return reactCompilerImplementation;
1444
+ } catch (error) {
1445
+ throw new Error(
1446
+ '[nasti] React Compiler requires the optional "oxc-transform-react" package. Install it before setting react.compiler.' + (error instanceof Error ? `
1447
+ ${error.message}` : "")
1448
+ );
1449
+ }
1450
+ }
1451
+ var JS_EXTENSIONS, TS_EXTENSIONS, JSX_EXTENSIONS, defaultReactCompilerCodeFilter, reactCompilerImplementation;
1345
1452
  var init_transformer = __esm({
1346
1453
  "src/core/transformer.ts"() {
1347
1454
  "use strict";
1348
1455
  JS_EXTENSIONS = /\.(js|mjs|cjs)$/;
1349
1456
  TS_EXTENSIONS = /\.(ts|mts|cts)$/;
1350
1457
  JSX_EXTENSIONS = /\.(jsx|tsx)$/;
1458
+ defaultReactCompilerCodeFilter = /forwardRef|memo|\b(?:[A-Z]|use[A-Z0-9])/;
1351
1459
  }
1352
1460
  });
1353
1461
 
@@ -1586,9 +1694,123 @@ var init_assets = __esm({
1586
1694
  }
1587
1695
  });
1588
1696
 
1589
- // src/server/middleware.ts
1590
- import path5 from "path";
1697
+ // src/server/fs-allow.ts
1591
1698
  import fs5 from "fs";
1699
+ import path5 from "path";
1700
+ function isUnderRoot(abs, root) {
1701
+ const rel = path5.relative(root, abs);
1702
+ return !!rel && !rel.startsWith("..") && !path5.isAbsolute(rel);
1703
+ }
1704
+ function discoverLinkedPackageRoots(projectRoot, maxDepth = 4) {
1705
+ const results = [];
1706
+ const seenReal = /* @__PURE__ */ new Set();
1707
+ const queued = /* @__PURE__ */ new Set([projectRoot]);
1708
+ const queue = [projectRoot];
1709
+ for (let depth = 0; depth < maxDepth && queue.length > 0; depth++) {
1710
+ const levelCount = queue.length;
1711
+ for (let i = 0; i < levelCount; i++) {
1712
+ const dir = queue.shift();
1713
+ const nm = path5.join(dir, "node_modules");
1714
+ let entries;
1715
+ try {
1716
+ entries = fs5.readdirSync(nm, { withFileTypes: true });
1717
+ } catch {
1718
+ continue;
1719
+ }
1720
+ for (const ent of entries) {
1721
+ if (ent.name.startsWith(".") || ent.name === "node_modules") continue;
1722
+ const pkgNames = ent.name.startsWith("@") ? listScopedPackages(nm, ent.name) : [ent.name];
1723
+ for (const pkgName of pkgNames) {
1724
+ const pkgPath = path5.join(nm, pkgName);
1725
+ let real;
1726
+ try {
1727
+ real = fs5.realpathSync(pkgPath);
1728
+ } catch {
1729
+ continue;
1730
+ }
1731
+ if (seenReal.has(real)) continue;
1732
+ seenReal.add(real);
1733
+ if (!queued.has(real)) {
1734
+ queued.add(real);
1735
+ queue.push(real);
1736
+ }
1737
+ if (real !== projectRoot && !isUnderRoot(real, projectRoot) && !real.includes(NM)) {
1738
+ results.push(real);
1739
+ }
1740
+ }
1741
+ }
1742
+ }
1743
+ }
1744
+ return results;
1745
+ }
1746
+ function listScopedPackages(nm, scope) {
1747
+ try {
1748
+ return fs5.readdirSync(path5.join(nm, scope)).filter((name) => !name.startsWith(".")).map((name) => path5.join(scope, name));
1749
+ } catch {
1750
+ return [];
1751
+ }
1752
+ }
1753
+ function getLinkedPackageRoots(projectRoot) {
1754
+ let mtimeMs = 0;
1755
+ try {
1756
+ mtimeMs = fs5.statSync(path5.join(projectRoot, "node_modules")).mtimeMs;
1757
+ } catch {
1758
+ mtimeMs = 0;
1759
+ }
1760
+ const cached2 = linkedRootsCache.get(projectRoot);
1761
+ if (cached2 && cached2.mtimeMs === mtimeMs) {
1762
+ return cached2.roots;
1763
+ }
1764
+ const roots = discoverLinkedPackageRoots(projectRoot);
1765
+ linkedRootsCache.set(projectRoot, { roots, mtimeMs });
1766
+ return roots;
1767
+ }
1768
+ function clearLinkedPackageRootsCache() {
1769
+ linkedRootsCache.clear();
1770
+ }
1771
+ function isAllowedDevModulePath(realId, projectRoot) {
1772
+ if (realId === projectRoot || isUnderRoot(realId, projectRoot)) return true;
1773
+ for (const pkgRoot of getLinkedPackageRoots(projectRoot)) {
1774
+ if (realId === pkgRoot || realId.startsWith(pkgRoot + path5.sep)) return true;
1775
+ }
1776
+ let dir = projectRoot;
1777
+ for (; ; ) {
1778
+ const nm = path5.join(dir, "node_modules");
1779
+ if (realId === nm || realId.startsWith(nm + path5.sep)) return true;
1780
+ const parent = path5.dirname(dir);
1781
+ if (parent === dir) break;
1782
+ dir = parent;
1783
+ }
1784
+ return false;
1785
+ }
1786
+ function findNearestPackageRoot(file) {
1787
+ let dir = path5.dirname(file);
1788
+ for (; ; ) {
1789
+ const pkgJson = path5.join(dir, "package.json");
1790
+ if (fs5.existsSync(pkgJson)) {
1791
+ try {
1792
+ const pkg = JSON.parse(fs5.readFileSync(pkgJson, "utf-8"));
1793
+ if (typeof pkg?.name === "string" && pkg.name) return dir;
1794
+ } catch {
1795
+ }
1796
+ }
1797
+ const parent = path5.dirname(dir);
1798
+ if (parent === dir) return null;
1799
+ dir = parent;
1800
+ }
1801
+ }
1802
+ var NM, linkedRootsCache;
1803
+ var init_fs_allow = __esm({
1804
+ "src/server/fs-allow.ts"() {
1805
+ "use strict";
1806
+ NM = `${path5.sep}node_modules${path5.sep}`;
1807
+ linkedRootsCache = /* @__PURE__ */ new Map();
1808
+ }
1809
+ });
1810
+
1811
+ // src/server/middleware.ts
1812
+ import path6 from "path";
1813
+ import fs6 from "fs";
1592
1814
  import { createRequire } from "module";
1593
1815
  import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "url";
1594
1816
  import pc3 from "picocolors";
@@ -1599,10 +1821,10 @@ function getReactRefreshRuntimeEsm(includeBoundaryHelpers = false) {
1599
1821
  let cjsPath;
1600
1822
  try {
1601
1823
  const pkgPath = __require2.resolve("react-refresh/package.json");
1602
- cjsPath = path5.join(path5.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
1824
+ cjsPath = path6.join(path6.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
1603
1825
  } catch (err) {
1604
- cjsPath = path5.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
1605
- if (!fs5.existsSync(cjsPath)) {
1826
+ cjsPath = path6.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
1827
+ if (!fs6.existsSync(cjsPath)) {
1606
1828
  const origMsg = err instanceof Error ? err.message : String(err);
1607
1829
  throw new Error(
1608
1830
  `[nasti] Missing dependency "react-refresh". Install it with: npm install react-refresh
@@ -1610,7 +1832,7 @@ Original resolve error: ${origMsg}`
1610
1832
  );
1611
1833
  }
1612
1834
  }
1613
- const cjsSource = fs5.readFileSync(cjsPath, "utf-8");
1835
+ const cjsSource = fs6.readFileSync(cjsPath, "utf-8");
1614
1836
  __refreshRuntimeCache = `// Wrapped react-refresh runtime -> ESM
1615
1837
  const exports = {};
1616
1838
  const module = { exports };
@@ -1781,8 +2003,8 @@ async function transformRequest(url, ctx) {
1781
2003
  let realIdValid = false;
1782
2004
  try {
1783
2005
  if (idParam) {
1784
- realId = fs5.realpathSync(idParam);
1785
- realIdValid = fs5.statSync(realId).isFile() && (realId.includes(`${path5.sep}node_modules${path5.sep}`) || isUnderRoot(realId, config.root));
2006
+ realId = fs6.realpathSync(idParam);
2007
+ realIdValid = fs6.statSync(realId).isFile() && isAllowedDevModulePath(realId, config.root);
1786
2008
  }
1787
2009
  } catch {
1788
2010
  realId = null;
@@ -1849,7 +2071,7 @@ async function transformRequest(url, ctx) {
1849
2071
  }
1850
2072
  }
1851
2073
  const filePath = resolveUrlToFile(url, config.root);
1852
- if (!filePath || !fs5.existsSync(filePath)) return null;
2074
+ if (!filePath || !fs6.existsSync(filePath)) return null;
1853
2075
  const mod = await moduleGraph.ensureEntryFromUrl(url);
1854
2076
  moduleGraph.registerModule(mod, filePath);
1855
2077
  const transformVersion = mod.invalidationVersion;
@@ -1860,7 +2082,7 @@ async function transformRequest(url, ctx) {
1860
2082
  return transformResult2;
1861
2083
  }
1862
2084
  const loaded = await pluginContainer.load(filePath);
1863
- let code = loaded == null ? fs5.readFileSync(filePath, "utf-8") : typeof loaded === "string" ? loaded : loaded.code;
2085
+ let code = loaded == null ? fs6.readFileSync(filePath, "utf-8") : typeof loaded === "string" ? loaded : loaded.code;
1864
2086
  let map = loaded && typeof loaded !== "string" ? loaded.map : void 0;
1865
2087
  const pluginResult = await pluginContainer.transform(code, filePath);
1866
2088
  if (pluginResult) {
@@ -1869,22 +2091,35 @@ async function transformRequest(url, ctx) {
1869
2091
  }
1870
2092
  const stableUrl = cleanReqUrl;
1871
2093
  let wrappedWithRefresh = false;
1872
- if (shouldTransform(filePath)) {
1873
- const isJsx = /\.[jt]sx$/.test(filePath);
1874
- const useRefresh = isJsx && config.framework !== "vue";
2094
+ if (config.framework === "react") {
2095
+ const refreshEnabled = (ctx.environment?.consumer ?? "client") === "client" && config.server.hmr !== false;
2096
+ const useRefresh = refreshEnabled && (!!config.react.compiler || /\.[jt]sx$/.test(filePath));
2097
+ const result = await transformReactCode(filePath, code, {
2098
+ react: config.react,
2099
+ consumer: ctx.environment?.consumer ?? "client",
2100
+ development: true,
2101
+ reactRefresh: useRefresh,
2102
+ sourcemap: true,
2103
+ target: ctx.environment?.options.build.target ?? config.build.target,
2104
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
2105
+ });
2106
+ if (result) {
2107
+ code = result.code;
2108
+ if (result.map) map = JSON.parse(result.map);
2109
+ if (useRefresh) {
2110
+ code = buildReactRefreshWrapper(stableUrl, code);
2111
+ wrappedWithRefresh = true;
2112
+ }
2113
+ }
2114
+ } else if (shouldTransform(filePath)) {
1875
2115
  const result = transformCode(filePath, code, {
1876
2116
  sourcemap: true,
1877
2117
  jsxRuntime: "automatic",
1878
- jsxImportSource: config.framework === "vue" ? "vue" : "react",
1879
- reactRefresh: useRefresh,
2118
+ jsxImportSource: "vue",
1880
2119
  target: ctx.environment?.options.build.target ?? config.build.target
1881
2120
  });
1882
2121
  code = result.code;
1883
2122
  if (result.map) map = JSON.parse(result.map);
1884
- if (useRefresh) {
1885
- code = buildReactRefreshWrapper(stableUrl, code);
1886
- wrappedWithRefresh = true;
1887
- }
1888
2123
  }
1889
2124
  const hotInfo = rewriteHotAcceptDeps(code, config, filePath);
1890
2125
  code = hotInfo.code;
@@ -1918,7 +2153,7 @@ async function loadVirtualModule(spec, ctx) {
1918
2153
  const resolved = await pluginContainer.resolveId(spec);
1919
2154
  if (resolved == null) return null;
1920
2155
  const resolvedId = typeof resolved === "string" ? resolved : resolved.id;
1921
- const looksVirtual = resolvedId.startsWith("\0") || !fs5.existsSync(resolvedId);
2156
+ const looksVirtual = resolvedId.startsWith("\0") || !fs6.existsSync(resolvedId);
1922
2157
  if (!looksVirtual) return null;
1923
2158
  const loadResult = await pluginContainer.load(resolvedId);
1924
2159
  if (loadResult == null) return null;
@@ -1932,7 +2167,7 @@ async function loadVirtualModule(spec, ctx) {
1932
2167
  config.mode,
1933
2168
  ssrDefineOverrides(ctx.environment?.consumer ?? "client")
1934
2169
  ));
1935
- const anchor = path5.join(config.root, "__nasti_virtual__.ts");
2170
+ const anchor = path6.join(config.root, "__nasti_virtual__.ts");
1936
2171
  code = rewriteImports(code, config, anchor);
1937
2172
  return { id: resolvedId, result: { code } };
1938
2173
  }
@@ -1958,7 +2193,7 @@ async function doBundlePackage(entryFile, root) {
1958
2193
  await bundle2.close();
1959
2194
  let code = result.output[0].code;
1960
2195
  code = code.replace(/process\.env\.NODE_ENV/g, '"development"');
1961
- const externalBaseDir = path5.dirname(entryFile);
2196
+ const externalBaseDir = path6.dirname(entryFile);
1962
2197
  code = code.replace(
1963
2198
  /^(import\b[^;'"]*?\bfrom\s+)(['"])([^'"./][^'"]*)(\2)/gm,
1964
2199
  (_, prefix, q, spec) => `${prefix}${q}${externalSpecToModuleUrl(spec, externalBaseDir, root)}${q}`
@@ -1976,16 +2211,16 @@ async function doBundlePackage(entryFile, root) {
1976
2211
  return code;
1977
2212
  }
1978
2213
  async function tryGenerateSubpathShim(entryFile, root) {
1979
- const NM = `${path5.sep}node_modules${path5.sep}`;
1980
- if (!entryFile.includes(NM)) return null;
2214
+ const NM2 = `${path6.sep}node_modules${path6.sep}`;
2215
+ if (!entryFile.includes(NM2)) return null;
1981
2216
  let pkgDir = null;
1982
2217
  let pkgName = null;
1983
- let dir = path5.dirname(entryFile);
2218
+ let dir = path6.dirname(entryFile);
1984
2219
  while (true) {
1985
- const pkgJsonPath = path5.join(dir, "package.json");
1986
- if (fs5.existsSync(pkgJsonPath)) {
2220
+ const pkgJsonPath = path6.join(dir, "package.json");
2221
+ if (fs6.existsSync(pkgJsonPath)) {
1987
2222
  try {
1988
- const pkg = JSON.parse(fs5.readFileSync(pkgJsonPath, "utf-8"));
2223
+ const pkg = JSON.parse(fs6.readFileSync(pkgJsonPath, "utf-8"));
1989
2224
  if (typeof pkg?.name === "string" && pkg.name) {
1990
2225
  pkgDir = dir;
1991
2226
  pkgName = pkg.name;
@@ -1994,16 +2229,16 @@ async function tryGenerateSubpathShim(entryFile, root) {
1994
2229
  } catch {
1995
2230
  }
1996
2231
  }
1997
- const parent = path5.dirname(dir);
2232
+ const parent = path6.dirname(dir);
1998
2233
  if (parent === dir) return null;
1999
2234
  dir = parent;
2000
- if (!dir.includes(NM)) return null;
2235
+ if (!dir.includes(NM2)) return null;
2001
2236
  }
2002
2237
  if (!pkgDir || !pkgName) return null;
2003
- const entryExt = path5.extname(entryFile);
2238
+ const entryExt = path6.extname(entryFile);
2004
2239
  const mainEntry = pickMainEntryByExtension(pkgDir, entryExt);
2005
2240
  if (!mainEntry) return null;
2006
- if (path5.resolve(mainEntry) === path5.resolve(entryFile)) return null;
2241
+ if (path6.resolve(mainEntry) === path6.resolve(entryFile)) return null;
2007
2242
  let mainNs;
2008
2243
  let subNs;
2009
2244
  try {
@@ -2027,7 +2262,7 @@ async function tryGenerateSubpathShim(entryFile, root) {
2027
2262
  if (mainNs["default"] !== subNs["default"]) return null;
2028
2263
  }
2029
2264
  const rootMain = resolveNodeModule(root, pkgName);
2030
- const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir + path5.sep) ? `/@modules/${pkgName}` : `/@modules/${pkgName}?id=${encodeURIComponent(mainEntry)}`;
2265
+ const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir + path6.sep) ? `/@modules/${pkgName}` : `/@modules/${pkgName}?id=${encodeURIComponent(mainEntry)}`;
2031
2266
  const lines = [
2032
2267
  `// Nasti subpath shim \u2192 ${pkgName} (avoid duplicate bundling)`,
2033
2268
  `import * as __pkg from "${mainEntryUrl}";`
@@ -2041,10 +2276,10 @@ async function tryGenerateSubpathShim(entryFile, root) {
2041
2276
  return lines.join("\n") + "\n";
2042
2277
  }
2043
2278
  function pickMainEntryByExtension(pkgDir, preferredExt) {
2044
- const pkgJsonPath = path5.join(pkgDir, "package.json");
2279
+ const pkgJsonPath = path6.join(pkgDir, "package.json");
2045
2280
  let pkg;
2046
2281
  try {
2047
- pkg = JSON.parse(fs5.readFileSync(pkgJsonPath, "utf-8"));
2282
+ pkg = JSON.parse(fs6.readFileSync(pkgJsonPath, "utf-8"));
2048
2283
  } catch {
2049
2284
  return null;
2050
2285
  }
@@ -2063,14 +2298,14 @@ function pickMainEntryByExtension(pkgDir, preferredExt) {
2063
2298
  if (typeof pkg.module === "string") candidates.push(pkg.module);
2064
2299
  if (typeof pkg.main === "string") candidates.push(pkg.main);
2065
2300
  for (const cand of candidates) {
2066
- if (path5.extname(cand) === preferredExt) {
2067
- const full = path5.resolve(pkgDir, cand);
2068
- if (fs5.existsSync(full)) return full;
2301
+ if (path6.extname(cand) === preferredExt) {
2302
+ const full = path6.resolve(pkgDir, cand);
2303
+ if (fs6.existsSync(full)) return full;
2069
2304
  }
2070
2305
  }
2071
2306
  for (const cand of candidates) {
2072
- const full = path5.resolve(pkgDir, cand);
2073
- if (fs5.existsSync(full)) return full;
2307
+ const full = path6.resolve(pkgDir, cand);
2308
+ if (fs6.existsSync(full)) return full;
2074
2309
  }
2075
2310
  return null;
2076
2311
  }
@@ -2095,8 +2330,8 @@ function rewriteExternalRequires(code, baseDir, root) {
2095
2330
  }
2096
2331
  async function injectCjsNamedExports(code, entryFile) {
2097
2332
  try {
2098
- const { createRequire: createRequire6 } = await import("module");
2099
- const req = createRequire6(entryFile);
2333
+ const { createRequire: createRequire7 } = await import("module");
2334
+ const req = createRequire7(entryFile);
2100
2335
  const cjsExports = req(entryFile);
2101
2336
  if (!cjsExports || typeof cjsExports !== "object" && typeof cjsExports !== "function" || Array.isArray(cjsExports)) return code;
2102
2337
  const namedKeys = Object.keys(cjsExports).filter(
@@ -2137,11 +2372,22 @@ function rewriteImports(code, config, filePath, importedUrls, moduleGraph) {
2137
2372
  }
2138
2373
  function createModuleSpecifierResolver(config, filePath) {
2139
2374
  const root = config.root;
2140
- const fileDir = path5.dirname(filePath);
2375
+ const fileDir = path6.dirname(filePath);
2141
2376
  const aliasEntries = Object.entries(config.resolve.alias).sort(
2142
2377
  ([a], [b]) => b.length - a.length
2143
2378
  );
2144
- const toRootUrl = (abs) => "/" + path5.relative(root, abs).replace(/\\/g, "/");
2379
+ const toServableUrl = (abs) => {
2380
+ if (isUnderRoot(abs, root)) {
2381
+ return "/" + path6.relative(root, abs).replace(/\\/g, "/");
2382
+ }
2383
+ for (const pkgRoot of getLinkedPackageRoots(root)) {
2384
+ if (abs === pkgRoot || abs.startsWith(pkgRoot + path6.sep)) {
2385
+ const normalized = abs.replace(/\\/g, "/");
2386
+ return "/@fs/" + (normalized.startsWith("/") ? normalized.slice(1) : normalized);
2387
+ }
2388
+ }
2389
+ return null;
2390
+ };
2145
2391
  return (specifier) => {
2146
2392
  const suffixMatch = specifier.match(/[?#].*$/);
2147
2393
  const suffix = suffixMatch ? suffixMatch[0] : "";
@@ -2150,18 +2396,21 @@ function createModuleSpecifierResolver(config, filePath) {
2150
2396
  if (baseSpec === key || baseSpec.startsWith(key + "/")) {
2151
2397
  const aliasBase = resolveAliasTarget(value, root);
2152
2398
  const sub = baseSpec.slice(key.length).replace(/^\//, "");
2153
- const target = sub ? path5.join(aliasBase, sub) : aliasBase;
2399
+ const target = sub ? path6.join(aliasBase, sub) : aliasBase;
2154
2400
  const resolved = tryResolveDiskPath(target);
2155
- return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
2401
+ const url = resolved ? toServableUrl(resolved) : null;
2402
+ return url ? url + suffix : specifier;
2156
2403
  }
2157
2404
  }
2158
2405
  if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
2159
- const resolved = tryResolveDiskPath(path5.resolve(fileDir, baseSpec));
2160
- return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
2406
+ const resolved = tryResolveDiskPath(path6.resolve(fileDir, baseSpec));
2407
+ const url = resolved ? toServableUrl(resolved) : null;
2408
+ return url ? url + suffix : specifier;
2161
2409
  }
2162
2410
  if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
2163
- const resolved = tryResolveDiskPath(path5.join(root, baseSpec.replace(/^\//, "")));
2164
- return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
2411
+ const resolved = tryResolveDiskPath(path6.join(root, baseSpec.replace(/^\//, "")));
2412
+ const url = resolved ? toServableUrl(resolved) : null;
2413
+ return url ? url + suffix : specifier;
2165
2414
  }
2166
2415
  if (baseSpec.startsWith("/")) return specifier;
2167
2416
  return `/@modules/${specifier}`;
@@ -2314,28 +2563,24 @@ function maskStringsAndComments(code) {
2314
2563
  return masked.join("");
2315
2564
  }
2316
2565
  function resolveAliasTarget(value, root) {
2317
- if (path5.isAbsolute(value) && fs5.existsSync(value)) return value;
2318
- if (value.startsWith("/")) return path5.join(root, value.slice(1));
2319
- return path5.resolve(root, value);
2566
+ if (path6.isAbsolute(value) && fs6.existsSync(value)) return value;
2567
+ if (value.startsWith("/")) return path6.join(root, value.slice(1));
2568
+ return path6.resolve(root, value);
2320
2569
  }
2321
2570
  function tryResolveDiskPath(target) {
2322
- if (fs5.existsSync(target) && fs5.statSync(target).isFile()) return target;
2571
+ if (fs6.existsSync(target) && fs6.statSync(target).isFile()) return target;
2323
2572
  for (const ext of RESOLVE_EXTENSIONS) {
2324
2573
  const withExt = target + ext;
2325
- if (fs5.existsSync(withExt) && fs5.statSync(withExt).isFile()) return withExt;
2574
+ if (fs6.existsSync(withExt) && fs6.statSync(withExt).isFile()) return withExt;
2326
2575
  }
2327
- if (fs5.existsSync(target) && fs5.statSync(target).isDirectory()) {
2576
+ if (fs6.existsSync(target) && fs6.statSync(target).isDirectory()) {
2328
2577
  for (const ext of RESOLVE_EXTENSIONS) {
2329
- const idx = path5.join(target, "index" + ext);
2330
- if (fs5.existsSync(idx) && fs5.statSync(idx).isFile()) return idx;
2578
+ const idx = path6.join(target, "index" + ext);
2579
+ if (fs6.existsSync(idx) && fs6.statSync(idx).isFile()) return idx;
2331
2580
  }
2332
2581
  }
2333
2582
  return null;
2334
2583
  }
2335
- function isUnderRoot(abs, root) {
2336
- const rel = path5.relative(root, abs);
2337
- return !!rel && !rel.startsWith("..") && !path5.isAbsolute(rel);
2338
- }
2339
2584
  function appendTimestampQuery(url, timestamp) {
2340
2585
  const hashIndex = url.indexOf("#");
2341
2586
  const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
@@ -2353,7 +2598,7 @@ function resolveNodeModule(baseDir, moduleName) {
2353
2598
  const resolved = resolveNodeModuleEntry(baseDir, moduleName);
2354
2599
  if (!resolved) return null;
2355
2600
  try {
2356
- return fs5.realpathSync(resolved);
2601
+ return fs6.realpathSync(resolved);
2357
2602
  } catch {
2358
2603
  return resolved;
2359
2604
  }
@@ -2373,21 +2618,21 @@ function resolveNodeModuleEntry(root, moduleName) {
2373
2618
  let pkgDir = null;
2374
2619
  let dir = root;
2375
2620
  for (; ; ) {
2376
- const candidate = path5.join(dir, "node_modules", pkgName);
2377
- if (fs5.existsSync(candidate)) {
2621
+ const candidate = path6.join(dir, "node_modules", pkgName);
2622
+ if (fs6.existsSync(candidate)) {
2378
2623
  pkgDir = candidate;
2379
2624
  break;
2380
2625
  }
2381
- const parent = path5.dirname(dir);
2626
+ const parent = path6.dirname(dir);
2382
2627
  if (parent === dir) break;
2383
2628
  dir = parent;
2384
2629
  }
2385
2630
  if (!pkgDir) return null;
2386
- const pkgJsonPath = path5.join(pkgDir, "package.json");
2387
- if (!fs5.existsSync(pkgJsonPath)) return null;
2631
+ const pkgJsonPath = path6.join(pkgDir, "package.json");
2632
+ if (!fs6.existsSync(pkgJsonPath)) return null;
2388
2633
  let pkg;
2389
2634
  try {
2390
- pkg = JSON.parse(fs5.readFileSync(pkgJsonPath, "utf-8"));
2635
+ pkg = JSON.parse(fs6.readFileSync(pkgJsonPath, "utf-8"));
2391
2636
  } catch {
2392
2637
  return null;
2393
2638
  }
@@ -2400,32 +2645,32 @@ function resolveNodeModuleEntry(root, moduleName) {
2400
2645
  const subDirs = [""];
2401
2646
  for (const field of ["module", "main"]) {
2402
2647
  if (typeof pkg[field] === "string") {
2403
- const dir2 = path5.dirname(pkg[field]);
2648
+ const dir2 = path6.dirname(pkg[field]);
2404
2649
  if (dir2 && dir2 !== "." && !subDirs.includes(dir2)) subDirs.push(dir2);
2405
2650
  }
2406
2651
  }
2407
2652
  for (const dir2 of subDirs) {
2408
- const direct = path5.join(pkgDir, dir2, subpath);
2409
- if (fs5.existsSync(direct) && fs5.statSync(direct).isFile()) return direct;
2653
+ const direct = path6.join(pkgDir, dir2, subpath);
2654
+ if (fs6.existsSync(direct) && fs6.statSync(direct).isFile()) return direct;
2410
2655
  for (const ext of RESOLVE_EXTENSIONS) {
2411
- if (fs5.existsSync(direct + ext)) return direct + ext;
2656
+ if (fs6.existsSync(direct + ext)) return direct + ext;
2412
2657
  }
2413
2658
  }
2414
2659
  return null;
2415
2660
  }
2416
2661
  for (const field of ["module", "jsnext:main", "jsnext", "main"]) {
2417
2662
  if (typeof pkg[field] === "string") {
2418
- const entry = path5.join(pkgDir, pkg[field]);
2419
- if (fs5.existsSync(entry)) return entry;
2663
+ const entry = path6.join(pkgDir, pkg[field]);
2664
+ if (fs6.existsSync(entry)) return entry;
2420
2665
  }
2421
2666
  }
2422
- const indexFallback = path5.join(pkgDir, "index.js");
2423
- if (fs5.existsSync(indexFallback)) return indexFallback;
2667
+ const indexFallback = path6.join(pkgDir, "index.js");
2668
+ if (fs6.existsSync(indexFallback)) return indexFallback;
2424
2669
  return null;
2425
2670
  }
2426
2671
  function resolvePackageExports(exports, key, pkgDir) {
2427
2672
  if (typeof exports === "string") {
2428
- return key === "." ? path5.join(pkgDir, exports) : null;
2673
+ return key === "." ? path6.join(pkgDir, exports) : null;
2429
2674
  }
2430
2675
  const entry = exports[key];
2431
2676
  if (entry === void 0) {
@@ -2437,7 +2682,7 @@ function resolvePackageExports(exports, key, pkgDir) {
2437
2682
  return resolveExportValue(entry, pkgDir);
2438
2683
  }
2439
2684
  function resolveExportValue(value, pkgDir) {
2440
- if (typeof value === "string") return path5.join(pkgDir, value);
2685
+ if (typeof value === "string") return path6.join(pkgDir, value);
2441
2686
  if (Array.isArray(value)) {
2442
2687
  for (const item of value) {
2443
2688
  const r = resolveExportValue(item, pkgDir);
@@ -2456,35 +2701,54 @@ function resolveExportValue(value, pkgDir) {
2456
2701
  return null;
2457
2702
  }
2458
2703
  function resolveUrlToFile(url, root) {
2459
- const cleanUrl = url.split("?")[0];
2704
+ const cleanUrl = url.split(/[?#]/)[0];
2460
2705
  if (cleanUrl.startsWith("/@modules/")) {
2461
2706
  const moduleName = cleanUrl.slice("/@modules/".length);
2462
2707
  return resolveNodeModule(root, moduleName);
2463
2708
  }
2464
- const filePath = path5.resolve(root, cleanUrl.replace(/^\//, ""));
2465
- if (fs5.existsSync(filePath) && fs5.statSync(filePath).isFile()) {
2709
+ if (cleanUrl.startsWith("/@fs/")) {
2710
+ let abs = cleanUrl.slice("/@fs/".length);
2711
+ if (process.platform === "win32") {
2712
+ abs = abs.replace(/\//g, path6.sep);
2713
+ } else if (!abs.startsWith("/")) {
2714
+ abs = "/" + abs;
2715
+ }
2716
+ try {
2717
+ const real = fs6.realpathSync(abs);
2718
+ if (fs6.statSync(real).isFile() && isAllowedDevModulePath(real, root)) return real;
2719
+ } catch {
2720
+ return null;
2721
+ }
2722
+ return null;
2723
+ }
2724
+ const filePath = path6.resolve(root, cleanUrl.replace(/^\//, ""));
2725
+ if (fs6.existsSync(filePath) && fs6.statSync(filePath).isFile()) {
2466
2726
  return filePath;
2467
2727
  }
2468
2728
  for (const ext of RESOLVE_EXTENSIONS) {
2469
2729
  const withExt = filePath + ext;
2470
- if (fs5.existsSync(withExt)) return withExt;
2730
+ if (fs6.existsSync(withExt)) return withExt;
2471
2731
  }
2472
2732
  for (const ext of RESOLVE_EXTENSIONS) {
2473
- const indexFile = path5.join(filePath, "index" + ext);
2474
- if (fs5.existsSync(indexFile)) return indexFile;
2733
+ const indexFile = path6.join(filePath, "index" + ext);
2734
+ if (fs6.existsSync(indexFile)) return indexFile;
2475
2735
  }
2476
2736
  return null;
2477
2737
  }
2478
2738
  function isModuleRequest(url, destination) {
2479
- const cleanUrl = url.split("?")[0];
2739
+ const cleanUrl = url.split(/[?#]/)[0];
2480
2740
  if (/\.(ts|tsx|jsx|js|mjs|vue|css|json)$/.test(cleanUrl)) return true;
2481
2741
  if (cleanUrl.startsWith("/@modules/")) return true;
2742
+ if (cleanUrl.startsWith("/@fs/")) return true;
2482
2743
  if (isAssetFile(cleanUrl)) {
2483
- const query = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
2744
+ const qIdx = url.indexOf("?");
2745
+ const hIdx = url.indexOf("#");
2746
+ const queryEnd = hIdx === -1 ? url.length : hIdx;
2747
+ const query = qIdx === -1 || qIdx > queryEnd ? "" : url.slice(qIdx + 1, queryEnd);
2484
2748
  const isExplicitAssetModule = /(?:^|&)(?:url|raw)(?:&|$)/.test(query);
2485
2749
  return isExplicitAssetModule || destination === "script";
2486
2750
  }
2487
- if (!path5.extname(cleanUrl)) return true;
2751
+ if (!path6.extname(cleanUrl)) return true;
2488
2752
  return false;
2489
2753
  }
2490
2754
  function getHmrClientCode() {
@@ -2723,7 +2987,8 @@ var init_middleware = __esm({
2723
2987
  init_env();
2724
2988
  init_url();
2725
2989
  init_assets();
2726
- __dirname_esm = path5.dirname(fileURLToPath(import.meta.url));
2990
+ init_fs_allow();
2991
+ __dirname_esm = path6.dirname(fileURLToPath(import.meta.url));
2727
2992
  __require2 = createRequire(import.meta.url);
2728
2993
  __refreshRuntimeCache = null;
2729
2994
  REACT_REFRESH_BOUNDARY_HELPERS = `
@@ -2804,8 +3069,8 @@ window.__vite_plugin_react_preamble_installed__ = true;
2804
3069
  });
2805
3070
 
2806
3071
  // src/server/hmr.ts
2807
- import path6 from "path";
2808
- import fs6 from "fs";
3072
+ import path7 from "path";
3073
+ import fs7 from "fs";
2809
3074
  import pc4 from "picocolors";
2810
3075
  async function handleFileChange(file, server, environmentName = "client", timestamp = Date.now()) {
2811
3076
  const { config } = server;
@@ -2815,9 +3080,26 @@ async function handleFileChange(file, server, environmentName = "client", timest
2815
3080
  }
2816
3081
  const moduleGraph = environment.moduleGraph;
2817
3082
  const logger = config.logger;
2818
- const relativePath = "/" + path6.relative(config.root, file);
2819
- const shortFile = path6.relative(config.root, file);
2820
- const mods = moduleGraph.getModulesByFile(file);
3083
+ const relativePath = "/" + path7.relative(config.root, file);
3084
+ const shortFile = path7.relative(config.root, file);
3085
+ let mods = moduleGraph.getModulesByFile(file);
3086
+ if (!mods || mods.size === 0) {
3087
+ try {
3088
+ const real = fs7.realpathSync(file);
3089
+ if (real !== file) mods = moduleGraph.getModulesByFile(real);
3090
+ if (mods && mods.size > 0) file = real;
3091
+ } catch {
3092
+ }
3093
+ }
3094
+ if (!mods || mods.size === 0) {
3095
+ const packageRoot = findNearestPackageRoot(file);
3096
+ if (packageRoot && getLinkedPackageRoots(config.root).some(
3097
+ (r) => packageRoot === r || packageRoot.startsWith(r + path7.sep)
3098
+ )) {
3099
+ const under = moduleGraph.getModulesWithFileUnder(packageRoot);
3100
+ if (under.size > 0) mods = under;
3101
+ }
3102
+ }
2821
3103
  if (!mods || mods.size === 0) {
2822
3104
  return null;
2823
3105
  }
@@ -2832,7 +3114,7 @@ async function handleFileChange(file, server, environmentName = "client", timest
2832
3114
  file,
2833
3115
  timestamp,
2834
3116
  modules: [mod],
2835
- read: () => fs6.readFileSync(file, "utf-8"),
3117
+ read: () => fs7.readFileSync(file, "utf-8"),
2836
3118
  server,
2837
3119
  environment
2838
3120
  };
@@ -2896,16 +3178,17 @@ async function handleFileChange(file, server, environmentName = "client", timest
2896
3178
  var init_hmr = __esm({
2897
3179
  "src/server/hmr.ts"() {
2898
3180
  "use strict";
3181
+ init_fs_allow();
2899
3182
  }
2900
3183
  });
2901
3184
 
2902
3185
  // src/plugins/resolve.ts
2903
- import path7 from "path";
2904
- import fs7 from "fs";
3186
+ import path8 from "path";
3187
+ import fs8 from "fs";
2905
3188
  import { createRequire as createRequire2 } from "module";
2906
3189
  function resolvePlugin(config) {
2907
3190
  const { alias, extensions } = config.resolve;
2908
- const require2 = createRequire2(path7.resolve(config.root, "package.json"));
3191
+ const require2 = createRequire2(path8.resolve(config.root, "package.json"));
2909
3192
  const aliasEntries = Object.entries(alias).sort(
2910
3193
  ([a], [b]) => b.length - a.length
2911
3194
  );
@@ -2913,10 +3196,10 @@ function resolvePlugin(config) {
2913
3196
  if (config.framework === "vue") {
2914
3197
  try {
2915
3198
  const vuePkgJson = require2.resolve("vue/package.json", { paths: [config.root] });
2916
- const vueDir = path7.dirname(vuePkgJson);
2917
- const mod = JSON.parse(fs7.readFileSync(vuePkgJson, "utf-8")).module;
2918
- const entry = path7.join(vueDir, mod ?? "dist/vue.runtime.esm-bundler.js");
2919
- if (fs7.existsSync(entry)) vueRuntimeEntry = entry;
3199
+ const vueDir = path8.dirname(vuePkgJson);
3200
+ const mod = JSON.parse(fs8.readFileSync(vuePkgJson, "utf-8")).module;
3201
+ const entry = path8.join(vueDir, mod ?? "dist/vue.runtime.esm-bundler.js");
3202
+ if (fs8.existsSync(entry)) vueRuntimeEntry = entry;
2920
3203
  } catch {
2921
3204
  }
2922
3205
  }
@@ -2928,24 +3211,24 @@ function resolvePlugin(config) {
2928
3211
  if (source === key || source.startsWith(key + "/")) {
2929
3212
  const aliasBase = resolveAliasTarget2(value, config.root);
2930
3213
  const sub = source.slice(key.length).replace(/^\//, "");
2931
- const target = sub ? path7.join(aliasBase, sub) : aliasBase;
3214
+ const target = sub ? path8.join(aliasBase, sub) : aliasBase;
2932
3215
  const resolved = tryResolveFile(target, extensions);
2933
3216
  if (resolved) return resolved;
2934
3217
  break;
2935
3218
  }
2936
3219
  }
2937
3220
  if (source.startsWith("/") && !source.startsWith("//")) {
2938
- const rootRelative = path7.join(config.root, source.slice(1));
3221
+ const rootRelative = path8.join(config.root, source.slice(1));
2939
3222
  const resolved = tryResolveFile(rootRelative, extensions);
2940
3223
  if (resolved) return resolved;
2941
3224
  }
2942
- if (path7.isAbsolute(source) && fs7.existsSync(source)) {
3225
+ if (path8.isAbsolute(source) && fs8.existsSync(source)) {
2943
3226
  const resolved = tryResolveFile(source, extensions);
2944
3227
  if (resolved) return resolved;
2945
3228
  }
2946
3229
  if (source.startsWith(".")) {
2947
- const dir = importer ? path7.dirname(importer) : config.root;
2948
- const absolute = path7.resolve(dir, source);
3230
+ const dir = importer ? path8.dirname(importer) : config.root;
3231
+ const absolute = path8.resolve(dir, source);
2949
3232
  const resolved = tryResolveFile(absolute, extensions);
2950
3233
  if (resolved) return resolved;
2951
3234
  }
@@ -2954,7 +3237,7 @@ function resolvePlugin(config) {
2954
3237
  if (config.command === "build") return null;
2955
3238
  try {
2956
3239
  const resolved = require2.resolve(source, {
2957
- paths: [importer ? path7.dirname(importer) : config.root]
3240
+ paths: [importer ? path8.dirname(importer) : config.root]
2958
3241
  });
2959
3242
  return resolved;
2960
3243
  } catch {
@@ -2965,9 +3248,9 @@ function resolvePlugin(config) {
2965
3248
  },
2966
3249
  load(id) {
2967
3250
  if (id.startsWith("\0")) return null;
2968
- if (!fs7.existsSync(id)) return null;
3251
+ if (!fs8.existsSync(id)) return null;
2969
3252
  if (id.endsWith(".json")) {
2970
- const content = fs7.readFileSync(id, "utf-8");
3253
+ const content = fs8.readFileSync(id, "utf-8");
2971
3254
  return `export default ${content}`;
2972
3255
  }
2973
3256
  return null;
@@ -2975,24 +3258,24 @@ function resolvePlugin(config) {
2975
3258
  };
2976
3259
  }
2977
3260
  function resolveAliasTarget2(value, root) {
2978
- if (path7.isAbsolute(value) && fs7.existsSync(value)) return value;
2979
- if (value.startsWith("/")) return path7.join(root, value.slice(1));
2980
- return path7.resolve(root, value);
3261
+ if (path8.isAbsolute(value) && fs8.existsSync(value)) return value;
3262
+ if (value.startsWith("/")) return path8.join(root, value.slice(1));
3263
+ return path8.resolve(root, value);
2981
3264
  }
2982
3265
  function tryResolveFile(file, extensions) {
2983
- if (fs7.existsSync(file) && fs7.statSync(file).isFile()) {
3266
+ if (fs8.existsSync(file) && fs8.statSync(file).isFile()) {
2984
3267
  return file;
2985
3268
  }
2986
3269
  for (const ext of extensions) {
2987
3270
  const withExt = file + ext;
2988
- if (fs7.existsSync(withExt) && fs7.statSync(withExt).isFile()) {
3271
+ if (fs8.existsSync(withExt) && fs8.statSync(withExt).isFile()) {
2989
3272
  return withExt;
2990
3273
  }
2991
3274
  }
2992
- if (fs7.existsSync(file) && fs7.statSync(file).isDirectory()) {
3275
+ if (fs8.existsSync(file) && fs8.statSync(file).isDirectory()) {
2993
3276
  for (const ext of extensions) {
2994
- const indexFile = path7.join(file, "index" + ext);
2995
- if (fs7.existsSync(indexFile)) {
3277
+ const indexFile = path8.join(file, "index" + ext);
3278
+ if (fs8.existsSync(indexFile)) {
2996
3279
  return indexFile;
2997
3280
  }
2998
3281
  }
@@ -3040,27 +3323,27 @@ var require_process = __commonJS({
3040
3323
  var require_filesystem = __commonJS({
3041
3324
  "node_modules/detect-libc/lib/filesystem.js"(exports, module) {
3042
3325
  "use strict";
3043
- var fs13 = __require("fs");
3326
+ var fs14 = __require("fs");
3044
3327
  var LDD_PATH = "/usr/bin/ldd";
3045
3328
  var SELF_PATH = "/proc/self/exe";
3046
3329
  var MAX_LENGTH = 2048;
3047
- var readFileSync = (path18) => {
3048
- const fd = fs13.openSync(path18, "r");
3330
+ var readFileSync = (path19) => {
3331
+ const fd = fs14.openSync(path19, "r");
3049
3332
  const buffer = Buffer.alloc(MAX_LENGTH);
3050
- const bytesRead = fs13.readSync(fd, buffer, 0, MAX_LENGTH, 0);
3051
- fs13.close(fd, () => {
3333
+ const bytesRead = fs14.readSync(fd, buffer, 0, MAX_LENGTH, 0);
3334
+ fs14.close(fd, () => {
3052
3335
  });
3053
3336
  return buffer.subarray(0, bytesRead);
3054
3337
  };
3055
- var readFile = (path18) => new Promise((resolve, reject) => {
3056
- fs13.open(path18, "r", (err, fd) => {
3338
+ var readFile = (path19) => new Promise((resolve, reject) => {
3339
+ fs14.open(path19, "r", (err, fd) => {
3057
3340
  if (err) {
3058
3341
  reject(err);
3059
3342
  } else {
3060
3343
  const buffer = Buffer.alloc(MAX_LENGTH);
3061
- fs13.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
3344
+ fs14.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
3062
3345
  resolve(buffer.subarray(0, bytesRead));
3063
- fs13.close(fd, () => {
3346
+ fs14.close(fd, () => {
3064
3347
  });
3065
3348
  });
3066
3349
  }
@@ -3172,11 +3455,11 @@ var require_detect_libc = __commonJS({
3172
3455
  }
3173
3456
  return null;
3174
3457
  };
3175
- var familyFromInterpreterPath = (path18) => {
3176
- if (path18) {
3177
- if (path18.includes("/ld-musl-")) {
3458
+ var familyFromInterpreterPath = (path19) => {
3459
+ if (path19) {
3460
+ if (path19.includes("/ld-musl-")) {
3178
3461
  return MUSL;
3179
- } else if (path18.includes("/ld-linux-")) {
3462
+ } else if (path19.includes("/ld-linux-")) {
3180
3463
  return GLIBC;
3181
3464
  }
3182
3465
  }
@@ -3223,8 +3506,8 @@ var require_detect_libc = __commonJS({
3223
3506
  cachedFamilyInterpreter = null;
3224
3507
  try {
3225
3508
  const selfContent = await readFile(SELF_PATH);
3226
- const path18 = interpreterPath(selfContent);
3227
- cachedFamilyInterpreter = familyFromInterpreterPath(path18);
3509
+ const path19 = interpreterPath(selfContent);
3510
+ cachedFamilyInterpreter = familyFromInterpreterPath(path19);
3228
3511
  } catch (e) {
3229
3512
  }
3230
3513
  return cachedFamilyInterpreter;
@@ -3236,8 +3519,8 @@ var require_detect_libc = __commonJS({
3236
3519
  cachedFamilyInterpreter = null;
3237
3520
  try {
3238
3521
  const selfContent = readFileSync(SELF_PATH);
3239
- const path18 = interpreterPath(selfContent);
3240
- cachedFamilyInterpreter = familyFromInterpreterPath(path18);
3522
+ const path19 = interpreterPath(selfContent);
3523
+ cachedFamilyInterpreter = familyFromInterpreterPath(path19);
3241
3524
  } catch (e) {
3242
3525
  }
3243
3526
  return cachedFamilyInterpreter;
@@ -3956,7 +4239,7 @@ var init_css_engine = __esm({
3956
4239
  });
3957
4240
 
3958
4241
  // src/plugins/tailwind.ts
3959
- import path8 from "path";
4242
+ import path9 from "path";
3960
4243
  import { createRequire as createRequire3 } from "module";
3961
4244
  import { pathToFileURL as pathToFileURL3 } from "url";
3962
4245
  function hasTailwindDirectives(css) {
@@ -3966,7 +4249,7 @@ function hasTailwindDirectives(css) {
3966
4249
  }
3967
4250
  async function loadTailwind(projectRoot) {
3968
4251
  if (cached && cachedRoot === projectRoot) return cached;
3969
- const req = createRequire3(path8.join(projectRoot, "package.json"));
4252
+ const req = createRequire3(path9.join(projectRoot, "package.json"));
3970
4253
  let nodePath;
3971
4254
  let oxidePath;
3972
4255
  try {
@@ -3987,7 +4270,7 @@ async function compileTailwind(css, fromFile, projectRoot) {
3987
4270
  const { node, oxide } = await loadTailwind(projectRoot);
3988
4271
  const dependencies = [];
3989
4272
  const compiler2 = await node.compile(css, {
3990
- base: path8.dirname(fromFile),
4273
+ base: path9.dirname(fromFile),
3991
4274
  from: fromFile,
3992
4275
  onDependency: (p) => dependencies.push(p)
3993
4276
  });
@@ -4009,7 +4292,7 @@ var init_tailwind = __esm({
4009
4292
  });
4010
4293
 
4011
4294
  // src/plugins/css.ts
4012
- import path9 from "path";
4295
+ import path10 from "path";
4013
4296
  import { SourceMapGenerator } from "source-map-js";
4014
4297
  function cssPlugin(config, engine, consumer = "client") {
4015
4298
  return {
@@ -4133,8 +4416,8 @@ function rewriteCssUrls(css, from, root) {
4133
4416
  if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
4134
4417
  return match;
4135
4418
  }
4136
- const resolved = path9.resolve(path9.dirname(from), url);
4137
- const relative = "/" + path9.relative(root, resolved).replace(/\\/g, "/");
4419
+ const resolved = path10.resolve(path10.dirname(from), url);
4420
+ const relative = "/" + path10.relative(root, resolved).replace(/\\/g, "/");
4138
4421
  return `url(${relative})`;
4139
4422
  });
4140
4423
  }
@@ -4264,8 +4547,8 @@ function vuePlugin(config, environmentName = "client") {
4264
4547
  let cached2 = descriptorCache.get(filePath);
4265
4548
  if (!cached2) {
4266
4549
  try {
4267
- const fs13 = await import("fs");
4268
- const rawSource = fs13.readFileSync(filePath, "utf-8");
4550
+ const fs14 = await import("fs");
4551
+ const rawSource = fs14.readFileSync(filePath, "utf-8");
4269
4552
  const transformedSfc = await applySourceTransform(
4270
4553
  vueOptions.transformSfc,
4271
4554
  rawSource,
@@ -4693,8 +4976,8 @@ __export(runnable_environment_exports, {
4693
4976
  NastiModuleRunner: () => NastiModuleRunner,
4694
4977
  createModuleRunner: () => createModuleRunner
4695
4978
  });
4696
- import path10 from "path";
4697
- import fs8 from "fs";
4979
+ import path11 from "path";
4980
+ import fs9 from "fs";
4698
4981
  import { builtinModules, createRequire as createRequire4 } from "module";
4699
4982
  import { pathToFileURL as pathToFileURL4 } from "url";
4700
4983
  function createModuleRunner(environment) {
@@ -4728,7 +5011,7 @@ var init_runnable_environment = __esm({
4728
5011
  this.config.mode,
4729
5012
  ssrDefineOverrides(environment.consumer)
4730
5013
  );
4731
- this.require = createRequire4(path10.join(this.config.root, "package.json"));
5014
+ this.require = createRequire4(path11.join(this.config.root, "package.json"));
4732
5015
  const handlers = {
4733
5016
  fetchModule: async (id, importer) => this.fetchModule(id, importer),
4734
5017
  getBuiltins: () => [/^node:/, ...builtinModules]
@@ -4752,9 +5035,9 @@ var init_runnable_environment = __esm({
4752
5035
  this.cache.clear();
4753
5036
  }
4754
5037
  resolveToId(rawUrl) {
4755
- if (path10.isAbsolute(rawUrl) && fs8.existsSync(rawUrl.split("?")[0])) return rawUrl;
5038
+ if (path11.isAbsolute(rawUrl) && fs9.existsSync(rawUrl.split("?")[0])) return rawUrl;
4756
5039
  const clean = rawUrl.replace(/^\//, "");
4757
- return path10.resolve(this.config.root, clean);
5040
+ return path11.resolve(this.config.root, clean);
4758
5041
  }
4759
5042
  /**
4760
5043
  * fetchModule(invoke 契约方法):环境管线产出 runner 可执行代码。
@@ -4763,14 +5046,14 @@ var init_runnable_environment = __esm({
4763
5046
  */
4764
5047
  async fetchModule(id, importer) {
4765
5048
  if (NODE_BUILTINS.has(id)) return { externalize: id };
4766
- if (!id.startsWith(".") && !path10.isAbsolute(id) && !id.startsWith("\0")) {
5049
+ if (!id.startsWith(".") && !path11.isAbsolute(id) && !id.startsWith("\0")) {
4767
5050
  return { externalize: id };
4768
5051
  }
4769
5052
  const container = this.environment.pluginContainer;
4770
5053
  let resolvedId = id;
4771
5054
  if (id.startsWith(".") && importer) {
4772
5055
  const resolved = await container.resolveId(id, importer);
4773
- resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id : path10.resolve(path10.dirname(importer.split("?")[0]), id);
5056
+ resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id : path11.resolve(path11.dirname(importer.split("?")[0]), id);
4774
5057
  }
4775
5058
  resolvedId = this.completeExtension(resolvedId);
4776
5059
  const cleanId = resolvedId.split("?")[0];
@@ -4778,8 +5061,8 @@ var init_runnable_environment = __esm({
4778
5061
  const loaded = await container.load(resolvedId);
4779
5062
  if (loaded != null) {
4780
5063
  code = typeof loaded === "string" ? loaded : loaded.code;
4781
- } else if (fs8.existsSync(cleanId)) {
4782
- code = fs8.readFileSync(cleanId, "utf-8");
5064
+ } else if (fs9.existsSync(cleanId)) {
5065
+ code = fs9.readFileSync(cleanId, "utf-8");
4783
5066
  } else {
4784
5067
  throw new Error(`[nasti:ssr] cannot load module: ${resolvedId}`);
4785
5068
  }
@@ -4787,12 +5070,32 @@ var init_runnable_environment = __esm({
4787
5070
  if (transformed != null) {
4788
5071
  code = typeof transformed === "string" ? transformed : transformed.code;
4789
5072
  }
4790
- if (shouldTransform(cleanId)) {
5073
+ if (this.config.framework === "react") {
5074
+ const result = await transformReactCode(cleanId, code, {
5075
+ react: this.config.react,
5076
+ consumer: this.environment.consumer,
5077
+ development: true,
5078
+ sourcemap: false,
5079
+ target: this.environment.options.build.target,
5080
+ onWarning: (message) => this.config.logger.warn(`[nasti:react] ${message}`)
5081
+ });
5082
+ if (result) {
5083
+ code = result.code;
5084
+ } else if (shouldTransform(cleanId)) {
5085
+ const fallback = transformCode(cleanId, code, {
5086
+ sourcemap: false,
5087
+ jsxRuntime: this.config.react.jsxRuntime,
5088
+ jsxImportSource: this.config.react.jsxImportSource,
5089
+ target: this.environment.options.build.target
5090
+ });
5091
+ code = fallback.code;
5092
+ }
5093
+ } else if (shouldTransform(cleanId)) {
4791
5094
  const result = transformCode(cleanId, code, {
4792
5095
  sourcemap: false,
4793
5096
  target: this.environment.options.build.target,
4794
5097
  jsxRuntime: "automatic",
4795
- jsxImportSource: this.config.framework === "vue" ? "vue" : "react"
5098
+ jsxImportSource: "vue"
4796
5099
  });
4797
5100
  code = result.code;
4798
5101
  }
@@ -4813,19 +5116,19 @@ var init_runnable_environment = __esm({
4813
5116
  completeExtension(id) {
4814
5117
  const clean = id.split("?")[0];
4815
5118
  const query = id.includes("?") ? id.slice(id.indexOf("?")) : "";
4816
- if (fs8.existsSync(clean) && fs8.statSync(clean).isFile()) return id;
5119
+ if (fs9.existsSync(clean) && fs9.statSync(clean).isFile()) return id;
4817
5120
  const jsMatch = clean.match(/^(.*)\.([mc]?)jsx?$/);
4818
5121
  if (jsMatch) {
4819
5122
  for (const tsExt of [`.${jsMatch[2]}ts`, `.${jsMatch[2]}tsx`]) {
4820
- if (fs8.existsSync(jsMatch[1] + tsExt)) return jsMatch[1] + tsExt + query;
5123
+ if (fs9.existsSync(jsMatch[1] + tsExt)) return jsMatch[1] + tsExt + query;
4821
5124
  }
4822
5125
  }
4823
5126
  for (const ext of this.config.resolve.extensions) {
4824
- if (fs8.existsSync(clean + ext)) return clean + ext + query;
5127
+ if (fs9.existsSync(clean + ext)) return clean + ext + query;
4825
5128
  }
4826
5129
  for (const ext of this.config.resolve.extensions) {
4827
- const indexPath = path10.join(clean, `index${ext}`);
4828
- if (fs8.existsSync(indexPath)) return indexPath;
5130
+ const indexPath = path11.join(clean, `index${ext}`);
5131
+ if (fs9.existsSync(indexPath)) return indexPath;
4829
5132
  }
4830
5133
  return id;
4831
5134
  }
@@ -4852,10 +5155,10 @@ var init_runnable_environment = __esm({
4852
5155
  return;
4853
5156
  }
4854
5157
  const ssrImport = async (dep) => {
4855
- if (NODE_BUILTINS.has(dep) || !dep.startsWith(".") && !path10.isAbsolute(dep) && !dep.startsWith("\0")) {
5158
+ if (NODE_BUILTINS.has(dep) || !dep.startsWith(".") && !path11.isAbsolute(dep) && !dep.startsWith("\0")) {
4856
5159
  return this.importExternal(dep);
4857
5160
  }
4858
- const depId = dep.startsWith(".") ? this.completeExtension(path10.resolve(path10.dirname(fetched.id.split("?")[0]), dep)) : this.completeExtension(dep);
5161
+ const depId = dep.startsWith(".") ? this.completeExtension(path11.resolve(path11.dirname(fetched.id.split("?")[0]), dep)) : this.completeExtension(dep);
4859
5162
  return this.instantiate(depId);
4860
5163
  };
4861
5164
  const ssrExportAll = (sourceModule) => {
@@ -4887,7 +5190,7 @@ var init_runnable_environment = __esm({
4887
5190
  }
4888
5191
  async importExternal(spec) {
4889
5192
  try {
4890
- return await (spec.startsWith("node:") || !path10.isAbsolute(spec) ? import(this.resolveExternalSpecifier(spec)) : import(pathToFileURL4(spec).href));
5193
+ return await (spec.startsWith("node:") || !path11.isAbsolute(spec) ? import(this.resolveExternalSpecifier(spec)) : import(pathToFileURL4(spec).href));
4891
5194
  } catch (err) {
4892
5195
  throw new Error(`[nasti:ssr] failed to import external "${spec}": ${err.message}`);
4893
5196
  }
@@ -4908,8 +5211,46 @@ var init_runnable_environment = __esm({
4908
5211
  }
4909
5212
  });
4910
5213
 
5214
+ // src/plugins/react.ts
5215
+ function reactPlugin(config, environment) {
5216
+ return {
5217
+ name: "nasti:oxc-transform",
5218
+ async transform(code, id) {
5219
+ const result = await transformReactCode(id, code, {
5220
+ react: config.react,
5221
+ consumer: environment.consumer,
5222
+ development: config.mode === "development",
5223
+ sourcemap: !!environment.options.build.sourcemap,
5224
+ target: environment.options.build.target,
5225
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
5226
+ });
5227
+ if (!result) return null;
5228
+ return {
5229
+ code: result.code,
5230
+ map: result.map ? JSON.parse(result.map) : void 0
5231
+ };
5232
+ },
5233
+ handleHotUpdate(ctx) {
5234
+ for (const mod of ctx.modules) {
5235
+ if (REACT_FILE_RE.test(mod.url) && matchesReactFilter(mod.url, config.react.include, config.react.exclude)) {
5236
+ mod.isSelfAccepting = true;
5237
+ }
5238
+ }
5239
+ return ctx.modules;
5240
+ }
5241
+ };
5242
+ }
5243
+ var REACT_FILE_RE;
5244
+ var init_react = __esm({
5245
+ "src/plugins/react.ts"() {
5246
+ "use strict";
5247
+ init_transformer();
5248
+ REACT_FILE_RE = /\.[jt]sx(?:[?#].*)?$/;
5249
+ }
5250
+ });
5251
+
4911
5252
  // src/build/reporter.ts
4912
- import path11 from "path";
5253
+ import path12 from "path";
4913
5254
  import { gzipSync } from "zlib";
4914
5255
  import pc5 from "picocolors";
4915
5256
  async function tryNativeReporterPlugin(config, logger) {
@@ -4950,7 +5291,7 @@ function reportBuildOutput(output, config, logger) {
4950
5291
  if (compressed && content != null) {
4951
5292
  gzip = gzipSync(typeof content === "string" ? Buffer.from(content) : content).byteLength;
4952
5293
  }
4953
- const ext = path11.extname(file.fileName);
5294
+ const ext = path12.extname(file.fileName);
4954
5295
  const group = file.type === "chunk" ? "js" : ext === ".css" ? "css" : "assets";
4955
5296
  entries.push({ name: file.fileName, size, gzip, group });
4956
5297
  }
@@ -4998,12 +5339,12 @@ var init_reporter = __esm({
4998
5339
  });
4999
5340
 
5000
5341
  // src/core/build-app-context.ts
5001
- import fs9 from "fs";
5002
- import path12 from "path";
5342
+ import fs10 from "fs";
5343
+ import path13 from "path";
5003
5344
  function createBuildAppContext(config, results) {
5004
5345
  const output = [];
5005
5346
  const emitted = /* @__PURE__ */ new Set();
5006
- const outDir = path12.resolve(config.root, config.build.outDir);
5347
+ const outDir = path13.resolve(config.root, config.build.outDir);
5007
5348
  let environmentArtifacts;
5008
5349
  return {
5009
5350
  config,
@@ -5059,14 +5400,14 @@ function createBuildAppContext(config, results) {
5059
5400
  if (environmentArtifacts.has(collisionKey)) {
5060
5401
  throw new Error(`[nasti] app artifact conflicts with environment output: ${fileName}`);
5061
5402
  }
5062
- const target = path12.resolve(outDir, ...fileName.split("/"));
5063
- const relative = path12.relative(outDir, target);
5064
- if (relative.startsWith("..") || path12.isAbsolute(relative)) {
5403
+ const target = path13.resolve(outDir, ...fileName.split("/"));
5404
+ const relative = path13.relative(outDir, target);
5405
+ if (relative.startsWith("..") || path13.isAbsolute(relative)) {
5065
5406
  throw new Error(`[nasti] app artifact must stay inside build.outDir: ${file.fileName}`);
5066
5407
  }
5067
5408
  assertNoSymlinkComponents(outDir, fileName);
5068
- fs9.mkdirSync(path12.dirname(target), { recursive: true });
5069
- fs9.writeFileSync(target, file.source);
5409
+ fs10.mkdirSync(path13.dirname(target), { recursive: true });
5410
+ fs10.writeFileSync(target, file.source);
5070
5411
  const artifact = {
5071
5412
  ...file,
5072
5413
  fileName,
@@ -5082,10 +5423,10 @@ function joinPublicPath(base, fileName) {
5082
5423
  return `${base.endsWith("/") ? base : `${base}/`}${fileName.replace(/^\//, "")}`;
5083
5424
  }
5084
5425
  function normalizeEnvironmentFileName(fileName) {
5085
- return path12.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
5426
+ return path13.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
5086
5427
  }
5087
5428
  function isInvalidEnvironmentFileName(fileName) {
5088
- return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || path12.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
5429
+ return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || path13.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
5089
5430
  }
5090
5431
  function normalizeAppFileName(fileName) {
5091
5432
  const normalized = normalizeEnvironmentFileName(fileName);
@@ -5102,14 +5443,14 @@ function collectEnvironmentArtifacts(config, results, appOutDir) {
5102
5443
  for (const [environmentName, result] of Object.entries(results)) {
5103
5444
  const environment = config.environments[environmentName];
5104
5445
  if (!environment) continue;
5105
- const environmentOutDir = path12.resolve(config.root, environment.build.outDir);
5446
+ const environmentOutDir = path13.resolve(config.root, environment.build.outDir);
5106
5447
  for (const artifact of result.output) {
5107
- const artifactPath = path12.resolve(
5448
+ const artifactPath = path13.resolve(
5108
5449
  environmentOutDir,
5109
5450
  ...normalizeEnvironmentFileName(artifact.fileName).split("/")
5110
5451
  );
5111
- const relative = path12.relative(appOutDir, artifactPath);
5112
- if (!relative.startsWith("..") && !path12.isAbsolute(relative)) {
5452
+ const relative = path13.relative(appOutDir, artifactPath);
5453
+ if (!relative.startsWith("..") && !path13.isAbsolute(relative)) {
5113
5454
  occupied.add(artifactCollisionKey(relative));
5114
5455
  }
5115
5456
  }
@@ -5119,10 +5460,10 @@ function collectEnvironmentArtifacts(config, results, appOutDir) {
5119
5460
  function assertNoSymlinkComponents(outDir, fileName) {
5120
5461
  let current = outDir;
5121
5462
  for (const segment of fileName.split("/")) {
5122
- current = path12.join(current, segment);
5463
+ current = path13.join(current, segment);
5123
5464
  let stats;
5124
5465
  try {
5125
- stats = fs9.lstatSync(current);
5466
+ stats = fs10.lstatSync(current);
5126
5467
  } catch (error) {
5127
5468
  if (error.code === "ENOENT") continue;
5128
5469
  throw error;
@@ -5155,8 +5496,8 @@ __export(build_exports, {
5155
5496
  resolveClientEntries: () => resolveClientEntries,
5156
5497
  toRolldownPlugins: () => toRolldownPlugins
5157
5498
  });
5158
- import path13 from "path";
5159
- import fs10 from "fs";
5499
+ import path14 from "path";
5500
+ import fs11 from "fs";
5160
5501
  import { builtinModules as builtinModules2 } from "module";
5161
5502
  import { rolldown } from "rolldown";
5162
5503
  import pc6 from "picocolors";
@@ -5164,7 +5505,7 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
5164
5505
  const config = environment.config;
5165
5506
  const envOptions = environment.options;
5166
5507
  const isServer = environment.consumer === "server";
5167
- const outDir = path13.resolve(config.root, envOptions.build.outDir);
5508
+ const outDir = path14.resolve(config.root, envOptions.build.outDir);
5168
5509
  const assetsDir = envOptions.build.assetsDir;
5169
5510
  const {
5170
5511
  output: userOutput,
@@ -5204,7 +5545,7 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
5204
5545
  // 相对/绝对/虚拟模块照常打包。需要内联依赖时经 rolldownOptions.external 覆盖。
5205
5546
  external: restInputOptions.external ?? ((id) => {
5206
5547
  if (NODE_BUILTINS2.has(id)) return true;
5207
- return !id.startsWith(".") && !path13.isAbsolute(id) && !id.startsWith("\0");
5548
+ return !id.startsWith(".") && !path14.isAbsolute(id) && !id.startsWith("\0") && !id.startsWith("virtual:");
5208
5549
  })
5209
5550
  } : {}
5210
5551
  };
@@ -5361,11 +5702,11 @@ function prepareBuildOutputDirectories(config, buildableNames) {
5361
5702
  const protectedPaths = /* @__PURE__ */ new Set();
5362
5703
  const clientIsBuilt = buildableNames.includes("client");
5363
5704
  if (!clientIsBuilt && config.build.emptyOutDir) {
5364
- directories.add(path13.resolve(config.root, config.build.outDir));
5705
+ directories.add(path14.resolve(config.root, config.build.outDir));
5365
5706
  }
5366
5707
  for (const name of buildableNames) {
5367
5708
  const environment = config.environments[name];
5368
- const outDir = path13.resolve(config.root, environment.build.outDir);
5709
+ const outDir = path14.resolve(config.root, environment.build.outDir);
5369
5710
  if (!environment.build.emptyOutDir) {
5370
5711
  protectedPaths.add(outDir);
5371
5712
  continue;
@@ -5373,8 +5714,8 @@ function prepareBuildOutputDirectories(config, buildableNames) {
5373
5714
  if (!environment.driver) directories.add(outDir);
5374
5715
  }
5375
5716
  const containsPath = (parent, child) => {
5376
- const relative = path13.relative(parent, child);
5377
- return relative === "" || !relative.startsWith("..") && !path13.isAbsolute(relative);
5717
+ const relative = path14.relative(parent, child);
5718
+ return relative === "" || !relative.startsWith("..") && !path14.isAbsolute(relative);
5378
5719
  };
5379
5720
  const roots = [...directories].filter(
5380
5721
  (directory) => ![...protectedPaths].some((protectedPath) => containsPath(directory, protectedPath))
@@ -5382,7 +5723,7 @@ function prepareBuildOutputDirectories(config, buildableNames) {
5382
5723
  (directory, index2, all) => !all.slice(0, index2).some((parent) => containsPath(parent, directory))
5383
5724
  );
5384
5725
  for (const directory of roots) {
5385
- if (fs10.existsSync(directory)) fs10.rmSync(directory, { recursive: true, force: true });
5726
+ if (fs11.existsSync(directory)) fs11.rmSync(directory, { recursive: true, force: true });
5386
5727
  }
5387
5728
  }
5388
5729
  function assertDriverBuildResult(environment, result) {
@@ -5401,7 +5742,7 @@ function resolveClientEntries(config, html) {
5401
5742
  if (configuredEntries.length > 0) return configuredEntries;
5402
5743
  const entryPoints = [];
5403
5744
  const htmlFile = config.environments.client?.html;
5404
- const htmlDir = htmlFile ? path13.dirname(htmlFile) : config.root;
5745
+ const htmlDir = htmlFile ? path14.dirname(htmlFile) : config.root;
5405
5746
  if (html) {
5406
5747
  const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
5407
5748
  for (const match of scriptMatches) {
@@ -5409,7 +5750,7 @@ function resolveClientEntries(config, html) {
5409
5750
  if (src && !src.startsWith("http")) {
5410
5751
  const cleanSrc = src.split(/[?#]/, 1)[0];
5411
5752
  entryPoints.push(
5412
- cleanSrc.startsWith("/") ? path13.resolve(config.root, cleanSrc.replace(/^\//, "")) : path13.resolve(htmlDir, cleanSrc)
5753
+ cleanSrc.startsWith("/") ? path14.resolve(config.root, cleanSrc.replace(/^\//, "")) : path14.resolve(htmlDir, cleanSrc)
5413
5754
  );
5414
5755
  }
5415
5756
  }
@@ -5417,8 +5758,8 @@ function resolveClientEntries(config, html) {
5417
5758
  if (entryPoints.length === 0) {
5418
5759
  const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
5419
5760
  for (const entry of fallbackEntries) {
5420
- const fullPath = path13.resolve(config.root, entry);
5421
- if (fs10.existsSync(fullPath)) {
5761
+ const fullPath = path14.resolve(config.root, entry);
5762
+ if (fs11.existsSync(fullPath)) {
5422
5763
  entryPoints.push(fullPath);
5423
5764
  break;
5424
5765
  }
@@ -5427,6 +5768,7 @@ function resolveClientEntries(config, html) {
5427
5768
  return entryPoints;
5428
5769
  }
5429
5770
  function createOxcTransformPlugin(config, environment) {
5771
+ if (config.framework === "react") return reactPlugin(config, environment);
5430
5772
  return {
5431
5773
  name: "nasti:oxc-transform",
5432
5774
  transform(code, id) {
@@ -5447,7 +5789,7 @@ async function build(inlineConfig = {}) {
5447
5789
  const startTime = performance.now();
5448
5790
  logger.info(
5449
5791
  pc6.cyan(`
5450
- nasti v${"2.4.3"} `) + pc6.green(`building for ${config.mode}...`)
5792
+ nasti v${"2.5.0"} `) + pc6.green(`building for ${config.mode}...`)
5451
5793
  );
5452
5794
  debug6?.(`root: ${config.root}`);
5453
5795
  const buildableNames = Object.keys(config.environments).filter((name) => {
@@ -5522,7 +5864,7 @@ nasti v${"2.4.3"} `) + pc6.green(`building for ${config.mode}...`)
5522
5864
  }
5523
5865
  async function buildClientEnvironment(config) {
5524
5866
  const logger = config.logger;
5525
- const outDir = path13.resolve(config.root, config.build.outDir);
5867
+ const outDir = path14.resolve(config.root, config.build.outDir);
5526
5868
  const cssEngine = createCssEngine();
5527
5869
  const pluginList = resolvePluginList(config, config.plugins, {
5528
5870
  cssEngine,
@@ -5545,8 +5887,8 @@ async function buildClientEnvironment(config) {
5545
5887
  assertDriverBuildResult(clientEnv, result);
5546
5888
  return { environment: clientEnv, result: finalizeEnvironmentResult(clientEnv, result) };
5547
5889
  }
5548
- fs10.mkdirSync(outDir, { recursive: true });
5549
- const htmlFile = config.environments.client.html ?? path13.resolve(config.root, "index.html");
5890
+ fs11.mkdirSync(outDir, { recursive: true });
5891
+ const htmlFile = config.environments.client.html ?? path14.resolve(config.root, "index.html");
5550
5892
  const html = await readHtmlFile(config.root, htmlFile);
5551
5893
  const entryPoints = resolveClientEntries(config, html);
5552
5894
  if (entryPoints.length === 0) {
@@ -5596,7 +5938,7 @@ async function buildClientEnvironment(config) {
5596
5938
  );
5597
5939
  }
5598
5940
  }
5599
- fs10.writeFileSync(path13.resolve(outDir, "index.html"), processedHtml);
5941
+ fs11.writeFileSync(path14.resolve(outDir, "index.html"), processedHtml);
5600
5942
  }
5601
5943
  if (!nativeReporter && config.logLevel !== "silent") {
5602
5944
  reportBuildOutput(output, config, logger);
@@ -5650,7 +5992,7 @@ async function buildServerEnvironment(config, name) {
5650
5992
  }
5651
5993
  }
5652
5994
  for (const entry of envOptions.entry) {
5653
- if (!fs10.existsSync(entry)) {
5995
+ if (!fs11.existsSync(entry)) {
5654
5996
  await environment.close();
5655
5997
  throw new Error(`[nasti] environment "${name}" entry not found: ${entry}`);
5656
5998
  }
@@ -5664,13 +6006,13 @@ async function buildServerEnvironment(config, name) {
5664
6006
  envOptions.entry,
5665
6007
  rolldownPlugins
5666
6008
  );
5667
- fs10.mkdirSync(outDir, { recursive: true });
6009
+ fs11.mkdirSync(outDir, { recursive: true });
5668
6010
  const bundle2 = await rolldown(inputOptions);
5669
6011
  const { output } = await bundle2.write(outputOptions);
5670
6012
  await bundle2.close();
5671
6013
  if (cssEngine) environment.setBuildMetadata({ css: getCssMetadata(cssEngine) });
5672
6014
  logger.info(
5673
- pc6.dim(` [${name}] `) + output.map((o) => path13.join(envOptions.build.outDir, o.fileName)).join(pc6.dim(", "))
6015
+ pc6.dim(` [${name}] `) + output.map((o) => path14.join(envOptions.build.outDir, o.fileName)).join(pc6.dim(", "))
5674
6016
  );
5675
6017
  return {
5676
6018
  environment,
@@ -5702,9 +6044,9 @@ function escapeRegExp(string) {
5702
6044
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5703
6045
  }
5704
6046
  function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, urlPrefix) {
5705
- const rootRelative = path13.relative(config.root, facadeModuleId).split(path13.sep).join("/");
5706
- const resolvedHtmlFile = path13.resolve(config.root, htmlFile);
5707
- const htmlRelative = path13.relative(path13.dirname(resolvedHtmlFile), facadeModuleId).split(path13.sep).join("/");
6047
+ const rootRelative = path14.relative(config.root, facadeModuleId).split(path14.sep).join("/");
6048
+ const resolvedHtmlFile = path14.resolve(config.root, htmlFile);
6049
+ const htmlRelative = path14.relative(path14.dirname(resolvedHtmlFile), facadeModuleId).split(path14.sep).join("/");
5708
6050
  const candidates = /* @__PURE__ */ new Set([
5709
6051
  rootRelative,
5710
6052
  `/${rootRelative}`,
@@ -5729,6 +6071,7 @@ var init_build = __esm({
5729
6071
  init_environment();
5730
6072
  init_css_engine();
5731
6073
  init_html();
6074
+ init_react();
5732
6075
  init_transformer();
5733
6076
  init_env();
5734
6077
  init_reporter();
@@ -5745,7 +6088,7 @@ var dev_engine_exports = {};
5745
6088
  __export(dev_engine_exports, {
5746
6089
  createBundledDevServer: () => createBundledDevServer
5747
6090
  });
5748
- import path14 from "path";
6091
+ import path15 from "path";
5749
6092
  import crypto3 from "crypto";
5750
6093
  import { WebSocketServer as WsServer2 } from "ws";
5751
6094
  import pc7 from "picocolors";
@@ -5775,11 +6118,11 @@ async function createBundledDevServer(opts) {
5775
6118
  const patches = new MemoryFiles();
5776
6119
  const entryFileNames = /* @__PURE__ */ new Map();
5777
6120
  const bundledClients = /* @__PURE__ */ new Map();
5778
- const useReactRefresh = config.framework !== "vue" && refreshWrapperFn != null;
6121
+ const useReactRefresh = config.framework === "react" && config.server.hmr !== false && refreshWrapperFn != null;
5779
6122
  const rolldownPlugins = [
5780
6123
  ...useReactRefresh ? [
5781
6124
  createReactRefreshRuntimePlugin(entryPoints),
5782
- createBundledOxcRefreshPlugin()
6125
+ createBundledOxcRefreshPlugin(config)
5783
6126
  ] : [],
5784
6127
  ...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins, clientEnv)),
5785
6128
  ...useReactRefresh ? [
@@ -5830,7 +6173,7 @@ async function createBundledDevServer(opts) {
5830
6173
  }
5831
6174
  const url = `/${patchPath}`;
5832
6175
  logger.info(
5833
- pc7.green("hmr update ") + pc7.dim(changedFiles.map((f) => path14.relative(config.root, f)).join(", ")),
6176
+ pc7.green("hmr update ") + pc7.dim(changedFiles.map((f) => path15.relative(config.root, f)).join(", ")),
5834
6177
  { timestamp: true }
5835
6178
  );
5836
6179
  sendTo(clientId, { type: "hmr:update", path: url, url });
@@ -5985,7 +6328,7 @@ async function createBundledDevServer(opts) {
5985
6328
  return;
5986
6329
  }
5987
6330
  res.setHeader("ETag", hit.etag);
5988
- res.setHeader("Content-Type", MIME_TYPES[path14.extname(fileName)] ?? "application/octet-stream");
6331
+ res.setHeader("Content-Type", MIME_TYPES[path15.extname(fileName)] ?? "application/octet-stream");
5989
6332
  res.setHeader("Cache-Control", "no-cache");
5990
6333
  res.once("finish", () => {
5991
6334
  void engine.notifyPayloadDelivered(fileName).catch(
@@ -6026,7 +6369,7 @@ function stripCatchAllLoad(plugins) {
6026
6369
  );
6027
6370
  }
6028
6371
  function createReactRefreshRuntimePlugin(entryPoints) {
6029
- const entryIds = new Set(entryPoints.map((p) => path14.resolve(p)));
6372
+ const entryIds = new Set(entryPoints.map((p) => path15.resolve(p)));
6030
6373
  return {
6031
6374
  name: "nasti:bundled-react-refresh",
6032
6375
  resolveId(source) {
@@ -6044,24 +6387,27 @@ function createReactRefreshRuntimePlugin(entryPoints) {
6044
6387
  return null;
6045
6388
  },
6046
6389
  transform(code, id) {
6047
- if (!entryIds.has(path14.resolve(id.split("?")[0]))) return null;
6390
+ if (!entryIds.has(path15.resolve(id.split("?")[0]))) return null;
6048
6391
  return { code: `import ${JSON.stringify(PREAMBLE_SPEC)};
6049
6392
  ${code}`, map: null };
6050
6393
  }
6051
6394
  };
6052
6395
  }
6053
- function createBundledOxcRefreshPlugin() {
6396
+ function createBundledOxcRefreshPlugin(config) {
6054
6397
  return {
6055
6398
  name: "nasti:bundled-oxc-refresh",
6056
- transform(code, id) {
6399
+ async transform(code, id) {
6057
6400
  const clean = id.split("?")[0];
6058
- if (!/\.[jt]sx$/.test(clean) || clean.includes("/node_modules/")) return null;
6059
- const result = transformCode(clean, code, {
6401
+ const result = await transformReactCode(clean, code, {
6402
+ react: config.react,
6403
+ consumer: "client",
6404
+ development: true,
6405
+ reactRefresh: true,
6060
6406
  sourcemap: true,
6061
- jsxRuntime: "automatic",
6062
- jsxImportSource: "react",
6063
- reactRefresh: true
6407
+ target: config.build.target,
6408
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
6064
6409
  });
6410
+ if (!result) return null;
6065
6411
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
6066
6412
  }
6067
6413
  };
@@ -6215,7 +6561,7 @@ __export(server_exports, {
6215
6561
  createServer: () => createServer
6216
6562
  });
6217
6563
  import http from "http";
6218
- import path15 from "path";
6564
+ import path16 from "path";
6219
6565
  import os from "os";
6220
6566
  import connect from "connect";
6221
6567
  import sirv from "sirv";
@@ -6308,20 +6654,39 @@ async function createServer(inlineConfig = {}) {
6308
6654
  app.use(bundledServer.middleware);
6309
6655
  }
6310
6656
  const ignoredSegments = /* @__PURE__ */ new Set(["node_modules", ".git", ".nasti"]);
6311
- const outDirAbs = path15.resolve(config.root, config.build.outDir);
6312
- const watcher = watch(config.root, {
6657
+ const outDirAbs = path16.resolve(config.root, config.build.outDir);
6658
+ const linkedPackageRoots = getLinkedPackageRoots(config.root).filter(
6659
+ (r) => r !== config.root && !isUnderRoot(config.root, r)
6660
+ );
6661
+ const watchTargets = [config.root, ...linkedPackageRoots];
6662
+ const watcher = watch(watchTargets, {
6313
6663
  ignored: (filePath) => {
6314
- if (filePath === config.root) return false;
6315
- if (filePath === outDirAbs || filePath.startsWith(outDirAbs + path15.sep)) return true;
6316
- const rel = path15.relative(config.root, filePath);
6317
- if (!rel || rel.startsWith("..") || path15.isAbsolute(rel)) return false;
6318
- for (const seg of rel.split(path15.sep)) {
6319
- if (ignoredSegments.has(seg)) return true;
6664
+ if (filePath === outDirAbs || filePath.startsWith(outDirAbs + path16.sep)) return true;
6665
+ for (const watchRoot of watchTargets) {
6666
+ if (filePath === watchRoot) return false;
6667
+ const rel = path16.relative(watchRoot, filePath);
6668
+ if (!rel || rel.startsWith("..") || path16.isAbsolute(rel)) continue;
6669
+ for (const seg of rel.split(path16.sep)) {
6670
+ if (ignoredSegments.has(seg)) return true;
6671
+ }
6672
+ return false;
6320
6673
  }
6321
6674
  return false;
6322
6675
  },
6323
6676
  ignoreInitial: true
6324
6677
  });
6678
+ await new Promise((resolve, reject) => {
6679
+ const onReady = () => {
6680
+ watcher.off("error", onError);
6681
+ resolve();
6682
+ };
6683
+ const onError = (err) => {
6684
+ watcher.off("ready", onReady);
6685
+ reject(err);
6686
+ };
6687
+ watcher.once("ready", onReady);
6688
+ watcher.once("error", onError);
6689
+ });
6325
6690
  let server;
6326
6691
  const environmentServices = {};
6327
6692
  let environmentDriversStarted = false;
@@ -6433,16 +6798,25 @@ async function createServer(inlineConfig = {}) {
6433
6798
  });
6434
6799
  };
6435
6800
  watcher.on("change", (file) => {
6801
+ if (file.includes(`${path16.sep}node_modules${path16.sep}`) || file.endsWith(`${path16.sep}node_modules`)) {
6802
+ clearLinkedPackageRootsCache();
6803
+ }
6436
6804
  ssrRunner?.invalidateFile(file);
6437
6805
  queueClientEnvironmentUpdate(file);
6438
6806
  notifyEnvironmentDrivers(file, "change");
6439
6807
  });
6440
6808
  watcher.on("add", (file) => {
6809
+ if (file.includes(`${path16.sep}node_modules${path16.sep}`) || file.endsWith(`${path16.sep}node_modules`)) {
6810
+ clearLinkedPackageRootsCache();
6811
+ }
6441
6812
  ssrRunner?.invalidateFile(file);
6442
6813
  queueClientEnvironmentUpdate(file);
6443
6814
  notifyEnvironmentDrivers(file, "add");
6444
6815
  });
6445
6816
  watcher.on("unlink", (file) => {
6817
+ if (file.includes(`${path16.sep}node_modules${path16.sep}`) || file.endsWith(`${path16.sep}node_modules`)) {
6818
+ clearLinkedPackageRootsCache();
6819
+ }
6446
6820
  ssrRunner?.invalidateFile(file);
6447
6821
  notifyEnvironmentDrivers(file, "unlink");
6448
6822
  });
@@ -6472,7 +6846,7 @@ async function createServer(inlineConfig = {}) {
6472
6846
  const readyIn = Math.ceil(performance.now() - startTime);
6473
6847
  logger.info(
6474
6848
  `
6475
- ${pc8.cyan(pc8.bold("NASTI"))} ${pc8.cyan(`v${"2.4.3"}`)} ${pc8.dim("ready in")} ${pc8.bold(readyIn)} ${pc8.dim("ms")}
6849
+ ${pc8.cyan(pc8.bold("NASTI"))} ${pc8.cyan(`v${"2.5.0"}`)} ${pc8.dim("ready in")} ${pc8.bold(readyIn)} ${pc8.dim("ms")}
6476
6850
  `
6477
6851
  );
6478
6852
  printServerUrls(
@@ -6569,7 +6943,7 @@ async function createServer(inlineConfig = {}) {
6569
6943
  throw error;
6570
6944
  }
6571
6945
  app.use(transformMiddleware(transformContexts.get("client")));
6572
- const publicDir = path15.resolve(config.root, "public");
6946
+ const publicDir = path16.resolve(config.root, "public");
6573
6947
  app.use(sirv(publicDir, { dev: true, etag: true }));
6574
6948
  app.use(sirv(config.root, { dev: true, etag: true }));
6575
6949
  const postMiddlewares = [];
@@ -6608,6 +6982,7 @@ var init_server = __esm({
6608
6982
  init_builtins();
6609
6983
  init_plugin_api();
6610
6984
  init_env();
6985
+ init_fs_allow();
6611
6986
  }
6612
6987
  });
6613
6988
 
@@ -6658,24 +7033,25 @@ __export(electron_exports, {
6658
7033
  detectInstalledElectron: () => detectInstalledElectron,
6659
7034
  normalizePreload: () => normalizePreload
6660
7035
  });
6661
- import path16 from "path";
6662
- import fs11 from "fs";
7036
+ import path17 from "path";
7037
+ import fs12 from "fs";
7038
+ import { createRequire as createRequire5 } from "module";
6663
7039
  import { rolldown as rolldown2 } from "rolldown";
6664
7040
  import pc9 from "picocolors";
6665
7041
  async function buildElectron(inlineConfig = {}) {
6666
7042
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
6667
7043
  const startTime = performance.now();
6668
7044
  assertElectronVersion(config);
6669
- console.log(pc9.cyan("\n\u26A1 nasti build (electron)") + pc9.dim(` v${"2.4.3"}`));
7045
+ console.log(pc9.cyan("\n\u26A1 nasti build (electron)") + pc9.dim(` v${"2.5.0"}`));
6670
7046
  console.log(pc9.dim(` root: ${config.root}`));
6671
7047
  console.log(pc9.dim(` mode: ${config.mode}`));
6672
7048
  console.log(pc9.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
6673
- const outDir = path16.resolve(config.root, config.build.outDir);
6674
- if (config.build.emptyOutDir && fs11.existsSync(outDir)) {
6675
- fs11.rmSync(outDir, { recursive: true, force: true });
7049
+ const outDir = path17.resolve(config.root, config.build.outDir);
7050
+ if (config.build.emptyOutDir && fs12.existsSync(outDir)) {
7051
+ fs12.rmSync(outDir, { recursive: true, force: true });
6676
7052
  }
6677
- fs11.mkdirSync(outDir, { recursive: true });
6678
- const rendererOutDir = path16.join(outDir, "renderer");
7053
+ fs12.mkdirSync(outDir, { recursive: true });
7054
+ const rendererOutDir = path17.join(outDir, "renderer");
6679
7055
  const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
6680
7056
  await build2(createElectronRendererConfig(config, inlineConfig, {
6681
7057
  build: {
@@ -6684,8 +7060,8 @@ async function buildElectron(inlineConfig = {}) {
6684
7060
  emptyOutDir: false
6685
7061
  }
6686
7062
  }));
6687
- const mainEntry = path16.resolve(config.root, config.electron.main);
6688
- if (!fs11.existsSync(mainEntry)) {
7063
+ const mainEntry = path17.resolve(config.root, config.electron.main);
7064
+ if (!fs12.existsSync(mainEntry)) {
6689
7065
  throw new Error(
6690
7066
  `Electron main entry not found: ${config.electron.main}
6691
7067
  \u5728 nasti.config.ts \u7684 electron.main \u6307\u5B9A\u4E3B\u8FDB\u7A0B\u5165\u53E3\u6587\u4EF6\u3002`
@@ -6699,11 +7075,11 @@ async function buildElectron(inlineConfig = {}) {
6699
7075
  const preloadEntries = normalizePreload(config.electron.preload, config.root);
6700
7076
  const preloadFiles = [];
6701
7077
  for (const entry of preloadEntries) {
6702
- if (!fs11.existsSync(entry)) {
7078
+ if (!fs12.existsSync(entry)) {
6703
7079
  console.warn(pc9.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
6704
7080
  continue;
6705
7081
  }
6706
- const base = path16.basename(entry).replace(/\.[^.]+$/, "");
7082
+ const base = path17.basename(entry).replace(/\.[^.]+$/, "");
6707
7083
  const out = outFileName(outDir, base, config.electron.preloadFormat);
6708
7084
  await bundleNode(config, entry, {
6709
7085
  outFile: out,
@@ -6715,10 +7091,10 @@ async function buildElectron(inlineConfig = {}) {
6715
7091
  const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
6716
7092
  console.log(pc9.green(`
6717
7093
  \u2713 Electron build complete in ${elapsed}s`));
6718
- console.log(pc9.dim(` renderer: ${path16.relative(config.root, rendererOutDir)}/`));
6719
- console.log(pc9.dim(` main: ${path16.relative(config.root, mainFile)}`));
7094
+ console.log(pc9.dim(` renderer: ${path17.relative(config.root, rendererOutDir)}/`));
7095
+ console.log(pc9.dim(` main: ${path17.relative(config.root, mainFile)}`));
6720
7096
  for (const pf of preloadFiles) {
6721
- console.log(pc9.dim(` preload: ${path16.relative(config.root, pf)}`));
7097
+ console.log(pc9.dim(` preload: ${path17.relative(config.root, pf)}`));
6722
7098
  }
6723
7099
  console.log();
6724
7100
  return { rendererOutDir, mainFile, preloadFiles };
@@ -6732,14 +7108,21 @@ async function bundleNode(config, entry, opts) {
6732
7108
  };
6733
7109
  const oxcTransformPlugin = {
6734
7110
  name: "nasti:oxc-transform",
6735
- transform(code, id) {
6736
- if (!shouldTransform(id)) return null;
6737
- const result = transformCode(id, code, {
7111
+ async transform(code, id) {
7112
+ const result = config.framework === "react" ? await transformReactCode(id, code, {
7113
+ react: config.react,
7114
+ consumer: "server",
7115
+ development: config.mode === "development",
7116
+ sourcemap: !!config.build.sourcemap,
7117
+ target: config.electron.nodeTarget,
7118
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
7119
+ }) : shouldTransform(id) ? transformCode(id, code, {
6738
7120
  sourcemap: !!config.build.sourcemap,
6739
7121
  jsxRuntime: "automatic",
6740
- jsxImportSource: config.framework === "vue" ? "vue" : "react",
7122
+ jsxImportSource: "vue",
6741
7123
  target: config.electron.nodeTarget
6742
- });
7124
+ }) : null;
7125
+ if (!result) return null;
6743
7126
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
6744
7127
  }
6745
7128
  };
@@ -6756,7 +7139,7 @@ async function bundleNode(config, entry, opts) {
6756
7139
  },
6757
7140
  plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
6758
7141
  });
6759
- fs11.mkdirSync(path16.dirname(opts.outFile), { recursive: true });
7142
+ fs12.mkdirSync(path17.dirname(opts.outFile), { recursive: true });
6760
7143
  await bundle2.write({
6761
7144
  sourcemap: !!config.build.sourcemap,
6762
7145
  minify: !!config.build.minify,
@@ -6767,7 +7150,7 @@ async function bundleNode(config, entry, opts) {
6767
7150
  codeSplitting: false
6768
7151
  });
6769
7152
  await bundle2.close();
6770
- console.log(pc9.dim(` \u2713 ${opts.label} \u2192 ${path16.relative(config.root, opts.outFile)}`));
7153
+ console.log(pc9.dim(` \u2713 ${opts.label} \u2192 ${path17.relative(config.root, opts.outFile)}`));
6771
7154
  return opts.outFile;
6772
7155
  }
6773
7156
  function createElectronRendererConfig(config, inlineConfig = {}, overrides = {}) {
@@ -6791,11 +7174,11 @@ function createElectronRendererConfig(config, inlineConfig = {}, overrides = {})
6791
7174
  }
6792
7175
  function outFileName(outDir, base, format) {
6793
7176
  const ext = format === "cjs" ? ".cjs" : ".mjs";
6794
- return path16.join(outDir, base + ext);
7177
+ return path17.join(outDir, base + ext);
6795
7178
  }
6796
7179
  function normalizePreload(preload, root) {
6797
7180
  const list = Array.isArray(preload) ? preload : preload ? [preload] : [];
6798
- return list.map((p) => path16.resolve(root, p));
7181
+ return list.map((p) => path17.resolve(root, p));
6799
7182
  }
6800
7183
  function assertElectronVersion(config) {
6801
7184
  const min = config.electron.minVersion;
@@ -6810,13 +7193,21 @@ function assertElectronVersion(config) {
6810
7193
  }
6811
7194
  function detectInstalledElectron(root) {
6812
7195
  try {
6813
- const pkgPath = path16.resolve(root, "node_modules/electron/package.json");
6814
- if (!fs11.existsSync(pkgPath)) return null;
6815
- const pkg = JSON.parse(fs11.readFileSync(pkgPath, "utf-8"));
7196
+ const require2 = createRequire5(path17.resolve(root, "package.json"));
7197
+ const pkgPath = require2.resolve("electron/package.json");
7198
+ const pkg = JSON.parse(fs12.readFileSync(pkgPath, "utf-8"));
6816
7199
  const major = parseInt(String(pkg.version).split(".")[0], 10);
6817
7200
  return Number.isFinite(major) ? major : null;
6818
7201
  } catch {
6819
- return null;
7202
+ try {
7203
+ const pkgPath = path17.resolve(root, "node_modules/electron/package.json");
7204
+ if (!fs12.existsSync(pkgPath)) return null;
7205
+ const pkg = JSON.parse(fs12.readFileSync(pkgPath, "utf-8"));
7206
+ const major = parseInt(String(pkg.version).split(".")[0], 10);
7207
+ return Number.isFinite(major) ? major : null;
7208
+ } catch {
7209
+ return null;
7210
+ }
6820
7211
  }
6821
7212
  }
6822
7213
  var init_electron2 = __esm({
@@ -6836,9 +7227,9 @@ __export(electron_dev_exports, {
6836
7227
  electronRendererDevPath: () => electronRendererDevPath,
6837
7228
  startElectronDev: () => startElectronDev
6838
7229
  });
6839
- import path17 from "path";
6840
- import fs12 from "fs";
6841
- import { createRequire as createRequire5 } from "module";
7230
+ import path18 from "path";
7231
+ import fs13 from "fs";
7232
+ import { createRequire as createRequire6 } from "module";
6842
7233
  import { spawn } from "child_process";
6843
7234
  import chokidar from "chokidar";
6844
7235
  import pc10 from "picocolors";
@@ -6847,7 +7238,7 @@ async function startElectronDev(inlineConfig = {}) {
6847
7238
  const { noSpawn, ...rest } = inlineConfig;
6848
7239
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
6849
7240
  warnElectronVersion(config);
6850
- console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.4.3"}`));
7241
+ console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.5.0"}`));
6851
7242
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
6852
7243
  const server = await createServer2({
6853
7244
  ...rest,
@@ -6857,11 +7248,11 @@ async function startElectronDev(inlineConfig = {}) {
6857
7248
  await server.listen();
6858
7249
  const devUrl = `http://localhost:${server.config.server.port}` + electronRendererDevPath(config.electron.renderer);
6859
7250
  console.log(pc10.dim(` renderer: ${devUrl}`));
6860
- const stageDir = path17.resolve(config.root, ".nasti");
6861
- fs12.mkdirSync(stageDir, { recursive: true });
6862
- const mainEntry = path17.resolve(config.root, config.electron.main);
7251
+ const stageDir = path18.resolve(config.root, ".nasti");
7252
+ fs13.mkdirSync(stageDir, { recursive: true });
7253
+ const mainEntry = path18.resolve(config.root, config.electron.main);
6863
7254
  const preloadEntries = normalizePreload(config.electron.preload, config.root);
6864
- const builtMainFile = path17.join(stageDir, "main" + extFor(config.electron.mainFormat));
7255
+ const builtMainFile = path18.join(stageDir, "main" + extFor(config.electron.mainFormat));
6865
7256
  const builtPreloadFiles = [];
6866
7257
  const compileAll = async () => {
6867
7258
  await compileNode(config, mainEntry, {
@@ -6871,9 +7262,9 @@ async function startElectronDev(inlineConfig = {}) {
6871
7262
  });
6872
7263
  builtPreloadFiles.length = 0;
6873
7264
  for (const entry of preloadEntries) {
6874
- if (!fs12.existsSync(entry)) continue;
6875
- const base = path17.basename(entry).replace(/\.[^.]+$/, "");
6876
- const out = path17.join(stageDir, base + extFor(config.electron.preloadFormat));
7265
+ if (!fs13.existsSync(entry)) continue;
7266
+ const base = path18.basename(entry).replace(/\.[^.]+$/, "");
7267
+ const out = path18.join(stageDir, base + extFor(config.electron.preloadFormat));
6877
7268
  await compileNode(config, entry, {
6878
7269
  outFile: out,
6879
7270
  format: config.electron.preloadFormat,
@@ -6912,7 +7303,7 @@ async function startElectronDev(inlineConfig = {}) {
6912
7303
  };
6913
7304
  spawnElectron();
6914
7305
  if (config.electron.autoRestart) {
6915
- const watchTargets = [mainEntry, ...preloadEntries].filter(fs12.existsSync);
7306
+ const watchTargets = [mainEntry, ...preloadEntries].filter(fs13.existsSync);
6916
7307
  const watcher = chokidar.watch(watchTargets, { ignoreInitial: true });
6917
7308
  let restarting = null;
6918
7309
  let pending = false;
@@ -6972,14 +7363,21 @@ async function compileNode(config, entry, opts) {
6972
7363
  };
6973
7364
  const oxcTransformPlugin = {
6974
7365
  name: "nasti:oxc-transform",
6975
- transform(code, id) {
6976
- if (!shouldTransform(id)) return null;
6977
- const result = transformCode(id, code, {
7366
+ async transform(code, id) {
7367
+ const result = config.framework === "react" ? await transformReactCode(id, code, {
7368
+ react: config.react,
7369
+ consumer: "server",
7370
+ development: true,
7371
+ sourcemap: true,
7372
+ target: config.electron.nodeTarget,
7373
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
7374
+ }) : shouldTransform(id) ? transformCode(id, code, {
6978
7375
  sourcemap: true,
6979
7376
  jsxRuntime: "automatic",
6980
- jsxImportSource: config.framework === "vue" ? "vue" : "react",
7377
+ jsxImportSource: "vue",
6981
7378
  target: config.electron.nodeTarget
6982
- });
7379
+ }) : null;
7380
+ if (!result) return null;
6983
7381
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
6984
7382
  }
6985
7383
  };
@@ -6992,7 +7390,7 @@ async function compileNode(config, entry, opts) {
6992
7390
  platform: "node",
6993
7391
  plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
6994
7392
  });
6995
- fs12.mkdirSync(path17.dirname(opts.outFile), { recursive: true });
7393
+ fs13.mkdirSync(path18.dirname(opts.outFile), { recursive: true });
6996
7394
  await bundle2.write({
6997
7395
  file: opts.outFile,
6998
7396
  format: opts.format === "cjs" ? "cjs" : "esm",
@@ -7005,18 +7403,18 @@ async function compileNode(config, entry, opts) {
7005
7403
  await bundle2.close();
7006
7404
  }
7007
7405
  function electronRendererDevPath(renderer) {
7008
- const normalized = renderer.split(path17.sep).join("/").replace(/^\.?\//, "");
7406
+ const normalized = renderer.split(path18.sep).join("/").replace(/^\.?\//, "");
7009
7407
  return normalized === "index.html" ? "/" : `/${normalized}`;
7010
7408
  }
7011
7409
  function resolveElectronBinary(config) {
7012
- if (config.electron.electronPath && fs12.existsSync(config.electron.electronPath)) {
7410
+ if (config.electron.electronPath && fs13.existsSync(config.electron.electronPath)) {
7013
7411
  return config.electron.electronPath;
7014
7412
  }
7015
7413
  try {
7016
- const require2 = createRequire5(path17.resolve(config.root, "package.json"));
7414
+ const require2 = createRequire6(path18.resolve(config.root, "package.json"));
7017
7415
  const pathFile = require2.resolve("electron");
7018
7416
  const electronModule = require2(pathFile);
7019
- if (typeof electronModule === "string" && fs12.existsSync(electronModule)) {
7417
+ if (typeof electronModule === "string" && fs13.existsSync(electronModule)) {
7020
7418
  return electronModule;
7021
7419
  }
7022
7420
  } catch {
@@ -7191,20 +7589,20 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
7191
7589
  const logger = createCliLogger(options);
7192
7590
  try {
7193
7591
  const http2 = await import("http");
7194
- const path18 = await import("path");
7592
+ const path19 = await import("path");
7195
7593
  const os2 = await import("os");
7196
7594
  const sirv2 = (await import("sirv")).default;
7197
7595
  const connect2 = (await import("connect")).default;
7198
7596
  const { printServerUrls: printServerUrls2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
7199
- const resolvedRoot = path18.resolve(root ?? ".");
7200
- const outDir = path18.resolve(resolvedRoot, options.outDir);
7597
+ const resolvedRoot = path19.resolve(root ?? ".");
7598
+ const outDir = path19.resolve(resolvedRoot, options.outDir);
7201
7599
  const app = connect2();
7202
7600
  app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
7203
7601
  const port = options.port;
7204
7602
  const host = options.host === true ? "0.0.0.0" : options.host ?? "localhost";
7205
7603
  http2.createServer(app).listen(port, host, () => {
7206
7604
  logger.info(`
7207
- ${pc11.cyan(pc11.bold("NASTI"))} ${pc11.cyan(`v${"2.4.3"}`)} ${pc11.dim("preview")}
7605
+ ${pc11.cyan(pc11.bold("NASTI"))} ${pc11.cyan(`v${"2.5.0"}`)} ${pc11.dim("preview")}
7208
7606
  `);
7209
7607
  printServerUrls2(
7210
7608
  {
@@ -7221,6 +7619,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
7221
7619
  }
7222
7620
  });
7223
7621
  cli.help();
7224
- cli.version("2.4.3");
7622
+ cli.version("2.5.0");
7225
7623
  cli.parse();
7226
7624
  //# sourceMappingURL=cli.js.map