@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.cjs CHANGED
@@ -5,10 +5,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __glob = (map) => (path18) => {
9
- var fn = map[path18];
8
+ var __glob = (map) => (path19) => {
9
+ var fn = map[path19];
10
10
  if (fn) return fn();
11
- throw new Error("Module not found in bundle: " + path18);
11
+ throw new Error("Module not found in bundle: " + path19);
12
12
  };
13
13
  var __esm = (fn, res) => function __init() {
14
14
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -157,7 +157,7 @@ var init_logger = __esm({
157
157
  });
158
158
 
159
159
  // src/config/defaults.ts
160
- var defaultResolve, defaultServer, defaultBuild, defaultElectron, defaultExperimental, defaults;
160
+ var defaultResolve, defaultServer, defaultBuild, defaultElectron, defaultExperimental, defaultReact, defaults;
161
161
  var init_defaults = __esm({
162
162
  "src/config/defaults.ts"() {
163
163
  "use strict";
@@ -210,12 +210,20 @@ var init_defaults = __esm({
210
210
  defaultExperimental = {
211
211
  bundledDev: false
212
212
  };
213
+ defaultReact = {
214
+ include: /\.[tj]sx?$/,
215
+ exclude: /node_modules/,
216
+ jsxImportSource: "react",
217
+ jsxRuntime: "automatic",
218
+ compiler: false
219
+ };
213
220
  defaults = {
214
221
  root: ".",
215
222
  base: "/",
216
223
  mode: "development",
217
224
  target: "web",
218
225
  framework: "auto",
226
+ react: defaultReact,
219
227
  resolve: defaultResolve,
220
228
  server: defaultServer,
221
229
  build: defaultBuild,
@@ -437,6 +445,13 @@ async function resolveConfig(inlineConfig = {}, command) {
437
445
  mode,
438
446
  target: merged.target ?? defaults.target,
439
447
  framework: (merged.framework ?? defaults.framework) === "auto" ? detectFramework(root) : merged.framework,
448
+ react: {
449
+ include: merged.react?.include ?? defaultReact.include,
450
+ exclude: merged.react?.exclude ?? defaultReact.exclude,
451
+ jsxImportSource: merged.react?.jsxImportSource ?? defaultReact.jsxImportSource,
452
+ jsxRuntime: merged.react?.jsxRuntime ?? defaultReact.jsxRuntime,
453
+ compiler: merged.react?.compiler === true ? {} : merged.react?.compiler ?? defaultReact.compiler
454
+ },
440
455
  command,
441
456
  resolve: {
442
457
  // tsconfig paths 优先级最低:tsconfig < defaults < user config
@@ -851,6 +866,24 @@ var init_module_graph = __esm({
851
866
  getModulesByFile(file) {
852
867
  return this.fileToModulesMap.get(file);
853
868
  }
869
+ /**
870
+ * Modules whose registered entry file lives under `dir` (inclusive).
871
+ * Used when a non-entry source inside a prebundled workspace package changes:
872
+ * only the package entry was registered, so getModulesByFile(changedFile)
873
+ * misses — we invalidate every /@modules entry rooted in that package.
874
+ */
875
+ getModulesWithFileUnder(dir) {
876
+ const result = /* @__PURE__ */ new Set();
877
+ const normDir = dir.replace(/\\/g, "/");
878
+ const normPrefix = normDir.endsWith("/") ? normDir : normDir + "/";
879
+ for (const [file, mods] of this.fileToModulesMap) {
880
+ const normFile = file.replace(/\\/g, "/");
881
+ if (normFile === normDir || normFile.startsWith(normPrefix)) {
882
+ for (const m of mods) result.add(m);
883
+ }
884
+ }
885
+ return result;
886
+ }
854
887
  async ensureEntryFromUrl(url) {
855
888
  const normalizedUrl = removeTimestampQuery(url);
856
889
  let mod = this.urlToModuleMap.get(normalizedUrl);
@@ -1336,7 +1369,81 @@ ${msg}`);
1336
1369
  map: result.map ? JSON.stringify(result.map) : null
1337
1370
  };
1338
1371
  }
1339
- var import_oxc_transform, JS_EXTENSIONS, TS_EXTENSIONS, JSX_EXTENSIONS;
1372
+ async function transformReactCode(filename, code, options) {
1373
+ if (!matchesReactFilter(filename, options.react.include, options.react.exclude)) {
1374
+ return null;
1375
+ }
1376
+ if (!options.react.compiler) {
1377
+ if (!shouldTransform(filename)) return null;
1378
+ return transformCode(filename, code, {
1379
+ sourcemap: options.sourcemap,
1380
+ jsxRuntime: options.react.jsxRuntime,
1381
+ jsxImportSource: options.react.jsxImportSource,
1382
+ reactRefresh: options.reactRefresh,
1383
+ target: options.target
1384
+ });
1385
+ }
1386
+ if (!shouldTransform(filename)) return null;
1387
+ const compiler2 = await loadReactCompiler();
1388
+ const compilerOptions = options.react.compiler;
1389
+ const shouldCompile = options.consumer === "client" && (compilerOptions.compilationMode === "annotation" ? /['"]use memo['"]/.test(code) : defaultReactCompilerCodeFilter.test(code));
1390
+ const result = await compiler2.transform(cleanTransformId(filename), code, {
1391
+ jsx: {
1392
+ runtime: options.react.jsxRuntime,
1393
+ development: options.development,
1394
+ importSource: options.react.jsxImportSource,
1395
+ refresh: options.consumer === "client" && !!options.reactRefresh
1396
+ },
1397
+ reactCompiler: shouldCompile ? compilerOptions : false,
1398
+ sourcemap: options.sourcemap ?? true
1399
+ });
1400
+ const diagnostics = result.errors.map(
1401
+ (error) => `${error.message}${error.codeframe ? `
1402
+ ${error.codeframe}` : ""}`
1403
+ );
1404
+ if (result.fatal) {
1405
+ throw new Error(
1406
+ diagnostics.join("\n\n") || `React Compiler transform failed for ${filename}`
1407
+ );
1408
+ }
1409
+ for (const diagnostic of diagnostics) options.onWarning?.(diagnostic);
1410
+ return {
1411
+ code: result.code,
1412
+ map: result.map ? JSON.stringify(result.map) : null
1413
+ };
1414
+ }
1415
+ function matchesReactFilter(id, include, exclude) {
1416
+ const cleanId = cleanTransformId(id);
1417
+ return matchesFilter(cleanId, include) && !matchesFilter(cleanId, exclude);
1418
+ }
1419
+ function matchesFilter(id, filter2) {
1420
+ const patterns = Array.isArray(filter2) ? filter2 : [filter2];
1421
+ return patterns.some((pattern) => {
1422
+ if (pattern instanceof RegExp) {
1423
+ pattern.lastIndex = 0;
1424
+ return pattern.test(id);
1425
+ }
1426
+ if (!pattern.includes("*")) return id.includes(pattern);
1427
+ const expression = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "\0").replace(/\*/g, "[^/]*").replace(/\0/g, ".*");
1428
+ return new RegExp(`^${expression}$`).test(id);
1429
+ });
1430
+ }
1431
+ function cleanTransformId(id) {
1432
+ return id.split(/[?#]/, 1)[0];
1433
+ }
1434
+ async function loadReactCompiler() {
1435
+ if (reactCompilerImplementation) return reactCompilerImplementation;
1436
+ try {
1437
+ reactCompilerImplementation = await import("oxc-transform-react");
1438
+ return reactCompilerImplementation;
1439
+ } catch (error) {
1440
+ throw new Error(
1441
+ '[nasti] React Compiler requires the optional "oxc-transform-react" package. Install it before setting react.compiler.' + (error instanceof Error ? `
1442
+ ${error.message}` : "")
1443
+ );
1444
+ }
1445
+ }
1446
+ var import_oxc_transform, JS_EXTENSIONS, TS_EXTENSIONS, JSX_EXTENSIONS, defaultReactCompilerCodeFilter, reactCompilerImplementation;
1340
1447
  var init_transformer = __esm({
1341
1448
  "src/core/transformer.ts"() {
1342
1449
  "use strict";
@@ -1344,6 +1451,7 @@ var init_transformer = __esm({
1344
1451
  JS_EXTENSIONS = /\.(js|mjs|cjs)$/;
1345
1452
  TS_EXTENSIONS = /\.(ts|mts|cts)$/;
1346
1453
  JSX_EXTENSIONS = /\.(jsx|tsx)$/;
1454
+ defaultReactCompilerCodeFilter = /forwardRef|memo|\b(?:[A-Z]|use[A-Z0-9])/;
1347
1455
  }
1348
1456
  });
1349
1457
 
@@ -1583,6 +1691,120 @@ var init_assets = __esm({
1583
1691
  }
1584
1692
  });
1585
1693
 
1694
+ // src/server/fs-allow.ts
1695
+ function isUnderRoot(abs, root) {
1696
+ const rel = import_node_path5.default.relative(root, abs);
1697
+ return !!rel && !rel.startsWith("..") && !import_node_path5.default.isAbsolute(rel);
1698
+ }
1699
+ function discoverLinkedPackageRoots(projectRoot, maxDepth = 4) {
1700
+ const results = [];
1701
+ const seenReal = /* @__PURE__ */ new Set();
1702
+ const queued = /* @__PURE__ */ new Set([projectRoot]);
1703
+ const queue = [projectRoot];
1704
+ for (let depth = 0; depth < maxDepth && queue.length > 0; depth++) {
1705
+ const levelCount = queue.length;
1706
+ for (let i = 0; i < levelCount; i++) {
1707
+ const dir = queue.shift();
1708
+ const nm = import_node_path5.default.join(dir, "node_modules");
1709
+ let entries;
1710
+ try {
1711
+ entries = import_node_fs5.default.readdirSync(nm, { withFileTypes: true });
1712
+ } catch {
1713
+ continue;
1714
+ }
1715
+ for (const ent of entries) {
1716
+ if (ent.name.startsWith(".") || ent.name === "node_modules") continue;
1717
+ const pkgNames = ent.name.startsWith("@") ? listScopedPackages(nm, ent.name) : [ent.name];
1718
+ for (const pkgName of pkgNames) {
1719
+ const pkgPath = import_node_path5.default.join(nm, pkgName);
1720
+ let real;
1721
+ try {
1722
+ real = import_node_fs5.default.realpathSync(pkgPath);
1723
+ } catch {
1724
+ continue;
1725
+ }
1726
+ if (seenReal.has(real)) continue;
1727
+ seenReal.add(real);
1728
+ if (!queued.has(real)) {
1729
+ queued.add(real);
1730
+ queue.push(real);
1731
+ }
1732
+ if (real !== projectRoot && !isUnderRoot(real, projectRoot) && !real.includes(NM)) {
1733
+ results.push(real);
1734
+ }
1735
+ }
1736
+ }
1737
+ }
1738
+ }
1739
+ return results;
1740
+ }
1741
+ function listScopedPackages(nm, scope) {
1742
+ try {
1743
+ return import_node_fs5.default.readdirSync(import_node_path5.default.join(nm, scope)).filter((name) => !name.startsWith(".")).map((name) => import_node_path5.default.join(scope, name));
1744
+ } catch {
1745
+ return [];
1746
+ }
1747
+ }
1748
+ function getLinkedPackageRoots(projectRoot) {
1749
+ let mtimeMs = 0;
1750
+ try {
1751
+ mtimeMs = import_node_fs5.default.statSync(import_node_path5.default.join(projectRoot, "node_modules")).mtimeMs;
1752
+ } catch {
1753
+ mtimeMs = 0;
1754
+ }
1755
+ const cached2 = linkedRootsCache.get(projectRoot);
1756
+ if (cached2 && cached2.mtimeMs === mtimeMs) {
1757
+ return cached2.roots;
1758
+ }
1759
+ const roots = discoverLinkedPackageRoots(projectRoot);
1760
+ linkedRootsCache.set(projectRoot, { roots, mtimeMs });
1761
+ return roots;
1762
+ }
1763
+ function clearLinkedPackageRootsCache() {
1764
+ linkedRootsCache.clear();
1765
+ }
1766
+ function isAllowedDevModulePath(realId, projectRoot) {
1767
+ if (realId === projectRoot || isUnderRoot(realId, projectRoot)) return true;
1768
+ for (const pkgRoot of getLinkedPackageRoots(projectRoot)) {
1769
+ if (realId === pkgRoot || realId.startsWith(pkgRoot + import_node_path5.default.sep)) return true;
1770
+ }
1771
+ let dir = projectRoot;
1772
+ for (; ; ) {
1773
+ const nm = import_node_path5.default.join(dir, "node_modules");
1774
+ if (realId === nm || realId.startsWith(nm + import_node_path5.default.sep)) return true;
1775
+ const parent = import_node_path5.default.dirname(dir);
1776
+ if (parent === dir) break;
1777
+ dir = parent;
1778
+ }
1779
+ return false;
1780
+ }
1781
+ function findNearestPackageRoot(file) {
1782
+ let dir = import_node_path5.default.dirname(file);
1783
+ for (; ; ) {
1784
+ const pkgJson = import_node_path5.default.join(dir, "package.json");
1785
+ if (import_node_fs5.default.existsSync(pkgJson)) {
1786
+ try {
1787
+ const pkg = JSON.parse(import_node_fs5.default.readFileSync(pkgJson, "utf-8"));
1788
+ if (typeof pkg?.name === "string" && pkg.name) return dir;
1789
+ } catch {
1790
+ }
1791
+ }
1792
+ const parent = import_node_path5.default.dirname(dir);
1793
+ if (parent === dir) return null;
1794
+ dir = parent;
1795
+ }
1796
+ }
1797
+ var import_node_fs5, import_node_path5, NM, linkedRootsCache;
1798
+ var init_fs_allow = __esm({
1799
+ "src/server/fs-allow.ts"() {
1800
+ "use strict";
1801
+ import_node_fs5 = __toESM(require("fs"), 1);
1802
+ import_node_path5 = __toESM(require("path"), 1);
1803
+ NM = `${import_node_path5.default.sep}node_modules${import_node_path5.default.sep}`;
1804
+ linkedRootsCache = /* @__PURE__ */ new Map();
1805
+ }
1806
+ });
1807
+
1586
1808
  // src/server/middleware.ts
1587
1809
  function getReactRefreshRuntimeEsm(includeBoundaryHelpers = false) {
1588
1810
  if (__refreshRuntimeCache) {
@@ -1591,10 +1813,10 @@ function getReactRefreshRuntimeEsm(includeBoundaryHelpers = false) {
1591
1813
  let cjsPath;
1592
1814
  try {
1593
1815
  const pkgPath = __require.resolve("react-refresh/package.json");
1594
- cjsPath = import_node_path5.default.join(import_node_path5.default.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
1816
+ cjsPath = import_node_path6.default.join(import_node_path6.default.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
1595
1817
  } catch (err) {
1596
- cjsPath = import_node_path5.default.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
1597
- if (!import_node_fs5.default.existsSync(cjsPath)) {
1818
+ cjsPath = import_node_path6.default.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
1819
+ if (!import_node_fs6.default.existsSync(cjsPath)) {
1598
1820
  const origMsg = err instanceof Error ? err.message : String(err);
1599
1821
  throw new Error(
1600
1822
  `[nasti] Missing dependency "react-refresh". Install it with: npm install react-refresh
@@ -1602,7 +1824,7 @@ Original resolve error: ${origMsg}`
1602
1824
  );
1603
1825
  }
1604
1826
  }
1605
- const cjsSource = import_node_fs5.default.readFileSync(cjsPath, "utf-8");
1827
+ const cjsSource = import_node_fs6.default.readFileSync(cjsPath, "utf-8");
1606
1828
  __refreshRuntimeCache = `// Wrapped react-refresh runtime -> ESM
1607
1829
  const exports = {};
1608
1830
  const module = { exports };
@@ -1773,8 +1995,8 @@ async function transformRequest(url, ctx) {
1773
1995
  let realIdValid = false;
1774
1996
  try {
1775
1997
  if (idParam) {
1776
- realId = import_node_fs5.default.realpathSync(idParam);
1777
- realIdValid = import_node_fs5.default.statSync(realId).isFile() && (realId.includes(`${import_node_path5.default.sep}node_modules${import_node_path5.default.sep}`) || isUnderRoot(realId, config.root));
1998
+ realId = import_node_fs6.default.realpathSync(idParam);
1999
+ realIdValid = import_node_fs6.default.statSync(realId).isFile() && isAllowedDevModulePath(realId, config.root);
1778
2000
  }
1779
2001
  } catch {
1780
2002
  realId = null;
@@ -1841,7 +2063,7 @@ async function transformRequest(url, ctx) {
1841
2063
  }
1842
2064
  }
1843
2065
  const filePath = resolveUrlToFile(url, config.root);
1844
- if (!filePath || !import_node_fs5.default.existsSync(filePath)) return null;
2066
+ if (!filePath || !import_node_fs6.default.existsSync(filePath)) return null;
1845
2067
  const mod = await moduleGraph.ensureEntryFromUrl(url);
1846
2068
  moduleGraph.registerModule(mod, filePath);
1847
2069
  const transformVersion = mod.invalidationVersion;
@@ -1852,7 +2074,7 @@ async function transformRequest(url, ctx) {
1852
2074
  return transformResult2;
1853
2075
  }
1854
2076
  const loaded = await pluginContainer.load(filePath);
1855
- let code = loaded == null ? import_node_fs5.default.readFileSync(filePath, "utf-8") : typeof loaded === "string" ? loaded : loaded.code;
2077
+ let code = loaded == null ? import_node_fs6.default.readFileSync(filePath, "utf-8") : typeof loaded === "string" ? loaded : loaded.code;
1856
2078
  let map = loaded && typeof loaded !== "string" ? loaded.map : void 0;
1857
2079
  const pluginResult = await pluginContainer.transform(code, filePath);
1858
2080
  if (pluginResult) {
@@ -1861,22 +2083,35 @@ async function transformRequest(url, ctx) {
1861
2083
  }
1862
2084
  const stableUrl = cleanReqUrl;
1863
2085
  let wrappedWithRefresh = false;
1864
- if (shouldTransform(filePath)) {
1865
- const isJsx = /\.[jt]sx$/.test(filePath);
1866
- const useRefresh = isJsx && config.framework !== "vue";
2086
+ if (config.framework === "react") {
2087
+ const refreshEnabled = (ctx.environment?.consumer ?? "client") === "client" && config.server.hmr !== false;
2088
+ const useRefresh = refreshEnabled && (!!config.react.compiler || /\.[jt]sx$/.test(filePath));
2089
+ const result = await transformReactCode(filePath, code, {
2090
+ react: config.react,
2091
+ consumer: ctx.environment?.consumer ?? "client",
2092
+ development: true,
2093
+ reactRefresh: useRefresh,
2094
+ sourcemap: true,
2095
+ target: ctx.environment?.options.build.target ?? config.build.target,
2096
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
2097
+ });
2098
+ if (result) {
2099
+ code = result.code;
2100
+ if (result.map) map = JSON.parse(result.map);
2101
+ if (useRefresh) {
2102
+ code = buildReactRefreshWrapper(stableUrl, code);
2103
+ wrappedWithRefresh = true;
2104
+ }
2105
+ }
2106
+ } else if (shouldTransform(filePath)) {
1867
2107
  const result = transformCode(filePath, code, {
1868
2108
  sourcemap: true,
1869
2109
  jsxRuntime: "automatic",
1870
- jsxImportSource: config.framework === "vue" ? "vue" : "react",
1871
- reactRefresh: useRefresh,
2110
+ jsxImportSource: "vue",
1872
2111
  target: ctx.environment?.options.build.target ?? config.build.target
1873
2112
  });
1874
2113
  code = result.code;
1875
2114
  if (result.map) map = JSON.parse(result.map);
1876
- if (useRefresh) {
1877
- code = buildReactRefreshWrapper(stableUrl, code);
1878
- wrappedWithRefresh = true;
1879
- }
1880
2115
  }
1881
2116
  const hotInfo = rewriteHotAcceptDeps(code, config, filePath);
1882
2117
  code = hotInfo.code;
@@ -1910,7 +2145,7 @@ async function loadVirtualModule(spec, ctx) {
1910
2145
  const resolved = await pluginContainer.resolveId(spec);
1911
2146
  if (resolved == null) return null;
1912
2147
  const resolvedId = typeof resolved === "string" ? resolved : resolved.id;
1913
- const looksVirtual = resolvedId.startsWith("\0") || !import_node_fs5.default.existsSync(resolvedId);
2148
+ const looksVirtual = resolvedId.startsWith("\0") || !import_node_fs6.default.existsSync(resolvedId);
1914
2149
  if (!looksVirtual) return null;
1915
2150
  const loadResult = await pluginContainer.load(resolvedId);
1916
2151
  if (loadResult == null) return null;
@@ -1924,7 +2159,7 @@ async function loadVirtualModule(spec, ctx) {
1924
2159
  config.mode,
1925
2160
  ssrDefineOverrides(ctx.environment?.consumer ?? "client")
1926
2161
  ));
1927
- const anchor = import_node_path5.default.join(config.root, "__nasti_virtual__.ts");
2162
+ const anchor = import_node_path6.default.join(config.root, "__nasti_virtual__.ts");
1928
2163
  code = rewriteImports(code, config, anchor);
1929
2164
  return { id: resolvedId, result: { code } };
1930
2165
  }
@@ -1950,7 +2185,7 @@ async function doBundlePackage(entryFile, root) {
1950
2185
  await bundle2.close();
1951
2186
  let code = result.output[0].code;
1952
2187
  code = code.replace(/process\.env\.NODE_ENV/g, '"development"');
1953
- const externalBaseDir = import_node_path5.default.dirname(entryFile);
2188
+ const externalBaseDir = import_node_path6.default.dirname(entryFile);
1954
2189
  code = code.replace(
1955
2190
  /^(import\b[^;'"]*?\bfrom\s+)(['"])([^'"./][^'"]*)(\2)/gm,
1956
2191
  (_, prefix, q, spec) => `${prefix}${q}${externalSpecToModuleUrl(spec, externalBaseDir, root)}${q}`
@@ -1968,16 +2203,16 @@ async function doBundlePackage(entryFile, root) {
1968
2203
  return code;
1969
2204
  }
1970
2205
  async function tryGenerateSubpathShim(entryFile, root) {
1971
- const NM = `${import_node_path5.default.sep}node_modules${import_node_path5.default.sep}`;
1972
- if (!entryFile.includes(NM)) return null;
2206
+ const NM2 = `${import_node_path6.default.sep}node_modules${import_node_path6.default.sep}`;
2207
+ if (!entryFile.includes(NM2)) return null;
1973
2208
  let pkgDir = null;
1974
2209
  let pkgName = null;
1975
- let dir = import_node_path5.default.dirname(entryFile);
2210
+ let dir = import_node_path6.default.dirname(entryFile);
1976
2211
  while (true) {
1977
- const pkgJsonPath = import_node_path5.default.join(dir, "package.json");
1978
- if (import_node_fs5.default.existsSync(pkgJsonPath)) {
2212
+ const pkgJsonPath = import_node_path6.default.join(dir, "package.json");
2213
+ if (import_node_fs6.default.existsSync(pkgJsonPath)) {
1979
2214
  try {
1980
- const pkg = JSON.parse(import_node_fs5.default.readFileSync(pkgJsonPath, "utf-8"));
2215
+ const pkg = JSON.parse(import_node_fs6.default.readFileSync(pkgJsonPath, "utf-8"));
1981
2216
  if (typeof pkg?.name === "string" && pkg.name) {
1982
2217
  pkgDir = dir;
1983
2218
  pkgName = pkg.name;
@@ -1986,16 +2221,16 @@ async function tryGenerateSubpathShim(entryFile, root) {
1986
2221
  } catch {
1987
2222
  }
1988
2223
  }
1989
- const parent = import_node_path5.default.dirname(dir);
2224
+ const parent = import_node_path6.default.dirname(dir);
1990
2225
  if (parent === dir) return null;
1991
2226
  dir = parent;
1992
- if (!dir.includes(NM)) return null;
2227
+ if (!dir.includes(NM2)) return null;
1993
2228
  }
1994
2229
  if (!pkgDir || !pkgName) return null;
1995
- const entryExt = import_node_path5.default.extname(entryFile);
2230
+ const entryExt = import_node_path6.default.extname(entryFile);
1996
2231
  const mainEntry = pickMainEntryByExtension(pkgDir, entryExt);
1997
2232
  if (!mainEntry) return null;
1998
- if (import_node_path5.default.resolve(mainEntry) === import_node_path5.default.resolve(entryFile)) return null;
2233
+ if (import_node_path6.default.resolve(mainEntry) === import_node_path6.default.resolve(entryFile)) return null;
1999
2234
  let mainNs;
2000
2235
  let subNs;
2001
2236
  try {
@@ -2019,7 +2254,7 @@ async function tryGenerateSubpathShim(entryFile, root) {
2019
2254
  if (mainNs["default"] !== subNs["default"]) return null;
2020
2255
  }
2021
2256
  const rootMain = resolveNodeModule(root, pkgName);
2022
- const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir + import_node_path5.default.sep) ? `/@modules/${pkgName}` : `/@modules/${pkgName}?id=${encodeURIComponent(mainEntry)}`;
2257
+ const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir + import_node_path6.default.sep) ? `/@modules/${pkgName}` : `/@modules/${pkgName}?id=${encodeURIComponent(mainEntry)}`;
2023
2258
  const lines = [
2024
2259
  `// Nasti subpath shim \u2192 ${pkgName} (avoid duplicate bundling)`,
2025
2260
  `import * as __pkg from "${mainEntryUrl}";`
@@ -2033,10 +2268,10 @@ async function tryGenerateSubpathShim(entryFile, root) {
2033
2268
  return lines.join("\n") + "\n";
2034
2269
  }
2035
2270
  function pickMainEntryByExtension(pkgDir, preferredExt) {
2036
- const pkgJsonPath = import_node_path5.default.join(pkgDir, "package.json");
2271
+ const pkgJsonPath = import_node_path6.default.join(pkgDir, "package.json");
2037
2272
  let pkg;
2038
2273
  try {
2039
- pkg = JSON.parse(import_node_fs5.default.readFileSync(pkgJsonPath, "utf-8"));
2274
+ pkg = JSON.parse(import_node_fs6.default.readFileSync(pkgJsonPath, "utf-8"));
2040
2275
  } catch {
2041
2276
  return null;
2042
2277
  }
@@ -2055,14 +2290,14 @@ function pickMainEntryByExtension(pkgDir, preferredExt) {
2055
2290
  if (typeof pkg.module === "string") candidates.push(pkg.module);
2056
2291
  if (typeof pkg.main === "string") candidates.push(pkg.main);
2057
2292
  for (const cand of candidates) {
2058
- if (import_node_path5.default.extname(cand) === preferredExt) {
2059
- const full = import_node_path5.default.resolve(pkgDir, cand);
2060
- if (import_node_fs5.default.existsSync(full)) return full;
2293
+ if (import_node_path6.default.extname(cand) === preferredExt) {
2294
+ const full = import_node_path6.default.resolve(pkgDir, cand);
2295
+ if (import_node_fs6.default.existsSync(full)) return full;
2061
2296
  }
2062
2297
  }
2063
2298
  for (const cand of candidates) {
2064
- const full = import_node_path5.default.resolve(pkgDir, cand);
2065
- if (import_node_fs5.default.existsSync(full)) return full;
2299
+ const full = import_node_path6.default.resolve(pkgDir, cand);
2300
+ if (import_node_fs6.default.existsSync(full)) return full;
2066
2301
  }
2067
2302
  return null;
2068
2303
  }
@@ -2087,8 +2322,8 @@ function rewriteExternalRequires(code, baseDir, root) {
2087
2322
  }
2088
2323
  async function injectCjsNamedExports(code, entryFile) {
2089
2324
  try {
2090
- const { createRequire: createRequire6 } = await import("module");
2091
- const req = createRequire6(entryFile);
2325
+ const { createRequire: createRequire7 } = await import("module");
2326
+ const req = createRequire7(entryFile);
2092
2327
  const cjsExports = req(entryFile);
2093
2328
  if (!cjsExports || typeof cjsExports !== "object" && typeof cjsExports !== "function" || Array.isArray(cjsExports)) return code;
2094
2329
  const namedKeys = Object.keys(cjsExports).filter(
@@ -2129,11 +2364,22 @@ function rewriteImports(code, config, filePath, importedUrls, moduleGraph) {
2129
2364
  }
2130
2365
  function createModuleSpecifierResolver(config, filePath) {
2131
2366
  const root = config.root;
2132
- const fileDir = import_node_path5.default.dirname(filePath);
2367
+ const fileDir = import_node_path6.default.dirname(filePath);
2133
2368
  const aliasEntries = Object.entries(config.resolve.alias).sort(
2134
2369
  ([a], [b]) => b.length - a.length
2135
2370
  );
2136
- const toRootUrl = (abs) => "/" + import_node_path5.default.relative(root, abs).replace(/\\/g, "/");
2371
+ const toServableUrl = (abs) => {
2372
+ if (isUnderRoot(abs, root)) {
2373
+ return "/" + import_node_path6.default.relative(root, abs).replace(/\\/g, "/");
2374
+ }
2375
+ for (const pkgRoot of getLinkedPackageRoots(root)) {
2376
+ if (abs === pkgRoot || abs.startsWith(pkgRoot + import_node_path6.default.sep)) {
2377
+ const normalized = abs.replace(/\\/g, "/");
2378
+ return "/@fs/" + (normalized.startsWith("/") ? normalized.slice(1) : normalized);
2379
+ }
2380
+ }
2381
+ return null;
2382
+ };
2137
2383
  return (specifier) => {
2138
2384
  const suffixMatch = specifier.match(/[?#].*$/);
2139
2385
  const suffix = suffixMatch ? suffixMatch[0] : "";
@@ -2142,18 +2388,21 @@ function createModuleSpecifierResolver(config, filePath) {
2142
2388
  if (baseSpec === key || baseSpec.startsWith(key + "/")) {
2143
2389
  const aliasBase = resolveAliasTarget(value, root);
2144
2390
  const sub = baseSpec.slice(key.length).replace(/^\//, "");
2145
- const target = sub ? import_node_path5.default.join(aliasBase, sub) : aliasBase;
2391
+ const target = sub ? import_node_path6.default.join(aliasBase, sub) : aliasBase;
2146
2392
  const resolved = tryResolveDiskPath(target);
2147
- return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
2393
+ const url = resolved ? toServableUrl(resolved) : null;
2394
+ return url ? url + suffix : specifier;
2148
2395
  }
2149
2396
  }
2150
2397
  if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
2151
- const resolved = tryResolveDiskPath(import_node_path5.default.resolve(fileDir, baseSpec));
2152
- return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
2398
+ const resolved = tryResolveDiskPath(import_node_path6.default.resolve(fileDir, baseSpec));
2399
+ const url = resolved ? toServableUrl(resolved) : null;
2400
+ return url ? url + suffix : specifier;
2153
2401
  }
2154
2402
  if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
2155
- const resolved = tryResolveDiskPath(import_node_path5.default.join(root, baseSpec.replace(/^\//, "")));
2156
- return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
2403
+ const resolved = tryResolveDiskPath(import_node_path6.default.join(root, baseSpec.replace(/^\//, "")));
2404
+ const url = resolved ? toServableUrl(resolved) : null;
2405
+ return url ? url + suffix : specifier;
2157
2406
  }
2158
2407
  if (baseSpec.startsWith("/")) return specifier;
2159
2408
  return `/@modules/${specifier}`;
@@ -2306,28 +2555,24 @@ function maskStringsAndComments(code) {
2306
2555
  return masked.join("");
2307
2556
  }
2308
2557
  function resolveAliasTarget(value, root) {
2309
- if (import_node_path5.default.isAbsolute(value) && import_node_fs5.default.existsSync(value)) return value;
2310
- if (value.startsWith("/")) return import_node_path5.default.join(root, value.slice(1));
2311
- return import_node_path5.default.resolve(root, value);
2558
+ if (import_node_path6.default.isAbsolute(value) && import_node_fs6.default.existsSync(value)) return value;
2559
+ if (value.startsWith("/")) return import_node_path6.default.join(root, value.slice(1));
2560
+ return import_node_path6.default.resolve(root, value);
2312
2561
  }
2313
2562
  function tryResolveDiskPath(target) {
2314
- if (import_node_fs5.default.existsSync(target) && import_node_fs5.default.statSync(target).isFile()) return target;
2563
+ if (import_node_fs6.default.existsSync(target) && import_node_fs6.default.statSync(target).isFile()) return target;
2315
2564
  for (const ext of RESOLVE_EXTENSIONS) {
2316
2565
  const withExt = target + ext;
2317
- if (import_node_fs5.default.existsSync(withExt) && import_node_fs5.default.statSync(withExt).isFile()) return withExt;
2566
+ if (import_node_fs6.default.existsSync(withExt) && import_node_fs6.default.statSync(withExt).isFile()) return withExt;
2318
2567
  }
2319
- if (import_node_fs5.default.existsSync(target) && import_node_fs5.default.statSync(target).isDirectory()) {
2568
+ if (import_node_fs6.default.existsSync(target) && import_node_fs6.default.statSync(target).isDirectory()) {
2320
2569
  for (const ext of RESOLVE_EXTENSIONS) {
2321
- const idx = import_node_path5.default.join(target, "index" + ext);
2322
- if (import_node_fs5.default.existsSync(idx) && import_node_fs5.default.statSync(idx).isFile()) return idx;
2570
+ const idx = import_node_path6.default.join(target, "index" + ext);
2571
+ if (import_node_fs6.default.existsSync(idx) && import_node_fs6.default.statSync(idx).isFile()) return idx;
2323
2572
  }
2324
2573
  }
2325
2574
  return null;
2326
2575
  }
2327
- function isUnderRoot(abs, root) {
2328
- const rel = import_node_path5.default.relative(root, abs);
2329
- return !!rel && !rel.startsWith("..") && !import_node_path5.default.isAbsolute(rel);
2330
- }
2331
2576
  function appendTimestampQuery(url, timestamp) {
2332
2577
  const hashIndex = url.indexOf("#");
2333
2578
  const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
@@ -2345,7 +2590,7 @@ function resolveNodeModule(baseDir, moduleName) {
2345
2590
  const resolved = resolveNodeModuleEntry(baseDir, moduleName);
2346
2591
  if (!resolved) return null;
2347
2592
  try {
2348
- return import_node_fs5.default.realpathSync(resolved);
2593
+ return import_node_fs6.default.realpathSync(resolved);
2349
2594
  } catch {
2350
2595
  return resolved;
2351
2596
  }
@@ -2365,21 +2610,21 @@ function resolveNodeModuleEntry(root, moduleName) {
2365
2610
  let pkgDir = null;
2366
2611
  let dir = root;
2367
2612
  for (; ; ) {
2368
- const candidate = import_node_path5.default.join(dir, "node_modules", pkgName);
2369
- if (import_node_fs5.default.existsSync(candidate)) {
2613
+ const candidate = import_node_path6.default.join(dir, "node_modules", pkgName);
2614
+ if (import_node_fs6.default.existsSync(candidate)) {
2370
2615
  pkgDir = candidate;
2371
2616
  break;
2372
2617
  }
2373
- const parent = import_node_path5.default.dirname(dir);
2618
+ const parent = import_node_path6.default.dirname(dir);
2374
2619
  if (parent === dir) break;
2375
2620
  dir = parent;
2376
2621
  }
2377
2622
  if (!pkgDir) return null;
2378
- const pkgJsonPath = import_node_path5.default.join(pkgDir, "package.json");
2379
- if (!import_node_fs5.default.existsSync(pkgJsonPath)) return null;
2623
+ const pkgJsonPath = import_node_path6.default.join(pkgDir, "package.json");
2624
+ if (!import_node_fs6.default.existsSync(pkgJsonPath)) return null;
2380
2625
  let pkg;
2381
2626
  try {
2382
- pkg = JSON.parse(import_node_fs5.default.readFileSync(pkgJsonPath, "utf-8"));
2627
+ pkg = JSON.parse(import_node_fs6.default.readFileSync(pkgJsonPath, "utf-8"));
2383
2628
  } catch {
2384
2629
  return null;
2385
2630
  }
@@ -2392,32 +2637,32 @@ function resolveNodeModuleEntry(root, moduleName) {
2392
2637
  const subDirs = [""];
2393
2638
  for (const field of ["module", "main"]) {
2394
2639
  if (typeof pkg[field] === "string") {
2395
- const dir2 = import_node_path5.default.dirname(pkg[field]);
2640
+ const dir2 = import_node_path6.default.dirname(pkg[field]);
2396
2641
  if (dir2 && dir2 !== "." && !subDirs.includes(dir2)) subDirs.push(dir2);
2397
2642
  }
2398
2643
  }
2399
2644
  for (const dir2 of subDirs) {
2400
- const direct = import_node_path5.default.join(pkgDir, dir2, subpath);
2401
- if (import_node_fs5.default.existsSync(direct) && import_node_fs5.default.statSync(direct).isFile()) return direct;
2645
+ const direct = import_node_path6.default.join(pkgDir, dir2, subpath);
2646
+ if (import_node_fs6.default.existsSync(direct) && import_node_fs6.default.statSync(direct).isFile()) return direct;
2402
2647
  for (const ext of RESOLVE_EXTENSIONS) {
2403
- if (import_node_fs5.default.existsSync(direct + ext)) return direct + ext;
2648
+ if (import_node_fs6.default.existsSync(direct + ext)) return direct + ext;
2404
2649
  }
2405
2650
  }
2406
2651
  return null;
2407
2652
  }
2408
2653
  for (const field of ["module", "jsnext:main", "jsnext", "main"]) {
2409
2654
  if (typeof pkg[field] === "string") {
2410
- const entry = import_node_path5.default.join(pkgDir, pkg[field]);
2411
- if (import_node_fs5.default.existsSync(entry)) return entry;
2655
+ const entry = import_node_path6.default.join(pkgDir, pkg[field]);
2656
+ if (import_node_fs6.default.existsSync(entry)) return entry;
2412
2657
  }
2413
2658
  }
2414
- const indexFallback = import_node_path5.default.join(pkgDir, "index.js");
2415
- if (import_node_fs5.default.existsSync(indexFallback)) return indexFallback;
2659
+ const indexFallback = import_node_path6.default.join(pkgDir, "index.js");
2660
+ if (import_node_fs6.default.existsSync(indexFallback)) return indexFallback;
2416
2661
  return null;
2417
2662
  }
2418
2663
  function resolvePackageExports(exports2, key, pkgDir) {
2419
2664
  if (typeof exports2 === "string") {
2420
- return key === "." ? import_node_path5.default.join(pkgDir, exports2) : null;
2665
+ return key === "." ? import_node_path6.default.join(pkgDir, exports2) : null;
2421
2666
  }
2422
2667
  const entry = exports2[key];
2423
2668
  if (entry === void 0) {
@@ -2429,7 +2674,7 @@ function resolvePackageExports(exports2, key, pkgDir) {
2429
2674
  return resolveExportValue(entry, pkgDir);
2430
2675
  }
2431
2676
  function resolveExportValue(value, pkgDir) {
2432
- if (typeof value === "string") return import_node_path5.default.join(pkgDir, value);
2677
+ if (typeof value === "string") return import_node_path6.default.join(pkgDir, value);
2433
2678
  if (Array.isArray(value)) {
2434
2679
  for (const item of value) {
2435
2680
  const r = resolveExportValue(item, pkgDir);
@@ -2448,35 +2693,54 @@ function resolveExportValue(value, pkgDir) {
2448
2693
  return null;
2449
2694
  }
2450
2695
  function resolveUrlToFile(url, root) {
2451
- const cleanUrl = url.split("?")[0];
2696
+ const cleanUrl = url.split(/[?#]/)[0];
2452
2697
  if (cleanUrl.startsWith("/@modules/")) {
2453
2698
  const moduleName = cleanUrl.slice("/@modules/".length);
2454
2699
  return resolveNodeModule(root, moduleName);
2455
2700
  }
2456
- const filePath = import_node_path5.default.resolve(root, cleanUrl.replace(/^\//, ""));
2457
- if (import_node_fs5.default.existsSync(filePath) && import_node_fs5.default.statSync(filePath).isFile()) {
2701
+ if (cleanUrl.startsWith("/@fs/")) {
2702
+ let abs = cleanUrl.slice("/@fs/".length);
2703
+ if (process.platform === "win32") {
2704
+ abs = abs.replace(/\//g, import_node_path6.default.sep);
2705
+ } else if (!abs.startsWith("/")) {
2706
+ abs = "/" + abs;
2707
+ }
2708
+ try {
2709
+ const real = import_node_fs6.default.realpathSync(abs);
2710
+ if (import_node_fs6.default.statSync(real).isFile() && isAllowedDevModulePath(real, root)) return real;
2711
+ } catch {
2712
+ return null;
2713
+ }
2714
+ return null;
2715
+ }
2716
+ const filePath = import_node_path6.default.resolve(root, cleanUrl.replace(/^\//, ""));
2717
+ if (import_node_fs6.default.existsSync(filePath) && import_node_fs6.default.statSync(filePath).isFile()) {
2458
2718
  return filePath;
2459
2719
  }
2460
2720
  for (const ext of RESOLVE_EXTENSIONS) {
2461
2721
  const withExt = filePath + ext;
2462
- if (import_node_fs5.default.existsSync(withExt)) return withExt;
2722
+ if (import_node_fs6.default.existsSync(withExt)) return withExt;
2463
2723
  }
2464
2724
  for (const ext of RESOLVE_EXTENSIONS) {
2465
- const indexFile = import_node_path5.default.join(filePath, "index" + ext);
2466
- if (import_node_fs5.default.existsSync(indexFile)) return indexFile;
2725
+ const indexFile = import_node_path6.default.join(filePath, "index" + ext);
2726
+ if (import_node_fs6.default.existsSync(indexFile)) return indexFile;
2467
2727
  }
2468
2728
  return null;
2469
2729
  }
2470
2730
  function isModuleRequest(url, destination) {
2471
- const cleanUrl = url.split("?")[0];
2731
+ const cleanUrl = url.split(/[?#]/)[0];
2472
2732
  if (/\.(ts|tsx|jsx|js|mjs|vue|css|json)$/.test(cleanUrl)) return true;
2473
2733
  if (cleanUrl.startsWith("/@modules/")) return true;
2734
+ if (cleanUrl.startsWith("/@fs/")) return true;
2474
2735
  if (isAssetFile(cleanUrl)) {
2475
- const query = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
2736
+ const qIdx = url.indexOf("?");
2737
+ const hIdx = url.indexOf("#");
2738
+ const queryEnd = hIdx === -1 ? url.length : hIdx;
2739
+ const query = qIdx === -1 || qIdx > queryEnd ? "" : url.slice(qIdx + 1, queryEnd);
2476
2740
  const isExplicitAssetModule = /(?:^|&)(?:url|raw)(?:&|$)/.test(query);
2477
2741
  return isExplicitAssetModule || destination === "script";
2478
2742
  }
2479
- if (!import_node_path5.default.extname(cleanUrl)) return true;
2743
+ if (!import_node_path6.default.extname(cleanUrl)) return true;
2480
2744
  return false;
2481
2745
  }
2482
2746
  function getHmrClientCode() {
@@ -2706,12 +2970,12 @@ function clearCustomListeners(ownerPath) {
2706
2970
  }
2707
2971
  `;
2708
2972
  }
2709
- var import_node_path5, import_node_fs5, import_node_module, import_node_url2, import_picocolors3, import_meta, __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_BOUNDARY_HELPERS, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
2973
+ var import_node_path6, import_node_fs6, import_node_module, import_node_url2, import_picocolors3, import_meta, __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_BOUNDARY_HELPERS, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
2710
2974
  var init_middleware = __esm({
2711
2975
  "src/server/middleware.ts"() {
2712
2976
  "use strict";
2713
- import_node_path5 = __toESM(require("path"), 1);
2714
- import_node_fs5 = __toESM(require("fs"), 1);
2977
+ import_node_path6 = __toESM(require("path"), 1);
2978
+ import_node_fs6 = __toESM(require("fs"), 1);
2715
2979
  import_node_module = require("module");
2716
2980
  import_node_url2 = require("url");
2717
2981
  import_picocolors3 = __toESM(require("picocolors"), 1);
@@ -2720,8 +2984,9 @@ var init_middleware = __esm({
2720
2984
  init_env();
2721
2985
  init_url();
2722
2986
  init_assets();
2987
+ init_fs_allow();
2723
2988
  import_meta = {};
2724
- __dirname_esm = import_node_path5.default.dirname((0, import_node_url2.fileURLToPath)(import_meta.url));
2989
+ __dirname_esm = import_node_path6.default.dirname((0, import_node_url2.fileURLToPath)(import_meta.url));
2725
2990
  __require = (0, import_node_module.createRequire)(import_meta.url);
2726
2991
  __refreshRuntimeCache = null;
2727
2992
  REACT_REFRESH_BOUNDARY_HELPERS = `
@@ -2810,9 +3075,26 @@ async function handleFileChange(file, server, environmentName = "client", timest
2810
3075
  }
2811
3076
  const moduleGraph = environment.moduleGraph;
2812
3077
  const logger = config.logger;
2813
- const relativePath = "/" + import_node_path6.default.relative(config.root, file);
2814
- const shortFile = import_node_path6.default.relative(config.root, file);
2815
- const mods = moduleGraph.getModulesByFile(file);
3078
+ const relativePath = "/" + import_node_path7.default.relative(config.root, file);
3079
+ const shortFile = import_node_path7.default.relative(config.root, file);
3080
+ let mods = moduleGraph.getModulesByFile(file);
3081
+ if (!mods || mods.size === 0) {
3082
+ try {
3083
+ const real = import_node_fs7.default.realpathSync(file);
3084
+ if (real !== file) mods = moduleGraph.getModulesByFile(real);
3085
+ if (mods && mods.size > 0) file = real;
3086
+ } catch {
3087
+ }
3088
+ }
3089
+ if (!mods || mods.size === 0) {
3090
+ const packageRoot = findNearestPackageRoot(file);
3091
+ if (packageRoot && getLinkedPackageRoots(config.root).some(
3092
+ (r) => packageRoot === r || packageRoot.startsWith(r + import_node_path7.default.sep)
3093
+ )) {
3094
+ const under = moduleGraph.getModulesWithFileUnder(packageRoot);
3095
+ if (under.size > 0) mods = under;
3096
+ }
3097
+ }
2816
3098
  if (!mods || mods.size === 0) {
2817
3099
  return null;
2818
3100
  }
@@ -2827,7 +3109,7 @@ async function handleFileChange(file, server, environmentName = "client", timest
2827
3109
  file,
2828
3110
  timestamp,
2829
3111
  modules: [mod],
2830
- read: () => import_node_fs6.default.readFileSync(file, "utf-8"),
3112
+ read: () => import_node_fs7.default.readFileSync(file, "utf-8"),
2831
3113
  server,
2832
3114
  environment
2833
3115
  };
@@ -2888,20 +3170,21 @@ async function handleFileChange(file, server, environmentName = "client", timest
2888
3170
  fullReload
2889
3171
  };
2890
3172
  }
2891
- var import_node_path6, import_node_fs6, import_picocolors4;
3173
+ var import_node_path7, import_node_fs7, import_picocolors4;
2892
3174
  var init_hmr = __esm({
2893
3175
  "src/server/hmr.ts"() {
2894
3176
  "use strict";
2895
- import_node_path6 = __toESM(require("path"), 1);
2896
- import_node_fs6 = __toESM(require("fs"), 1);
3177
+ import_node_path7 = __toESM(require("path"), 1);
3178
+ import_node_fs7 = __toESM(require("fs"), 1);
2897
3179
  import_picocolors4 = __toESM(require("picocolors"), 1);
3180
+ init_fs_allow();
2898
3181
  }
2899
3182
  });
2900
3183
 
2901
3184
  // src/plugins/resolve.ts
2902
3185
  function resolvePlugin(config) {
2903
3186
  const { alias, extensions } = config.resolve;
2904
- const require2 = (0, import_node_module2.createRequire)(import_node_path7.default.resolve(config.root, "package.json"));
3187
+ const require2 = (0, import_node_module2.createRequire)(import_node_path8.default.resolve(config.root, "package.json"));
2905
3188
  const aliasEntries = Object.entries(alias).sort(
2906
3189
  ([a], [b]) => b.length - a.length
2907
3190
  );
@@ -2909,10 +3192,10 @@ function resolvePlugin(config) {
2909
3192
  if (config.framework === "vue") {
2910
3193
  try {
2911
3194
  const vuePkgJson = require2.resolve("vue/package.json", { paths: [config.root] });
2912
- const vueDir = import_node_path7.default.dirname(vuePkgJson);
2913
- const mod = JSON.parse(import_node_fs7.default.readFileSync(vuePkgJson, "utf-8")).module;
2914
- const entry = import_node_path7.default.join(vueDir, mod ?? "dist/vue.runtime.esm-bundler.js");
2915
- if (import_node_fs7.default.existsSync(entry)) vueRuntimeEntry = entry;
3195
+ const vueDir = import_node_path8.default.dirname(vuePkgJson);
3196
+ const mod = JSON.parse(import_node_fs8.default.readFileSync(vuePkgJson, "utf-8")).module;
3197
+ const entry = import_node_path8.default.join(vueDir, mod ?? "dist/vue.runtime.esm-bundler.js");
3198
+ if (import_node_fs8.default.existsSync(entry)) vueRuntimeEntry = entry;
2916
3199
  } catch {
2917
3200
  }
2918
3201
  }
@@ -2924,24 +3207,24 @@ function resolvePlugin(config) {
2924
3207
  if (source === key || source.startsWith(key + "/")) {
2925
3208
  const aliasBase = resolveAliasTarget2(value, config.root);
2926
3209
  const sub = source.slice(key.length).replace(/^\//, "");
2927
- const target = sub ? import_node_path7.default.join(aliasBase, sub) : aliasBase;
3210
+ const target = sub ? import_node_path8.default.join(aliasBase, sub) : aliasBase;
2928
3211
  const resolved = tryResolveFile(target, extensions);
2929
3212
  if (resolved) return resolved;
2930
3213
  break;
2931
3214
  }
2932
3215
  }
2933
3216
  if (source.startsWith("/") && !source.startsWith("//")) {
2934
- const rootRelative = import_node_path7.default.join(config.root, source.slice(1));
3217
+ const rootRelative = import_node_path8.default.join(config.root, source.slice(1));
2935
3218
  const resolved = tryResolveFile(rootRelative, extensions);
2936
3219
  if (resolved) return resolved;
2937
3220
  }
2938
- if (import_node_path7.default.isAbsolute(source) && import_node_fs7.default.existsSync(source)) {
3221
+ if (import_node_path8.default.isAbsolute(source) && import_node_fs8.default.existsSync(source)) {
2939
3222
  const resolved = tryResolveFile(source, extensions);
2940
3223
  if (resolved) return resolved;
2941
3224
  }
2942
3225
  if (source.startsWith(".")) {
2943
- const dir = importer ? import_node_path7.default.dirname(importer) : config.root;
2944
- const absolute = import_node_path7.default.resolve(dir, source);
3226
+ const dir = importer ? import_node_path8.default.dirname(importer) : config.root;
3227
+ const absolute = import_node_path8.default.resolve(dir, source);
2945
3228
  const resolved = tryResolveFile(absolute, extensions);
2946
3229
  if (resolved) return resolved;
2947
3230
  }
@@ -2950,7 +3233,7 @@ function resolvePlugin(config) {
2950
3233
  if (config.command === "build") return null;
2951
3234
  try {
2952
3235
  const resolved = require2.resolve(source, {
2953
- paths: [importer ? import_node_path7.default.dirname(importer) : config.root]
3236
+ paths: [importer ? import_node_path8.default.dirname(importer) : config.root]
2954
3237
  });
2955
3238
  return resolved;
2956
3239
  } catch {
@@ -2961,9 +3244,9 @@ function resolvePlugin(config) {
2961
3244
  },
2962
3245
  load(id) {
2963
3246
  if (id.startsWith("\0")) return null;
2964
- if (!import_node_fs7.default.existsSync(id)) return null;
3247
+ if (!import_node_fs8.default.existsSync(id)) return null;
2965
3248
  if (id.endsWith(".json")) {
2966
- const content = import_node_fs7.default.readFileSync(id, "utf-8");
3249
+ const content = import_node_fs8.default.readFileSync(id, "utf-8");
2967
3250
  return `export default ${content}`;
2968
3251
  }
2969
3252
  return null;
@@ -2971,36 +3254,36 @@ function resolvePlugin(config) {
2971
3254
  };
2972
3255
  }
2973
3256
  function resolveAliasTarget2(value, root) {
2974
- if (import_node_path7.default.isAbsolute(value) && import_node_fs7.default.existsSync(value)) return value;
2975
- if (value.startsWith("/")) return import_node_path7.default.join(root, value.slice(1));
2976
- return import_node_path7.default.resolve(root, value);
3257
+ if (import_node_path8.default.isAbsolute(value) && import_node_fs8.default.existsSync(value)) return value;
3258
+ if (value.startsWith("/")) return import_node_path8.default.join(root, value.slice(1));
3259
+ return import_node_path8.default.resolve(root, value);
2977
3260
  }
2978
3261
  function tryResolveFile(file, extensions) {
2979
- if (import_node_fs7.default.existsSync(file) && import_node_fs7.default.statSync(file).isFile()) {
3262
+ if (import_node_fs8.default.existsSync(file) && import_node_fs8.default.statSync(file).isFile()) {
2980
3263
  return file;
2981
3264
  }
2982
3265
  for (const ext of extensions) {
2983
3266
  const withExt = file + ext;
2984
- if (import_node_fs7.default.existsSync(withExt) && import_node_fs7.default.statSync(withExt).isFile()) {
3267
+ if (import_node_fs8.default.existsSync(withExt) && import_node_fs8.default.statSync(withExt).isFile()) {
2985
3268
  return withExt;
2986
3269
  }
2987
3270
  }
2988
- if (import_node_fs7.default.existsSync(file) && import_node_fs7.default.statSync(file).isDirectory()) {
3271
+ if (import_node_fs8.default.existsSync(file) && import_node_fs8.default.statSync(file).isDirectory()) {
2989
3272
  for (const ext of extensions) {
2990
- const indexFile = import_node_path7.default.join(file, "index" + ext);
2991
- if (import_node_fs7.default.existsSync(indexFile)) {
3273
+ const indexFile = import_node_path8.default.join(file, "index" + ext);
3274
+ if (import_node_fs8.default.existsSync(indexFile)) {
2992
3275
  return indexFile;
2993
3276
  }
2994
3277
  }
2995
3278
  }
2996
3279
  return null;
2997
3280
  }
2998
- var import_node_path7, import_node_fs7, import_node_module2;
3281
+ var import_node_path8, import_node_fs8, import_node_module2;
2999
3282
  var init_resolve = __esm({
3000
3283
  "src/plugins/resolve.ts"() {
3001
3284
  "use strict";
3002
- import_node_path7 = __toESM(require("path"), 1);
3003
- import_node_fs7 = __toESM(require("fs"), 1);
3285
+ import_node_path8 = __toESM(require("path"), 1);
3286
+ import_node_fs8 = __toESM(require("fs"), 1);
3004
3287
  import_node_module2 = require("module");
3005
3288
  }
3006
3289
  });
@@ -3040,27 +3323,27 @@ var require_process = __commonJS({
3040
3323
  var require_filesystem = __commonJS({
3041
3324
  "node_modules/detect-libc/lib/filesystem.js"(exports2, module2) {
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;
@@ -3963,7 +4246,7 @@ function hasTailwindDirectives(css) {
3963
4246
  }
3964
4247
  async function loadTailwind(projectRoot) {
3965
4248
  if (cached && cachedRoot === projectRoot) return cached;
3966
- const req = (0, import_node_module3.createRequire)(import_node_path8.default.join(projectRoot, "package.json"));
4249
+ const req = (0, import_node_module3.createRequire)(import_node_path9.default.join(projectRoot, "package.json"));
3967
4250
  let nodePath;
3968
4251
  let oxidePath;
3969
4252
  try {
@@ -3984,7 +4267,7 @@ async function compileTailwind(css, fromFile, projectRoot) {
3984
4267
  const { node, oxide } = await loadTailwind(projectRoot);
3985
4268
  const dependencies = [];
3986
4269
  const compiler2 = await node.compile(css, {
3987
- base: import_node_path8.default.dirname(fromFile),
4270
+ base: import_node_path9.default.dirname(fromFile),
3988
4271
  from: fromFile,
3989
4272
  onDependency: (p) => dependencies.push(p)
3990
4273
  });
@@ -3995,11 +4278,11 @@ async function compileTailwind(css, fromFile, projectRoot) {
3995
4278
  dependencies: [...dependencies, ...scanner.files]
3996
4279
  };
3997
4280
  }
3998
- var import_node_path8, import_node_module3, import_node_url3, TAILWIND_DIRECTIVE_RE, cached, cachedRoot;
4281
+ var import_node_path9, import_node_module3, import_node_url3, TAILWIND_DIRECTIVE_RE, cached, cachedRoot;
3999
4282
  var init_tailwind = __esm({
4000
4283
  "src/plugins/tailwind.ts"() {
4001
4284
  "use strict";
4002
- import_node_path8 = __toESM(require("path"), 1);
4285
+ import_node_path9 = __toESM(require("path"), 1);
4003
4286
  import_node_module3 = require("module");
4004
4287
  import_node_url3 = require("url");
4005
4288
  TAILWIND_DIRECTIVE_RE = /@(?:import\s+["']tailwindcss(?:\b|\/)|tailwind\b|theme\b|apply\b|plugin\b|source\b|utility\b|variant\b|custom-variant\b|reference\b)/;
@@ -4131,16 +4414,16 @@ function rewriteCssUrls(css, from, root) {
4131
4414
  if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
4132
4415
  return match;
4133
4416
  }
4134
- const resolved = import_node_path9.default.resolve(import_node_path9.default.dirname(from), url);
4135
- const relative = "/" + import_node_path9.default.relative(root, resolved).replace(/\\/g, "/");
4417
+ const resolved = import_node_path10.default.resolve(import_node_path10.default.dirname(from), url);
4418
+ const relative = "/" + import_node_path10.default.relative(root, resolved).replace(/\\/g, "/");
4136
4419
  return `url(${relative})`;
4137
4420
  });
4138
4421
  }
4139
- var import_node_path9, import_source_map_js;
4422
+ var import_node_path10, import_source_map_js;
4140
4423
  var init_css = __esm({
4141
4424
  "src/plugins/css.ts"() {
4142
4425
  "use strict";
4143
- import_node_path9 = __toESM(require("path"), 1);
4426
+ import_node_path10 = __toESM(require("path"), 1);
4144
4427
  import_source_map_js = require("source-map-js");
4145
4428
  init_css_engine();
4146
4429
  init_tailwind();
@@ -4259,8 +4542,8 @@ function vuePlugin(config, environmentName = "client") {
4259
4542
  let cached2 = descriptorCache.get(filePath);
4260
4543
  if (!cached2) {
4261
4544
  try {
4262
- const fs13 = await import("fs");
4263
- const rawSource = fs13.readFileSync(filePath, "utf-8");
4545
+ const fs14 = await import("fs");
4546
+ const rawSource = fs14.readFileSync(filePath, "utf-8");
4264
4547
  const transformedSfc = await applySourceTransform(
4265
4548
  vueOptions.transformSfc,
4266
4549
  rawSource,
@@ -4698,12 +4981,12 @@ function createModuleRunner(environment) {
4698
4981
  }
4699
4982
  return new NastiModuleRunner(environment);
4700
4983
  }
4701
- var import_node_path10, import_node_fs8, import_node_module4, import_node_url4, debug4, NODE_BUILTINS, NastiModuleRunner, AsyncFunction;
4984
+ var import_node_path11, import_node_fs9, import_node_module4, import_node_url4, debug4, NODE_BUILTINS, NastiModuleRunner, AsyncFunction;
4702
4985
  var init_runnable_environment = __esm({
4703
4986
  "src/server/runnable-environment.ts"() {
4704
4987
  "use strict";
4705
- import_node_path10 = __toESM(require("path"), 1);
4706
- import_node_fs8 = __toESM(require("fs"), 1);
4988
+ import_node_path11 = __toESM(require("path"), 1);
4989
+ import_node_fs9 = __toESM(require("fs"), 1);
4707
4990
  import_node_module4 = require("module");
4708
4991
  import_node_url4 = require("url");
4709
4992
  init_transformer();
@@ -4725,7 +5008,7 @@ var init_runnable_environment = __esm({
4725
5008
  this.config.mode,
4726
5009
  ssrDefineOverrides(environment.consumer)
4727
5010
  );
4728
- this.require = (0, import_node_module4.createRequire)(import_node_path10.default.join(this.config.root, "package.json"));
5011
+ this.require = (0, import_node_module4.createRequire)(import_node_path11.default.join(this.config.root, "package.json"));
4729
5012
  const handlers = {
4730
5013
  fetchModule: async (id, importer) => this.fetchModule(id, importer),
4731
5014
  getBuiltins: () => [/^node:/, ...import_node_module4.builtinModules]
@@ -4749,9 +5032,9 @@ var init_runnable_environment = __esm({
4749
5032
  this.cache.clear();
4750
5033
  }
4751
5034
  resolveToId(rawUrl) {
4752
- if (import_node_path10.default.isAbsolute(rawUrl) && import_node_fs8.default.existsSync(rawUrl.split("?")[0])) return rawUrl;
5035
+ if (import_node_path11.default.isAbsolute(rawUrl) && import_node_fs9.default.existsSync(rawUrl.split("?")[0])) return rawUrl;
4753
5036
  const clean = rawUrl.replace(/^\//, "");
4754
- return import_node_path10.default.resolve(this.config.root, clean);
5037
+ return import_node_path11.default.resolve(this.config.root, clean);
4755
5038
  }
4756
5039
  /**
4757
5040
  * fetchModule(invoke 契约方法):环境管线产出 runner 可执行代码。
@@ -4760,14 +5043,14 @@ var init_runnable_environment = __esm({
4760
5043
  */
4761
5044
  async fetchModule(id, importer) {
4762
5045
  if (NODE_BUILTINS.has(id)) return { externalize: id };
4763
- if (!id.startsWith(".") && !import_node_path10.default.isAbsolute(id) && !id.startsWith("\0")) {
5046
+ if (!id.startsWith(".") && !import_node_path11.default.isAbsolute(id) && !id.startsWith("\0")) {
4764
5047
  return { externalize: id };
4765
5048
  }
4766
5049
  const container = this.environment.pluginContainer;
4767
5050
  let resolvedId = id;
4768
5051
  if (id.startsWith(".") && importer) {
4769
5052
  const resolved = await container.resolveId(id, importer);
4770
- resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id : import_node_path10.default.resolve(import_node_path10.default.dirname(importer.split("?")[0]), id);
5053
+ resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id : import_node_path11.default.resolve(import_node_path11.default.dirname(importer.split("?")[0]), id);
4771
5054
  }
4772
5055
  resolvedId = this.completeExtension(resolvedId);
4773
5056
  const cleanId = resolvedId.split("?")[0];
@@ -4775,8 +5058,8 @@ var init_runnable_environment = __esm({
4775
5058
  const loaded = await container.load(resolvedId);
4776
5059
  if (loaded != null) {
4777
5060
  code = typeof loaded === "string" ? loaded : loaded.code;
4778
- } else if (import_node_fs8.default.existsSync(cleanId)) {
4779
- code = import_node_fs8.default.readFileSync(cleanId, "utf-8");
5061
+ } else if (import_node_fs9.default.existsSync(cleanId)) {
5062
+ code = import_node_fs9.default.readFileSync(cleanId, "utf-8");
4780
5063
  } else {
4781
5064
  throw new Error(`[nasti:ssr] cannot load module: ${resolvedId}`);
4782
5065
  }
@@ -4784,12 +5067,32 @@ var init_runnable_environment = __esm({
4784
5067
  if (transformed != null) {
4785
5068
  code = typeof transformed === "string" ? transformed : transformed.code;
4786
5069
  }
4787
- if (shouldTransform(cleanId)) {
5070
+ if (this.config.framework === "react") {
5071
+ const result = await transformReactCode(cleanId, code, {
5072
+ react: this.config.react,
5073
+ consumer: this.environment.consumer,
5074
+ development: true,
5075
+ sourcemap: false,
5076
+ target: this.environment.options.build.target,
5077
+ onWarning: (message) => this.config.logger.warn(`[nasti:react] ${message}`)
5078
+ });
5079
+ if (result) {
5080
+ code = result.code;
5081
+ } else if (shouldTransform(cleanId)) {
5082
+ const fallback = transformCode(cleanId, code, {
5083
+ sourcemap: false,
5084
+ jsxRuntime: this.config.react.jsxRuntime,
5085
+ jsxImportSource: this.config.react.jsxImportSource,
5086
+ target: this.environment.options.build.target
5087
+ });
5088
+ code = fallback.code;
5089
+ }
5090
+ } else if (shouldTransform(cleanId)) {
4788
5091
  const result = transformCode(cleanId, code, {
4789
5092
  sourcemap: false,
4790
5093
  target: this.environment.options.build.target,
4791
5094
  jsxRuntime: "automatic",
4792
- jsxImportSource: this.config.framework === "vue" ? "vue" : "react"
5095
+ jsxImportSource: "vue"
4793
5096
  });
4794
5097
  code = result.code;
4795
5098
  }
@@ -4810,19 +5113,19 @@ var init_runnable_environment = __esm({
4810
5113
  completeExtension(id) {
4811
5114
  const clean = id.split("?")[0];
4812
5115
  const query = id.includes("?") ? id.slice(id.indexOf("?")) : "";
4813
- if (import_node_fs8.default.existsSync(clean) && import_node_fs8.default.statSync(clean).isFile()) return id;
5116
+ if (import_node_fs9.default.existsSync(clean) && import_node_fs9.default.statSync(clean).isFile()) return id;
4814
5117
  const jsMatch = clean.match(/^(.*)\.([mc]?)jsx?$/);
4815
5118
  if (jsMatch) {
4816
5119
  for (const tsExt of [`.${jsMatch[2]}ts`, `.${jsMatch[2]}tsx`]) {
4817
- if (import_node_fs8.default.existsSync(jsMatch[1] + tsExt)) return jsMatch[1] + tsExt + query;
5120
+ if (import_node_fs9.default.existsSync(jsMatch[1] + tsExt)) return jsMatch[1] + tsExt + query;
4818
5121
  }
4819
5122
  }
4820
5123
  for (const ext of this.config.resolve.extensions) {
4821
- if (import_node_fs8.default.existsSync(clean + ext)) return clean + ext + query;
5124
+ if (import_node_fs9.default.existsSync(clean + ext)) return clean + ext + query;
4822
5125
  }
4823
5126
  for (const ext of this.config.resolve.extensions) {
4824
- const indexPath = import_node_path10.default.join(clean, `index${ext}`);
4825
- if (import_node_fs8.default.existsSync(indexPath)) return indexPath;
5127
+ const indexPath = import_node_path11.default.join(clean, `index${ext}`);
5128
+ if (import_node_fs9.default.existsSync(indexPath)) return indexPath;
4826
5129
  }
4827
5130
  return id;
4828
5131
  }
@@ -4849,10 +5152,10 @@ var init_runnable_environment = __esm({
4849
5152
  return;
4850
5153
  }
4851
5154
  const ssrImport = async (dep) => {
4852
- if (NODE_BUILTINS.has(dep) || !dep.startsWith(".") && !import_node_path10.default.isAbsolute(dep) && !dep.startsWith("\0")) {
5155
+ if (NODE_BUILTINS.has(dep) || !dep.startsWith(".") && !import_node_path11.default.isAbsolute(dep) && !dep.startsWith("\0")) {
4853
5156
  return this.importExternal(dep);
4854
5157
  }
4855
- const depId = dep.startsWith(".") ? this.completeExtension(import_node_path10.default.resolve(import_node_path10.default.dirname(fetched.id.split("?")[0]), dep)) : this.completeExtension(dep);
5158
+ const depId = dep.startsWith(".") ? this.completeExtension(import_node_path11.default.resolve(import_node_path11.default.dirname(fetched.id.split("?")[0]), dep)) : this.completeExtension(dep);
4856
5159
  return this.instantiate(depId);
4857
5160
  };
4858
5161
  const ssrExportAll = (sourceModule) => {
@@ -4884,7 +5187,7 @@ var init_runnable_environment = __esm({
4884
5187
  }
4885
5188
  async importExternal(spec) {
4886
5189
  try {
4887
- return await (spec.startsWith("node:") || !import_node_path10.default.isAbsolute(spec) ? import(this.resolveExternalSpecifier(spec)) : import((0, import_node_url4.pathToFileURL)(spec).href));
5190
+ return await (spec.startsWith("node:") || !import_node_path11.default.isAbsolute(spec) ? import(this.resolveExternalSpecifier(spec)) : import((0, import_node_url4.pathToFileURL)(spec).href));
4888
5191
  } catch (err) {
4889
5192
  throw new Error(`[nasti:ssr] failed to import external "${spec}": ${err.message}`);
4890
5193
  }
@@ -4905,6 +5208,44 @@ var init_runnable_environment = __esm({
4905
5208
  }
4906
5209
  });
4907
5210
 
5211
+ // src/plugins/react.ts
5212
+ function reactPlugin(config, environment) {
5213
+ return {
5214
+ name: "nasti:oxc-transform",
5215
+ async transform(code, id) {
5216
+ const result = await transformReactCode(id, code, {
5217
+ react: config.react,
5218
+ consumer: environment.consumer,
5219
+ development: config.mode === "development",
5220
+ sourcemap: !!environment.options.build.sourcemap,
5221
+ target: environment.options.build.target,
5222
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
5223
+ });
5224
+ if (!result) return null;
5225
+ return {
5226
+ code: result.code,
5227
+ map: result.map ? JSON.parse(result.map) : void 0
5228
+ };
5229
+ },
5230
+ handleHotUpdate(ctx) {
5231
+ for (const mod of ctx.modules) {
5232
+ if (REACT_FILE_RE.test(mod.url) && matchesReactFilter(mod.url, config.react.include, config.react.exclude)) {
5233
+ mod.isSelfAccepting = true;
5234
+ }
5235
+ }
5236
+ return ctx.modules;
5237
+ }
5238
+ };
5239
+ }
5240
+ var REACT_FILE_RE;
5241
+ var init_react = __esm({
5242
+ "src/plugins/react.ts"() {
5243
+ "use strict";
5244
+ init_transformer();
5245
+ REACT_FILE_RE = /\.[jt]sx(?:[?#].*)?$/;
5246
+ }
5247
+ });
5248
+
4908
5249
  // src/build/reporter.ts
4909
5250
  async function tryNativeReporterPlugin(config, logger) {
4910
5251
  try {
@@ -4944,7 +5285,7 @@ function reportBuildOutput(output, config, logger) {
4944
5285
  if (compressed && content != null) {
4945
5286
  gzip = (0, import_node_zlib.gzipSync)(typeof content === "string" ? Buffer.from(content) : content).byteLength;
4946
5287
  }
4947
- const ext = import_node_path11.default.extname(file.fileName);
5288
+ const ext = import_node_path12.default.extname(file.fileName);
4948
5289
  const group = file.type === "chunk" ? "js" : ext === ".css" ? "css" : "assets";
4949
5290
  entries.push({ name: file.fileName, size, gzip, group });
4950
5291
  }
@@ -4978,11 +5319,11 @@ function warnLargeChunks(output, config, logger) {
4978
5319
  )
4979
5320
  );
4980
5321
  }
4981
- var import_node_path11, import_node_zlib, import_picocolors5, debug5, numberFormatter;
5322
+ var import_node_path12, import_node_zlib, import_picocolors5, debug5, numberFormatter;
4982
5323
  var init_reporter = __esm({
4983
5324
  "src/build/reporter.ts"() {
4984
5325
  "use strict";
4985
- import_node_path11 = __toESM(require("path"), 1);
5326
+ import_node_path12 = __toESM(require("path"), 1);
4986
5327
  import_node_zlib = require("zlib");
4987
5328
  import_picocolors5 = __toESM(require("picocolors"), 1);
4988
5329
  init_debug();
@@ -4998,7 +5339,7 @@ var init_reporter = __esm({
4998
5339
  function createBuildAppContext(config, results) {
4999
5340
  const output = [];
5000
5341
  const emitted = /* @__PURE__ */ new Set();
5001
- const outDir = import_node_path12.default.resolve(config.root, config.build.outDir);
5342
+ const outDir = import_node_path13.default.resolve(config.root, config.build.outDir);
5002
5343
  let environmentArtifacts;
5003
5344
  return {
5004
5345
  config,
@@ -5054,14 +5395,14 @@ function createBuildAppContext(config, results) {
5054
5395
  if (environmentArtifacts.has(collisionKey)) {
5055
5396
  throw new Error(`[nasti] app artifact conflicts with environment output: ${fileName}`);
5056
5397
  }
5057
- const target = import_node_path12.default.resolve(outDir, ...fileName.split("/"));
5058
- const relative = import_node_path12.default.relative(outDir, target);
5059
- if (relative.startsWith("..") || import_node_path12.default.isAbsolute(relative)) {
5398
+ const target = import_node_path13.default.resolve(outDir, ...fileName.split("/"));
5399
+ const relative = import_node_path13.default.relative(outDir, target);
5400
+ if (relative.startsWith("..") || import_node_path13.default.isAbsolute(relative)) {
5060
5401
  throw new Error(`[nasti] app artifact must stay inside build.outDir: ${file.fileName}`);
5061
5402
  }
5062
5403
  assertNoSymlinkComponents(outDir, fileName);
5063
- import_node_fs9.default.mkdirSync(import_node_path12.default.dirname(target), { recursive: true });
5064
- import_node_fs9.default.writeFileSync(target, file.source);
5404
+ import_node_fs10.default.mkdirSync(import_node_path13.default.dirname(target), { recursive: true });
5405
+ import_node_fs10.default.writeFileSync(target, file.source);
5065
5406
  const artifact = {
5066
5407
  ...file,
5067
5408
  fileName,
@@ -5077,10 +5418,10 @@ function joinPublicPath(base, fileName) {
5077
5418
  return `${base.endsWith("/") ? base : `${base}/`}${fileName.replace(/^\//, "")}`;
5078
5419
  }
5079
5420
  function normalizeEnvironmentFileName(fileName) {
5080
- return import_node_path12.default.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
5421
+ return import_node_path13.default.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
5081
5422
  }
5082
5423
  function isInvalidEnvironmentFileName(fileName) {
5083
- return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || import_node_path12.default.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
5424
+ return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || import_node_path13.default.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
5084
5425
  }
5085
5426
  function normalizeAppFileName(fileName) {
5086
5427
  const normalized = normalizeEnvironmentFileName(fileName);
@@ -5097,14 +5438,14 @@ function collectEnvironmentArtifacts(config, results, appOutDir) {
5097
5438
  for (const [environmentName, result] of Object.entries(results)) {
5098
5439
  const environment = config.environments[environmentName];
5099
5440
  if (!environment) continue;
5100
- const environmentOutDir = import_node_path12.default.resolve(config.root, environment.build.outDir);
5441
+ const environmentOutDir = import_node_path13.default.resolve(config.root, environment.build.outDir);
5101
5442
  for (const artifact of result.output) {
5102
- const artifactPath = import_node_path12.default.resolve(
5443
+ const artifactPath = import_node_path13.default.resolve(
5103
5444
  environmentOutDir,
5104
5445
  ...normalizeEnvironmentFileName(artifact.fileName).split("/")
5105
5446
  );
5106
- const relative = import_node_path12.default.relative(appOutDir, artifactPath);
5107
- if (!relative.startsWith("..") && !import_node_path12.default.isAbsolute(relative)) {
5447
+ const relative = import_node_path13.default.relative(appOutDir, artifactPath);
5448
+ if (!relative.startsWith("..") && !import_node_path13.default.isAbsolute(relative)) {
5108
5449
  occupied.add(artifactCollisionKey(relative));
5109
5450
  }
5110
5451
  }
@@ -5114,10 +5455,10 @@ function collectEnvironmentArtifacts(config, results, appOutDir) {
5114
5455
  function assertNoSymlinkComponents(outDir, fileName) {
5115
5456
  let current = outDir;
5116
5457
  for (const segment of fileName.split("/")) {
5117
- current = import_node_path12.default.join(current, segment);
5458
+ current = import_node_path13.default.join(current, segment);
5118
5459
  let stats;
5119
5460
  try {
5120
- stats = import_node_fs9.default.lstatSync(current);
5461
+ stats = import_node_fs10.default.lstatSync(current);
5121
5462
  } catch (error) {
5122
5463
  if (error.code === "ENOENT") continue;
5123
5464
  throw error;
@@ -5135,12 +5476,12 @@ function inferEnvironmentEntries(output) {
5135
5476
  }
5136
5477
  return Object.keys(entries).length > 0 ? entries : void 0;
5137
5478
  }
5138
- var import_node_fs9, import_node_path12;
5479
+ var import_node_fs10, import_node_path13;
5139
5480
  var init_build_app_context = __esm({
5140
5481
  "src/core/build-app-context.ts"() {
5141
5482
  "use strict";
5142
- import_node_fs9 = __toESM(require("fs"), 1);
5143
- import_node_path12 = __toESM(require("path"), 1);
5483
+ import_node_fs10 = __toESM(require("fs"), 1);
5484
+ import_node_path13 = __toESM(require("path"), 1);
5144
5485
  }
5145
5486
  });
5146
5487
 
@@ -5157,7 +5498,7 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
5157
5498
  const config = environment.config;
5158
5499
  const envOptions = environment.options;
5159
5500
  const isServer = environment.consumer === "server";
5160
- const outDir = import_node_path13.default.resolve(config.root, envOptions.build.outDir);
5501
+ const outDir = import_node_path14.default.resolve(config.root, envOptions.build.outDir);
5161
5502
  const assetsDir = envOptions.build.assetsDir;
5162
5503
  const {
5163
5504
  output: userOutput,
@@ -5197,7 +5538,7 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
5197
5538
  // 相对/绝对/虚拟模块照常打包。需要内联依赖时经 rolldownOptions.external 覆盖。
5198
5539
  external: restInputOptions.external ?? ((id) => {
5199
5540
  if (NODE_BUILTINS2.has(id)) return true;
5200
- return !id.startsWith(".") && !import_node_path13.default.isAbsolute(id) && !id.startsWith("\0");
5541
+ return !id.startsWith(".") && !import_node_path14.default.isAbsolute(id) && !id.startsWith("\0") && !id.startsWith("virtual:");
5201
5542
  })
5202
5543
  } : {}
5203
5544
  };
@@ -5354,11 +5695,11 @@ function prepareBuildOutputDirectories(config, buildableNames) {
5354
5695
  const protectedPaths = /* @__PURE__ */ new Set();
5355
5696
  const clientIsBuilt = buildableNames.includes("client");
5356
5697
  if (!clientIsBuilt && config.build.emptyOutDir) {
5357
- directories.add(import_node_path13.default.resolve(config.root, config.build.outDir));
5698
+ directories.add(import_node_path14.default.resolve(config.root, config.build.outDir));
5358
5699
  }
5359
5700
  for (const name of buildableNames) {
5360
5701
  const environment = config.environments[name];
5361
- const outDir = import_node_path13.default.resolve(config.root, environment.build.outDir);
5702
+ const outDir = import_node_path14.default.resolve(config.root, environment.build.outDir);
5362
5703
  if (!environment.build.emptyOutDir) {
5363
5704
  protectedPaths.add(outDir);
5364
5705
  continue;
@@ -5366,8 +5707,8 @@ function prepareBuildOutputDirectories(config, buildableNames) {
5366
5707
  if (!environment.driver) directories.add(outDir);
5367
5708
  }
5368
5709
  const containsPath = (parent, child) => {
5369
- const relative = import_node_path13.default.relative(parent, child);
5370
- return relative === "" || !relative.startsWith("..") && !import_node_path13.default.isAbsolute(relative);
5710
+ const relative = import_node_path14.default.relative(parent, child);
5711
+ return relative === "" || !relative.startsWith("..") && !import_node_path14.default.isAbsolute(relative);
5371
5712
  };
5372
5713
  const roots = [...directories].filter(
5373
5714
  (directory) => ![...protectedPaths].some((protectedPath) => containsPath(directory, protectedPath))
@@ -5375,7 +5716,7 @@ function prepareBuildOutputDirectories(config, buildableNames) {
5375
5716
  (directory, index2, all) => !all.slice(0, index2).some((parent) => containsPath(parent, directory))
5376
5717
  );
5377
5718
  for (const directory of roots) {
5378
- if (import_node_fs10.default.existsSync(directory)) import_node_fs10.default.rmSync(directory, { recursive: true, force: true });
5719
+ if (import_node_fs11.default.existsSync(directory)) import_node_fs11.default.rmSync(directory, { recursive: true, force: true });
5379
5720
  }
5380
5721
  }
5381
5722
  function assertDriverBuildResult(environment, result) {
@@ -5394,7 +5735,7 @@ function resolveClientEntries(config, html) {
5394
5735
  if (configuredEntries.length > 0) return configuredEntries;
5395
5736
  const entryPoints = [];
5396
5737
  const htmlFile = config.environments.client?.html;
5397
- const htmlDir = htmlFile ? import_node_path13.default.dirname(htmlFile) : config.root;
5738
+ const htmlDir = htmlFile ? import_node_path14.default.dirname(htmlFile) : config.root;
5398
5739
  if (html) {
5399
5740
  const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
5400
5741
  for (const match of scriptMatches) {
@@ -5402,7 +5743,7 @@ function resolveClientEntries(config, html) {
5402
5743
  if (src && !src.startsWith("http")) {
5403
5744
  const cleanSrc = src.split(/[?#]/, 1)[0];
5404
5745
  entryPoints.push(
5405
- cleanSrc.startsWith("/") ? import_node_path13.default.resolve(config.root, cleanSrc.replace(/^\//, "")) : import_node_path13.default.resolve(htmlDir, cleanSrc)
5746
+ cleanSrc.startsWith("/") ? import_node_path14.default.resolve(config.root, cleanSrc.replace(/^\//, "")) : import_node_path14.default.resolve(htmlDir, cleanSrc)
5406
5747
  );
5407
5748
  }
5408
5749
  }
@@ -5410,8 +5751,8 @@ function resolveClientEntries(config, html) {
5410
5751
  if (entryPoints.length === 0) {
5411
5752
  const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
5412
5753
  for (const entry of fallbackEntries) {
5413
- const fullPath = import_node_path13.default.resolve(config.root, entry);
5414
- if (import_node_fs10.default.existsSync(fullPath)) {
5754
+ const fullPath = import_node_path14.default.resolve(config.root, entry);
5755
+ if (import_node_fs11.default.existsSync(fullPath)) {
5415
5756
  entryPoints.push(fullPath);
5416
5757
  break;
5417
5758
  }
@@ -5420,6 +5761,7 @@ function resolveClientEntries(config, html) {
5420
5761
  return entryPoints;
5421
5762
  }
5422
5763
  function createOxcTransformPlugin(config, environment) {
5764
+ if (config.framework === "react") return reactPlugin(config, environment);
5423
5765
  return {
5424
5766
  name: "nasti:oxc-transform",
5425
5767
  transform(code, id) {
@@ -5440,7 +5782,7 @@ async function build(inlineConfig = {}) {
5440
5782
  const startTime = performance.now();
5441
5783
  logger.info(
5442
5784
  import_picocolors6.default.cyan(`
5443
- nasti v${"2.4.3"} `) + import_picocolors6.default.green(`building for ${config.mode}...`)
5785
+ nasti v${"2.5.0"} `) + import_picocolors6.default.green(`building for ${config.mode}...`)
5444
5786
  );
5445
5787
  debug6?.(`root: ${config.root}`);
5446
5788
  const buildableNames = Object.keys(config.environments).filter((name) => {
@@ -5515,7 +5857,7 @@ nasti v${"2.4.3"} `) + import_picocolors6.default.green(`building for ${config.m
5515
5857
  }
5516
5858
  async function buildClientEnvironment(config) {
5517
5859
  const logger = config.logger;
5518
- const outDir = import_node_path13.default.resolve(config.root, config.build.outDir);
5860
+ const outDir = import_node_path14.default.resolve(config.root, config.build.outDir);
5519
5861
  const cssEngine = createCssEngine();
5520
5862
  const pluginList = resolvePluginList(config, config.plugins, {
5521
5863
  cssEngine,
@@ -5538,8 +5880,8 @@ async function buildClientEnvironment(config) {
5538
5880
  assertDriverBuildResult(clientEnv, result);
5539
5881
  return { environment: clientEnv, result: finalizeEnvironmentResult(clientEnv, result) };
5540
5882
  }
5541
- import_node_fs10.default.mkdirSync(outDir, { recursive: true });
5542
- const htmlFile = config.environments.client.html ?? import_node_path13.default.resolve(config.root, "index.html");
5883
+ import_node_fs11.default.mkdirSync(outDir, { recursive: true });
5884
+ const htmlFile = config.environments.client.html ?? import_node_path14.default.resolve(config.root, "index.html");
5543
5885
  const html = await readHtmlFile(config.root, htmlFile);
5544
5886
  const entryPoints = resolveClientEntries(config, html);
5545
5887
  if (entryPoints.length === 0) {
@@ -5589,7 +5931,7 @@ async function buildClientEnvironment(config) {
5589
5931
  );
5590
5932
  }
5591
5933
  }
5592
- import_node_fs10.default.writeFileSync(import_node_path13.default.resolve(outDir, "index.html"), processedHtml);
5934
+ import_node_fs11.default.writeFileSync(import_node_path14.default.resolve(outDir, "index.html"), processedHtml);
5593
5935
  }
5594
5936
  if (!nativeReporter && config.logLevel !== "silent") {
5595
5937
  reportBuildOutput(output, config, logger);
@@ -5643,7 +5985,7 @@ async function buildServerEnvironment(config, name) {
5643
5985
  }
5644
5986
  }
5645
5987
  for (const entry of envOptions.entry) {
5646
- if (!import_node_fs10.default.existsSync(entry)) {
5988
+ if (!import_node_fs11.default.existsSync(entry)) {
5647
5989
  await environment.close();
5648
5990
  throw new Error(`[nasti] environment "${name}" entry not found: ${entry}`);
5649
5991
  }
@@ -5657,13 +5999,13 @@ async function buildServerEnvironment(config, name) {
5657
5999
  envOptions.entry,
5658
6000
  rolldownPlugins
5659
6001
  );
5660
- import_node_fs10.default.mkdirSync(outDir, { recursive: true });
6002
+ import_node_fs11.default.mkdirSync(outDir, { recursive: true });
5661
6003
  const bundle2 = await (0, import_rolldown.rolldown)(inputOptions);
5662
6004
  const { output } = await bundle2.write(outputOptions);
5663
6005
  await bundle2.close();
5664
6006
  if (cssEngine) environment.setBuildMetadata({ css: getCssMetadata(cssEngine) });
5665
6007
  logger.info(
5666
- import_picocolors6.default.dim(` [${name}] `) + output.map((o) => import_node_path13.default.join(envOptions.build.outDir, o.fileName)).join(import_picocolors6.default.dim(", "))
6008
+ import_picocolors6.default.dim(` [${name}] `) + output.map((o) => import_node_path14.default.join(envOptions.build.outDir, o.fileName)).join(import_picocolors6.default.dim(", "))
5667
6009
  );
5668
6010
  return {
5669
6011
  environment,
@@ -5695,9 +6037,9 @@ function escapeRegExp(string) {
5695
6037
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5696
6038
  }
5697
6039
  function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, urlPrefix) {
5698
- const rootRelative = import_node_path13.default.relative(config.root, facadeModuleId).split(import_node_path13.default.sep).join("/");
5699
- const resolvedHtmlFile = import_node_path13.default.resolve(config.root, htmlFile);
5700
- const htmlRelative = import_node_path13.default.relative(import_node_path13.default.dirname(resolvedHtmlFile), facadeModuleId).split(import_node_path13.default.sep).join("/");
6040
+ const rootRelative = import_node_path14.default.relative(config.root, facadeModuleId).split(import_node_path14.default.sep).join("/");
6041
+ const resolvedHtmlFile = import_node_path14.default.resolve(config.root, htmlFile);
6042
+ const htmlRelative = import_node_path14.default.relative(import_node_path14.default.dirname(resolvedHtmlFile), facadeModuleId).split(import_node_path14.default.sep).join("/");
5701
6043
  const candidates = /* @__PURE__ */ new Set([
5702
6044
  rootRelative,
5703
6045
  `/${rootRelative}`,
@@ -5713,12 +6055,12 @@ function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, ur
5713
6055
  }
5714
6056
  return processed;
5715
6057
  }
5716
- var import_node_path13, import_node_fs10, import_node_module5, import_rolldown, import_picocolors6, debug6, NODE_BUILTINS2;
6058
+ var import_node_path14, import_node_fs11, import_node_module5, import_rolldown, import_picocolors6, debug6, NODE_BUILTINS2;
5717
6059
  var init_build = __esm({
5718
6060
  "src/build/index.ts"() {
5719
6061
  "use strict";
5720
- import_node_path13 = __toESM(require("path"), 1);
5721
- import_node_fs10 = __toESM(require("fs"), 1);
6062
+ import_node_path14 = __toESM(require("path"), 1);
6063
+ import_node_fs11 = __toESM(require("fs"), 1);
5722
6064
  import_node_module5 = require("module");
5723
6065
  import_rolldown = require("rolldown");
5724
6066
  init_config();
@@ -5726,6 +6068,7 @@ var init_build = __esm({
5726
6068
  init_environment();
5727
6069
  init_css_engine();
5728
6070
  init_html();
6071
+ init_react();
5729
6072
  init_transformer();
5730
6073
  init_env();
5731
6074
  init_reporter();
@@ -5769,11 +6112,11 @@ async function createBundledDevServer(opts) {
5769
6112
  const patches = new MemoryFiles();
5770
6113
  const entryFileNames = /* @__PURE__ */ new Map();
5771
6114
  const bundledClients = /* @__PURE__ */ new Map();
5772
- const useReactRefresh = config.framework !== "vue" && refreshWrapperFn != null;
6115
+ const useReactRefresh = config.framework === "react" && config.server.hmr !== false && refreshWrapperFn != null;
5773
6116
  const rolldownPlugins = [
5774
6117
  ...useReactRefresh ? [
5775
6118
  createReactRefreshRuntimePlugin(entryPoints),
5776
- createBundledOxcRefreshPlugin()
6119
+ createBundledOxcRefreshPlugin(config)
5777
6120
  ] : [],
5778
6121
  ...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins, clientEnv)),
5779
6122
  ...useReactRefresh ? [
@@ -5824,7 +6167,7 @@ async function createBundledDevServer(opts) {
5824
6167
  }
5825
6168
  const url = `/${patchPath}`;
5826
6169
  logger.info(
5827
- import_picocolors7.default.green("hmr update ") + import_picocolors7.default.dim(changedFiles.map((f) => import_node_path14.default.relative(config.root, f)).join(", ")),
6170
+ import_picocolors7.default.green("hmr update ") + import_picocolors7.default.dim(changedFiles.map((f) => import_node_path15.default.relative(config.root, f)).join(", ")),
5828
6171
  { timestamp: true }
5829
6172
  );
5830
6173
  sendTo(clientId, { type: "hmr:update", path: url, url });
@@ -5979,7 +6322,7 @@ async function createBundledDevServer(opts) {
5979
6322
  return;
5980
6323
  }
5981
6324
  res.setHeader("ETag", hit.etag);
5982
- res.setHeader("Content-Type", MIME_TYPES[import_node_path14.default.extname(fileName)] ?? "application/octet-stream");
6325
+ res.setHeader("Content-Type", MIME_TYPES[import_node_path15.default.extname(fileName)] ?? "application/octet-stream");
5983
6326
  res.setHeader("Cache-Control", "no-cache");
5984
6327
  res.once("finish", () => {
5985
6328
  void engine.notifyPayloadDelivered(fileName).catch(
@@ -6020,7 +6363,7 @@ function stripCatchAllLoad(plugins) {
6020
6363
  );
6021
6364
  }
6022
6365
  function createReactRefreshRuntimePlugin(entryPoints) {
6023
- const entryIds = new Set(entryPoints.map((p) => import_node_path14.default.resolve(p)));
6366
+ const entryIds = new Set(entryPoints.map((p) => import_node_path15.default.resolve(p)));
6024
6367
  return {
6025
6368
  name: "nasti:bundled-react-refresh",
6026
6369
  resolveId(source) {
@@ -6038,24 +6381,27 @@ function createReactRefreshRuntimePlugin(entryPoints) {
6038
6381
  return null;
6039
6382
  },
6040
6383
  transform(code, id) {
6041
- if (!entryIds.has(import_node_path14.default.resolve(id.split("?")[0]))) return null;
6384
+ if (!entryIds.has(import_node_path15.default.resolve(id.split("?")[0]))) return null;
6042
6385
  return { code: `import ${JSON.stringify(PREAMBLE_SPEC)};
6043
6386
  ${code}`, map: null };
6044
6387
  }
6045
6388
  };
6046
6389
  }
6047
- function createBundledOxcRefreshPlugin() {
6390
+ function createBundledOxcRefreshPlugin(config) {
6048
6391
  return {
6049
6392
  name: "nasti:bundled-oxc-refresh",
6050
- transform(code, id) {
6393
+ async transform(code, id) {
6051
6394
  const clean = id.split("?")[0];
6052
- if (!/\.[jt]sx$/.test(clean) || clean.includes("/node_modules/")) return null;
6053
- const result = transformCode(clean, code, {
6395
+ const result = await transformReactCode(clean, code, {
6396
+ react: config.react,
6397
+ consumer: "client",
6398
+ development: true,
6399
+ reactRefresh: true,
6054
6400
  sourcemap: true,
6055
- jsxRuntime: "automatic",
6056
- jsxImportSource: "react",
6057
- reactRefresh: true
6401
+ target: config.build.target,
6402
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
6058
6403
  });
6404
+ if (!result) return null;
6059
6405
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
6060
6406
  }
6061
6407
  };
@@ -6085,11 +6431,11 @@ async function renderBundledIndexHtml(html, config, entryFileNames) {
6085
6431
  }
6086
6432
  return processed;
6087
6433
  }
6088
- var import_node_path14, import_node_crypto3, import_ws2, import_picocolors7, debug7, MIME_TYPES, MemoryFiles, PREAMBLE_SPEC, RESOLVED_PREAMBLE_ID, REFRESH_RUNTIME_URL, BUNDLED_PREAMBLE_CODE, WRAPPER_RUNTIME_HELPERS;
6434
+ var import_node_path15, import_node_crypto3, import_ws2, import_picocolors7, debug7, MIME_TYPES, MemoryFiles, PREAMBLE_SPEC, RESOLVED_PREAMBLE_ID, REFRESH_RUNTIME_URL, BUNDLED_PREAMBLE_CODE, WRAPPER_RUNTIME_HELPERS;
6089
6435
  var init_dev_engine = __esm({
6090
6436
  "src/server/bundled/dev-engine.ts"() {
6091
6437
  "use strict";
6092
- import_node_path14 = __toESM(require("path"), 1);
6438
+ import_node_path15 = __toESM(require("path"), 1);
6093
6439
  import_node_crypto3 = __toESM(require("crypto"), 1);
6094
6440
  import_ws2 = require("ws");
6095
6441
  import_picocolors7 = __toESM(require("picocolors"), 1);
@@ -6299,20 +6645,39 @@ async function createServer(inlineConfig = {}) {
6299
6645
  app.use(bundledServer.middleware);
6300
6646
  }
6301
6647
  const ignoredSegments = /* @__PURE__ */ new Set(["node_modules", ".git", ".nasti"]);
6302
- const outDirAbs = import_node_path15.default.resolve(config.root, config.build.outDir);
6303
- const watcher = (0, import_chokidar.watch)(config.root, {
6648
+ const outDirAbs = import_node_path16.default.resolve(config.root, config.build.outDir);
6649
+ const linkedPackageRoots = getLinkedPackageRoots(config.root).filter(
6650
+ (r) => r !== config.root && !isUnderRoot(config.root, r)
6651
+ );
6652
+ const watchTargets = [config.root, ...linkedPackageRoots];
6653
+ const watcher = (0, import_chokidar.watch)(watchTargets, {
6304
6654
  ignored: (filePath) => {
6305
- if (filePath === config.root) return false;
6306
- if (filePath === outDirAbs || filePath.startsWith(outDirAbs + import_node_path15.default.sep)) return true;
6307
- const rel = import_node_path15.default.relative(config.root, filePath);
6308
- if (!rel || rel.startsWith("..") || import_node_path15.default.isAbsolute(rel)) return false;
6309
- for (const seg of rel.split(import_node_path15.default.sep)) {
6310
- if (ignoredSegments.has(seg)) return true;
6655
+ if (filePath === outDirAbs || filePath.startsWith(outDirAbs + import_node_path16.default.sep)) return true;
6656
+ for (const watchRoot of watchTargets) {
6657
+ if (filePath === watchRoot) return false;
6658
+ const rel = import_node_path16.default.relative(watchRoot, filePath);
6659
+ if (!rel || rel.startsWith("..") || import_node_path16.default.isAbsolute(rel)) continue;
6660
+ for (const seg of rel.split(import_node_path16.default.sep)) {
6661
+ if (ignoredSegments.has(seg)) return true;
6662
+ }
6663
+ return false;
6311
6664
  }
6312
6665
  return false;
6313
6666
  },
6314
6667
  ignoreInitial: true
6315
6668
  });
6669
+ await new Promise((resolve, reject) => {
6670
+ const onReady = () => {
6671
+ watcher.off("error", onError);
6672
+ resolve();
6673
+ };
6674
+ const onError = (err) => {
6675
+ watcher.off("ready", onReady);
6676
+ reject(err);
6677
+ };
6678
+ watcher.once("ready", onReady);
6679
+ watcher.once("error", onError);
6680
+ });
6316
6681
  let server;
6317
6682
  const environmentServices = {};
6318
6683
  let environmentDriversStarted = false;
@@ -6424,16 +6789,25 @@ async function createServer(inlineConfig = {}) {
6424
6789
  });
6425
6790
  };
6426
6791
  watcher.on("change", (file) => {
6792
+ if (file.includes(`${import_node_path16.default.sep}node_modules${import_node_path16.default.sep}`) || file.endsWith(`${import_node_path16.default.sep}node_modules`)) {
6793
+ clearLinkedPackageRootsCache();
6794
+ }
6427
6795
  ssrRunner?.invalidateFile(file);
6428
6796
  queueClientEnvironmentUpdate(file);
6429
6797
  notifyEnvironmentDrivers(file, "change");
6430
6798
  });
6431
6799
  watcher.on("add", (file) => {
6800
+ if (file.includes(`${import_node_path16.default.sep}node_modules${import_node_path16.default.sep}`) || file.endsWith(`${import_node_path16.default.sep}node_modules`)) {
6801
+ clearLinkedPackageRootsCache();
6802
+ }
6432
6803
  ssrRunner?.invalidateFile(file);
6433
6804
  queueClientEnvironmentUpdate(file);
6434
6805
  notifyEnvironmentDrivers(file, "add");
6435
6806
  });
6436
6807
  watcher.on("unlink", (file) => {
6808
+ if (file.includes(`${import_node_path16.default.sep}node_modules${import_node_path16.default.sep}`) || file.endsWith(`${import_node_path16.default.sep}node_modules`)) {
6809
+ clearLinkedPackageRootsCache();
6810
+ }
6437
6811
  ssrRunner?.invalidateFile(file);
6438
6812
  notifyEnvironmentDrivers(file, "unlink");
6439
6813
  });
@@ -6463,7 +6837,7 @@ async function createServer(inlineConfig = {}) {
6463
6837
  const readyIn = Math.ceil(performance.now() - startTime);
6464
6838
  logger.info(
6465
6839
  `
6466
- ${import_picocolors8.default.cyan(import_picocolors8.default.bold("NASTI"))} ${import_picocolors8.default.cyan(`v${"2.4.3"}`)} ${import_picocolors8.default.dim("ready in")} ${import_picocolors8.default.bold(readyIn)} ${import_picocolors8.default.dim("ms")}
6840
+ ${import_picocolors8.default.cyan(import_picocolors8.default.bold("NASTI"))} ${import_picocolors8.default.cyan(`v${"2.5.0"}`)} ${import_picocolors8.default.dim("ready in")} ${import_picocolors8.default.bold(readyIn)} ${import_picocolors8.default.dim("ms")}
6467
6841
  `
6468
6842
  );
6469
6843
  printServerUrls(
@@ -6560,7 +6934,7 @@ async function createServer(inlineConfig = {}) {
6560
6934
  throw error;
6561
6935
  }
6562
6936
  app.use(transformMiddleware(transformContexts.get("client")));
6563
- const publicDir = import_node_path15.default.resolve(config.root, "public");
6937
+ const publicDir = import_node_path16.default.resolve(config.root, "public");
6564
6938
  app.use((0, import_sirv.default)(publicDir, { dev: true, etag: true }));
6565
6939
  app.use((0, import_sirv.default)(config.root, { dev: true, etag: true }));
6566
6940
  const postMiddlewares = [];
@@ -6586,12 +6960,12 @@ function getNetworkAddress() {
6586
6960
  }
6587
6961
  return "localhost";
6588
6962
  }
6589
- var import_node_http, import_node_path15, import_node_os, import_connect, import_sirv, import_chokidar, import_picocolors8;
6963
+ var import_node_http, import_node_path16, import_node_os, import_connect, import_sirv, import_chokidar, import_picocolors8;
6590
6964
  var init_server = __esm({
6591
6965
  "src/server/index.ts"() {
6592
6966
  "use strict";
6593
6967
  import_node_http = __toESM(require("http"), 1);
6594
- import_node_path15 = __toESM(require("path"), 1);
6968
+ import_node_path16 = __toESM(require("path"), 1);
6595
6969
  import_node_os = __toESM(require("os"), 1);
6596
6970
  import_connect = __toESM(require("connect"), 1);
6597
6971
  import_sirv = __toESM(require("sirv"), 1);
@@ -6607,6 +6981,7 @@ var init_server = __esm({
6607
6981
  init_builtins();
6608
6982
  init_plugin_api();
6609
6983
  init_env();
6984
+ init_fs_allow();
6610
6985
  }
6611
6986
  });
6612
6987
 
@@ -6661,16 +7036,16 @@ async function buildElectron(inlineConfig = {}) {
6661
7036
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
6662
7037
  const startTime = performance.now();
6663
7038
  assertElectronVersion(config);
6664
- console.log(import_picocolors9.default.cyan("\n\u26A1 nasti build (electron)") + import_picocolors9.default.dim(` v${"2.4.3"}`));
7039
+ console.log(import_picocolors9.default.cyan("\n\u26A1 nasti build (electron)") + import_picocolors9.default.dim(` v${"2.5.0"}`));
6665
7040
  console.log(import_picocolors9.default.dim(` root: ${config.root}`));
6666
7041
  console.log(import_picocolors9.default.dim(` mode: ${config.mode}`));
6667
7042
  console.log(import_picocolors9.default.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
6668
- const outDir = import_node_path16.default.resolve(config.root, config.build.outDir);
6669
- if (config.build.emptyOutDir && import_node_fs11.default.existsSync(outDir)) {
6670
- import_node_fs11.default.rmSync(outDir, { recursive: true, force: true });
7043
+ const outDir = import_node_path17.default.resolve(config.root, config.build.outDir);
7044
+ if (config.build.emptyOutDir && import_node_fs12.default.existsSync(outDir)) {
7045
+ import_node_fs12.default.rmSync(outDir, { recursive: true, force: true });
6671
7046
  }
6672
- import_node_fs11.default.mkdirSync(outDir, { recursive: true });
6673
- const rendererOutDir = import_node_path16.default.join(outDir, "renderer");
7047
+ import_node_fs12.default.mkdirSync(outDir, { recursive: true });
7048
+ const rendererOutDir = import_node_path17.default.join(outDir, "renderer");
6674
7049
  const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
6675
7050
  await build2(createElectronRendererConfig(config, inlineConfig, {
6676
7051
  build: {
@@ -6679,8 +7054,8 @@ async function buildElectron(inlineConfig = {}) {
6679
7054
  emptyOutDir: false
6680
7055
  }
6681
7056
  }));
6682
- const mainEntry = import_node_path16.default.resolve(config.root, config.electron.main);
6683
- if (!import_node_fs11.default.existsSync(mainEntry)) {
7057
+ const mainEntry = import_node_path17.default.resolve(config.root, config.electron.main);
7058
+ if (!import_node_fs12.default.existsSync(mainEntry)) {
6684
7059
  throw new Error(
6685
7060
  `Electron main entry not found: ${config.electron.main}
6686
7061
  \u5728 nasti.config.ts \u7684 electron.main \u6307\u5B9A\u4E3B\u8FDB\u7A0B\u5165\u53E3\u6587\u4EF6\u3002`
@@ -6694,11 +7069,11 @@ async function buildElectron(inlineConfig = {}) {
6694
7069
  const preloadEntries = normalizePreload(config.electron.preload, config.root);
6695
7070
  const preloadFiles = [];
6696
7071
  for (const entry of preloadEntries) {
6697
- if (!import_node_fs11.default.existsSync(entry)) {
7072
+ if (!import_node_fs12.default.existsSync(entry)) {
6698
7073
  console.warn(import_picocolors9.default.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
6699
7074
  continue;
6700
7075
  }
6701
- const base = import_node_path16.default.basename(entry).replace(/\.[^.]+$/, "");
7076
+ const base = import_node_path17.default.basename(entry).replace(/\.[^.]+$/, "");
6702
7077
  const out = outFileName(outDir, base, config.electron.preloadFormat);
6703
7078
  await bundleNode(config, entry, {
6704
7079
  outFile: out,
@@ -6710,10 +7085,10 @@ async function buildElectron(inlineConfig = {}) {
6710
7085
  const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
6711
7086
  console.log(import_picocolors9.default.green(`
6712
7087
  \u2713 Electron build complete in ${elapsed}s`));
6713
- console.log(import_picocolors9.default.dim(` renderer: ${import_node_path16.default.relative(config.root, rendererOutDir)}/`));
6714
- console.log(import_picocolors9.default.dim(` main: ${import_node_path16.default.relative(config.root, mainFile)}`));
7088
+ console.log(import_picocolors9.default.dim(` renderer: ${import_node_path17.default.relative(config.root, rendererOutDir)}/`));
7089
+ console.log(import_picocolors9.default.dim(` main: ${import_node_path17.default.relative(config.root, mainFile)}`));
6715
7090
  for (const pf of preloadFiles) {
6716
- console.log(import_picocolors9.default.dim(` preload: ${import_node_path16.default.relative(config.root, pf)}`));
7091
+ console.log(import_picocolors9.default.dim(` preload: ${import_node_path17.default.relative(config.root, pf)}`));
6717
7092
  }
6718
7093
  console.log();
6719
7094
  return { rendererOutDir, mainFile, preloadFiles };
@@ -6727,14 +7102,21 @@ async function bundleNode(config, entry, opts) {
6727
7102
  };
6728
7103
  const oxcTransformPlugin = {
6729
7104
  name: "nasti:oxc-transform",
6730
- transform(code, id) {
6731
- if (!shouldTransform(id)) return null;
6732
- const result = transformCode(id, code, {
7105
+ async transform(code, id) {
7106
+ const result = config.framework === "react" ? await transformReactCode(id, code, {
7107
+ react: config.react,
7108
+ consumer: "server",
7109
+ development: config.mode === "development",
7110
+ sourcemap: !!config.build.sourcemap,
7111
+ target: config.electron.nodeTarget,
7112
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
7113
+ }) : shouldTransform(id) ? transformCode(id, code, {
6733
7114
  sourcemap: !!config.build.sourcemap,
6734
7115
  jsxRuntime: "automatic",
6735
- jsxImportSource: config.framework === "vue" ? "vue" : "react",
7116
+ jsxImportSource: "vue",
6736
7117
  target: config.electron.nodeTarget
6737
- });
7118
+ }) : null;
7119
+ if (!result) return null;
6738
7120
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
6739
7121
  }
6740
7122
  };
@@ -6751,7 +7133,7 @@ async function bundleNode(config, entry, opts) {
6751
7133
  },
6752
7134
  plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
6753
7135
  });
6754
- import_node_fs11.default.mkdirSync(import_node_path16.default.dirname(opts.outFile), { recursive: true });
7136
+ import_node_fs12.default.mkdirSync(import_node_path17.default.dirname(opts.outFile), { recursive: true });
6755
7137
  await bundle2.write({
6756
7138
  sourcemap: !!config.build.sourcemap,
6757
7139
  minify: !!config.build.minify,
@@ -6762,7 +7144,7 @@ async function bundleNode(config, entry, opts) {
6762
7144
  codeSplitting: false
6763
7145
  });
6764
7146
  await bundle2.close();
6765
- console.log(import_picocolors9.default.dim(` \u2713 ${opts.label} \u2192 ${import_node_path16.default.relative(config.root, opts.outFile)}`));
7147
+ console.log(import_picocolors9.default.dim(` \u2713 ${opts.label} \u2192 ${import_node_path17.default.relative(config.root, opts.outFile)}`));
6766
7148
  return opts.outFile;
6767
7149
  }
6768
7150
  function createElectronRendererConfig(config, inlineConfig = {}, overrides = {}) {
@@ -6786,11 +7168,11 @@ function createElectronRendererConfig(config, inlineConfig = {}, overrides = {})
6786
7168
  }
6787
7169
  function outFileName(outDir, base, format) {
6788
7170
  const ext = format === "cjs" ? ".cjs" : ".mjs";
6789
- return import_node_path16.default.join(outDir, base + ext);
7171
+ return import_node_path17.default.join(outDir, base + ext);
6790
7172
  }
6791
7173
  function normalizePreload(preload, root) {
6792
7174
  const list = Array.isArray(preload) ? preload : preload ? [preload] : [];
6793
- return list.map((p) => import_node_path16.default.resolve(root, p));
7175
+ return list.map((p) => import_node_path17.default.resolve(root, p));
6794
7176
  }
6795
7177
  function assertElectronVersion(config) {
6796
7178
  const min = config.electron.minVersion;
@@ -6805,21 +7187,30 @@ function assertElectronVersion(config) {
6805
7187
  }
6806
7188
  function detectInstalledElectron(root) {
6807
7189
  try {
6808
- const pkgPath = import_node_path16.default.resolve(root, "node_modules/electron/package.json");
6809
- if (!import_node_fs11.default.existsSync(pkgPath)) return null;
6810
- const pkg = JSON.parse(import_node_fs11.default.readFileSync(pkgPath, "utf-8"));
7190
+ const require2 = (0, import_node_module7.createRequire)(import_node_path17.default.resolve(root, "package.json"));
7191
+ const pkgPath = require2.resolve("electron/package.json");
7192
+ const pkg = JSON.parse(import_node_fs12.default.readFileSync(pkgPath, "utf-8"));
6811
7193
  const major = parseInt(String(pkg.version).split(".")[0], 10);
6812
7194
  return Number.isFinite(major) ? major : null;
6813
7195
  } catch {
6814
- return null;
7196
+ try {
7197
+ const pkgPath = import_node_path17.default.resolve(root, "node_modules/electron/package.json");
7198
+ if (!import_node_fs12.default.existsSync(pkgPath)) return null;
7199
+ const pkg = JSON.parse(import_node_fs12.default.readFileSync(pkgPath, "utf-8"));
7200
+ const major = parseInt(String(pkg.version).split(".")[0], 10);
7201
+ return Number.isFinite(major) ? major : null;
7202
+ } catch {
7203
+ return null;
7204
+ }
6815
7205
  }
6816
7206
  }
6817
- var import_node_path16, import_node_fs11, import_rolldown2, import_picocolors9;
7207
+ var import_node_path17, import_node_fs12, import_node_module7, import_rolldown2, import_picocolors9;
6818
7208
  var init_electron2 = __esm({
6819
7209
  "src/build/electron.ts"() {
6820
7210
  "use strict";
6821
- import_node_path16 = __toESM(require("path"), 1);
6822
- import_node_fs11 = __toESM(require("fs"), 1);
7211
+ import_node_path17 = __toESM(require("path"), 1);
7212
+ import_node_fs12 = __toESM(require("fs"), 1);
7213
+ import_node_module7 = require("module");
6823
7214
  import_rolldown2 = require("rolldown");
6824
7215
  import_picocolors9 = __toESM(require("picocolors"), 1);
6825
7216
  init_config();
@@ -6840,7 +7231,7 @@ async function startElectronDev(inlineConfig = {}) {
6840
7231
  const { noSpawn, ...rest } = inlineConfig;
6841
7232
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
6842
7233
  warnElectronVersion(config);
6843
- console.log(import_picocolors10.default.cyan("\n\u26A1 nasti electron dev") + import_picocolors10.default.dim(` v${"2.4.3"}`));
7234
+ console.log(import_picocolors10.default.cyan("\n\u26A1 nasti electron dev") + import_picocolors10.default.dim(` v${"2.5.0"}`));
6844
7235
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
6845
7236
  const server = await createServer2({
6846
7237
  ...rest,
@@ -6850,11 +7241,11 @@ async function startElectronDev(inlineConfig = {}) {
6850
7241
  await server.listen();
6851
7242
  const devUrl = `http://localhost:${server.config.server.port}` + electronRendererDevPath(config.electron.renderer);
6852
7243
  console.log(import_picocolors10.default.dim(` renderer: ${devUrl}`));
6853
- const stageDir = import_node_path17.default.resolve(config.root, ".nasti");
6854
- import_node_fs12.default.mkdirSync(stageDir, { recursive: true });
6855
- const mainEntry = import_node_path17.default.resolve(config.root, config.electron.main);
7244
+ const stageDir = import_node_path18.default.resolve(config.root, ".nasti");
7245
+ import_node_fs13.default.mkdirSync(stageDir, { recursive: true });
7246
+ const mainEntry = import_node_path18.default.resolve(config.root, config.electron.main);
6856
7247
  const preloadEntries = normalizePreload(config.electron.preload, config.root);
6857
- const builtMainFile = import_node_path17.default.join(stageDir, "main" + extFor(config.electron.mainFormat));
7248
+ const builtMainFile = import_node_path18.default.join(stageDir, "main" + extFor(config.electron.mainFormat));
6858
7249
  const builtPreloadFiles = [];
6859
7250
  const compileAll = async () => {
6860
7251
  await compileNode(config, mainEntry, {
@@ -6864,9 +7255,9 @@ async function startElectronDev(inlineConfig = {}) {
6864
7255
  });
6865
7256
  builtPreloadFiles.length = 0;
6866
7257
  for (const entry of preloadEntries) {
6867
- if (!import_node_fs12.default.existsSync(entry)) continue;
6868
- const base = import_node_path17.default.basename(entry).replace(/\.[^.]+$/, "");
6869
- const out = import_node_path17.default.join(stageDir, base + extFor(config.electron.preloadFormat));
7258
+ if (!import_node_fs13.default.existsSync(entry)) continue;
7259
+ const base = import_node_path18.default.basename(entry).replace(/\.[^.]+$/, "");
7260
+ const out = import_node_path18.default.join(stageDir, base + extFor(config.electron.preloadFormat));
6870
7261
  await compileNode(config, entry, {
6871
7262
  outFile: out,
6872
7263
  format: config.electron.preloadFormat,
@@ -6905,7 +7296,7 @@ async function startElectronDev(inlineConfig = {}) {
6905
7296
  };
6906
7297
  spawnElectron();
6907
7298
  if (config.electron.autoRestart) {
6908
- const watchTargets = [mainEntry, ...preloadEntries].filter(import_node_fs12.default.existsSync);
7299
+ const watchTargets = [mainEntry, ...preloadEntries].filter(import_node_fs13.default.existsSync);
6909
7300
  const watcher = import_chokidar2.default.watch(watchTargets, { ignoreInitial: true });
6910
7301
  let restarting = null;
6911
7302
  let pending = false;
@@ -6965,14 +7356,21 @@ async function compileNode(config, entry, opts) {
6965
7356
  };
6966
7357
  const oxcTransformPlugin = {
6967
7358
  name: "nasti:oxc-transform",
6968
- transform(code, id) {
6969
- if (!shouldTransform(id)) return null;
6970
- const result = transformCode(id, code, {
7359
+ async transform(code, id) {
7360
+ const result = config.framework === "react" ? await transformReactCode(id, code, {
7361
+ react: config.react,
7362
+ consumer: "server",
7363
+ development: true,
7364
+ sourcemap: true,
7365
+ target: config.electron.nodeTarget,
7366
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
7367
+ }) : shouldTransform(id) ? transformCode(id, code, {
6971
7368
  sourcemap: true,
6972
7369
  jsxRuntime: "automatic",
6973
- jsxImportSource: config.framework === "vue" ? "vue" : "react",
7370
+ jsxImportSource: "vue",
6974
7371
  target: config.electron.nodeTarget
6975
- });
7372
+ }) : null;
7373
+ if (!result) return null;
6976
7374
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
6977
7375
  }
6978
7376
  };
@@ -6985,7 +7383,7 @@ async function compileNode(config, entry, opts) {
6985
7383
  platform: "node",
6986
7384
  plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
6987
7385
  });
6988
- import_node_fs12.default.mkdirSync(import_node_path17.default.dirname(opts.outFile), { recursive: true });
7386
+ import_node_fs13.default.mkdirSync(import_node_path18.default.dirname(opts.outFile), { recursive: true });
6989
7387
  await bundle2.write({
6990
7388
  file: opts.outFile,
6991
7389
  format: opts.format === "cjs" ? "cjs" : "esm",
@@ -6998,18 +7396,18 @@ async function compileNode(config, entry, opts) {
6998
7396
  await bundle2.close();
6999
7397
  }
7000
7398
  function electronRendererDevPath(renderer) {
7001
- const normalized = renderer.split(import_node_path17.default.sep).join("/").replace(/^\.?\//, "");
7399
+ const normalized = renderer.split(import_node_path18.default.sep).join("/").replace(/^\.?\//, "");
7002
7400
  return normalized === "index.html" ? "/" : `/${normalized}`;
7003
7401
  }
7004
7402
  function resolveElectronBinary(config) {
7005
- if (config.electron.electronPath && import_node_fs12.default.existsSync(config.electron.electronPath)) {
7403
+ if (config.electron.electronPath && import_node_fs13.default.existsSync(config.electron.electronPath)) {
7006
7404
  return config.electron.electronPath;
7007
7405
  }
7008
7406
  try {
7009
- const require2 = (0, import_node_module7.createRequire)(import_node_path17.default.resolve(config.root, "package.json"));
7407
+ const require2 = (0, import_node_module8.createRequire)(import_node_path18.default.resolve(config.root, "package.json"));
7010
7408
  const pathFile = require2.resolve("electron");
7011
7409
  const electronModule = require2(pathFile);
7012
- if (typeof electronModule === "string" && import_node_fs12.default.existsSync(electronModule)) {
7410
+ if (typeof electronModule === "string" && import_node_fs13.default.existsSync(electronModule)) {
7013
7411
  return electronModule;
7014
7412
  }
7015
7413
  } catch {
@@ -7034,13 +7432,13 @@ function warnElectronVersion(config) {
7034
7432
  );
7035
7433
  }
7036
7434
  }
7037
- var import_node_path17, import_node_fs12, import_node_module7, import_node_child_process, import_chokidar2, import_picocolors10, import_rolldown3;
7435
+ var import_node_path18, import_node_fs13, import_node_module8, import_node_child_process, import_chokidar2, import_picocolors10, import_rolldown3;
7038
7436
  var init_electron_dev = __esm({
7039
7437
  "src/server/electron-dev.ts"() {
7040
7438
  "use strict";
7041
- import_node_path17 = __toESM(require("path"), 1);
7042
- import_node_fs12 = __toESM(require("fs"), 1);
7043
- import_node_module7 = require("module");
7439
+ import_node_path18 = __toESM(require("path"), 1);
7440
+ import_node_fs13 = __toESM(require("fs"), 1);
7441
+ import_node_module8 = require("module");
7044
7442
  import_node_child_process = require("child_process");
7045
7443
  import_chokidar2 = __toESM(require("chokidar"), 1);
7046
7444
  import_picocolors10 = __toESM(require("picocolors"), 1);
@@ -7192,20 +7590,20 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
7192
7590
  const logger = createCliLogger(options);
7193
7591
  try {
7194
7592
  const http2 = await import("http");
7195
- const path18 = await import("path");
7593
+ const path19 = await import("path");
7196
7594
  const os2 = await import("os");
7197
7595
  const sirv2 = (await import("sirv")).default;
7198
7596
  const connect2 = (await import("connect")).default;
7199
7597
  const { printServerUrls: printServerUrls2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
7200
- const resolvedRoot = path18.resolve(root ?? ".");
7201
- const outDir = path18.resolve(resolvedRoot, options.outDir);
7598
+ const resolvedRoot = path19.resolve(root ?? ".");
7599
+ const outDir = path19.resolve(resolvedRoot, options.outDir);
7202
7600
  const app = connect2();
7203
7601
  app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
7204
7602
  const port = options.port;
7205
7603
  const host = options.host === true ? "0.0.0.0" : options.host ?? "localhost";
7206
7604
  http2.createServer(app).listen(port, host, () => {
7207
7605
  logger.info(`
7208
- ${import_picocolors11.default.cyan(import_picocolors11.default.bold("NASTI"))} ${import_picocolors11.default.cyan(`v${"2.4.3"}`)} ${import_picocolors11.default.dim("preview")}
7606
+ ${import_picocolors11.default.cyan(import_picocolors11.default.bold("NASTI"))} ${import_picocolors11.default.cyan(`v${"2.5.0"}`)} ${import_picocolors11.default.dim("preview")}
7209
7607
  `);
7210
7608
  printServerUrls2(
7211
7609
  {
@@ -7222,6 +7620,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
7222
7620
  }
7223
7621
  });
7224
7622
  cli.help();
7225
- cli.version("2.4.3");
7623
+ cli.version("2.5.0");
7226
7624
  cli.parse();
7227
7625
  //# sourceMappingURL=cli.cjs.map