@nasti-toolchain/nasti 2.4.4 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -162,7 +162,7 @@ var init_logger = __esm({
162
162
  });
163
163
 
164
164
  // src/config/defaults.ts
165
- var defaultResolve, defaultServer, defaultBuild, defaultElectron, defaultExperimental, defaults;
165
+ var defaultResolve, defaultServer, defaultBuild, defaultElectron, defaultExperimental, defaultReact, defaults;
166
166
  var init_defaults = __esm({
167
167
  "src/config/defaults.ts"() {
168
168
  "use strict";
@@ -215,12 +215,20 @@ var init_defaults = __esm({
215
215
  defaultExperimental = {
216
216
  bundledDev: false
217
217
  };
218
+ defaultReact = {
219
+ include: /\.[tj]sx?$/,
220
+ exclude: /node_modules/,
221
+ jsxImportSource: "react",
222
+ jsxRuntime: "automatic",
223
+ compiler: false
224
+ };
218
225
  defaults = {
219
226
  root: ".",
220
227
  base: "/",
221
228
  mode: "development",
222
229
  target: "web",
223
230
  framework: "auto",
231
+ react: defaultReact,
224
232
  resolve: defaultResolve,
225
233
  server: defaultServer,
226
234
  build: defaultBuild,
@@ -445,6 +453,13 @@ async function resolveConfig(inlineConfig = {}, command) {
445
453
  mode,
446
454
  target: merged.target ?? defaults.target,
447
455
  framework: (merged.framework ?? defaults.framework) === "auto" ? detectFramework(root) : merged.framework,
456
+ react: {
457
+ include: merged.react?.include ?? defaultReact.include,
458
+ exclude: merged.react?.exclude ?? defaultReact.exclude,
459
+ jsxImportSource: merged.react?.jsxImportSource ?? defaultReact.jsxImportSource,
460
+ jsxRuntime: merged.react?.jsxRuntime ?? defaultReact.jsxRuntime,
461
+ compiler: merged.react?.compiler === true ? {} : merged.react?.compiler ?? defaultReact.compiler
462
+ },
448
463
  command,
449
464
  resolve: {
450
465
  // tsconfig paths 优先级最低:tsconfig < defaults < user config
@@ -1359,13 +1374,88 @@ ${msg}`);
1359
1374
  map: result.map ? JSON.stringify(result.map) : null
1360
1375
  };
1361
1376
  }
1362
- var JS_EXTENSIONS, TS_EXTENSIONS, JSX_EXTENSIONS;
1377
+ async function transformReactCode(filename, code, options) {
1378
+ if (!matchesReactFilter(filename, options.react.include, options.react.exclude)) {
1379
+ return null;
1380
+ }
1381
+ if (!options.react.compiler) {
1382
+ if (!shouldTransform(filename)) return null;
1383
+ return transformCode(filename, code, {
1384
+ sourcemap: options.sourcemap,
1385
+ jsxRuntime: options.react.jsxRuntime,
1386
+ jsxImportSource: options.react.jsxImportSource,
1387
+ reactRefresh: options.reactRefresh,
1388
+ target: options.target
1389
+ });
1390
+ }
1391
+ if (!shouldTransform(filename)) return null;
1392
+ const compiler2 = await loadReactCompiler();
1393
+ const compilerOptions = options.react.compiler;
1394
+ const shouldCompile = options.consumer === "client" && (compilerOptions.compilationMode === "annotation" ? /['"]use memo['"]/.test(code) : defaultReactCompilerCodeFilter.test(code));
1395
+ const result = await compiler2.transform(cleanTransformId(filename), code, {
1396
+ jsx: {
1397
+ runtime: options.react.jsxRuntime,
1398
+ development: options.development,
1399
+ importSource: options.react.jsxImportSource,
1400
+ refresh: options.consumer === "client" && !!options.reactRefresh
1401
+ },
1402
+ reactCompiler: shouldCompile ? compilerOptions : false,
1403
+ sourcemap: options.sourcemap ?? true
1404
+ });
1405
+ const diagnostics = result.errors.map(
1406
+ (error) => `${error.message}${error.codeframe ? `
1407
+ ${error.codeframe}` : ""}`
1408
+ );
1409
+ if (result.fatal) {
1410
+ throw new Error(
1411
+ diagnostics.join("\n\n") || `React Compiler transform failed for ${filename}`
1412
+ );
1413
+ }
1414
+ for (const diagnostic of diagnostics) options.onWarning?.(diagnostic);
1415
+ return {
1416
+ code: result.code,
1417
+ map: result.map ? JSON.stringify(result.map) : null
1418
+ };
1419
+ }
1420
+ function matchesReactFilter(id, include, exclude) {
1421
+ const cleanId = cleanTransformId(id);
1422
+ return matchesFilter(cleanId, include) && !matchesFilter(cleanId, exclude);
1423
+ }
1424
+ function matchesFilter(id, filter2) {
1425
+ const patterns = Array.isArray(filter2) ? filter2 : [filter2];
1426
+ return patterns.some((pattern) => {
1427
+ if (pattern instanceof RegExp) {
1428
+ pattern.lastIndex = 0;
1429
+ return pattern.test(id);
1430
+ }
1431
+ if (!pattern.includes("*")) return id.includes(pattern);
1432
+ const expression = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "\0").replace(/\*/g, "[^/]*").replace(/\0/g, ".*");
1433
+ return new RegExp(`^${expression}$`).test(id);
1434
+ });
1435
+ }
1436
+ function cleanTransformId(id) {
1437
+ return id.split(/[?#]/, 1)[0];
1438
+ }
1439
+ async function loadReactCompiler() {
1440
+ if (reactCompilerImplementation) return reactCompilerImplementation;
1441
+ try {
1442
+ reactCompilerImplementation = await import("oxc-transform-react");
1443
+ return reactCompilerImplementation;
1444
+ } catch (error) {
1445
+ throw new Error(
1446
+ '[nasti] React Compiler requires the optional "oxc-transform-react" package. Install it before setting react.compiler.' + (error instanceof Error ? `
1447
+ ${error.message}` : "")
1448
+ );
1449
+ }
1450
+ }
1451
+ var JS_EXTENSIONS, TS_EXTENSIONS, JSX_EXTENSIONS, defaultReactCompilerCodeFilter, reactCompilerImplementation;
1363
1452
  var init_transformer = __esm({
1364
1453
  "src/core/transformer.ts"() {
1365
1454
  "use strict";
1366
1455
  JS_EXTENSIONS = /\.(js|mjs|cjs)$/;
1367
1456
  TS_EXTENSIONS = /\.(ts|mts|cts)$/;
1368
1457
  JSX_EXTENSIONS = /\.(jsx|tsx)$/;
1458
+ defaultReactCompilerCodeFilter = /forwardRef|memo|\b(?:[A-Z]|use[A-Z0-9])/;
1369
1459
  }
1370
1460
  });
1371
1461
 
@@ -2001,22 +2091,35 @@ async function transformRequest(url, ctx) {
2001
2091
  }
2002
2092
  const stableUrl = cleanReqUrl;
2003
2093
  let wrappedWithRefresh = false;
2004
- if (shouldTransform(filePath)) {
2005
- const isJsx = /\.[jt]sx$/.test(filePath);
2006
- const useRefresh = isJsx && config.framework !== "vue";
2094
+ if (config.framework === "react") {
2095
+ const refreshEnabled = (ctx.environment?.consumer ?? "client") === "client" && config.server.hmr !== false;
2096
+ const useRefresh = refreshEnabled && (!!config.react.compiler || /\.[jt]sx$/.test(filePath));
2097
+ const result = await transformReactCode(filePath, code, {
2098
+ react: config.react,
2099
+ consumer: ctx.environment?.consumer ?? "client",
2100
+ development: true,
2101
+ reactRefresh: useRefresh,
2102
+ sourcemap: true,
2103
+ target: ctx.environment?.options.build.target ?? config.build.target,
2104
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
2105
+ });
2106
+ if (result) {
2107
+ code = result.code;
2108
+ if (result.map) map = JSON.parse(result.map);
2109
+ if (useRefresh) {
2110
+ code = buildReactRefreshWrapper(stableUrl, code);
2111
+ wrappedWithRefresh = true;
2112
+ }
2113
+ }
2114
+ } else if (shouldTransform(filePath)) {
2007
2115
  const result = transformCode(filePath, code, {
2008
2116
  sourcemap: true,
2009
2117
  jsxRuntime: "automatic",
2010
- jsxImportSource: config.framework === "vue" ? "vue" : "react",
2011
- reactRefresh: useRefresh,
2118
+ jsxImportSource: "vue",
2012
2119
  target: ctx.environment?.options.build.target ?? config.build.target
2013
2120
  });
2014
2121
  code = result.code;
2015
2122
  if (result.map) map = JSON.parse(result.map);
2016
- if (useRefresh) {
2017
- code = buildReactRefreshWrapper(stableUrl, code);
2018
- wrappedWithRefresh = true;
2019
- }
2020
2123
  }
2021
2124
  const hotInfo = rewriteHotAcceptDeps(code, config, filePath);
2022
2125
  code = hotInfo.code;
@@ -4967,12 +5070,32 @@ var init_runnable_environment = __esm({
4967
5070
  if (transformed != null) {
4968
5071
  code = typeof transformed === "string" ? transformed : transformed.code;
4969
5072
  }
4970
- if (shouldTransform(cleanId)) {
5073
+ if (this.config.framework === "react") {
5074
+ const result = await transformReactCode(cleanId, code, {
5075
+ react: this.config.react,
5076
+ consumer: this.environment.consumer,
5077
+ development: true,
5078
+ sourcemap: false,
5079
+ target: this.environment.options.build.target,
5080
+ onWarning: (message) => this.config.logger.warn(`[nasti:react] ${message}`)
5081
+ });
5082
+ if (result) {
5083
+ code = result.code;
5084
+ } else if (shouldTransform(cleanId)) {
5085
+ const fallback = transformCode(cleanId, code, {
5086
+ sourcemap: false,
5087
+ jsxRuntime: this.config.react.jsxRuntime,
5088
+ jsxImportSource: this.config.react.jsxImportSource,
5089
+ target: this.environment.options.build.target
5090
+ });
5091
+ code = fallback.code;
5092
+ }
5093
+ } else if (shouldTransform(cleanId)) {
4971
5094
  const result = transformCode(cleanId, code, {
4972
5095
  sourcemap: false,
4973
5096
  target: this.environment.options.build.target,
4974
5097
  jsxRuntime: "automatic",
4975
- jsxImportSource: this.config.framework === "vue" ? "vue" : "react"
5098
+ jsxImportSource: "vue"
4976
5099
  });
4977
5100
  code = result.code;
4978
5101
  }
@@ -5088,6 +5211,44 @@ var init_runnable_environment = __esm({
5088
5211
  }
5089
5212
  });
5090
5213
 
5214
+ // src/plugins/react.ts
5215
+ function reactPlugin(config, environment) {
5216
+ return {
5217
+ name: "nasti:oxc-transform",
5218
+ async transform(code, id) {
5219
+ const result = await transformReactCode(id, code, {
5220
+ react: config.react,
5221
+ consumer: environment.consumer,
5222
+ development: config.mode === "development",
5223
+ sourcemap: !!environment.options.build.sourcemap,
5224
+ target: environment.options.build.target,
5225
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
5226
+ });
5227
+ if (!result) return null;
5228
+ return {
5229
+ code: result.code,
5230
+ map: result.map ? JSON.parse(result.map) : void 0
5231
+ };
5232
+ },
5233
+ handleHotUpdate(ctx) {
5234
+ for (const mod of ctx.modules) {
5235
+ if (REACT_FILE_RE.test(mod.url) && matchesReactFilter(mod.url, config.react.include, config.react.exclude)) {
5236
+ mod.isSelfAccepting = true;
5237
+ }
5238
+ }
5239
+ return ctx.modules;
5240
+ }
5241
+ };
5242
+ }
5243
+ var REACT_FILE_RE;
5244
+ var init_react = __esm({
5245
+ "src/plugins/react.ts"() {
5246
+ "use strict";
5247
+ init_transformer();
5248
+ REACT_FILE_RE = /\.[jt]sx(?:[?#].*)?$/;
5249
+ }
5250
+ });
5251
+
5091
5252
  // src/build/reporter.ts
5092
5253
  import path12 from "path";
5093
5254
  import { gzipSync } from "zlib";
@@ -5384,7 +5545,7 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
5384
5545
  // 相对/绝对/虚拟模块照常打包。需要内联依赖时经 rolldownOptions.external 覆盖。
5385
5546
  external: restInputOptions.external ?? ((id) => {
5386
5547
  if (NODE_BUILTINS2.has(id)) return true;
5387
- return !id.startsWith(".") && !path14.isAbsolute(id) && !id.startsWith("\0");
5548
+ return !id.startsWith(".") && !path14.isAbsolute(id) && !id.startsWith("\0") && !id.startsWith("virtual:");
5388
5549
  })
5389
5550
  } : {}
5390
5551
  };
@@ -5607,6 +5768,7 @@ function resolveClientEntries(config, html) {
5607
5768
  return entryPoints;
5608
5769
  }
5609
5770
  function createOxcTransformPlugin(config, environment) {
5771
+ if (config.framework === "react") return reactPlugin(config, environment);
5610
5772
  return {
5611
5773
  name: "nasti:oxc-transform",
5612
5774
  transform(code, id) {
@@ -5627,7 +5789,7 @@ async function build(inlineConfig = {}) {
5627
5789
  const startTime = performance.now();
5628
5790
  logger.info(
5629
5791
  pc6.cyan(`
5630
- nasti v${"2.4.4"} `) + pc6.green(`building for ${config.mode}...`)
5792
+ nasti v${"2.5.0"} `) + pc6.green(`building for ${config.mode}...`)
5631
5793
  );
5632
5794
  debug6?.(`root: ${config.root}`);
5633
5795
  const buildableNames = Object.keys(config.environments).filter((name) => {
@@ -5909,6 +6071,7 @@ var init_build = __esm({
5909
6071
  init_environment();
5910
6072
  init_css_engine();
5911
6073
  init_html();
6074
+ init_react();
5912
6075
  init_transformer();
5913
6076
  init_env();
5914
6077
  init_reporter();
@@ -5955,11 +6118,11 @@ async function createBundledDevServer(opts) {
5955
6118
  const patches = new MemoryFiles();
5956
6119
  const entryFileNames = /* @__PURE__ */ new Map();
5957
6120
  const bundledClients = /* @__PURE__ */ new Map();
5958
- const useReactRefresh = config.framework !== "vue" && refreshWrapperFn != null;
6121
+ const useReactRefresh = config.framework === "react" && config.server.hmr !== false && refreshWrapperFn != null;
5959
6122
  const rolldownPlugins = [
5960
6123
  ...useReactRefresh ? [
5961
6124
  createReactRefreshRuntimePlugin(entryPoints),
5962
- createBundledOxcRefreshPlugin()
6125
+ createBundledOxcRefreshPlugin(config)
5963
6126
  ] : [],
5964
6127
  ...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins, clientEnv)),
5965
6128
  ...useReactRefresh ? [
@@ -6230,18 +6393,21 @@ ${code}`, map: null };
6230
6393
  }
6231
6394
  };
6232
6395
  }
6233
- function createBundledOxcRefreshPlugin() {
6396
+ function createBundledOxcRefreshPlugin(config) {
6234
6397
  return {
6235
6398
  name: "nasti:bundled-oxc-refresh",
6236
- transform(code, id) {
6399
+ async transform(code, id) {
6237
6400
  const clean = id.split("?")[0];
6238
- if (!/\.[jt]sx$/.test(clean) || clean.includes("/node_modules/")) return null;
6239
- const result = transformCode(clean, code, {
6401
+ const result = await transformReactCode(clean, code, {
6402
+ react: config.react,
6403
+ consumer: "client",
6404
+ development: true,
6405
+ reactRefresh: true,
6240
6406
  sourcemap: true,
6241
- jsxRuntime: "automatic",
6242
- jsxImportSource: "react",
6243
- reactRefresh: true
6407
+ target: config.build.target,
6408
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
6244
6409
  });
6410
+ if (!result) return null;
6245
6411
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
6246
6412
  }
6247
6413
  };
@@ -6680,7 +6846,7 @@ async function createServer(inlineConfig = {}) {
6680
6846
  const readyIn = Math.ceil(performance.now() - startTime);
6681
6847
  logger.info(
6682
6848
  `
6683
- ${pc8.cyan(pc8.bold("NASTI"))} ${pc8.cyan(`v${"2.4.4"}`)} ${pc8.dim("ready in")} ${pc8.bold(readyIn)} ${pc8.dim("ms")}
6849
+ ${pc8.cyan(pc8.bold("NASTI"))} ${pc8.cyan(`v${"2.5.0"}`)} ${pc8.dim("ready in")} ${pc8.bold(readyIn)} ${pc8.dim("ms")}
6684
6850
  `
6685
6851
  );
6686
6852
  printServerUrls(
@@ -6876,7 +7042,7 @@ async function buildElectron(inlineConfig = {}) {
6876
7042
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
6877
7043
  const startTime = performance.now();
6878
7044
  assertElectronVersion(config);
6879
- console.log(pc9.cyan("\n\u26A1 nasti build (electron)") + pc9.dim(` v${"2.4.4"}`));
7045
+ console.log(pc9.cyan("\n\u26A1 nasti build (electron)") + pc9.dim(` v${"2.5.0"}`));
6880
7046
  console.log(pc9.dim(` root: ${config.root}`));
6881
7047
  console.log(pc9.dim(` mode: ${config.mode}`));
6882
7048
  console.log(pc9.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
@@ -6942,14 +7108,21 @@ async function bundleNode(config, entry, opts) {
6942
7108
  };
6943
7109
  const oxcTransformPlugin = {
6944
7110
  name: "nasti:oxc-transform",
6945
- transform(code, id) {
6946
- if (!shouldTransform(id)) return null;
6947
- const result = transformCode(id, code, {
7111
+ async transform(code, id) {
7112
+ const result = config.framework === "react" ? await transformReactCode(id, code, {
7113
+ react: config.react,
7114
+ consumer: "server",
7115
+ development: config.mode === "development",
7116
+ sourcemap: !!config.build.sourcemap,
7117
+ target: config.electron.nodeTarget,
7118
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
7119
+ }) : shouldTransform(id) ? transformCode(id, code, {
6948
7120
  sourcemap: !!config.build.sourcemap,
6949
7121
  jsxRuntime: "automatic",
6950
- jsxImportSource: config.framework === "vue" ? "vue" : "react",
7122
+ jsxImportSource: "vue",
6951
7123
  target: config.electron.nodeTarget
6952
- });
7124
+ }) : null;
7125
+ if (!result) return null;
6953
7126
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
6954
7127
  }
6955
7128
  };
@@ -7065,7 +7238,7 @@ async function startElectronDev(inlineConfig = {}) {
7065
7238
  const { noSpawn, ...rest } = inlineConfig;
7066
7239
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
7067
7240
  warnElectronVersion(config);
7068
- console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.4.4"}`));
7241
+ console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.5.0"}`));
7069
7242
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
7070
7243
  const server = await createServer2({
7071
7244
  ...rest,
@@ -7190,14 +7363,21 @@ async function compileNode(config, entry, opts) {
7190
7363
  };
7191
7364
  const oxcTransformPlugin = {
7192
7365
  name: "nasti:oxc-transform",
7193
- transform(code, id) {
7194
- if (!shouldTransform(id)) return null;
7195
- const result = transformCode(id, code, {
7366
+ async transform(code, id) {
7367
+ const result = config.framework === "react" ? await transformReactCode(id, code, {
7368
+ react: config.react,
7369
+ consumer: "server",
7370
+ development: true,
7371
+ sourcemap: true,
7372
+ target: config.electron.nodeTarget,
7373
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
7374
+ }) : shouldTransform(id) ? transformCode(id, code, {
7196
7375
  sourcemap: true,
7197
7376
  jsxRuntime: "automatic",
7198
- jsxImportSource: config.framework === "vue" ? "vue" : "react",
7377
+ jsxImportSource: "vue",
7199
7378
  target: config.electron.nodeTarget
7200
- });
7379
+ }) : null;
7380
+ if (!result) return null;
7201
7381
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
7202
7382
  }
7203
7383
  };
@@ -7422,7 +7602,7 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
7422
7602
  const host = options.host === true ? "0.0.0.0" : options.host ?? "localhost";
7423
7603
  http2.createServer(app).listen(port, host, () => {
7424
7604
  logger.info(`
7425
- ${pc11.cyan(pc11.bold("NASTI"))} ${pc11.cyan(`v${"2.4.4"}`)} ${pc11.dim("preview")}
7605
+ ${pc11.cyan(pc11.bold("NASTI"))} ${pc11.cyan(`v${"2.5.0"}`)} ${pc11.dim("preview")}
7426
7606
  `);
7427
7607
  printServerUrls2(
7428
7608
  {
@@ -7439,6 +7619,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
7439
7619
  }
7440
7620
  });
7441
7621
  cli.help();
7442
- cli.version("2.4.4");
7622
+ cli.version("2.5.0");
7443
7623
  cli.parse();
7444
7624
  //# sourceMappingURL=cli.js.map