@nasti-toolchain/nasti 1.1.0 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,11 +1,5 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
- }) : x)(function(x) {
6
- if (typeof require !== "undefined") return require.apply(this, arguments);
7
- throw Error('Dynamic require of "' + x + '" is not supported');
8
- });
9
3
  var __esm = (fn, res) => function __init() {
10
4
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
5
  };
@@ -97,6 +91,11 @@ function transformCode(filename, code, options = {}) {
97
91
  } : void 0,
98
92
  sourcemap: options.sourcemap ?? true
99
93
  });
94
+ if (result.errors && result.errors.length > 0) {
95
+ const msg = result.errors.map((e) => e.message ?? String(e)).join("\n");
96
+ throw new Error(`OXC transform failed for ${filename}:
97
+ ${msg}`);
98
+ }
100
99
  return {
101
100
  code: result.code,
102
101
  map: result.map ? JSON.stringify(result.map) : null
@@ -112,17 +111,90 @@ var init_transformer = __esm({
112
111
  }
113
112
  });
114
113
 
114
+ // src/core/env.ts
115
+ import path6 from "path";
116
+ import fs5 from "fs";
117
+ function loadEnv(mode, root, prefixes) {
118
+ const envFiles = [
119
+ ".env",
120
+ `.env.${mode}`,
121
+ ".env.local",
122
+ `.env.${mode}.local`
123
+ ];
124
+ const raw = {};
125
+ for (const file of envFiles) {
126
+ const filePath = path6.resolve(root, file);
127
+ if (!fs5.existsSync(filePath)) continue;
128
+ const content = fs5.readFileSync(filePath, "utf-8");
129
+ for (const line of content.split("\n")) {
130
+ const trimmed = line.trim();
131
+ if (!trimmed || trimmed.startsWith("#")) continue;
132
+ const eqIdx = trimmed.indexOf("=");
133
+ if (eqIdx === -1) continue;
134
+ const key = trimmed.slice(0, eqIdx).trim();
135
+ let value = trimmed.slice(eqIdx + 1).trim();
136
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
137
+ value = value.slice(1, -1);
138
+ }
139
+ raw[key] = value;
140
+ }
141
+ }
142
+ const filtered = {};
143
+ for (const [key, value] of Object.entries(raw)) {
144
+ if (prefixes.some((prefix) => key.startsWith(prefix))) {
145
+ filtered[key] = value;
146
+ }
147
+ }
148
+ return filtered;
149
+ }
150
+ function buildEnvDefine(env, mode) {
151
+ const define = {};
152
+ for (const [key, value] of Object.entries(env)) {
153
+ define[`import.meta.env.${key}`] = JSON.stringify(value);
154
+ }
155
+ define["import.meta.env.MODE"] = JSON.stringify(mode);
156
+ define["import.meta.env.DEV"] = mode !== "production" ? "true" : "false";
157
+ define["import.meta.env.PROD"] = mode === "production" ? "true" : "false";
158
+ define["import.meta.env.SSR"] = "false";
159
+ return define;
160
+ }
161
+ function replaceEnvInCode(code, define) {
162
+ let result = code;
163
+ for (const [key, value] of Object.entries(define)) {
164
+ const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
165
+ result = result.replace(new RegExp(escaped, "g"), value);
166
+ }
167
+ return result;
168
+ }
169
+ var init_env = __esm({
170
+ "src/core/env.ts"() {
171
+ "use strict";
172
+ }
173
+ });
174
+
115
175
  // src/server/middleware.ts
116
176
  var middleware_exports = {};
117
177
  __export(middleware_exports, {
118
178
  transformMiddleware: () => transformMiddleware,
119
179
  transformRequest: () => transformRequest
120
180
  });
121
- import path7 from "path";
122
- import fs6 from "fs";
181
+ import path8 from "path";
182
+ import fs7 from "fs";
183
+ import { createRequire as createRequire2 } from "module";
123
184
  function transformMiddleware(ctx) {
124
185
  return async (req, res, next) => {
125
186
  const url = req.url ?? "/";
187
+ if (ctx.config.server.cors) {
188
+ const origin = req.headers.origin ?? "*";
189
+ res.setHeader("Access-Control-Allow-Origin", origin);
190
+ res.setHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
191
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
192
+ if (req.method === "OPTIONS") {
193
+ res.statusCode = 204;
194
+ res.end();
195
+ return;
196
+ }
197
+ }
126
198
  if (req.method !== "GET") return next();
127
199
  if (url === "/@nasti/client") {
128
200
  res.setHeader("Content-Type", "application/javascript");
@@ -145,10 +217,12 @@ function transformMiddleware(ctx) {
145
217
  }
146
218
  }
147
219
  }
148
- processedHtml = processedHtml.replace(
149
- "<head>",
150
- '<head>\n <script type="module" src="/@nasti/client"></script>'
151
- );
220
+ if (ctx.config.server.hmr !== false) {
221
+ processedHtml = processedHtml.replace(
222
+ "<head>",
223
+ '<head>\n <script type="module" src="/@nasti/client"></script>'
224
+ );
225
+ }
152
226
  res.setHeader("Content-Type", "text/html");
153
227
  res.end(processedHtml);
154
228
  return;
@@ -181,10 +255,10 @@ async function transformRequest(url, ctx) {
181
255
  return cached.transformResult;
182
256
  }
183
257
  const filePath = resolveUrlToFile(url, config.root);
184
- if (!filePath || !fs6.existsSync(filePath)) return null;
258
+ if (!filePath || !fs7.existsSync(filePath)) return null;
185
259
  const mod = await moduleGraph.ensureEntryFromUrl(url);
186
260
  moduleGraph.registerModule(mod, filePath);
187
- let code = fs6.readFileSync(filePath, "utf-8");
261
+ let code = fs7.readFileSync(filePath, "utf-8");
188
262
  const pluginResult = await pluginContainer.transform(code, filePath);
189
263
  if (pluginResult) {
190
264
  code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
@@ -198,23 +272,31 @@ async function transformRequest(url, ctx) {
198
272
  });
199
273
  code = result.code;
200
274
  }
275
+ const env = loadEnv(config.mode, config.root, config.envPrefix);
276
+ const envDefine = buildEnvDefine(env, config.mode);
277
+ code = replaceEnvInCode(code, envDefine);
201
278
  code = rewriteImports(code, config);
202
279
  const transformResult = { code };
203
280
  mod.transformResult = transformResult;
204
281
  return transformResult;
205
282
  }
206
- function rewriteImports(code, config) {
283
+ function rewriteImports(code, _config) {
207
284
  return code.replace(
208
- /from\s+['"]([^'"./][^'"]*)['"]/g,
209
- (match, specifier) => {
210
- if (specifier.startsWith("/") || specifier.startsWith(".")) return match;
211
- return `from "/@modules/${specifier}"`;
285
+ /\bfrom\s+(['"])([^'"./][^'"]*)\1/g,
286
+ (match, quote, specifier) => {
287
+ return `from ${quote}/@modules/${specifier}${quote}`;
212
288
  }
213
289
  ).replace(
214
- /import\s+['"]([^'"./][^'"]*)['"]/g,
215
- (match, specifier) => {
216
- if (specifier.startsWith("/") || specifier.startsWith(".")) return match;
217
- return `import "/@modules/${specifier}"`;
290
+ // 处理纯副作用导入: import 'bare-specifier'
291
+ /\bimport\s+(['"])([^'"./][^'"]*)\1/g,
292
+ (match, quote, specifier) => {
293
+ return `import ${quote}/@modules/${specifier}${quote}`;
294
+ }
295
+ ).replace(
296
+ // 处理动态导入: import('bare-specifier')
297
+ /\bimport\s*\(\s*(['"])([^'"./][^'"]*)\1\s*\)/g,
298
+ (match, quote, specifier) => {
299
+ return `import(${quote}/@modules/${specifier}${quote})`;
218
300
  }
219
301
  );
220
302
  }
@@ -223,14 +305,13 @@ function resolveUrlToFile(url, root) {
223
305
  if (cleanUrl.startsWith("/@modules/")) {
224
306
  const moduleName = cleanUrl.slice("/@modules/".length);
225
307
  try {
226
- const { createRequire: createRequire2 } = __require("module");
227
- const req = createRequire2(path7.resolve(root, "package.json"));
308
+ const req = createRequire2(path8.resolve(root, "package.json"));
228
309
  return req.resolve(moduleName);
229
310
  } catch {
230
311
  return null;
231
312
  }
232
313
  }
233
- return path7.resolve(root, cleanUrl.replace(/^\//, ""));
314
+ return path8.resolve(root, cleanUrl.replace(/^\//, ""));
234
315
  }
235
316
  function isModuleRequest(url) {
236
317
  const cleanUrl = url.split("?")[0];
@@ -292,7 +373,18 @@ function showErrorOverlay(err) {
292
373
  const overlay = document.createElement('div');
293
374
  overlay.id = 'nasti-error-overlay';
294
375
  overlay.style.cssText = 'position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,0.85);color:#fff;font-family:monospace;padding:2rem;overflow:auto;';
295
- overlay.innerHTML = \`<h2 style="color:#ff5555">Build Error</h2><pre>\${err.message}\\n\${err.stack || ''}</pre><button onclick="this.parentElement.remove()" style="margin-top:1rem;padding:0.5rem 1rem;cursor:pointer">Close</button>\`;
376
+ const title = document.createElement('h2');
377
+ title.style.color = '#ff5555';
378
+ title.textContent = 'Build Error';
379
+ const pre = document.createElement('pre');
380
+ pre.textContent = err.message + '\\n' + (err.stack || '');
381
+ const btn = document.createElement('button');
382
+ btn.style.cssText = 'margin-top:1rem;padding:0.5rem 1rem;cursor:pointer';
383
+ btn.textContent = 'Close';
384
+ btn.onclick = () => overlay.remove();
385
+ overlay.appendChild(title);
386
+ overlay.appendChild(pre);
387
+ overlay.appendChild(btn);
296
388
  document.body.appendChild(overlay);
297
389
  }
298
390
 
@@ -328,6 +420,7 @@ var init_middleware = __esm({
328
420
  "use strict";
329
421
  init_transformer();
330
422
  init_html();
423
+ init_env();
331
424
  }
332
425
  });
333
426
 
@@ -375,6 +468,27 @@ var defaults = {
375
468
  };
376
469
 
377
470
  // src/config/index.ts
471
+ function loadTsconfigPaths(root) {
472
+ const tsconfigPath = path.resolve(root, "tsconfig.json");
473
+ if (!fs.existsSync(tsconfigPath)) return {};
474
+ try {
475
+ const content = fs.readFileSync(tsconfigPath, "utf-8");
476
+ const stripped = content.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
477
+ const tsconfig = JSON.parse(stripped);
478
+ const paths = tsconfig?.compilerOptions?.paths ?? {};
479
+ const baseUrl = tsconfig?.compilerOptions?.baseUrl ?? ".";
480
+ const alias = {};
481
+ for (const [pattern, targets] of Object.entries(paths)) {
482
+ if (!targets.length) continue;
483
+ const cleanKey = pattern.replace(/\/\*$/, "");
484
+ const cleanTarget = targets[0].replace(/\/\*$/, "");
485
+ alias[cleanKey] = path.resolve(root, baseUrl, cleanTarget);
486
+ }
487
+ return alias;
488
+ } catch {
489
+ return {};
490
+ }
491
+ }
378
492
  function defineConfig(config) {
379
493
  return config;
380
494
  }
@@ -426,11 +540,6 @@ async function resolveConfig(inlineConfig = {}, command) {
426
540
  if (result) Object.assign(merged, result);
427
541
  }
428
542
  }
429
- const filteredPlugins = rawPlugins.filter((p) => {
430
- if (!p.apply) return true;
431
- if (typeof p.apply === "function") return p.apply(resolved, env);
432
- return p.apply === command;
433
- });
434
543
  const resolved = {
435
544
  root,
436
545
  base: merged.base ?? defaults.base,
@@ -438,17 +547,24 @@ async function resolveConfig(inlineConfig = {}, command) {
438
547
  framework: merged.framework ?? defaults.framework,
439
548
  command,
440
549
  resolve: {
441
- alias: { ...defaults.resolve.alias, ...merged.resolve?.alias },
550
+ // tsconfig paths 优先级最低:tsconfig < defaults < user config
551
+ alias: { ...loadTsconfigPaths(root), ...defaults.resolve.alias, ...merged.resolve?.alias },
442
552
  extensions: merged.resolve?.extensions ?? defaults.resolve.extensions,
443
553
  conditions: merged.resolve?.conditions ?? defaults.resolve.conditions,
444
554
  mainFields: merged.resolve?.mainFields ?? defaults.resolve.mainFields
445
555
  },
446
- plugins: filteredPlugins,
556
+ plugins: [],
447
557
  server: { ...defaults.server, ...merged.server },
448
558
  build: { ...defaults.build, ...merged.build },
449
559
  envPrefix: Array.isArray(merged.envPrefix) ? merged.envPrefix : merged.envPrefix ? [merged.envPrefix] : [...defaults.envPrefix],
450
560
  logLevel: merged.logLevel ?? defaults.logLevel
451
561
  };
562
+ const filteredPlugins = rawPlugins.filter((p) => {
563
+ if (!p.apply) return true;
564
+ if (typeof p.apply === "function") return p.apply(resolved, env);
565
+ return p.apply === command;
566
+ });
567
+ resolved.plugins = filteredPlugins;
452
568
  for (const plugin of resolved.plugins) {
453
569
  if (plugin.configResolved) {
454
570
  await plugin.configResolved(resolved);
@@ -473,8 +589,8 @@ function deepMerge(target, source) {
473
589
  }
474
590
 
475
591
  // src/build/index.ts
476
- import path6 from "path";
477
- import fs5 from "fs";
592
+ import path7 from "path";
593
+ import fs6 from "fs";
478
594
  import { rolldown } from "rolldown";
479
595
 
480
596
  // src/plugins/resolve.ts
@@ -520,10 +636,12 @@ function resolvePlugin(config) {
520
636
  return null;
521
637
  },
522
638
  load(id) {
523
- if (fs2.existsSync(id)) {
524
- return fs2.readFileSync(id, "utf-8");
639
+ if (!fs2.existsSync(id)) return null;
640
+ if (id.endsWith(".json")) {
641
+ const content = fs2.readFileSync(id, "utf-8");
642
+ return `export default ${content}`;
525
643
  }
526
- return null;
644
+ return fs2.readFileSync(id, "utf-8");
527
645
  }
528
646
  };
529
647
  }
@@ -559,13 +677,17 @@ function cssPlugin(config) {
559
677
  },
560
678
  transform(code, id) {
561
679
  if (!id.endsWith(".css")) return null;
680
+ const rewritten = rewriteCssUrls(code, id, config.root);
562
681
  if (config.command === "serve") {
563
- const escaped = JSON.stringify(code);
682
+ const escaped = JSON.stringify(rewritten);
564
683
  return {
565
684
  code: `
566
685
  const css = ${escaped};
686
+ const __nasti_css_id__ = ${JSON.stringify(id)};
687
+ const __nasti_existing__ = document.querySelector('style[data-nasti-css=' + JSON.stringify(__nasti_css_id__) + ']');
688
+ if (__nasti_existing__) __nasti_existing__.remove();
567
689
  const style = document.createElement('style');
568
- style.setAttribute('data-nasti-css', ${JSON.stringify(id)});
690
+ style.setAttribute('data-nasti-css', __nasti_css_id__);
569
691
  style.textContent = css;
570
692
  document.head.appendChild(style);
571
693
 
@@ -581,10 +703,20 @@ export default css;
581
703
  `
582
704
  };
583
705
  }
584
- return null;
706
+ return rewritten !== code ? { code: rewritten } : null;
585
707
  }
586
708
  };
587
709
  }
710
+ function rewriteCssUrls(css, from, root) {
711
+ return css.replace(/url\(\s*['"]?([^'")\s]+)['"]?\s*\)/g, (match, url) => {
712
+ if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
713
+ return match;
714
+ }
715
+ const resolved = path3.resolve(path3.dirname(from), url);
716
+ const relative = "/" + path3.relative(root, resolved);
717
+ return `url(${relative})`;
718
+ });
719
+ }
588
720
 
589
721
  // src/plugins/assets.ts
590
722
  import path4 from "path";
@@ -653,6 +785,123 @@ function assetsPlugin(config) {
653
785
  // src/build/index.ts
654
786
  init_html();
655
787
  init_transformer();
788
+ init_env();
789
+
790
+ // src/core/plugin-container.ts
791
+ var PluginContainer = class {
792
+ plugins;
793
+ config;
794
+ ctx;
795
+ emittedFiles = /* @__PURE__ */ new Map();
796
+ constructor(config) {
797
+ this.config = config;
798
+ this.plugins = sortPlugins(config.plugins);
799
+ this.ctx = this.createContext();
800
+ }
801
+ createContext() {
802
+ const container = this;
803
+ return {
804
+ async resolve(source, importer) {
805
+ return container.resolveId(source, importer);
806
+ },
807
+ emitFile(file) {
808
+ const fileName = file.fileName ?? file.name ?? `asset-${container.emittedFiles.size}`;
809
+ const id = `emitted:${fileName}`;
810
+ container.emittedFiles.set(id, {
811
+ fileName,
812
+ source: file.source ?? ""
813
+ });
814
+ return id;
815
+ },
816
+ getModuleInfo(_id) {
817
+ return null;
818
+ }
819
+ };
820
+ }
821
+ /** 返回所有通过 emitFile() 输出的文件 */
822
+ getEmittedFiles() {
823
+ return Array.from(this.emittedFiles.values());
824
+ }
825
+ async buildStart() {
826
+ for (const plugin of this.plugins) {
827
+ if (plugin.buildStart) {
828
+ await plugin.buildStart.call(this.ctx);
829
+ }
830
+ }
831
+ }
832
+ async buildEnd(error) {
833
+ for (const plugin of this.plugins) {
834
+ if (plugin.buildEnd) {
835
+ await plugin.buildEnd.call(this.ctx, error);
836
+ }
837
+ }
838
+ }
839
+ async resolveId(source, importer, options = {}) {
840
+ for (const plugin of this.plugins) {
841
+ if (!plugin.resolveId) continue;
842
+ const result = await plugin.resolveId.call(
843
+ this.ctx,
844
+ source,
845
+ importer ?? void 0,
846
+ { isEntry: options.isEntry ?? false, ssr: false }
847
+ );
848
+ if (result != null) return result;
849
+ }
850
+ return null;
851
+ }
852
+ async load(id) {
853
+ for (const plugin of this.plugins) {
854
+ if (!plugin.load) continue;
855
+ const result = await plugin.load.call(this.ctx, id);
856
+ if (result != null) return result;
857
+ }
858
+ return null;
859
+ }
860
+ async transform(code, id) {
861
+ let currentCode = code;
862
+ for (const plugin of this.plugins) {
863
+ if (!plugin.transform) continue;
864
+ const result = await plugin.transform.call(this.ctx, currentCode, id);
865
+ if (result == null) continue;
866
+ if (typeof result === "string") {
867
+ currentCode = result;
868
+ } else {
869
+ currentCode = result.code;
870
+ }
871
+ }
872
+ return currentCode === code ? null : { code: currentCode };
873
+ }
874
+ /** 完整的模块处理管道: resolveId → load → transform */
875
+ async processModule(source, importer) {
876
+ const resolveResult = await this.resolveId(source, importer, {
877
+ isEntry: !importer
878
+ });
879
+ if (resolveResult == null) return null;
880
+ const id = typeof resolveResult === "string" ? resolveResult : resolveResult.id;
881
+ const loadResult = await this.load(id);
882
+ if (loadResult == null) return null;
883
+ const loadedCode = typeof loadResult === "string" ? loadResult : loadResult.code;
884
+ const transformResult = await this.transform(loadedCode, id);
885
+ const finalCode = transformResult == null ? loadedCode : typeof transformResult === "string" ? transformResult : transformResult.code;
886
+ return { id, code: finalCode };
887
+ }
888
+ getPlugins() {
889
+ return this.plugins;
890
+ }
891
+ };
892
+ function sortPlugins(plugins) {
893
+ const pre = [];
894
+ const normal = [];
895
+ const post = [];
896
+ for (const plugin of plugins) {
897
+ if (plugin.enforce === "pre") pre.push(plugin);
898
+ else if (plugin.enforce === "post") post.push(plugin);
899
+ else normal.push(plugin);
900
+ }
901
+ return [...pre, ...normal, ...post];
902
+ }
903
+
904
+ // src/build/index.ts
656
905
  import pc from "picocolors";
657
906
  async function build(inlineConfig = {}) {
658
907
  const config = await resolveConfig(inlineConfig, "build");
@@ -660,11 +909,11 @@ async function build(inlineConfig = {}) {
660
909
  console.log(pc.cyan("\n\u{1F528} nasti build") + pc.dim(` v${process.env.npm_package_version ?? "0.0.1"}`));
661
910
  console.log(pc.dim(` root: ${config.root}`));
662
911
  console.log(pc.dim(` mode: ${config.mode}`));
663
- const outDir = path6.resolve(config.root, config.build.outDir);
664
- if (config.build.emptyOutDir && fs5.existsSync(outDir)) {
665
- fs5.rmSync(outDir, { recursive: true, force: true });
912
+ const outDir = path7.resolve(config.root, config.build.outDir);
913
+ if (config.build.emptyOutDir && fs6.existsSync(outDir)) {
914
+ fs6.rmSync(outDir, { recursive: true, force: true });
666
915
  }
667
- fs5.mkdirSync(outDir, { recursive: true });
916
+ fs6.mkdirSync(outDir, { recursive: true });
668
917
  const html = await readHtmlFile(config.root);
669
918
  let entryPoints = [];
670
919
  if (html) {
@@ -672,15 +921,15 @@ async function build(inlineConfig = {}) {
672
921
  for (const match of scriptMatches) {
673
922
  const src = match[1];
674
923
  if (src && !src.startsWith("http")) {
675
- entryPoints.push(path6.resolve(config.root, src.replace(/^\//, "")));
924
+ entryPoints.push(path7.resolve(config.root, src.replace(/^\//, "")));
676
925
  }
677
926
  }
678
927
  }
679
928
  if (entryPoints.length === 0) {
680
929
  const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
681
930
  for (const entry of fallbackEntries) {
682
- const fullPath = path6.resolve(config.root, entry);
683
- if (fs5.existsSync(fullPath)) {
931
+ const fullPath = path7.resolve(config.root, entry);
932
+ if (fs6.existsSync(fullPath)) {
684
933
  entryPoints.push(fullPath);
685
934
  break;
686
935
  }
@@ -695,6 +944,8 @@ async function build(inlineConfig = {}) {
695
944
  assetsPlugin(config)
696
945
  ];
697
946
  const allPlugins = [...builtinPlugins, ...config.plugins];
947
+ const pluginContainer = new PluginContainer(config);
948
+ await pluginContainer.buildStart();
698
949
  const oxcTransformPlugin = {
699
950
  name: "nasti:oxc-transform",
700
951
  transform(code, id) {
@@ -707,8 +958,11 @@ async function build(inlineConfig = {}) {
707
958
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
708
959
  }
709
960
  };
961
+ const env = loadEnv(config.mode, config.root, config.envPrefix);
962
+ const envDefine = buildEnvDefine(env, config.mode);
710
963
  const bundle = await rolldown({
711
964
  input: entryPoints,
965
+ define: envDefine,
712
966
  plugins: [
713
967
  oxcTransformPlugin,
714
968
  // 转换 Nasti 插件为 Rolldown 插件格式
@@ -727,11 +981,18 @@ async function build(inlineConfig = {}) {
727
981
  dir: outDir,
728
982
  format: "esm",
729
983
  sourcemap: !!config.build.sourcemap,
984
+ minify: !!config.build.minify,
730
985
  entryFileNames: "assets/[name].[hash].js",
731
986
  chunkFileNames: "assets/[name].[hash].js",
732
987
  assetFileNames: "assets/[name].[hash][extname]"
733
988
  });
734
989
  await bundle.close();
990
+ await pluginContainer.buildEnd();
991
+ for (const ef of pluginContainer.getEmittedFiles()) {
992
+ const dest = path7.resolve(outDir, ef.fileName);
993
+ fs6.mkdirSync(path7.dirname(dest), { recursive: true });
994
+ fs6.writeFileSync(dest, ef.source);
995
+ }
735
996
  if (html) {
736
997
  let processedHtml = html;
737
998
  const htmlPlugin_ = htmlPlugin(config);
@@ -746,15 +1007,15 @@ async function build(inlineConfig = {}) {
746
1007
  }
747
1008
  }
748
1009
  for (const chunk of output) {
749
- if (chunk.type === "chunk" && chunk.isEntry) {
750
- const originalEntry = path6.relative(config.root, entryPoints[0]);
1010
+ if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
1011
+ const originalEntry = path7.relative(config.root, chunk.facadeModuleId);
751
1012
  processedHtml = processedHtml.replace(
752
1013
  new RegExp(`(src=["'])/?(${escapeRegExp(originalEntry)})(["'])`, "g"),
753
1014
  `$1${config.base}${chunk.fileName}$3`
754
1015
  );
755
1016
  }
756
1017
  }
757
- fs5.writeFileSync(path6.resolve(outDir, "index.html"), processedHtml);
1018
+ fs6.writeFileSync(path7.resolve(outDir, "index.html"), processedHtml);
758
1019
  }
759
1020
  const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
760
1021
  const totalSize = output.reduce((sum, chunk) => {
@@ -779,115 +1040,13 @@ function escapeRegExp(string) {
779
1040
 
780
1041
  // src/server/index.ts
781
1042
  import http from "http";
782
- import path9 from "path";
1043
+ import path10 from "path";
1044
+ import os from "os";
783
1045
  import connect from "connect";
784
1046
  import sirv from "sirv";
785
1047
  import { watch } from "chokidar";
786
1048
  import pc2 from "picocolors";
787
1049
 
788
- // src/core/plugin-container.ts
789
- var PluginContainer = class {
790
- plugins;
791
- config;
792
- ctx;
793
- constructor(config) {
794
- this.config = config;
795
- this.plugins = sortPlugins(config.plugins);
796
- this.ctx = this.createContext();
797
- }
798
- createContext() {
799
- const container = this;
800
- return {
801
- async resolve(source, importer) {
802
- return container.resolveId(source, importer);
803
- },
804
- emitFile(_file) {
805
- return "";
806
- },
807
- getModuleInfo(_id) {
808
- return null;
809
- }
810
- };
811
- }
812
- async buildStart() {
813
- for (const plugin of this.plugins) {
814
- if (plugin.buildStart) {
815
- await plugin.buildStart.call(this.ctx);
816
- }
817
- }
818
- }
819
- async buildEnd(error) {
820
- for (const plugin of this.plugins) {
821
- if (plugin.buildEnd) {
822
- await plugin.buildEnd.call(this.ctx, error);
823
- }
824
- }
825
- }
826
- async resolveId(source, importer, options = {}) {
827
- for (const plugin of this.plugins) {
828
- if (!plugin.resolveId) continue;
829
- const result = await plugin.resolveId.call(
830
- this.ctx,
831
- source,
832
- importer ?? void 0,
833
- { isEntry: options.isEntry ?? false, ssr: false }
834
- );
835
- if (result != null) return result;
836
- }
837
- return null;
838
- }
839
- async load(id) {
840
- for (const plugin of this.plugins) {
841
- if (!plugin.load) continue;
842
- const result = await plugin.load.call(this.ctx, id);
843
- if (result != null) return result;
844
- }
845
- return null;
846
- }
847
- async transform(code, id) {
848
- let currentCode = code;
849
- for (const plugin of this.plugins) {
850
- if (!plugin.transform) continue;
851
- const result = await plugin.transform.call(this.ctx, currentCode, id);
852
- if (result == null) continue;
853
- if (typeof result === "string") {
854
- currentCode = result;
855
- } else {
856
- currentCode = result.code;
857
- }
858
- }
859
- return currentCode === code ? null : { code: currentCode };
860
- }
861
- /** 完整的模块处理管道: resolveId → load → transform */
862
- async processModule(source, importer) {
863
- const resolveResult = await this.resolveId(source, importer, {
864
- isEntry: !importer
865
- });
866
- if (resolveResult == null) return null;
867
- const id = typeof resolveResult === "string" ? resolveResult : resolveResult.id;
868
- const loadResult = await this.load(id);
869
- if (loadResult == null) return null;
870
- const loadedCode = typeof loadResult === "string" ? loadResult : loadResult.code;
871
- const transformResult = await this.transform(loadedCode, id);
872
- const finalCode = transformResult == null ? loadedCode : typeof transformResult === "string" ? transformResult : transformResult.code;
873
- return { id, code: finalCode };
874
- }
875
- getPlugins() {
876
- return this.plugins;
877
- }
878
- };
879
- function sortPlugins(plugins) {
880
- const pre = [];
881
- const normal = [];
882
- const post = [];
883
- for (const plugin of plugins) {
884
- if (plugin.enforce === "pre") pre.push(plugin);
885
- else if (plugin.enforce === "post") post.push(plugin);
886
- else normal.push(plugin);
887
- }
888
- return [...pre, ...normal, ...post];
889
- }
890
-
891
1050
  // src/core/module-graph.ts
892
1051
  var ModuleGraph = class {
893
1052
  urlToModuleMap = /* @__PURE__ */ new Map();
@@ -1037,11 +1196,11 @@ function createWebSocketServer(server) {
1037
1196
  init_middleware();
1038
1197
 
1039
1198
  // src/server/hmr.ts
1040
- import path8 from "path";
1041
- import fs7 from "fs";
1199
+ import path9 from "path";
1200
+ import fs8 from "fs";
1042
1201
  async function handleFileChange(file, server) {
1043
1202
  const { moduleGraph, ws, config } = server;
1044
- const relativePath = "/" + path8.relative(config.root, file);
1203
+ const relativePath = "/" + path9.relative(config.root, file);
1045
1204
  const mods = moduleGraph.getModulesByFile(file);
1046
1205
  if (!mods || mods.size === 0) {
1047
1206
  return;
@@ -1054,7 +1213,7 @@ async function handleFileChange(file, server) {
1054
1213
  file,
1055
1214
  timestamp,
1056
1215
  modules: [mod],
1057
- read: () => fs7.readFileSync(file, "utf-8"),
1216
+ read: () => fs8.readFileSync(file, "utf-8"),
1058
1217
  server
1059
1218
  };
1060
1219
  let affectedModules = [mod];
@@ -1107,7 +1266,7 @@ async function createServer(inlineConfig = {}) {
1107
1266
  pluginContainer,
1108
1267
  moduleGraph
1109
1268
  }));
1110
- const publicDir = path9.resolve(config.root, "public");
1269
+ const publicDir = path10.resolve(config.root, "public");
1111
1270
  app.use(sirv(publicDir, { dev: true, etag: true }));
1112
1271
  app.use(sirv(config.root, { dev: true, etag: true }));
1113
1272
  const httpServer = http.createServer(app);
@@ -1184,7 +1343,6 @@ async function createServer(inlineConfig = {}) {
1184
1343
  return server;
1185
1344
  }
1186
1345
  function getNetworkAddress() {
1187
- const os = __require("os");
1188
1346
  const interfaces = os.networkInterfaces();
1189
1347
  for (const name of Object.keys(interfaces)) {
1190
1348
  for (const iface of interfaces[name] ?? []) {