@nasti-toolchain/nasti 1.7.1 → 2.0.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/index.cjs CHANGED
@@ -5,9 +5,17 @@ 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];
10
+ if (fn) return fn();
11
+ throw new Error("Module not found in bundle: " + path18);
12
+ };
8
13
  var __esm = (fn, res) => function __init() {
9
14
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
15
  };
16
+ var __commonJS = (cb, mod) => function __require2() {
17
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
18
+ };
11
19
  var __export = (target, all) => {
12
20
  for (var name in all)
13
21
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -31,7 +39,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
39
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
40
 
33
41
  // src/config/defaults.ts
34
- var defaultResolve, defaultServer, defaultBuild, defaultElectron, defaults;
42
+ var defaultResolve, defaultServer, defaultBuild, defaultElectron, defaultExperimental, defaults;
35
43
  var init_defaults = __esm({
36
44
  "src/config/defaults.ts"() {
37
45
  "use strict";
@@ -58,7 +66,12 @@ var init_defaults = __esm({
58
66
  target: "es2022",
59
67
  rolldownOptions: {},
60
68
  emptyOutDir: true,
61
- css: {}
69
+ css: {},
70
+ reportCompressedSize: true,
71
+ chunkSizeWarningLimit: 500,
72
+ cssCodeSplit: true,
73
+ // 默认跟随 build.minify(resolveConfig 中按 minify 取值填充)
74
+ cssMinify: true
62
75
  };
63
76
  defaultElectron = {
64
77
  main: "src/electron/main.ts",
@@ -73,6 +86,9 @@ var init_defaults = __esm({
73
86
  minVersion: 41,
74
87
  external: ["electron"]
75
88
  };
89
+ defaultExperimental = {
90
+ bundledDev: false
91
+ };
76
92
  defaults = {
77
93
  root: ".",
78
94
  base: "/",
@@ -85,8 +101,123 @@ var init_defaults = __esm({
85
101
  electron: defaultElectron,
86
102
  plugins: [],
87
103
  envPrefix: ["NASTI_", "VITE_"],
88
- logLevel: "info"
104
+ logLevel: "info",
105
+ clearScreen: true,
106
+ experimental: defaultExperimental
107
+ };
108
+ }
109
+ });
110
+
111
+ // src/core/logger.ts
112
+ function getTimeFormatter() {
113
+ return new Intl.DateTimeFormat(void 0, {
114
+ hour: "numeric",
115
+ minute: "numeric",
116
+ second: "numeric"
117
+ });
118
+ }
119
+ function createLogger(level = "info", options = {}) {
120
+ if (options.customLogger) {
121
+ return options.customLogger;
122
+ }
123
+ const timeFormatter = getTimeFormatter();
124
+ const loggedErrors = /* @__PURE__ */ new WeakSet();
125
+ const { prefix = "[nasti]", allowClearScreen = true, console: console_ = console } = options;
126
+ const thresh = LogLevels[level];
127
+ const canClearScreen = allowClearScreen && process.stdout.isTTY && !process.env.CI;
128
+ const clear = canClearScreen ? clearScreen : () => {
129
+ };
130
+ function format(type, msg, options2 = {}) {
131
+ if (options2.timestamp) {
132
+ const tag = type === "info" ? import_picocolors.default.cyan(import_picocolors.default.bold(prefix)) : type === "warn" ? import_picocolors.default.yellow(import_picocolors.default.bold(prefix)) : import_picocolors.default.red(import_picocolors.default.bold(prefix));
133
+ return `${import_picocolors.default.dim(timeFormatter.format(/* @__PURE__ */ new Date()))} ${tag} ${msg}`;
134
+ }
135
+ return msg;
136
+ }
137
+ function output(type, msg, options2 = {}) {
138
+ if (thresh < LogLevels[type]) return;
139
+ const method = type === "info" ? "log" : type;
140
+ if (options2.error) {
141
+ loggedErrors.add(options2.error);
142
+ }
143
+ if (canClearScreen) {
144
+ if (type === lastType && msg === lastMsg) {
145
+ sameCount++;
146
+ clear();
147
+ console_[method](format(type, msg, options2), import_picocolors.default.yellow(`(x${sameCount + 1})`));
148
+ } else {
149
+ sameCount = 0;
150
+ lastMsg = msg;
151
+ lastType = type;
152
+ if (options2.clear) clear();
153
+ console_[method](format(type, msg, options2));
154
+ }
155
+ } else {
156
+ console_[method](format(type, msg, options2));
157
+ }
158
+ }
159
+ const warnedMessages = /* @__PURE__ */ new Set();
160
+ const logger = {
161
+ hasWarned: false,
162
+ info(msg, opts) {
163
+ output("info", msg, opts);
164
+ },
165
+ warn(msg, opts) {
166
+ logger.hasWarned = true;
167
+ output("warn", msg, opts);
168
+ },
169
+ warnOnce(msg, opts) {
170
+ if (warnedMessages.has(msg)) return;
171
+ logger.hasWarned = true;
172
+ output("warn", msg, opts);
173
+ warnedMessages.add(msg);
174
+ },
175
+ error(msg, opts) {
176
+ output("error", msg, opts);
177
+ },
178
+ clearScreen(type) {
179
+ if (thresh >= LogLevels[type]) clear();
180
+ },
181
+ hasErrorLogged(error) {
182
+ return loggedErrors.has(error);
183
+ }
184
+ };
185
+ return logger;
186
+ }
187
+ function clearScreen() {
188
+ const repeatCount = process.stdout.rows - 2;
189
+ const blank = repeatCount > 0 ? "\n".repeat(repeatCount) : "";
190
+ console.log(blank);
191
+ import_node_readline.default.cursorTo(process.stdout, 0, 0);
192
+ import_node_readline.default.clearScreenDown(process.stdout);
193
+ }
194
+ function printServerUrls(urls, info) {
195
+ const colorUrl = (url) => import_picocolors.default.cyan(url.replace(/:(\d+)\//, (_, port) => `:${import_picocolors.default.bold(port)}/`));
196
+ for (const url of urls.local) {
197
+ info(` ${import_picocolors.default.green("\u279C")} ${import_picocolors.default.bold("Local")}: ${colorUrl(url)}`);
198
+ }
199
+ for (const url of urls.network) {
200
+ info(` ${import_picocolors.default.green("\u279C")} ${import_picocolors.default.bold("Network")}: ${colorUrl(url)}`);
201
+ }
202
+ if (urls.network.length === 0) {
203
+ info(
204
+ import_picocolors.default.dim(` ${import_picocolors.default.green("\u279C")} ${import_picocolors.default.bold("Network")}: use `) + import_picocolors.default.bold("--host") + import_picocolors.default.dim(" to expose")
205
+ );
206
+ }
207
+ }
208
+ var import_node_readline, import_picocolors, LogLevels, lastType, lastMsg, sameCount;
209
+ var init_logger = __esm({
210
+ "src/core/logger.ts"() {
211
+ "use strict";
212
+ import_node_readline = __toESM(require("readline"), 1);
213
+ import_picocolors = __toESM(require("picocolors"), 1);
214
+ LogLevels = {
215
+ silent: 0,
216
+ error: 1,
217
+ warn: 2,
218
+ info: 3
89
219
  };
220
+ sameCount = 0;
90
221
  }
91
222
  });
92
223
 
@@ -150,17 +281,28 @@ async function resolveConfig(inlineConfig = {}, command) {
150
281
  ...fileConfig.plugins ?? [],
151
282
  ...inlineConfig.plugins ?? []
152
283
  ];
153
- const env = { mode: merged.mode ?? defaults.mode, command };
284
+ const mode = merged.mode ?? (command === "build" ? "production" : "development");
285
+ const env = { mode, command };
154
286
  for (const plugin of rawPlugins) {
155
287
  if (plugin.config) {
156
288
  const result = await plugin.config(merged, env);
157
289
  if (result) Object.assign(merged, result);
158
290
  }
159
291
  }
292
+ const logLevel = merged.logLevel ?? defaults.logLevel;
293
+ const clearScreen2 = merged.clearScreen ?? defaults.clearScreen;
294
+ const logger = createLogger(logLevel, {
295
+ allowClearScreen: clearScreen2,
296
+ customLogger: merged.customLogger
297
+ });
298
+ const mergedBuild = { ...defaults.build, ...merged.build };
299
+ if (merged.build?.cssMinify === void 0) {
300
+ mergedBuild.cssMinify = !!mergedBuild.minify;
301
+ }
160
302
  const resolved = {
161
303
  root,
162
304
  base: merged.base ?? defaults.base,
163
- mode: command === "build" ? "production" : "development",
305
+ mode,
164
306
  target: merged.target ?? defaults.target,
165
307
  framework: merged.framework ?? defaults.framework,
166
308
  command,
@@ -173,11 +315,70 @@ async function resolveConfig(inlineConfig = {}, command) {
173
315
  },
174
316
  plugins: [],
175
317
  server: { ...defaults.server, ...merged.server },
176
- build: { ...defaults.build, ...merged.build },
318
+ build: mergedBuild,
177
319
  electron: { ...defaults.electron, ...merged.electron },
178
320
  envPrefix: Array.isArray(merged.envPrefix) ? merged.envPrefix : merged.envPrefix ? [merged.envPrefix] : [...defaults.envPrefix],
179
- logLevel: merged.logLevel ?? defaults.logLevel
321
+ logLevel,
322
+ clearScreen: clearScreen2,
323
+ logger,
324
+ environments: {},
325
+ experimental: {
326
+ bundledDev: merged.experimental?.bundledDev ?? defaults.experimental.bundledDev
327
+ }
180
328
  };
329
+ const userEnvironments = {
330
+ client: {},
331
+ ssr: {},
332
+ ...merged.environments ?? {}
333
+ };
334
+ for (const [name, envOptions] of Object.entries(userEnvironments)) {
335
+ for (const plugin of rawPlugins) {
336
+ if (plugin.configEnvironment) {
337
+ const result = await plugin.configEnvironment(name, envOptions, env);
338
+ if (result) Object.assign(envOptions, deepMerge(envOptions, result));
339
+ }
340
+ }
341
+ }
342
+ for (const [name, envOptions] of Object.entries(userEnvironments)) {
343
+ const consumer = envOptions.consumer ?? (name === "client" ? "client" : "server");
344
+ if (name === "client") {
345
+ if (envOptions.resolve) {
346
+ Object.assign(resolved.resolve, {
347
+ ...envOptions.resolve,
348
+ alias: { ...resolved.resolve.alias, ...envOptions.resolve.alias }
349
+ });
350
+ }
351
+ if (envOptions.build) Object.assign(resolved.build, envOptions.build);
352
+ resolved.environments.client = {
353
+ consumer,
354
+ entry: [],
355
+ // 同引用 —— 精确镜像(assertClientEnvironmentMirror 校验)
356
+ resolve: resolved.resolve,
357
+ build: resolved.build
358
+ };
359
+ continue;
360
+ }
361
+ resolved.environments[name] = {
362
+ consumer,
363
+ entry: (Array.isArray(envOptions.entry) ? envOptions.entry : envOptions.entry ? [envOptions.entry] : []).map((e) => import_node_path.default.resolve(root, e)),
364
+ resolve: {
365
+ alias: { ...resolved.resolve.alias, ...envOptions.resolve?.alias },
366
+ extensions: envOptions.resolve?.extensions ?? [...resolved.resolve.extensions],
367
+ // server consumer:node conditions(去 'browser');client 非默认环境沿用 top-level
368
+ conditions: envOptions.resolve?.conditions ?? (consumer === "server" ? ["node", ...resolved.resolve.conditions.filter((c) => c !== "browser")] : [...resolved.resolve.conditions]),
369
+ mainFields: envOptions.resolve?.mainFields ?? (consumer === "server" ? ["module", "main"] : [...resolved.resolve.mainFields])
370
+ },
371
+ build: {
372
+ ...resolved.build,
373
+ ...envOptions.build,
374
+ // 非 client 环境默认产出到 <outDir>/<envName>(如 dist/ssr),可显式覆盖
375
+ outDir: envOptions.build?.outDir ?? import_node_path.default.join(resolved.build.outDir, name),
376
+ // server 产物默认不压缩(可调试性优先,与 Vite SSR 默认一致),可显式覆盖
377
+ minify: envOptions.build?.minify ?? (consumer === "server" ? false : resolved.build.minify)
378
+ }
379
+ };
380
+ }
381
+ assertClientEnvironmentMirror(resolved);
181
382
  const filteredPlugins = rawPlugins.filter((p) => {
182
383
  if (!p.apply) return true;
183
384
  if (typeof p.apply === "function") return p.apply(resolved, env);
@@ -266,11 +467,40 @@ function hasDotNodeFile(dir, depth = 0) {
266
467
  }
267
468
  return false;
268
469
  }
470
+ function assertClientEnvironmentMirror(config) {
471
+ if (process.env.NASTI_DISABLE_MIRROR_ASSERT) return;
472
+ const client = config.environments.client;
473
+ if (!client) {
474
+ throw new Error("[nasti] internal: environments.client missing after resolveConfig");
475
+ }
476
+ if (client.resolve === config.resolve && client.build === config.build) return;
477
+ const pairs = [
478
+ ["resolve", config.resolve, client.resolve],
479
+ ["build", config.build, client.build]
480
+ ];
481
+ for (const [field, top, env] of pairs) {
482
+ const a = JSON.stringify(top);
483
+ const b = JSON.stringify(env);
484
+ if (a !== b) {
485
+ throw new Error(
486
+ `[nasti] config mirror violation: top-level \`${field}\` and \`environments.client.${field}\` diverged.
487
+ top-level: ${a}
488
+ client: ${b}
489
+ top-level \u4E0E client \u73AF\u5883\u5FC5\u987B\u7CBE\u786E\u955C\u50CF \u2014\u2014 \u8BF7\u901A\u8FC7 top-level \u6216 environments.client \u4E4B\u4E00\u914D\u7F6E\uFF0C\u4E0D\u8981\u5728\u89E3\u6790\u540E\u5206\u522B\u4FEE\u6539\u4E24\u8005\u3002`
490
+ );
491
+ }
492
+ }
493
+ }
494
+ function isPlainObject(val) {
495
+ if (val === null || typeof val !== "object") return false;
496
+ const proto = Object.getPrototypeOf(val);
497
+ return proto === Object.prototype || proto === null;
498
+ }
269
499
  function deepMerge(target, source) {
270
500
  const result = { ...target };
271
501
  for (const key of Object.keys(source)) {
272
502
  const val = source[key];
273
- if (val && typeof val === "object" && !Array.isArray(val)) {
503
+ if (isPlainObject(val)) {
274
504
  result[key] = deepMerge(
275
505
  result[key] ?? {},
276
506
  val
@@ -289,6 +519,7 @@ var init_config = __esm({
289
519
  import_node_path = __toESM(require("path"), 1);
290
520
  import_node_fs = __toESM(require("fs"), 1);
291
521
  init_defaults();
522
+ init_logger();
292
523
  CONFIG_FILES = [
293
524
  "nasti.config.ts",
294
525
  "nasti.config.js",
@@ -404,203 +635,1247 @@ var init_resolve = __esm({
404
635
  }
405
636
  });
406
637
 
407
- // src/plugins/tailwind.ts
408
- function hasTailwindDirectives(css) {
409
- const withoutBlockComments = css.replace(/\/\*[\s\S]*?\*\//g, "");
410
- const withoutLineComments = withoutBlockComments.replace(/\/\/.*$/gm, "");
411
- return TAILWIND_DIRECTIVE_RE.test(withoutLineComments);
412
- }
413
- async function loadTailwind(projectRoot) {
414
- if (cached && cachedRoot === projectRoot) return cached;
415
- const req = (0, import_node_module2.createRequire)(import_node_path3.default.join(projectRoot, "package.json"));
416
- let nodePath;
417
- let oxidePath;
418
- try {
419
- nodePath = req.resolve("@tailwindcss/node");
420
- oxidePath = req.resolve("@tailwindcss/oxide");
421
- } catch {
422
- throw new Error(
423
- "[nasti] CSS contains Tailwind v4 directives but `@tailwindcss/node` and/or `@tailwindcss/oxide` are not installed in this project. Install them with: npm i -D tailwindcss @tailwindcss/node @tailwindcss/oxide"
424
- );
425
- }
426
- const node = await import((0, import_node_url2.pathToFileURL)(nodePath).href);
427
- const oxide = await import((0, import_node_url2.pathToFileURL)(oxidePath).href);
428
- cached = { node, oxide };
429
- cachedRoot = projectRoot;
430
- return cached;
431
- }
432
- async function compileTailwind(css, fromFile, projectRoot) {
433
- const { node, oxide } = await loadTailwind(projectRoot);
434
- const dependencies = [];
435
- const compiler2 = await node.compile(css, {
436
- base: import_node_path3.default.dirname(fromFile),
437
- from: fromFile,
438
- onDependency: (p) => dependencies.push(p)
638
+ // src/core/debug.ts
639
+ function createDebugger(namespace, options = {}) {
640
+ if (!DEBUG) return void 0;
641
+ const patterns = DEBUG.split(",").map((p) => p.trim());
642
+ const enabled = patterns.some((p) => {
643
+ if (p === "*" || p === "nasti:*" || p === "vite:*") return true;
644
+ const normalized = p.startsWith("vite:") ? `nasti:${p.slice(5)}` : p;
645
+ return normalized === namespace;
439
646
  });
440
- const scanner = new oxide.Scanner({ sources: compiler2.sources });
441
- const candidates = scanner.scan();
442
- return {
443
- css: compiler2.build(candidates),
444
- dependencies: [...dependencies, ...scanner.files]
647
+ if (!enabled) return void 0;
648
+ if (options.onlyWhenFocused) {
649
+ const focus = typeof options.onlyWhenFocused === "string" ? options.onlyWhenFocused : namespace;
650
+ if (!patterns.includes(focus)) return void 0;
651
+ }
652
+ let lastTime = performance.now();
653
+ return (...args) => {
654
+ const now = performance.now();
655
+ const elapsed = now - lastTime;
656
+ lastTime = now;
657
+ const msg = args.map((a) => {
658
+ if (typeof a === "string") return a;
659
+ try {
660
+ return JSON.stringify(a);
661
+ } catch {
662
+ return String(a);
663
+ }
664
+ }).join(" ");
665
+ if (filter && !msg.includes(filter)) return;
666
+ console.debug(
667
+ `${import_picocolors2.default.magenta(namespace)} ${msg} ${import_picocolors2.default.dim(`+${Math.round(elapsed)}ms`)}`
668
+ );
445
669
  };
446
670
  }
447
- var import_node_path3, import_node_module2, import_node_url2, TAILWIND_DIRECTIVE_RE, cached, cachedRoot;
448
- var init_tailwind = __esm({
449
- "src/plugins/tailwind.ts"() {
671
+ var import_picocolors2, DEBUG, filter;
672
+ var init_debug = __esm({
673
+ "src/core/debug.ts"() {
450
674
  "use strict";
451
- import_node_path3 = __toESM(require("path"), 1);
452
- import_node_module2 = require("module");
453
- import_node_url2 = require("url");
454
- 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)/;
455
- cached = null;
456
- cachedRoot = null;
675
+ import_picocolors2 = __toESM(require("picocolors"), 1);
676
+ DEBUG = process.env.DEBUG;
677
+ filter = process.env.NASTI_DEBUG_FILTER || process.env.VITE_DEBUG_FILTER;
457
678
  }
458
679
  });
459
680
 
460
- // src/plugins/css.ts
461
- function cssPlugin(config) {
462
- return {
463
- name: "nasti:css",
464
- resolveId(source) {
465
- if (source.endsWith(".css")) return null;
466
- return null;
467
- },
468
- async transform(code, id) {
469
- if (!id.endsWith(".css")) return null;
470
- let cssSource = code;
471
- if (hasTailwindDirectives(code)) {
472
- const compiled = await compileTailwind(code, id, config.root);
473
- cssSource = compiled.css;
474
- }
475
- const rewritten = rewriteCssUrls(cssSource, id, config.root);
476
- const escaped = JSON.stringify(rewritten);
477
- if (config.command === "serve") {
478
- return {
479
- code: `
480
- const css = ${escaped};
481
- const __nasti_css_id__ = ${JSON.stringify(id)};
482
- const __nasti_existing__ = document.querySelector('style[data-nasti-css=' + JSON.stringify(__nasti_css_id__) + ']');
483
- if (__nasti_existing__) __nasti_existing__.remove();
484
- const style = document.createElement('style');
485
- style.setAttribute('data-nasti-css', __nasti_css_id__);
486
- style.textContent = css;
487
- document.head.appendChild(style);
488
-
489
- // HMR
490
- if (import.meta.hot) {
491
- import.meta.hot.accept();
492
- import.meta.hot.prune(() => {
493
- style.remove();
494
- });
495
- }
496
-
497
- export default css;
498
- `
499
- };
500
- }
501
- const cssConfig = config.build.css || {};
502
- const nonce = cssConfig.nonce;
503
- const emitCssFile = cssConfig.emitCssFile;
504
- if (emitCssFile) {
505
- const fileName = `assets/${import_node_path4.default.basename(id, ".css")}.css`;
506
- this.emitFile({
507
- type: "asset",
508
- fileName,
509
- source: rewritten
510
- });
511
- return {
512
- code: `
513
- const link = document.createElement('link');
514
- link.rel = 'stylesheet';
515
- link.href = ${JSON.stringify("/" + fileName)};
516
- document.head.appendChild(link);
681
+ // require("../lightningcss.*.node") in node_modules/lightningcss/node/index.js
682
+ var globRequire_lightningcss_node;
683
+ var init_ = __esm({
684
+ 'require("../lightningcss.*.node") in node_modules/lightningcss/node/index.js'() {
685
+ globRequire_lightningcss_node = __glob({});
686
+ }
687
+ });
517
688
 
518
- export default ${escaped};
519
- `,
520
- moduleType: "js"
521
- };
689
+ // node_modules/detect-libc/lib/process.js
690
+ var require_process = __commonJS({
691
+ "node_modules/detect-libc/lib/process.js"(exports2, module2) {
692
+ "use strict";
693
+ var isLinux = () => process.platform === "linux";
694
+ var report = null;
695
+ var getReport = () => {
696
+ if (!report) {
697
+ if (isLinux() && process.report) {
698
+ const orig = process.report.excludeNetwork;
699
+ process.report.excludeNetwork = true;
700
+ report = process.report.getReport();
701
+ process.report.excludeNetwork = orig;
702
+ } else {
703
+ report = {};
704
+ }
522
705
  }
523
- const nonceAttr = nonce ? `style.setAttribute('nonce', ${JSON.stringify(nonce)});` : "";
524
- return {
525
- code: `
526
- const css = ${escaped};
527
- const style = document.createElement('style');
528
- style.setAttribute('data-nasti-css', ${JSON.stringify(id)});
529
- ${nonceAttr}
530
- style.textContent = css;
531
- document.head.appendChild(style);
706
+ return report;
707
+ };
708
+ module2.exports = { isLinux, getReport };
709
+ }
710
+ });
532
711
 
533
- export default css;
534
- `,
535
- moduleType: "js"
536
- };
537
- }
538
- };
539
- }
540
- function rewriteCssUrls(css, from, root) {
541
- return css.replace(/url\(\s*['"]?([^'")\s]+)['"]?\s*\)/g, (match, url) => {
542
- if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
543
- return match;
544
- }
545
- const resolved = import_node_path4.default.resolve(import_node_path4.default.dirname(from), url);
546
- const relative = "/" + import_node_path4.default.relative(root, resolved);
547
- return `url(${relative})`;
548
- });
549
- }
550
- var import_node_path4;
551
- var init_css = __esm({
552
- "src/plugins/css.ts"() {
712
+ // node_modules/detect-libc/lib/filesystem.js
713
+ var require_filesystem = __commonJS({
714
+ "node_modules/detect-libc/lib/filesystem.js"(exports2, module2) {
553
715
  "use strict";
554
- import_node_path4 = __toESM(require("path"), 1);
555
- init_tailwind();
716
+ var fs13 = require("fs");
717
+ var LDD_PATH = "/usr/bin/ldd";
718
+ var SELF_PATH = "/proc/self/exe";
719
+ var MAX_LENGTH = 2048;
720
+ var readFileSync = (path18) => {
721
+ const fd = fs13.openSync(path18, "r");
722
+ const buffer = Buffer.alloc(MAX_LENGTH);
723
+ const bytesRead = fs13.readSync(fd, buffer, 0, MAX_LENGTH, 0);
724
+ fs13.close(fd, () => {
725
+ });
726
+ return buffer.subarray(0, bytesRead);
727
+ };
728
+ var readFile = (path18) => new Promise((resolve, reject) => {
729
+ fs13.open(path18, "r", (err, fd) => {
730
+ if (err) {
731
+ reject(err);
732
+ } else {
733
+ const buffer = Buffer.alloc(MAX_LENGTH);
734
+ fs13.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
735
+ resolve(buffer.subarray(0, bytesRead));
736
+ fs13.close(fd, () => {
737
+ });
738
+ });
739
+ }
740
+ });
741
+ });
742
+ module2.exports = {
743
+ LDD_PATH,
744
+ SELF_PATH,
745
+ readFileSync,
746
+ readFile
747
+ };
556
748
  }
557
749
  });
558
750
 
559
- // src/plugins/assets.ts
560
- function assetsPlugin(config) {
561
- return {
562
- name: "nasti:assets",
563
- resolveId(source) {
564
- if (source.endsWith("?url") || source.endsWith("?raw")) {
565
- return source;
751
+ // node_modules/detect-libc/lib/elf.js
752
+ var require_elf = __commonJS({
753
+ "node_modules/detect-libc/lib/elf.js"(exports2, module2) {
754
+ "use strict";
755
+ var interpreterPath = (elf) => {
756
+ if (elf.length < 64) {
757
+ return null;
758
+ }
759
+ if (elf.readUInt32BE(0) !== 2135247942) {
760
+ return null;
761
+ }
762
+ if (elf.readUInt8(4) !== 2) {
763
+ return null;
764
+ }
765
+ if (elf.readUInt8(5) !== 1) {
766
+ return null;
767
+ }
768
+ const offset = elf.readUInt32LE(32);
769
+ const size = elf.readUInt16LE(54);
770
+ const count = elf.readUInt16LE(56);
771
+ for (let i = 0; i < count; i++) {
772
+ const headerOffset = offset + i * size;
773
+ const type = elf.readUInt32LE(headerOffset);
774
+ if (type === 3) {
775
+ const fileOffset = elf.readUInt32LE(headerOffset + 8);
776
+ const fileSize = elf.readUInt32LE(headerOffset + 32);
777
+ return elf.subarray(fileOffset, fileOffset + fileSize).toString().replace(/\0.*$/g, "");
778
+ }
566
779
  }
567
780
  return null;
568
- },
569
- load(id) {
570
- const ext = import_node_path5.default.extname(id.replace(/\?.*$/, ""));
571
- if (id.endsWith("?raw")) {
572
- const file = id.slice(0, -4);
573
- if (import_node_fs3.default.existsSync(file)) {
574
- const content = import_node_fs3.default.readFileSync(file, "utf-8");
575
- return `export default ${JSON.stringify(content)}`;
781
+ };
782
+ module2.exports = {
783
+ interpreterPath
784
+ };
785
+ }
786
+ });
787
+
788
+ // node_modules/detect-libc/lib/detect-libc.js
789
+ var require_detect_libc = __commonJS({
790
+ "node_modules/detect-libc/lib/detect-libc.js"(exports2, module2) {
791
+ "use strict";
792
+ var childProcess = require("child_process");
793
+ var { isLinux, getReport } = require_process();
794
+ var { LDD_PATH, SELF_PATH, readFile, readFileSync } = require_filesystem();
795
+ var { interpreterPath } = require_elf();
796
+ var cachedFamilyInterpreter;
797
+ var cachedFamilyFilesystem;
798
+ var cachedVersionFilesystem;
799
+ var command = "getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true";
800
+ var commandOut = "";
801
+ var safeCommand = () => {
802
+ if (!commandOut) {
803
+ return new Promise((resolve) => {
804
+ childProcess.exec(command, (err, out) => {
805
+ commandOut = err ? " " : out;
806
+ resolve(commandOut);
807
+ });
808
+ });
809
+ }
810
+ return commandOut;
811
+ };
812
+ var safeCommandSync = () => {
813
+ if (!commandOut) {
814
+ try {
815
+ commandOut = childProcess.execSync(command, { encoding: "utf8" });
816
+ } catch (_err) {
817
+ commandOut = " ";
576
818
  }
577
819
  }
578
- if (id.endsWith("?url") || ASSET_EXTENSIONS.has(ext)) {
579
- const file = id.replace(/\?.*$/, "");
580
- if (!import_node_fs3.default.existsSync(file)) return null;
581
- if (config.command === "serve") {
582
- const url = "/" + import_node_path5.default.relative(config.root, file);
583
- return `export default ${JSON.stringify(url)}`;
820
+ return commandOut;
821
+ };
822
+ var GLIBC = "glibc";
823
+ var RE_GLIBC_VERSION = /LIBC[a-z0-9 \-).]*?(\d+\.\d+)/i;
824
+ var MUSL = "musl";
825
+ var isFileMusl = (f) => f.includes("libc.musl-") || f.includes("ld-musl-");
826
+ var familyFromReport = () => {
827
+ const report = getReport();
828
+ if (report.header && report.header.glibcVersionRuntime) {
829
+ return GLIBC;
830
+ }
831
+ if (Array.isArray(report.sharedObjects)) {
832
+ if (report.sharedObjects.some(isFileMusl)) {
833
+ return MUSL;
584
834
  }
585
- const content = import_node_fs3.default.readFileSync(file);
586
- const hash = import_node_crypto.default.createHash("sha256").update(content).digest("hex").slice(0, 8);
587
- const basename = import_node_path5.default.basename(file, ext);
588
- const hashedName = `${config.build.assetsDir}/${basename}.${hash}${ext}`;
589
- return `export default ${JSON.stringify(config.base + hashedName)}`;
590
835
  }
591
836
  return null;
592
- }
593
- };
594
- }
595
- var import_node_path5, import_node_fs3, import_node_crypto, ASSET_EXTENSIONS;
596
- var init_assets = __esm({
597
- "src/plugins/assets.ts"() {
598
- "use strict";
599
- import_node_path5 = __toESM(require("path"), 1);
600
- import_node_fs3 = __toESM(require("fs"), 1);
601
- import_node_crypto = __toESM(require("crypto"), 1);
602
- ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
603
- ".png",
837
+ };
838
+ var familyFromCommand = (out) => {
839
+ const [getconf, ldd1] = out.split(/[\r\n]+/);
840
+ if (getconf && getconf.includes(GLIBC)) {
841
+ return GLIBC;
842
+ }
843
+ if (ldd1 && ldd1.includes(MUSL)) {
844
+ return MUSL;
845
+ }
846
+ return null;
847
+ };
848
+ var familyFromInterpreterPath = (path18) => {
849
+ if (path18) {
850
+ if (path18.includes("/ld-musl-")) {
851
+ return MUSL;
852
+ } else if (path18.includes("/ld-linux-")) {
853
+ return GLIBC;
854
+ }
855
+ }
856
+ return null;
857
+ };
858
+ var getFamilyFromLddContent = (content) => {
859
+ content = content.toString();
860
+ if (content.includes("musl")) {
861
+ return MUSL;
862
+ }
863
+ if (content.includes("GNU C Library")) {
864
+ return GLIBC;
865
+ }
866
+ return null;
867
+ };
868
+ var familyFromFilesystem = async () => {
869
+ if (cachedFamilyFilesystem !== void 0) {
870
+ return cachedFamilyFilesystem;
871
+ }
872
+ cachedFamilyFilesystem = null;
873
+ try {
874
+ const lddContent = await readFile(LDD_PATH);
875
+ cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
876
+ } catch (e) {
877
+ }
878
+ return cachedFamilyFilesystem;
879
+ };
880
+ var familyFromFilesystemSync = () => {
881
+ if (cachedFamilyFilesystem !== void 0) {
882
+ return cachedFamilyFilesystem;
883
+ }
884
+ cachedFamilyFilesystem = null;
885
+ try {
886
+ const lddContent = readFileSync(LDD_PATH);
887
+ cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
888
+ } catch (e) {
889
+ }
890
+ return cachedFamilyFilesystem;
891
+ };
892
+ var familyFromInterpreter = async () => {
893
+ if (cachedFamilyInterpreter !== void 0) {
894
+ return cachedFamilyInterpreter;
895
+ }
896
+ cachedFamilyInterpreter = null;
897
+ try {
898
+ const selfContent = await readFile(SELF_PATH);
899
+ const path18 = interpreterPath(selfContent);
900
+ cachedFamilyInterpreter = familyFromInterpreterPath(path18);
901
+ } catch (e) {
902
+ }
903
+ return cachedFamilyInterpreter;
904
+ };
905
+ var familyFromInterpreterSync = () => {
906
+ if (cachedFamilyInterpreter !== void 0) {
907
+ return cachedFamilyInterpreter;
908
+ }
909
+ cachedFamilyInterpreter = null;
910
+ try {
911
+ const selfContent = readFileSync(SELF_PATH);
912
+ const path18 = interpreterPath(selfContent);
913
+ cachedFamilyInterpreter = familyFromInterpreterPath(path18);
914
+ } catch (e) {
915
+ }
916
+ return cachedFamilyInterpreter;
917
+ };
918
+ var family = async () => {
919
+ let family2 = null;
920
+ if (isLinux()) {
921
+ family2 = await familyFromInterpreter();
922
+ if (!family2) {
923
+ family2 = await familyFromFilesystem();
924
+ if (!family2) {
925
+ family2 = familyFromReport();
926
+ }
927
+ if (!family2) {
928
+ const out = await safeCommand();
929
+ family2 = familyFromCommand(out);
930
+ }
931
+ }
932
+ }
933
+ return family2;
934
+ };
935
+ var familySync = () => {
936
+ let family2 = null;
937
+ if (isLinux()) {
938
+ family2 = familyFromInterpreterSync();
939
+ if (!family2) {
940
+ family2 = familyFromFilesystemSync();
941
+ if (!family2) {
942
+ family2 = familyFromReport();
943
+ }
944
+ if (!family2) {
945
+ const out = safeCommandSync();
946
+ family2 = familyFromCommand(out);
947
+ }
948
+ }
949
+ }
950
+ return family2;
951
+ };
952
+ var isNonGlibcLinux = async () => isLinux() && await family() !== GLIBC;
953
+ var isNonGlibcLinuxSync = () => isLinux() && familySync() !== GLIBC;
954
+ var versionFromFilesystem = async () => {
955
+ if (cachedVersionFilesystem !== void 0) {
956
+ return cachedVersionFilesystem;
957
+ }
958
+ cachedVersionFilesystem = null;
959
+ try {
960
+ const lddContent = await readFile(LDD_PATH);
961
+ const versionMatch = lddContent.match(RE_GLIBC_VERSION);
962
+ if (versionMatch) {
963
+ cachedVersionFilesystem = versionMatch[1];
964
+ }
965
+ } catch (e) {
966
+ }
967
+ return cachedVersionFilesystem;
968
+ };
969
+ var versionFromFilesystemSync = () => {
970
+ if (cachedVersionFilesystem !== void 0) {
971
+ return cachedVersionFilesystem;
972
+ }
973
+ cachedVersionFilesystem = null;
974
+ try {
975
+ const lddContent = readFileSync(LDD_PATH);
976
+ const versionMatch = lddContent.match(RE_GLIBC_VERSION);
977
+ if (versionMatch) {
978
+ cachedVersionFilesystem = versionMatch[1];
979
+ }
980
+ } catch (e) {
981
+ }
982
+ return cachedVersionFilesystem;
983
+ };
984
+ var versionFromReport = () => {
985
+ const report = getReport();
986
+ if (report.header && report.header.glibcVersionRuntime) {
987
+ return report.header.glibcVersionRuntime;
988
+ }
989
+ return null;
990
+ };
991
+ var versionSuffix = (s) => s.trim().split(/\s+/)[1];
992
+ var versionFromCommand = (out) => {
993
+ const [getconf, ldd1, ldd2] = out.split(/[\r\n]+/);
994
+ if (getconf && getconf.includes(GLIBC)) {
995
+ return versionSuffix(getconf);
996
+ }
997
+ if (ldd1 && ldd2 && ldd1.includes(MUSL)) {
998
+ return versionSuffix(ldd2);
999
+ }
1000
+ return null;
1001
+ };
1002
+ var version = async () => {
1003
+ let version2 = null;
1004
+ if (isLinux()) {
1005
+ version2 = await versionFromFilesystem();
1006
+ if (!version2) {
1007
+ version2 = versionFromReport();
1008
+ }
1009
+ if (!version2) {
1010
+ const out = await safeCommand();
1011
+ version2 = versionFromCommand(out);
1012
+ }
1013
+ }
1014
+ return version2;
1015
+ };
1016
+ var versionSync = () => {
1017
+ let version2 = null;
1018
+ if (isLinux()) {
1019
+ version2 = versionFromFilesystemSync();
1020
+ if (!version2) {
1021
+ version2 = versionFromReport();
1022
+ }
1023
+ if (!version2) {
1024
+ const out = safeCommandSync();
1025
+ version2 = versionFromCommand(out);
1026
+ }
1027
+ }
1028
+ return version2;
1029
+ };
1030
+ module2.exports = {
1031
+ GLIBC,
1032
+ MUSL,
1033
+ family,
1034
+ familySync,
1035
+ isNonGlibcLinux,
1036
+ isNonGlibcLinuxSync,
1037
+ version,
1038
+ versionSync
1039
+ };
1040
+ }
1041
+ });
1042
+
1043
+ // node_modules/lightningcss/node/browserslistToTargets.js
1044
+ var require_browserslistToTargets = __commonJS({
1045
+ "node_modules/lightningcss/node/browserslistToTargets.js"(exports2, module2) {
1046
+ "use strict";
1047
+ var BROWSER_MAPPING = {
1048
+ and_chr: "chrome",
1049
+ and_ff: "firefox",
1050
+ ie_mob: "ie",
1051
+ op_mob: "opera",
1052
+ and_qq: null,
1053
+ and_uc: null,
1054
+ baidu: null,
1055
+ bb: null,
1056
+ kaios: null,
1057
+ op_mini: null
1058
+ };
1059
+ function browserslistToTargets2(browserslist) {
1060
+ let targets = {};
1061
+ for (let browser of browserslist) {
1062
+ let [name, v] = browser.split(" ");
1063
+ if (BROWSER_MAPPING[name] === null) {
1064
+ continue;
1065
+ }
1066
+ let version = parseVersion(v);
1067
+ if (version == null) {
1068
+ continue;
1069
+ }
1070
+ if (targets[name] == null || version < targets[name]) {
1071
+ targets[name] = version;
1072
+ }
1073
+ }
1074
+ return targets;
1075
+ }
1076
+ function parseVersion(version) {
1077
+ let [major, minor = 0, patch = 0] = version.split("-")[0].split(".").map((v) => parseInt(v, 10));
1078
+ if (isNaN(major) || isNaN(minor) || isNaN(patch)) {
1079
+ return null;
1080
+ }
1081
+ return major << 16 | minor << 8 | patch;
1082
+ }
1083
+ module2.exports = browserslistToTargets2;
1084
+ }
1085
+ });
1086
+
1087
+ // node_modules/lightningcss/node/composeVisitors.js
1088
+ var require_composeVisitors = __commonJS({
1089
+ "node_modules/lightningcss/node/composeVisitors.js"(exports2, module2) {
1090
+ "use strict";
1091
+ function composeVisitors2(visitors) {
1092
+ if (visitors.length === 1) {
1093
+ return visitors[0];
1094
+ }
1095
+ if (visitors.some((v) => typeof v === "function")) {
1096
+ return (opts) => {
1097
+ let v = visitors.map((v2) => typeof v2 === "function" ? v2(opts) : v2);
1098
+ return composeVisitors2(v);
1099
+ };
1100
+ }
1101
+ let res = {};
1102
+ composeSimpleVisitors(res, visitors, "StyleSheet");
1103
+ composeSimpleVisitors(res, visitors, "StyleSheetExit");
1104
+ composeObjectVisitors(res, visitors, "Rule", ruleVisitor, wrapCustomAndUnknownAtRule);
1105
+ composeObjectVisitors(res, visitors, "RuleExit", ruleVisitor, wrapCustomAndUnknownAtRule);
1106
+ composeObjectVisitors(res, visitors, "Declaration", declarationVisitor, wrapCustomProperty);
1107
+ composeObjectVisitors(res, visitors, "DeclarationExit", declarationVisitor, wrapCustomProperty);
1108
+ composeSimpleVisitors(res, visitors, "Url");
1109
+ composeSimpleVisitors(res, visitors, "Color");
1110
+ composeSimpleVisitors(res, visitors, "Image");
1111
+ composeSimpleVisitors(res, visitors, "ImageExit");
1112
+ composeSimpleVisitors(res, visitors, "Length");
1113
+ composeSimpleVisitors(res, visitors, "Angle");
1114
+ composeSimpleVisitors(res, visitors, "Ratio");
1115
+ composeSimpleVisitors(res, visitors, "Resolution");
1116
+ composeSimpleVisitors(res, visitors, "Time");
1117
+ composeSimpleVisitors(res, visitors, "CustomIdent");
1118
+ composeSimpleVisitors(res, visitors, "DashedIdent");
1119
+ composeArrayFunctions(res, visitors, "MediaQuery");
1120
+ composeArrayFunctions(res, visitors, "MediaQueryExit");
1121
+ composeSimpleVisitors(res, visitors, "SupportsCondition");
1122
+ composeSimpleVisitors(res, visitors, "SupportsConditionExit");
1123
+ composeArrayFunctions(res, visitors, "Selector");
1124
+ composeTokenVisitors(res, visitors, "Token", "token", false);
1125
+ composeTokenVisitors(res, visitors, "Function", "function", false);
1126
+ composeTokenVisitors(res, visitors, "FunctionExit", "function", true);
1127
+ composeTokenVisitors(res, visitors, "Variable", "var", false);
1128
+ composeTokenVisitors(res, visitors, "VariableExit", "var", true);
1129
+ composeTokenVisitors(res, visitors, "EnvironmentVariable", "env", false);
1130
+ composeTokenVisitors(res, visitors, "EnvironmentVariableExit", "env", true);
1131
+ return res;
1132
+ }
1133
+ module2.exports = composeVisitors2;
1134
+ function wrapCustomAndUnknownAtRule(k, f) {
1135
+ if (k === "unknown") {
1136
+ return ((value) => f({ type: "unknown", value }));
1137
+ }
1138
+ if (k === "custom") {
1139
+ return ((value) => f({ type: "custom", value }));
1140
+ }
1141
+ return f;
1142
+ }
1143
+ function wrapCustomProperty(k, f) {
1144
+ return k === "custom" ? ((value) => f({ property: "custom", value })) : f;
1145
+ }
1146
+ function ruleVisitor(f, item) {
1147
+ if (typeof f === "object") {
1148
+ if (item.type === "unknown") {
1149
+ let v = f.unknown;
1150
+ if (typeof v === "object") {
1151
+ v = v[item.value.name];
1152
+ }
1153
+ return v?.(item.value);
1154
+ }
1155
+ if (item.type === "custom") {
1156
+ let v = f.custom;
1157
+ if (typeof v === "object") {
1158
+ v = v[item.value.name];
1159
+ }
1160
+ return v?.(item.value);
1161
+ }
1162
+ return f[item.type]?.(item);
1163
+ }
1164
+ return f?.(item);
1165
+ }
1166
+ function declarationVisitor(f, item) {
1167
+ if (typeof f === "object") {
1168
+ let name = item.property;
1169
+ if (item.property === "unparsed") {
1170
+ name = item.value.propertyId.property;
1171
+ } else if (item.property === "custom") {
1172
+ let v = f.custom;
1173
+ if (typeof v === "object") {
1174
+ v = v[item.value.name];
1175
+ }
1176
+ return v?.(item.value);
1177
+ }
1178
+ return f[name]?.(item);
1179
+ }
1180
+ return f?.(item);
1181
+ }
1182
+ function extractObjectsOrFunctions(visitors, key) {
1183
+ let values = [];
1184
+ let hasFunction = false;
1185
+ let allKeys = /* @__PURE__ */ new Set();
1186
+ for (let visitor of visitors) {
1187
+ let v = visitor[key];
1188
+ if (v) {
1189
+ if (typeof v === "function") {
1190
+ hasFunction = true;
1191
+ } else {
1192
+ for (let key2 in v) {
1193
+ allKeys.add(key2);
1194
+ }
1195
+ }
1196
+ values.push(v);
1197
+ }
1198
+ }
1199
+ return [values, hasFunction, allKeys];
1200
+ }
1201
+ function composeObjectVisitors(res, visitors, key, apply, wrapKey) {
1202
+ let [values, hasFunction, allKeys] = extractObjectsOrFunctions(visitors, key);
1203
+ if (values.length === 0) {
1204
+ return;
1205
+ }
1206
+ if (values.length === 1) {
1207
+ res[key] = values[0];
1208
+ return;
1209
+ }
1210
+ let f = createArrayVisitor(visitors, (visitor, item) => apply(visitor[key], item));
1211
+ if (hasFunction) {
1212
+ res[key] = f;
1213
+ } else {
1214
+ let v = {};
1215
+ for (let k of allKeys) {
1216
+ v[k] = wrapKey(k, f);
1217
+ }
1218
+ res[key] = v;
1219
+ }
1220
+ }
1221
+ function composeTokenVisitors(res, visitors, key, type, isExit) {
1222
+ let [values, hasFunction, allKeys] = extractObjectsOrFunctions(visitors, key);
1223
+ if (values.length === 0) {
1224
+ return;
1225
+ }
1226
+ if (values.length === 1) {
1227
+ res[key] = values[0];
1228
+ return;
1229
+ }
1230
+ let f = createTokenVisitor(visitors, type, isExit);
1231
+ if (hasFunction) {
1232
+ res[key] = f;
1233
+ } else {
1234
+ let v = {};
1235
+ for (let key2 of allKeys) {
1236
+ v[key2] = f;
1237
+ }
1238
+ res[key] = v;
1239
+ }
1240
+ }
1241
+ function createTokenVisitor(visitors, type, isExit) {
1242
+ let v = createArrayVisitor(visitors, (visitor, item) => {
1243
+ let f;
1244
+ switch (item.type) {
1245
+ case "token":
1246
+ f = visitor.Token;
1247
+ if (typeof f === "object") {
1248
+ f = f[item.value.type];
1249
+ }
1250
+ break;
1251
+ case "function":
1252
+ f = isExit ? visitor.FunctionExit : visitor.Function;
1253
+ if (typeof f === "object") {
1254
+ f = f[item.value.name];
1255
+ }
1256
+ break;
1257
+ case "var":
1258
+ f = isExit ? visitor.VariableExit : visitor.Variable;
1259
+ break;
1260
+ case "env":
1261
+ f = isExit ? visitor.EnvironmentVariableExit : visitor.EnvironmentVariable;
1262
+ if (typeof f === "object") {
1263
+ let name;
1264
+ switch (item.value.name.type) {
1265
+ case "ua":
1266
+ case "unknown":
1267
+ name = item.value.name.value;
1268
+ break;
1269
+ case "custom":
1270
+ name = item.value.name.ident;
1271
+ break;
1272
+ }
1273
+ f = f[name];
1274
+ }
1275
+ break;
1276
+ case "color":
1277
+ f = visitor.Color;
1278
+ break;
1279
+ case "url":
1280
+ f = visitor.Url;
1281
+ break;
1282
+ case "length":
1283
+ f = visitor.Length;
1284
+ break;
1285
+ case "angle":
1286
+ f = visitor.Angle;
1287
+ break;
1288
+ case "time":
1289
+ f = visitor.Time;
1290
+ break;
1291
+ case "resolution":
1292
+ f = visitor.Resolution;
1293
+ break;
1294
+ case "dashed-ident":
1295
+ f = visitor.DashedIdent;
1296
+ break;
1297
+ }
1298
+ if (!f) {
1299
+ return;
1300
+ }
1301
+ let res = f(item.value);
1302
+ switch (item.type) {
1303
+ case "color":
1304
+ case "url":
1305
+ case "length":
1306
+ case "angle":
1307
+ case "time":
1308
+ case "resolution":
1309
+ case "dashed-ident":
1310
+ if (Array.isArray(res)) {
1311
+ res = res.map((value) => ({ type: item.type, value }));
1312
+ } else if (res) {
1313
+ res = { type: item.type, value: res };
1314
+ }
1315
+ break;
1316
+ }
1317
+ return res;
1318
+ });
1319
+ return (value) => v({ type, value });
1320
+ }
1321
+ function extractFunctions(visitors, key) {
1322
+ let functions = [];
1323
+ for (let visitor of visitors) {
1324
+ let f = visitor[key];
1325
+ if (f) {
1326
+ functions.push(f);
1327
+ }
1328
+ }
1329
+ return functions;
1330
+ }
1331
+ function composeSimpleVisitors(res, visitors, key) {
1332
+ let functions = extractFunctions(visitors, key);
1333
+ if (functions.length === 0) {
1334
+ return;
1335
+ }
1336
+ if (functions.length === 1) {
1337
+ res[key] = functions[0];
1338
+ return;
1339
+ }
1340
+ res[key] = (arg) => {
1341
+ let mutated = false;
1342
+ for (let f of functions) {
1343
+ let res2 = f(arg);
1344
+ if (res2) {
1345
+ arg = res2;
1346
+ mutated = true;
1347
+ }
1348
+ }
1349
+ return mutated ? arg : void 0;
1350
+ };
1351
+ }
1352
+ function composeArrayFunctions(res, visitors, key) {
1353
+ let functions = extractFunctions(visitors, key);
1354
+ if (functions.length === 0) {
1355
+ return;
1356
+ }
1357
+ if (functions.length === 1) {
1358
+ res[key] = functions[0];
1359
+ return;
1360
+ }
1361
+ res[key] = createArrayVisitor(functions, (f, item) => f(item));
1362
+ }
1363
+ function createArrayVisitor(visitors, apply) {
1364
+ let seen = new Bitset(visitors.length);
1365
+ return (arg) => {
1366
+ let arr = [arg];
1367
+ let mutated = false;
1368
+ seen.clear();
1369
+ for (let i = 0; i < arr.length; i++) {
1370
+ for (let v = 0; v < visitors.length && i < arr.length; ) {
1371
+ if (seen.get(v)) {
1372
+ v++;
1373
+ continue;
1374
+ }
1375
+ let item = arr[i];
1376
+ let visitor = visitors[v];
1377
+ let res = apply(visitor, item);
1378
+ if (Array.isArray(res)) {
1379
+ if (res.length === 0) {
1380
+ arr.splice(i, 1);
1381
+ } else if (res.length === 1) {
1382
+ arr[i] = res[0];
1383
+ } else {
1384
+ arr.splice(i, 1, ...res);
1385
+ }
1386
+ mutated = true;
1387
+ seen.set(v);
1388
+ v = 0;
1389
+ } else if (res) {
1390
+ arr[i] = res;
1391
+ mutated = true;
1392
+ seen.set(v);
1393
+ v = 0;
1394
+ } else {
1395
+ v++;
1396
+ }
1397
+ }
1398
+ }
1399
+ if (!mutated) {
1400
+ return;
1401
+ }
1402
+ return arr.length === 1 ? arr[0] : arr;
1403
+ };
1404
+ }
1405
+ var Bitset = class {
1406
+ constructor(maxBits = 32) {
1407
+ this.bits = 0;
1408
+ this.more = maxBits > 32 ? new Uint32Array(Math.ceil((maxBits - 32) / 32)) : null;
1409
+ }
1410
+ /** @param {number} bit */
1411
+ get(bit) {
1412
+ if (bit >= 32 && this.more) {
1413
+ let i = Math.floor((bit - 32) / 32);
1414
+ let b = bit % 32;
1415
+ return Boolean(this.more[i] & 1 << b);
1416
+ } else {
1417
+ return Boolean(this.bits & 1 << bit);
1418
+ }
1419
+ }
1420
+ /** @param {number} bit */
1421
+ set(bit) {
1422
+ if (bit >= 32 && this.more) {
1423
+ let i = Math.floor((bit - 32) / 32);
1424
+ let b = bit % 32;
1425
+ this.more[i] |= 1 << b;
1426
+ } else {
1427
+ this.bits |= 1 << bit;
1428
+ }
1429
+ }
1430
+ clear() {
1431
+ this.bits = 0;
1432
+ if (this.more) {
1433
+ this.more.fill(0);
1434
+ }
1435
+ }
1436
+ };
1437
+ }
1438
+ });
1439
+
1440
+ // node_modules/lightningcss/node/flags.js
1441
+ var require_flags = __commonJS({
1442
+ "node_modules/lightningcss/node/flags.js"(exports2) {
1443
+ "use strict";
1444
+ exports2.Features = {
1445
+ Nesting: 1,
1446
+ NotSelectorList: 2,
1447
+ DirSelector: 4,
1448
+ LangSelectorList: 8,
1449
+ IsSelector: 16,
1450
+ TextDecorationThicknessPercent: 32,
1451
+ MediaIntervalSyntax: 64,
1452
+ MediaRangeSyntax: 128,
1453
+ CustomMediaQueries: 256,
1454
+ ClampFunction: 512,
1455
+ ColorFunction: 1024,
1456
+ OklabColors: 2048,
1457
+ LabColors: 4096,
1458
+ P3Colors: 8192,
1459
+ HexAlphaColors: 16384,
1460
+ SpaceSeparatedColorNotation: 32768,
1461
+ FontFamilySystemUi: 65536,
1462
+ DoublePositionGradients: 131072,
1463
+ VendorPrefixes: 262144,
1464
+ LogicalProperties: 524288,
1465
+ LightDark: 1048576,
1466
+ Selectors: 31,
1467
+ MediaQueries: 448,
1468
+ Colors: 1113088
1469
+ };
1470
+ }
1471
+ });
1472
+
1473
+ // node_modules/lightningcss/node/index.js
1474
+ var require_node = __commonJS({
1475
+ "node_modules/lightningcss/node/index.js"(exports2, module2) {
1476
+ "use strict";
1477
+ init_();
1478
+ var parts = [process.platform, process.arch];
1479
+ if (process.platform === "linux") {
1480
+ const { MUSL, familySync } = require_detect_libc();
1481
+ const family = familySync();
1482
+ if (family === MUSL) {
1483
+ parts.push("musl");
1484
+ } else if (process.arch === "arm") {
1485
+ parts.push("gnueabihf");
1486
+ } else {
1487
+ parts.push("gnu");
1488
+ }
1489
+ } else if (process.platform === "win32") {
1490
+ parts.push("msvc");
1491
+ }
1492
+ var native;
1493
+ try {
1494
+ native = require(`lightningcss-${parts.join("-")}`);
1495
+ } catch (err) {
1496
+ native = globRequire_lightningcss_node(`../lightningcss.${parts.join("-")}.node`);
1497
+ }
1498
+ module2.exports.transform = wrap(native.transform);
1499
+ module2.exports.transformStyleAttribute = wrap(native.transformStyleAttribute);
1500
+ module2.exports.bundle = wrap(native.bundle);
1501
+ module2.exports.bundleAsync = wrap(native.bundleAsync);
1502
+ module2.exports.browserslistToTargets = require_browserslistToTargets();
1503
+ module2.exports.composeVisitors = require_composeVisitors();
1504
+ module2.exports.Features = require_flags().Features;
1505
+ function wrap(call) {
1506
+ return (options) => {
1507
+ if (typeof options.visitor === "function") {
1508
+ let deps = [];
1509
+ options.visitor = options.visitor({
1510
+ addDependency(dep) {
1511
+ deps.push(dep);
1512
+ }
1513
+ });
1514
+ let result = call(options);
1515
+ if (result instanceof Promise) {
1516
+ result = result.then((res) => {
1517
+ if (deps.length) {
1518
+ res.dependencies ??= [];
1519
+ res.dependencies.push(...deps);
1520
+ }
1521
+ return res;
1522
+ });
1523
+ } else if (deps.length) {
1524
+ result.dependencies ??= [];
1525
+ result.dependencies.push(...deps);
1526
+ }
1527
+ return result;
1528
+ } else {
1529
+ return call(options);
1530
+ }
1531
+ };
1532
+ }
1533
+ }
1534
+ });
1535
+
1536
+ // node_modules/lightningcss/node/index.mjs
1537
+ var node_exports = {};
1538
+ __export(node_exports, {
1539
+ Features: () => Features,
1540
+ browserslistToTargets: () => browserslistToTargets,
1541
+ bundle: () => bundle,
1542
+ bundleAsync: () => bundleAsync,
1543
+ composeVisitors: () => composeVisitors,
1544
+ transform: () => transform,
1545
+ transformStyleAttribute: () => transformStyleAttribute
1546
+ });
1547
+ var import_index, transform, transformStyleAttribute, bundle, bundleAsync, browserslistToTargets, composeVisitors, Features;
1548
+ var init_node = __esm({
1549
+ "node_modules/lightningcss/node/index.mjs"() {
1550
+ "use strict";
1551
+ import_index = __toESM(require_node(), 1);
1552
+ ({ transform, transformStyleAttribute, bundle, bundleAsync, browserslistToTargets, composeVisitors, Features } = import_index.default);
1553
+ }
1554
+ });
1555
+
1556
+ // src/core/css-engine.ts
1557
+ function createCssEngine() {
1558
+ return {
1559
+ styles: /* @__PURE__ */ new Map(),
1560
+ entryCss: /* @__PURE__ */ new Map(),
1561
+ allCss: [],
1562
+ pendingSingle: [],
1563
+ singleFileName: null
1564
+ };
1565
+ }
1566
+ function normalizeCssModuleId(id) {
1567
+ return id.startsWith("\0") ? id.slice(1) : id;
1568
+ }
1569
+ async function minifyCss(css, config) {
1570
+ if (lightningCss === void 0) {
1571
+ try {
1572
+ lightningCss = await Promise.resolve().then(() => (init_node(), node_exports));
1573
+ } catch {
1574
+ lightningCss = null;
1575
+ debug?.("lightningcss unavailable, falling back to regex minifier");
1576
+ }
1577
+ }
1578
+ if (lightningCss) {
1579
+ try {
1580
+ const result = lightningCss.transform({
1581
+ filename: "bundle.css",
1582
+ code: Buffer.from(css),
1583
+ minify: true,
1584
+ // 不展开 @import(Tailwind 已 flatten;裸 @import 保留原样交给浏览器)
1585
+ errorRecovery: true
1586
+ });
1587
+ for (const w of result.warnings ?? []) {
1588
+ config.logger.warnOnce(`[nasti:css] ${w.message}`);
1589
+ }
1590
+ return result.code.toString();
1591
+ } catch (err) {
1592
+ config.logger.warnOnce(
1593
+ `[nasti:css] Lightning CSS minify failed (${err.message}), emitting unminified CSS`
1594
+ );
1595
+ return css;
1596
+ }
1597
+ }
1598
+ return fallbackMinify(css);
1599
+ }
1600
+ function fallbackMinify(css) {
1601
+ return css.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s*([{}:;,])\s*/g, "$1").replace(/;}/g, "}").replace(/\s+/g, " ").trim();
1602
+ }
1603
+ var debug, lightningCss;
1604
+ var init_css_engine = __esm({
1605
+ "src/core/css-engine.ts"() {
1606
+ "use strict";
1607
+ init_debug();
1608
+ debug = createDebugger("nasti:css");
1609
+ }
1610
+ });
1611
+
1612
+ // src/plugins/tailwind.ts
1613
+ function hasTailwindDirectives(css) {
1614
+ const withoutBlockComments = css.replace(/\/\*[\s\S]*?\*\//g, "");
1615
+ const withoutLineComments = withoutBlockComments.replace(/\/\/.*$/gm, "");
1616
+ return TAILWIND_DIRECTIVE_RE.test(withoutLineComments);
1617
+ }
1618
+ async function loadTailwind(projectRoot) {
1619
+ if (cached && cachedRoot === projectRoot) return cached;
1620
+ const req = (0, import_node_module2.createRequire)(import_node_path3.default.join(projectRoot, "package.json"));
1621
+ let nodePath;
1622
+ let oxidePath;
1623
+ try {
1624
+ nodePath = req.resolve("@tailwindcss/node");
1625
+ oxidePath = req.resolve("@tailwindcss/oxide");
1626
+ } catch {
1627
+ throw new Error(
1628
+ "[nasti] CSS contains Tailwind v4 directives but `@tailwindcss/node` and/or `@tailwindcss/oxide` are not installed in this project. Install them with: npm i -D tailwindcss @tailwindcss/node @tailwindcss/oxide"
1629
+ );
1630
+ }
1631
+ const node = await import((0, import_node_url2.pathToFileURL)(nodePath).href);
1632
+ const oxide = await import((0, import_node_url2.pathToFileURL)(oxidePath).href);
1633
+ cached = { node, oxide };
1634
+ cachedRoot = projectRoot;
1635
+ return cached;
1636
+ }
1637
+ async function compileTailwind(css, fromFile, projectRoot) {
1638
+ const { node, oxide } = await loadTailwind(projectRoot);
1639
+ const dependencies = [];
1640
+ const compiler2 = await node.compile(css, {
1641
+ base: import_node_path3.default.dirname(fromFile),
1642
+ from: fromFile,
1643
+ onDependency: (p) => dependencies.push(p)
1644
+ });
1645
+ const scanner = new oxide.Scanner({ sources: compiler2.sources });
1646
+ const candidates = scanner.scan();
1647
+ return {
1648
+ css: compiler2.build(candidates),
1649
+ dependencies: [...dependencies, ...scanner.files]
1650
+ };
1651
+ }
1652
+ var import_node_path3, import_node_module2, import_node_url2, TAILWIND_DIRECTIVE_RE, cached, cachedRoot;
1653
+ var init_tailwind = __esm({
1654
+ "src/plugins/tailwind.ts"() {
1655
+ "use strict";
1656
+ import_node_path3 = __toESM(require("path"), 1);
1657
+ import_node_module2 = require("module");
1658
+ import_node_url2 = require("url");
1659
+ 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)/;
1660
+ cached = null;
1661
+ cachedRoot = null;
1662
+ }
1663
+ });
1664
+
1665
+ // src/plugins/css.ts
1666
+ function cssPlugin(config, engine, consumer = "client") {
1667
+ return {
1668
+ name: "nasti:css",
1669
+ resolveId(source) {
1670
+ if (source.endsWith(".css")) return null;
1671
+ return null;
1672
+ },
1673
+ async transform(code, id) {
1674
+ const [file, query = ""] = id.split("?", 2);
1675
+ const isCssRequest = file.endsWith(".css") || /\.css$/.test(id);
1676
+ if (!isCssRequest) return null;
1677
+ if (query === "raw" || query === "url") return null;
1678
+ let cssSource = code;
1679
+ if (hasTailwindDirectives(code)) {
1680
+ const compiled = await compileTailwind(code, id, config.root);
1681
+ cssSource = compiled.css;
1682
+ }
1683
+ const rewritten = rewriteCssUrls(cssSource, file, config.root);
1684
+ const escaped = JSON.stringify(rewritten);
1685
+ if (query === "inline") {
1686
+ return { code: `export default ${escaped};
1687
+ `, moduleType: "js" };
1688
+ }
1689
+ if (consumer === "server") {
1690
+ return { code: `export default ${escaped};
1691
+ `, moduleType: "js" };
1692
+ }
1693
+ if (config.command === "serve") {
1694
+ return {
1695
+ code: `
1696
+ const css = ${escaped};
1697
+ const __nasti_css_id__ = ${JSON.stringify(id)};
1698
+ const __nasti_existing__ = document.querySelector('style[data-nasti-css=' + JSON.stringify(__nasti_css_id__) + ']');
1699
+ if (__nasti_existing__) __nasti_existing__.remove();
1700
+ const style = document.createElement('style');
1701
+ style.setAttribute('data-nasti-css', __nasti_css_id__);
1702
+ style.textContent = css;
1703
+ document.head.appendChild(style);
1704
+
1705
+ // HMR\uFF08prune \u5728 bundled \u6A21\u5F0F\u7684 rolldown hot context \u4E0A\u4E0D\u5B58\u5728\uFF0C\u987B\u5B88\u536B\uFF09
1706
+ if (import.meta.hot) {
1707
+ import.meta.hot.accept();
1708
+ if (import.meta.hot.prune) {
1709
+ import.meta.hot.prune(() => {
1710
+ style.remove();
1711
+ });
1712
+ }
1713
+ }
1714
+
1715
+ export default css;
1716
+ `,
1717
+ // bundled dev(DevEngine)下该模块会进 Rolldown:不标 js 会按 .css
1718
+ // 扩展名走 CSS 管线触发 #4271 报错;unbundled 中间件忽略此字段
1719
+ moduleType: "js"
1720
+ };
1721
+ }
1722
+ if (engine) {
1723
+ engine.styles.set(normalizeCssModuleId(id), rewritten);
1724
+ return {
1725
+ code: `export default '';
1726
+ `,
1727
+ moduleType: "js",
1728
+ // 防止空 stub 被 tree-shake 出 chunk.moduleIds(css-post 靠它定位)
1729
+ moduleSideEffects: "no-treeshake"
1730
+ };
1731
+ }
1732
+ const cssConfig = config.build.css || {};
1733
+ const nonce = cssConfig.nonce;
1734
+ const nonceAttr = nonce ? `style.setAttribute('nonce', ${JSON.stringify(nonce)});` : "";
1735
+ return {
1736
+ code: `
1737
+ const css = ${escaped};
1738
+ const style = document.createElement('style');
1739
+ style.setAttribute('data-nasti-css', ${JSON.stringify(id)});
1740
+ ${nonceAttr}
1741
+ style.textContent = css;
1742
+ document.head.appendChild(style);
1743
+
1744
+ export default css;
1745
+ `,
1746
+ moduleType: "js"
1747
+ };
1748
+ }
1749
+ };
1750
+ }
1751
+ function rewriteCssUrls(css, from, root) {
1752
+ return css.replace(/url\(\s*['"]?([^'")\s]+)['"]?\s*\)/g, (match, url) => {
1753
+ if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
1754
+ return match;
1755
+ }
1756
+ const resolved = import_node_path4.default.resolve(import_node_path4.default.dirname(from), url);
1757
+ const relative = "/" + import_node_path4.default.relative(root, resolved).replace(/\\/g, "/");
1758
+ return `url(${relative})`;
1759
+ });
1760
+ }
1761
+ var import_node_path4;
1762
+ var init_css = __esm({
1763
+ "src/plugins/css.ts"() {
1764
+ "use strict";
1765
+ import_node_path4 = __toESM(require("path"), 1);
1766
+ init_css_engine();
1767
+ init_tailwind();
1768
+ }
1769
+ });
1770
+
1771
+ // src/plugins/css-post.ts
1772
+ function collectChunkCss(chunk, engine) {
1773
+ const ids = chunk.moduleIds ?? Object.keys(chunk.modules);
1774
+ let css = "";
1775
+ for (const id of ids) {
1776
+ const styles = engine.styles.get(normalizeCssModuleId(id));
1777
+ if (styles) css += styles + "\n";
1778
+ }
1779
+ return css;
1780
+ }
1781
+ function cssPostPlugin(config, engine) {
1782
+ return {
1783
+ name: "nasti:css-post",
1784
+ enforce: "post",
1785
+ async renderChunk(code, chunk) {
1786
+ const css = collectChunkCss(chunk, engine);
1787
+ if (!css) return null;
1788
+ if (!config.build.cssCodeSplit) {
1789
+ engine.pendingSingle.push(css);
1790
+ return null;
1791
+ }
1792
+ const finalCss = config.build.cssMinify ? await minifyCss(css, config) : css;
1793
+ const ref = this.emitFile({
1794
+ type: "asset",
1795
+ name: `${chunk.name}.css`,
1796
+ source: finalCss
1797
+ });
1798
+ const fileName = this.getFileName(ref);
1799
+ engine.allCss.push(fileName);
1800
+ if (chunk.isEntry) {
1801
+ const key = chunk.facadeModuleId ?? chunk.name;
1802
+ const existing = engine.entryCss.get(key) ?? [];
1803
+ existing.push(fileName);
1804
+ engine.entryCss.set(key, existing);
1805
+ return null;
1806
+ }
1807
+ const href = JSON.stringify(config.base + fileName);
1808
+ const snippet = `
1809
+ ;(function(){try{var d=document,h=${href};if(!d.querySelector('link[data-nasti-css="'+h+'"]')){var l=d.createElement('link');l.rel='stylesheet';l.href=h;l.setAttribute('data-nasti-css',h);d.head.appendChild(l);}}catch(e){}})();`;
1810
+ return { code: code + snippet, map: null };
1811
+ },
1812
+ augmentChunkHash(chunk) {
1813
+ const css = collectChunkCss(chunk, engine);
1814
+ return css || void 0;
1815
+ },
1816
+ async generateBundle() {
1817
+ if (config.build.cssCodeSplit || engine.pendingSingle.length === 0) return;
1818
+ const merged = engine.pendingSingle.join("\n");
1819
+ const finalCss = config.build.cssMinify ? await minifyCss(merged, config) : merged;
1820
+ const ref = this.emitFile({ type: "asset", name: "style.css", source: finalCss });
1821
+ const fileName = this.getFileName(ref);
1822
+ engine.singleFileName = fileName;
1823
+ engine.allCss.push(fileName);
1824
+ }
1825
+ };
1826
+ }
1827
+ var init_css_post = __esm({
1828
+ "src/plugins/css-post.ts"() {
1829
+ "use strict";
1830
+ init_css_engine();
1831
+ }
1832
+ });
1833
+
1834
+ // src/plugins/assets.ts
1835
+ function assetsPlugin(config) {
1836
+ return {
1837
+ name: "nasti:assets",
1838
+ resolveId(source) {
1839
+ if (source.endsWith("?url") || source.endsWith("?raw")) {
1840
+ return source;
1841
+ }
1842
+ return null;
1843
+ },
1844
+ load(id) {
1845
+ const ext = import_node_path5.default.extname(id.replace(/\?.*$/, ""));
1846
+ if (id.endsWith("?raw")) {
1847
+ const file = id.slice(0, -4);
1848
+ if (import_node_fs3.default.existsSync(file)) {
1849
+ const content = import_node_fs3.default.readFileSync(file, "utf-8");
1850
+ return `export default ${JSON.stringify(content)}`;
1851
+ }
1852
+ }
1853
+ if (id.endsWith("?url") || ASSET_EXTENSIONS.has(ext)) {
1854
+ const file = id.replace(/\?.*$/, "");
1855
+ if (!import_node_fs3.default.existsSync(file)) return null;
1856
+ if (config.command === "serve") {
1857
+ const url = "/" + import_node_path5.default.relative(config.root, file);
1858
+ return `export default ${JSON.stringify(url)}`;
1859
+ }
1860
+ const content = import_node_fs3.default.readFileSync(file);
1861
+ const hash = import_node_crypto.default.createHash("sha256").update(content).digest("hex").slice(0, 8);
1862
+ const basename = import_node_path5.default.basename(file, ext);
1863
+ const hashedName = `${config.build.assetsDir}/${basename}.${hash}${ext}`;
1864
+ return `export default ${JSON.stringify(config.base + hashedName)}`;
1865
+ }
1866
+ return null;
1867
+ }
1868
+ };
1869
+ }
1870
+ var import_node_path5, import_node_fs3, import_node_crypto, ASSET_EXTENSIONS;
1871
+ var init_assets = __esm({
1872
+ "src/plugins/assets.ts"() {
1873
+ "use strict";
1874
+ import_node_path5 = __toESM(require("path"), 1);
1875
+ import_node_fs3 = __toESM(require("fs"), 1);
1876
+ import_node_crypto = __toESM(require("crypto"), 1);
1877
+ ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
1878
+ ".png",
604
1879
  ".jpg",
605
1880
  ".jpeg",
606
1881
  ".gif",
@@ -685,6 +1960,43 @@ function vuePlugin(config) {
685
1960
  }
686
1961
  return null;
687
1962
  },
1963
+ // 虚拟子模块必须有 load 钩子:build 下 Rolldown 否则会按字面路径读盘,
1964
+ // 抛 UNLOADABLE_DEPENDENCY(1.x Vue 生产构建因此直接失败)。
1965
+ // style 子块在这里编译成 CSS 字符串,交给 css 插件统一处理
1966
+ // (dev = <style> 注入 + HMR;build = CssEngine 抽取成 hashed .css)。
1967
+ async load(id) {
1968
+ const match = id.match(/(.+\.vue)\?vue&type=style(?:&index=(\d+))?/);
1969
+ if (!match) return null;
1970
+ const sfc = await loadVueCompiler();
1971
+ if (!sfc) return null;
1972
+ const [, filePath, indexStr] = match;
1973
+ let descriptor = descriptorCache.get(filePath);
1974
+ if (!descriptor) {
1975
+ try {
1976
+ const fs13 = await import("fs");
1977
+ const source = fs13.readFileSync(filePath, "utf-8");
1978
+ const parsed = sfc.parse(source, { filename: filePath });
1979
+ if (parsed.errors.length) return null;
1980
+ descriptor = parsed.descriptor;
1981
+ descriptorCache.set(filePath, descriptor);
1982
+ } catch {
1983
+ return null;
1984
+ }
1985
+ }
1986
+ const index2 = parseInt(indexStr ?? "0", 10);
1987
+ const style = descriptor.styles[index2];
1988
+ if (!style) return null;
1989
+ const scopeId = hashId(filePath);
1990
+ const result = await sfc.compileStyleAsync({
1991
+ source: style.content,
1992
+ filename: filePath,
1993
+ id: `data-v-${scopeId}`,
1994
+ scoped: style.scoped ?? false,
1995
+ // <style lang="scss|less|stylus"> 需经对应预处理器(缺省 undefined = 纯 CSS)
1996
+ preprocessLang: style.lang
1997
+ });
1998
+ return result.code;
1999
+ },
688
2000
  async transform(code, id) {
689
2001
  if (!VUE_FILE_RE.test(id) && !VUE_QUERY_RE.test(id)) return null;
690
2002
  const sfc = await loadVueCompiler();
@@ -693,7 +2005,7 @@ function vuePlugin(config) {
693
2005
  return null;
694
2006
  }
695
2007
  if (VUE_QUERY_RE.test(id)) {
696
- return handleVueSubBlock(id, sfc, descriptorCache, config);
2008
+ return null;
697
2009
  }
698
2010
  const { descriptor, errors } = sfc.parse(code, { filename: id });
699
2011
  if (errors.length) {
@@ -736,10 +2048,8 @@ __sfc__.render = render
736
2048
  }
737
2049
  if (descriptor.styles.length > 0) {
738
2050
  for (let i = 0; i < descriptor.styles.length; i++) {
739
- const style = descriptor.styles[i];
740
- const lang2 = style.lang ?? "css";
741
2051
  output += `
742
- import "${id}?vue&type=style&index=${i}&lang=${lang2}"
2052
+ import "${id}?vue&type=style&index=${i}&lang.css"
743
2053
  `;
744
2054
  }
745
2055
  }
@@ -785,41 +2095,6 @@ export default __sfc__
785
2095
  }
786
2096
  };
787
2097
  }
788
- async function handleVueSubBlock(id, sfc, cache, config) {
789
- const match = id.match(/(.+\.vue)\?vue&type=(\w+)(?:&index=(\d+))?(?:&lang=(\w+))?/);
790
- if (!match) return null;
791
- const [, filePath, type, indexStr, lang] = match;
792
- const descriptor = cache.get(filePath);
793
- if (!descriptor) return null;
794
- if (type === "style") {
795
- const index = parseInt(indexStr ?? "0", 10);
796
- const style = descriptor.styles[index];
797
- if (!style) return null;
798
- const scopeId = hashId(filePath);
799
- const result = await sfc.compileStyleAsync({
800
- source: style.content,
801
- filename: filePath,
802
- id: `data-v-${scopeId}`,
803
- scoped: style.scoped ?? false
804
- });
805
- const cssCode = JSON.stringify(result.code);
806
- return {
807
- code: `
808
- const css = ${cssCode};
809
- const style = document.createElement('style');
810
- style.setAttribute('data-v-${scopeId}', '');
811
- style.textContent = css;
812
- document.head.appendChild(style);
813
-
814
- if (import.meta.hot) {
815
- import.meta.hot.accept();
816
- import.meta.hot.prune(() => style.remove());
817
- }
818
- `
819
- };
820
- }
821
- return null;
822
- }
823
2098
  function hashId(filename) {
824
2099
  return import_node_crypto2.default.createHash("sha256").update(filename).digest("hex").slice(0, 8);
825
2100
  }
@@ -830,7 +2105,7 @@ var init_vue = __esm({
830
2105
  import_node_crypto2 = __toESM(require("crypto"), 1);
831
2106
  init_transformer();
832
2107
  VUE_FILE_RE = /\.vue$/;
833
- VUE_QUERY_RE = /\.vue\?vue&type=(script|template|style)(&index=\d+)?(&lang=\w+)?/;
2108
+ VUE_QUERY_RE = /\.vue\?vue&type=(script|template|style)(&index=\d+)?(&lang[.=]\w+)?/;
834
2109
  compiler = null;
835
2110
  }
836
2111
  });
@@ -918,65 +2193,30 @@ window.__vite_plugin_react_preamble_installed__ = true;
918
2193
  }
919
2194
  });
920
2195
 
921
- // src/core/env.ts
922
- function loadEnv(mode, root, prefixes) {
923
- const envFiles = [
924
- ".env",
925
- `.env.${mode}`,
926
- ".env.local",
927
- `.env.${mode}.local`
2196
+ // src/plugins/builtins.ts
2197
+ function resolvePluginList(config, userPlugins, opts = {}) {
2198
+ const isServe = config.command === "serve";
2199
+ return [
2200
+ // vuePlugin 排最前(enforce: 'pre' 语义):.vue 先编译成 JS 再走后续管道
2201
+ ...config.framework === "vue" ? [vuePlugin(config)] : [],
2202
+ resolvePlugin(config),
2203
+ cssPlugin(config, opts.cssEngine, opts.consumer),
2204
+ assetsPlugin(config),
2205
+ ...isServe ? [htmlPlugin(config)] : [],
2206
+ ...userPlugins,
2207
+ // cssPostPlugin 最后(enforce: 'post' 语义):renderChunk 聚合抽取
2208
+ ...!isServe && opts.cssEngine ? [cssPostPlugin(config, opts.cssEngine)] : []
928
2209
  ];
929
- const raw = {};
930
- for (const file of envFiles) {
931
- const filePath = import_node_path7.default.resolve(root, file);
932
- if (!import_node_fs5.default.existsSync(filePath)) continue;
933
- const content = import_node_fs5.default.readFileSync(filePath, "utf-8");
934
- for (const line of content.split("\n")) {
935
- const trimmed = line.trim();
936
- if (!trimmed || trimmed.startsWith("#")) continue;
937
- const eqIdx = trimmed.indexOf("=");
938
- if (eqIdx === -1) continue;
939
- const key = trimmed.slice(0, eqIdx).trim();
940
- let value = trimmed.slice(eqIdx + 1).trim();
941
- if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
942
- value = value.slice(1, -1);
943
- }
944
- raw[key] = value;
945
- }
946
- }
947
- const filtered = {};
948
- for (const [key, value] of Object.entries(raw)) {
949
- if (prefixes.some((prefix) => key.startsWith(prefix))) {
950
- filtered[key] = value;
951
- }
952
- }
953
- return filtered;
954
- }
955
- function buildEnvDefine(env, mode) {
956
- const define = {};
957
- for (const [key, value] of Object.entries(env)) {
958
- define[`import.meta.env.${key}`] = JSON.stringify(value);
959
- }
960
- define["import.meta.env.MODE"] = JSON.stringify(mode);
961
- define["import.meta.env.DEV"] = mode !== "production" ? "true" : "false";
962
- define["import.meta.env.PROD"] = mode === "production" ? "true" : "false";
963
- define["import.meta.env.SSR"] = "false";
964
- return define;
965
2210
  }
966
- function replaceEnvInCode(code, define) {
967
- let result = code;
968
- for (const [key, value] of Object.entries(define)) {
969
- const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
970
- result = result.replace(new RegExp(escaped, "g"), value);
971
- }
972
- return result;
973
- }
974
- var import_node_path7, import_node_fs5;
975
- var init_env = __esm({
976
- "src/core/env.ts"() {
2211
+ var init_builtins = __esm({
2212
+ "src/plugins/builtins.ts"() {
977
2213
  "use strict";
978
- import_node_path7 = __toESM(require("path"), 1);
979
- import_node_fs5 = __toESM(require("fs"), 1);
2214
+ init_resolve();
2215
+ init_css();
2216
+ init_css_post();
2217
+ init_assets();
2218
+ init_vue();
2219
+ init_html();
980
2220
  }
981
2221
  });
982
2222
 
@@ -1001,8 +2241,11 @@ var init_plugin_container = __esm({
1001
2241
  config;
1002
2242
  ctx;
1003
2243
  emittedFiles = /* @__PURE__ */ new Map();
1004
- constructor(config) {
2244
+ /** Environment API:容器所属环境(未传时为 undefined,行为同 1.x client) */
2245
+ environment;
2246
+ constructor(config, environment) {
1005
2247
  this.config = config;
2248
+ this.environment = environment;
1006
2249
  this.plugins = sortPlugins(config.plugins);
1007
2250
  this.ctx = this.createContext();
1008
2251
  }
@@ -1023,7 +2266,8 @@ var init_plugin_container = __esm({
1023
2266
  },
1024
2267
  getModuleInfo(_id) {
1025
2268
  return null;
1026
- }
2269
+ },
2270
+ environment: container.environment
1027
2271
  };
1028
2272
  }
1029
2273
  /** 返回所有通过 emitFile() 输出的文件 */
@@ -1045,13 +2289,14 @@ var init_plugin_container = __esm({
1045
2289
  }
1046
2290
  }
1047
2291
  async resolveId(source, importer, options = {}) {
2292
+ const ssr = this.environment?.consumer === "server";
1048
2293
  for (const plugin of this.plugins) {
1049
2294
  if (!plugin.resolveId) continue;
1050
2295
  const result = await plugin.resolveId.call(
1051
2296
  this.ctx,
1052
2297
  source,
1053
2298
  importer ?? void 0,
1054
- { isEntry: options.isEntry ?? false, ssr: false }
2299
+ { isEntry: options.isEntry ?? false, ssr }
1055
2300
  );
1056
2301
  if (result != null) return result;
1057
2302
  }
@@ -1084,193 +2329,19 @@ var init_plugin_container = __esm({
1084
2329
  const resolveResult = await this.resolveId(source, importer, {
1085
2330
  isEntry: !importer
1086
2331
  });
1087
- if (resolveResult == null) return null;
1088
- const id = typeof resolveResult === "string" ? resolveResult : resolveResult.id;
1089
- const loadResult = await this.load(id);
1090
- if (loadResult == null) return null;
1091
- const loadedCode = typeof loadResult === "string" ? loadResult : loadResult.code;
1092
- const transformResult = await this.transform(loadedCode, id);
1093
- const finalCode = transformResult == null ? loadedCode : typeof transformResult === "string" ? transformResult : transformResult.code;
1094
- return { id, code: finalCode };
1095
- }
1096
- getPlugins() {
1097
- return this.plugins;
1098
- }
1099
- };
1100
- }
1101
- });
1102
-
1103
- // src/build/index.ts
1104
- var build_exports = {};
1105
- __export(build_exports, {
1106
- build: () => build
1107
- });
1108
- async function build(inlineConfig = {}) {
1109
- const config = await resolveConfig(inlineConfig, "build");
1110
- const startTime = performance.now();
1111
- console.log(import_picocolors.default.cyan("\n\u{1F528} nasti build") + import_picocolors.default.dim(` v${"1.7.1"}`));
1112
- console.log(import_picocolors.default.dim(` root: ${config.root}`));
1113
- console.log(import_picocolors.default.dim(` mode: ${config.mode}`));
1114
- const outDir = import_node_path8.default.resolve(config.root, config.build.outDir);
1115
- if (config.build.emptyOutDir && import_node_fs6.default.existsSync(outDir)) {
1116
- import_node_fs6.default.rmSync(outDir, { recursive: true, force: true });
1117
- }
1118
- import_node_fs6.default.mkdirSync(outDir, { recursive: true });
1119
- const html = await readHtmlFile(config.root);
1120
- let entryPoints = [];
1121
- if (html) {
1122
- const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
1123
- for (const match of scriptMatches) {
1124
- const src = match[1];
1125
- if (src && !src.startsWith("http")) {
1126
- entryPoints.push(import_node_path8.default.resolve(config.root, src.replace(/^\//, "")));
1127
- }
1128
- }
1129
- }
1130
- if (entryPoints.length === 0) {
1131
- const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
1132
- for (const entry of fallbackEntries) {
1133
- const fullPath = import_node_path8.default.resolve(config.root, entry);
1134
- if (import_node_fs6.default.existsSync(fullPath)) {
1135
- entryPoints.push(fullPath);
1136
- break;
1137
- }
1138
- }
1139
- }
1140
- if (entryPoints.length === 0) {
1141
- throw new Error("No entry point found. Add a <script> tag to index.html or create src/main.ts");
1142
- }
1143
- const builtinPlugins = [
1144
- ...config.framework === "vue" ? [vuePlugin(config)] : [],
1145
- resolvePlugin(config),
1146
- cssPlugin(config),
1147
- assetsPlugin(config)
1148
- ];
1149
- const allPlugins = [...builtinPlugins, ...config.plugins];
1150
- const pluginContainer = new PluginContainer(config);
1151
- await pluginContainer.buildStart();
1152
- const oxcTransformPlugin = {
1153
- name: "nasti:oxc-transform",
1154
- transform(code, id) {
1155
- if (!shouldTransform(id)) return null;
1156
- const result = transformCode(id, code, {
1157
- sourcemap: !!config.build.sourcemap,
1158
- jsxRuntime: "automatic",
1159
- jsxImportSource: config.framework === "vue" ? "vue" : "react"
1160
- });
1161
- return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
1162
- }
1163
- };
1164
- const env = loadEnv(config.mode, config.root, config.envPrefix);
1165
- const envDefine = buildEnvDefine(env, config.mode);
1166
- const { output: userOutput, transform: userTransform, ...restInputOptions } = config.build.rolldownOptions;
1167
- const vueDefine = config.framework === "vue" ? {
1168
- __VUE_OPTIONS_API__: "true",
1169
- __VUE_PROD_DEVTOOLS__: "false",
1170
- __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: "false"
1171
- } : {};
1172
- const mergedDefine = { ...vueDefine, ...userTransform?.define ?? {}, ...envDefine };
1173
- const bundle = await (0, import_rolldown.rolldown)({
1174
- ...restInputOptions,
1175
- input: entryPoints,
1176
- transform: { ...userTransform, define: mergedDefine },
1177
- plugins: [
1178
- oxcTransformPlugin,
1179
- // 转换 Nasti 插件为 Rolldown 插件格式
1180
- ...allPlugins.map((p) => ({
1181
- name: p.name,
1182
- resolveId: p.resolveId,
1183
- load: p.load,
1184
- transform: p.transform,
1185
- buildStart: p.buildStart,
1186
- buildEnd: p.buildEnd,
1187
- // Forward `closeBundle` to Rolldown — it invokes the hook during
1188
- // `bundle.close()` below. This is the hook Vite plugins (e.g. PWA
1189
- // manifest/SW writers) rely on for final-stage artifact emission.
1190
- closeBundle: p.closeBundle
1191
- }))
1192
- ]
1193
- });
1194
- const { output } = await bundle.write({
1195
- format: "esm",
1196
- sourcemap: !!config.build.sourcemap,
1197
- minify: !!config.build.minify,
1198
- entryFileNames: "assets/[name].[hash].js",
1199
- chunkFileNames: "assets/[name].[hash].js",
1200
- assetFileNames: "assets/[name].[hash][extname]",
1201
- // 用户可覆盖默认输出:代码拆分(advancedChunks / codeSplitting)、chunk 命名等
1202
- ...userOutput,
1203
- // dir 始终由 Nasti 掌管 —— 下方 HTML 改写依赖固定的产物目录,故放在最后强制生效
1204
- dir: outDir
1205
- });
1206
- await bundle.close();
1207
- await pluginContainer.buildEnd();
1208
- for (const ef of pluginContainer.getEmittedFiles()) {
1209
- const dest = import_node_path8.default.resolve(outDir, ef.fileName);
1210
- import_node_fs6.default.mkdirSync(import_node_path8.default.dirname(dest), { recursive: true });
1211
- import_node_fs6.default.writeFileSync(dest, ef.source);
1212
- }
1213
- if (html) {
1214
- let processedHtml = html;
1215
- const htmlPlugin_ = htmlPlugin(config);
1216
- if (htmlPlugin_.transformIndexHtml) {
1217
- const result = await htmlPlugin_.transformIndexHtml(processedHtml);
1218
- if (typeof result === "string") {
1219
- processedHtml = result;
1220
- } else if (result && "html" in result) {
1221
- processedHtml = processHtml(result.html, result.tags);
1222
- } else if (Array.isArray(result)) {
1223
- processedHtml = processHtml(processedHtml, result);
1224
- }
1225
- }
1226
- for (const chunk of output) {
1227
- if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
1228
- const originalEntry = import_node_path8.default.relative(config.root, chunk.facadeModuleId);
1229
- processedHtml = processedHtml.replace(
1230
- new RegExp(`(src=["'])/?(${escapeRegExp(originalEntry)})(["'])`, "g"),
1231
- `$1${config.base}${chunk.fileName}$3`
1232
- );
1233
- }
1234
- }
1235
- import_node_fs6.default.writeFileSync(import_node_path8.default.resolve(outDir, "index.html"), processedHtml);
1236
- }
1237
- const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
1238
- const totalSize = output.reduce((sum, chunk) => {
1239
- if (chunk.type === "chunk" && chunk.code) return sum + chunk.code.length;
1240
- return sum;
1241
- }, 0);
1242
- console.log(import_picocolors.default.green(`
1243
- \u2713 Built in ${elapsed}s`));
1244
- console.log(import_picocolors.default.dim(` ${output.length} files, ${formatSize(totalSize)} total`));
1245
- console.log(import_picocolors.default.dim(` output: ${config.build.outDir}/
1246
- `));
1247
- return { output };
1248
- }
1249
- function formatSize(bytes) {
1250
- if (bytes < 1024) return `${bytes} B`;
1251
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} kB`;
1252
- return `${(bytes / 1024 / 1024).toFixed(2)} MB`;
1253
- }
1254
- function escapeRegExp(string) {
1255
- return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1256
- }
1257
- var import_node_path8, import_node_fs6, import_rolldown, import_picocolors;
1258
- var init_build = __esm({
1259
- "src/build/index.ts"() {
1260
- "use strict";
1261
- import_node_path8 = __toESM(require("path"), 1);
1262
- import_node_fs6 = __toESM(require("fs"), 1);
1263
- import_rolldown = require("rolldown");
1264
- init_config();
1265
- init_resolve();
1266
- init_css();
1267
- init_assets();
1268
- init_vue();
1269
- init_html();
1270
- init_transformer();
1271
- init_env();
1272
- init_plugin_container();
1273
- import_picocolors = __toESM(require("picocolors"), 1);
2332
+ if (resolveResult == null) return null;
2333
+ const id = typeof resolveResult === "string" ? resolveResult : resolveResult.id;
2334
+ const loadResult = await this.load(id);
2335
+ if (loadResult == null) return null;
2336
+ const loadedCode = typeof loadResult === "string" ? loadResult : loadResult.code;
2337
+ const transformResult = await this.transform(loadedCode, id);
2338
+ const finalCode = transformResult == null ? loadedCode : typeof transformResult === "string" ? transformResult : transformResult.code;
2339
+ return { id, code: finalCode };
2340
+ }
2341
+ getPlugins() {
2342
+ return this.plugins;
2343
+ }
2344
+ };
1274
2345
  }
1275
2346
  });
1276
2347
 
@@ -1395,7 +2466,580 @@ var init_module_graph = __esm({
1395
2466
  }
1396
2467
  return boundaries;
1397
2468
  }
1398
- };
2469
+ };
2470
+ }
2471
+ });
2472
+
2473
+ // src/core/hot-channel.ts
2474
+ function createNoopHotChannel() {
2475
+ return {
2476
+ send() {
2477
+ },
2478
+ on() {
2479
+ },
2480
+ off() {
2481
+ },
2482
+ listen() {
2483
+ },
2484
+ close() {
2485
+ },
2486
+ setInvokeHandler() {
2487
+ }
2488
+ };
2489
+ }
2490
+ function createWsHotChannel(ws) {
2491
+ const listeners = /* @__PURE__ */ new Map();
2492
+ let invokeHandlers;
2493
+ return {
2494
+ send(payload) {
2495
+ ws.send(payload);
2496
+ },
2497
+ on(event, listener) {
2498
+ let set = listeners.get(event);
2499
+ if (!set) listeners.set(event, set = /* @__PURE__ */ new Set());
2500
+ set.add(listener);
2501
+ },
2502
+ off(event, listener) {
2503
+ listeners.get(event)?.delete(listener);
2504
+ },
2505
+ listen() {
2506
+ },
2507
+ close() {
2508
+ ws.close();
2509
+ },
2510
+ setInvokeHandler(handlers) {
2511
+ invokeHandlers = handlers;
2512
+ void invokeHandlers;
2513
+ }
2514
+ };
2515
+ }
2516
+ var init_hot_channel = __esm({
2517
+ "src/core/hot-channel.ts"() {
2518
+ "use strict";
2519
+ }
2520
+ });
2521
+
2522
+ // src/core/environment.ts
2523
+ function resolveEnvironmentPlugins(environment, plugins) {
2524
+ return plugins.filter((p) => {
2525
+ if (!p.applyToEnvironment) return true;
2526
+ try {
2527
+ return p.applyToEnvironment(environment);
2528
+ } catch (err) {
2529
+ environment.config.logger.error(
2530
+ `[nasti] plugin "${p.name}" applyToEnvironment threw: ${err.message}`,
2531
+ { error: err }
2532
+ );
2533
+ return false;
2534
+ }
2535
+ });
2536
+ }
2537
+ var debug2, NastiEnvironment;
2538
+ var init_environment = __esm({
2539
+ "src/core/environment.ts"() {
2540
+ "use strict";
2541
+ init_plugin_container();
2542
+ init_module_graph();
2543
+ init_hot_channel();
2544
+ init_debug();
2545
+ debug2 = createDebugger("nasti:environment");
2546
+ NastiEnvironment = class {
2547
+ name;
2548
+ consumer;
2549
+ mode;
2550
+ config;
2551
+ options;
2552
+ hot;
2553
+ /** applyToEnvironment 过滤后的插件(init() 后可用) */
2554
+ plugins = [];
2555
+ /** per-env 插件容器(init() 后可用;dev 管线使用) */
2556
+ pluginContainer = null;
2557
+ /** per-env 模块图(dev 管线使用) */
2558
+ moduleGraph;
2559
+ candidatePlugins;
2560
+ initialized = false;
2561
+ constructor(name, config, init = {}) {
2562
+ const options = config.environments[name];
2563
+ if (!options) {
2564
+ throw new Error(
2565
+ `[nasti] unknown environment "${name}" \u2014 declare it in config.environments`
2566
+ );
2567
+ }
2568
+ this.name = name;
2569
+ this.consumer = options.consumer;
2570
+ this.mode = init.mode ?? (config.command === "build" ? "build" : "dev");
2571
+ this.config = config;
2572
+ this.options = options;
2573
+ this.hot = init.hot ?? createNoopHotChannel();
2574
+ this.moduleGraph = new ModuleGraph();
2575
+ this.candidatePlugins = init.plugins ?? config.plugins;
2576
+ }
2577
+ /** 过滤插件并建 per-env PluginContainer */
2578
+ async init() {
2579
+ if (this.initialized) return;
2580
+ this.initialized = true;
2581
+ this.plugins = resolveEnvironmentPlugins(this, this.candidatePlugins);
2582
+ this.pluginContainer = new PluginContainer(
2583
+ { ...this.config, plugins: this.plugins },
2584
+ this
2585
+ );
2586
+ debug2?.(`env "${this.name}" initialized (${this.plugins.length} plugins)`);
2587
+ }
2588
+ async close() {
2589
+ await this.hot.close?.();
2590
+ }
2591
+ };
2592
+ }
2593
+ });
2594
+
2595
+ // src/core/env.ts
2596
+ function loadEnv(mode, root, prefixes) {
2597
+ const envFiles = [
2598
+ ".env",
2599
+ `.env.${mode}`,
2600
+ ".env.local",
2601
+ `.env.${mode}.local`
2602
+ ];
2603
+ const raw = {};
2604
+ for (const file of envFiles) {
2605
+ const filePath = import_node_path7.default.resolve(root, file);
2606
+ if (!import_node_fs5.default.existsSync(filePath)) continue;
2607
+ const content = import_node_fs5.default.readFileSync(filePath, "utf-8");
2608
+ for (const line of content.split("\n")) {
2609
+ const trimmed = line.trim();
2610
+ if (!trimmed || trimmed.startsWith("#")) continue;
2611
+ const eqIdx = trimmed.indexOf("=");
2612
+ if (eqIdx === -1) continue;
2613
+ const key = trimmed.slice(0, eqIdx).trim();
2614
+ let value = trimmed.slice(eqIdx + 1).trim();
2615
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
2616
+ value = value.slice(1, -1);
2617
+ }
2618
+ raw[key] = value;
2619
+ }
2620
+ }
2621
+ const filtered = {};
2622
+ for (const [key, value] of Object.entries(raw)) {
2623
+ if (prefixes.some((prefix) => key.startsWith(prefix))) {
2624
+ filtered[key] = value;
2625
+ }
2626
+ }
2627
+ return filtered;
2628
+ }
2629
+ function buildEnvDefine(env, mode, overrides = {}) {
2630
+ const define = {};
2631
+ for (const [key, value] of Object.entries(env)) {
2632
+ define[`import.meta.env.${key}`] = JSON.stringify(value);
2633
+ }
2634
+ define["import.meta.env.MODE"] = JSON.stringify(mode);
2635
+ define["import.meta.env.DEV"] = mode !== "production" ? "true" : "false";
2636
+ define["import.meta.env.PROD"] = mode === "production" ? "true" : "false";
2637
+ define["import.meta.env.SSR"] = "false";
2638
+ return { ...define, ...overrides };
2639
+ }
2640
+ function ssrDefineOverrides(consumer) {
2641
+ return { "import.meta.env.SSR": consumer === "server" ? "true" : "false" };
2642
+ }
2643
+ function replaceEnvInCode(code, define) {
2644
+ let result = code;
2645
+ for (const [key, value] of Object.entries(define)) {
2646
+ const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2647
+ result = result.replace(new RegExp(escaped, "g"), value);
2648
+ }
2649
+ return result;
2650
+ }
2651
+ var import_node_path7, import_node_fs5;
2652
+ var init_env = __esm({
2653
+ "src/core/env.ts"() {
2654
+ "use strict";
2655
+ import_node_path7 = __toESM(require("path"), 1);
2656
+ import_node_fs5 = __toESM(require("fs"), 1);
2657
+ }
2658
+ });
2659
+
2660
+ // src/build/reporter.ts
2661
+ async function tryNativeReporterPlugin(config, logger) {
2662
+ try {
2663
+ const { viteReporterPlugin } = await import("rolldown/experimental");
2664
+ if (typeof viteReporterPlugin !== "function") return null;
2665
+ return viteReporterPlugin({
2666
+ root: config.root,
2667
+ isTty: process.stdout.isTTY ?? false,
2668
+ isLib: false,
2669
+ assetsDir: config.build.assetsDir,
2670
+ chunkLimit: config.build.chunkSizeWarningLimit,
2671
+ // 大 chunk 警告由 JS 侧 warnLargeChunks() 经 logger.warn 输出,
2672
+ // 原生侧只产 info 级表格,避免警告被 logLevel 过滤吞掉
2673
+ warnLargeChunks: false,
2674
+ reportCompressedSize: config.build.reportCompressedSize,
2675
+ logInfo: (msg) => logger.info(msg)
2676
+ });
2677
+ } catch (err) {
2678
+ debug3?.(`native viteReporterPlugin unavailable, falling back to JS table: ${err}`);
2679
+ return null;
2680
+ }
2681
+ }
2682
+ function displaySize(bytes) {
2683
+ return `${numberFormatter.format(bytes / 1e3)} kB`;
2684
+ }
2685
+ function byteLength(content) {
2686
+ if (content == null) return 0;
2687
+ return typeof content === "string" ? Buffer.byteLength(content) : content.byteLength;
2688
+ }
2689
+ function reportBuildOutput(output, config, logger) {
2690
+ const entries = [];
2691
+ const compressed = config.build.reportCompressedSize;
2692
+ for (const file of output) {
2693
+ const content = file.type === "chunk" ? file.code : file.source;
2694
+ const size = byteLength(content);
2695
+ let gzip = null;
2696
+ if (compressed && content != null) {
2697
+ gzip = (0, import_node_zlib.gzipSync)(typeof content === "string" ? Buffer.from(content) : content).byteLength;
2698
+ }
2699
+ const ext = import_node_path8.default.extname(file.fileName);
2700
+ const group = file.type === "chunk" ? "js" : ext === ".css" ? "css" : "assets";
2701
+ entries.push({ name: file.fileName, size, gzip, group });
2702
+ }
2703
+ const groupOrder = { assets: 0, css: 1, js: 2 };
2704
+ entries.sort((a, b) => groupOrder[a.group] - groupOrder[b.group] || a.size - b.size);
2705
+ const outDirPrefix = `${config.build.outDir.replace(/\/$/, "")}/`;
2706
+ const maxNameLen = Math.max(...entries.map((e) => (outDirPrefix + e.name).length), 0);
2707
+ const maxSizeLen = Math.max(...entries.map((e) => displaySize(e.size).length), 0);
2708
+ const groupColor = { assets: import_picocolors3.default.green, css: import_picocolors3.default.magenta, js: import_picocolors3.default.cyan };
2709
+ for (const e of entries) {
2710
+ const color = groupColor[e.group];
2711
+ const namePart = import_picocolors3.default.dim(outDirPrefix) + color(e.name.padEnd(maxNameLen - outDirPrefix.length));
2712
+ const sizePart = import_picocolors3.default.dim(import_picocolors3.default.bold(displaySize(e.size).padStart(maxSizeLen)));
2713
+ const gzipPart = e.gzip != null ? import_picocolors3.default.dim(` \u2502 gzip: ${displaySize(e.gzip)}`) : "";
2714
+ logger.info(`${namePart} ${sizePart}${gzipPart}`);
2715
+ }
2716
+ }
2717
+ function warnLargeChunks(output, config, logger) {
2718
+ const limit = config.build.chunkSizeWarningLimit;
2719
+ const large = output.filter(
2720
+ (f) => f.type === "chunk" && byteLength(f.code) / 1e3 > limit
2721
+ );
2722
+ if (large.length === 0) return;
2723
+ logger.warn(
2724
+ import_picocolors3.default.yellow(
2725
+ `
2726
+ (!) Some chunks are larger than ${limit} kB after minification. Consider:
2727
+ - Using dynamic import() to code-split the application
2728
+ - Configuring build.rolldownOptions.output.advancedChunks to isolate large dependencies
2729
+ - Adjusting build.chunkSizeWarningLimit to silence this warning`
2730
+ )
2731
+ );
2732
+ }
2733
+ var import_node_path8, import_node_zlib, import_picocolors3, debug3, numberFormatter;
2734
+ var init_reporter = __esm({
2735
+ "src/build/reporter.ts"() {
2736
+ "use strict";
2737
+ import_node_path8 = __toESM(require("path"), 1);
2738
+ import_node_zlib = require("zlib");
2739
+ import_picocolors3 = __toESM(require("picocolors"), 1);
2740
+ init_debug();
2741
+ debug3 = createDebugger("nasti:reporter");
2742
+ numberFormatter = new Intl.NumberFormat("en", {
2743
+ maximumFractionDigits: 2,
2744
+ minimumFractionDigits: 2
2745
+ });
2746
+ }
2747
+ });
2748
+
2749
+ // src/build/index.ts
2750
+ var build_exports = {};
2751
+ __export(build_exports, {
2752
+ build: () => build,
2753
+ getRolldownOptions: () => getRolldownOptions,
2754
+ resolveClientEntries: () => resolveClientEntries,
2755
+ toRolldownPlugins: () => toRolldownPlugins
2756
+ });
2757
+ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
2758
+ const config = environment.config;
2759
+ const envOptions = environment.options;
2760
+ const isServer = environment.consumer === "server";
2761
+ const outDir = import_node_path9.default.resolve(config.root, envOptions.build.outDir);
2762
+ const assetsDir = envOptions.build.assetsDir;
2763
+ const { output: userOutput, transform: userTransform, ...restInputOptions } = envOptions.build.rolldownOptions;
2764
+ const vueDefine = config.framework === "vue" ? {
2765
+ __VUE_OPTIONS_API__: "true",
2766
+ __VUE_PROD_DEVTOOLS__: "false",
2767
+ __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: "false"
2768
+ } : {};
2769
+ const env = loadEnv(config.mode, config.root, config.envPrefix);
2770
+ const envDefine = buildEnvDefine(env, config.mode, ssrDefineOverrides(environment.consumer));
2771
+ const mergedDefine = { ...vueDefine, ...userTransform?.define ?? {}, ...envDefine };
2772
+ const inputOptions = {
2773
+ ...restInputOptions,
2774
+ input: entryPoints,
2775
+ transform: { ...userTransform, define: mergedDefine },
2776
+ plugins: rolldownPlugins,
2777
+ ...isServer ? {
2778
+ platform: restInputOptions.platform ?? "node",
2779
+ resolve: {
2780
+ conditionNames: envOptions.resolve.conditions,
2781
+ mainFields: envOptions.resolve.mainFields,
2782
+ ...restInputOptions.resolve
2783
+ },
2784
+ // server 产物:node 内建恒外部化;bare specifier 默认外部化
2785
+ //(同 Vite ssr.external 默认 —— 依赖由 node_modules 运行时解析),
2786
+ // 相对/绝对/虚拟模块照常打包。需要内联依赖时经 rolldownOptions.external 覆盖。
2787
+ external: restInputOptions.external ?? ((id) => {
2788
+ if (NODE_BUILTINS.has(id)) return true;
2789
+ return !id.startsWith(".") && !import_node_path9.default.isAbsolute(id) && !id.startsWith("\0");
2790
+ })
2791
+ } : {}
2792
+ };
2793
+ const outputOptions = isServer ? {
2794
+ format: "esm",
2795
+ sourcemap: !!envOptions.build.sourcemap,
2796
+ minify: !!envOptions.build.minify,
2797
+ entryFileNames: "[name].js",
2798
+ chunkFileNames: "chunks/[name]-[hash].js",
2799
+ assetFileNames: `${assetsDir}/[name].[hash][extname]`,
2800
+ ...userOutput,
2801
+ dir: outDir
2802
+ } : {
2803
+ format: "esm",
2804
+ sourcemap: !!envOptions.build.sourcemap,
2805
+ minify: !!envOptions.build.minify,
2806
+ entryFileNames: `${assetsDir}/[name].[hash].js`,
2807
+ chunkFileNames: `${assetsDir}/[name].[hash].js`,
2808
+ assetFileNames: `${assetsDir}/[name].[hash][extname]`,
2809
+ // 用户可覆盖默认输出:代码拆分(advancedChunks / codeSplitting)、chunk 命名等
2810
+ ...userOutput,
2811
+ // dir 始终由 Nasti 掌管 —— HTML 改写依赖固定的产物目录,故放在最后强制生效
2812
+ dir: outDir
2813
+ };
2814
+ return { inputOptions, outputOptions, outDir };
2815
+ }
2816
+ function toRolldownPlugins(plugins) {
2817
+ return plugins.map((p) => ({
2818
+ name: p.name,
2819
+ resolveId: p.resolveId,
2820
+ load: p.load,
2821
+ transform: p.transform,
2822
+ buildStart: p.buildStart,
2823
+ buildEnd: p.buildEnd,
2824
+ // closeBundle 在 bundle.close() 时触发 —— PWA manifest/SW 等终态产物依赖
2825
+ closeBundle: p.closeBundle,
2826
+ renderChunk: p.renderChunk,
2827
+ augmentChunkHash: p.augmentChunkHash,
2828
+ generateBundle: p.generateBundle
2829
+ }));
2830
+ }
2831
+ function resolveClientEntries(config, html) {
2832
+ const entryPoints = [];
2833
+ if (html) {
2834
+ const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
2835
+ for (const match of scriptMatches) {
2836
+ const src = match[1];
2837
+ if (src && !src.startsWith("http")) {
2838
+ entryPoints.push(import_node_path9.default.resolve(config.root, src.replace(/^\//, "")));
2839
+ }
2840
+ }
2841
+ }
2842
+ if (entryPoints.length === 0) {
2843
+ const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
2844
+ for (const entry of fallbackEntries) {
2845
+ const fullPath = import_node_path9.default.resolve(config.root, entry);
2846
+ if (import_node_fs6.default.existsSync(fullPath)) {
2847
+ entryPoints.push(fullPath);
2848
+ break;
2849
+ }
2850
+ }
2851
+ }
2852
+ return entryPoints;
2853
+ }
2854
+ function createOxcTransformPlugin(config, environment) {
2855
+ return {
2856
+ name: "nasti:oxc-transform",
2857
+ transform(code, id) {
2858
+ if (!shouldTransform(id)) return null;
2859
+ const result = transformCode(id, code, {
2860
+ sourcemap: !!environment.options.build.sourcemap,
2861
+ jsxRuntime: "automatic",
2862
+ jsxImportSource: config.framework === "vue" ? "vue" : "react"
2863
+ });
2864
+ return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
2865
+ }
2866
+ };
2867
+ }
2868
+ async function build(inlineConfig = {}) {
2869
+ const config = await resolveConfig(inlineConfig, "build");
2870
+ const logger = config.logger;
2871
+ const startTime = performance.now();
2872
+ logger.info(
2873
+ import_picocolors4.default.cyan(`
2874
+ nasti v${"2.0.0"} `) + import_picocolors4.default.green(`building for ${config.mode}...`)
2875
+ );
2876
+ debug4?.(`root: ${config.root}`);
2877
+ const buildableNames = Object.keys(config.environments).filter(
2878
+ (name) => name === "client" || config.environments[name].entry.length > 0
2879
+ );
2880
+ buildableNames.sort((a, b) => a === "client" ? -1 : b === "client" ? 1 : 0);
2881
+ const environments = {};
2882
+ let clientOutput = [];
2883
+ for (const name of buildableNames) {
2884
+ const output = name === "client" ? await buildClientEnvironment(config) : await buildServerEnvironment(config, name);
2885
+ environments[name] = output;
2886
+ if (name === "client") clientOutput = output;
2887
+ if (buildableNames.length > 1) {
2888
+ debug4?.(`environment "${name}" built (${output.length} files)`);
2889
+ }
2890
+ }
2891
+ const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
2892
+ const totalSize = Object.values(environments).flat().reduce((sum, chunk) => {
2893
+ const content = chunk.type === "chunk" ? chunk.code : chunk.source;
2894
+ if (content == null) return sum;
2895
+ return sum + (typeof content === "string" ? Buffer.byteLength(content) : content.byteLength);
2896
+ }, 0);
2897
+ const fileCount = Object.values(environments).flat().length;
2898
+ const envSuffix = buildableNames.length > 1 ? ` (${buildableNames.join(" + ")})` : "";
2899
+ logger.info(import_picocolors4.default.green(`\u2713 built in ${elapsed}s`) + import_picocolors4.default.dim(envSuffix));
2900
+ logger.info(import_picocolors4.default.dim(` ${fileCount} files, ${displaySize(totalSize)} total \u2192 ${config.build.outDir}/`));
2901
+ return { output: clientOutput, environments };
2902
+ }
2903
+ async function buildClientEnvironment(config) {
2904
+ const logger = config.logger;
2905
+ const outDir = import_node_path9.default.resolve(config.root, config.build.outDir);
2906
+ if (config.build.emptyOutDir && import_node_fs6.default.existsSync(outDir)) {
2907
+ import_node_fs6.default.rmSync(outDir, { recursive: true, force: true });
2908
+ }
2909
+ import_node_fs6.default.mkdirSync(outDir, { recursive: true });
2910
+ const html = await readHtmlFile(config.root);
2911
+ const entryPoints = resolveClientEntries(config, html);
2912
+ if (entryPoints.length === 0) {
2913
+ throw new Error("No entry point found. Add a <script> tag to index.html or create src/main.ts");
2914
+ }
2915
+ const cssEngine = createCssEngine();
2916
+ const pluginList = resolvePluginList(config, config.plugins, { cssEngine });
2917
+ const clientEnv = new NastiEnvironment("client", { ...config, plugins: pluginList }, {
2918
+ mode: "build",
2919
+ plugins: pluginList
2920
+ });
2921
+ await clientEnv.init();
2922
+ const allPlugins = clientEnv.plugins;
2923
+ const nativeReporter = config.logLevel === "silent" ? null : await tryNativeReporterPlugin(config, logger);
2924
+ const rolldownPlugins = [
2925
+ createOxcTransformPlugin(config, clientEnv),
2926
+ ...toRolldownPlugins(allPlugins),
2927
+ ...nativeReporter ? [nativeReporter] : []
2928
+ ];
2929
+ const { inputOptions, outputOptions } = getRolldownOptions(clientEnv, entryPoints, rolldownPlugins);
2930
+ const bundle2 = await (0, import_rolldown.rolldown)(inputOptions);
2931
+ const { output } = await bundle2.write(outputOptions);
2932
+ await bundle2.close();
2933
+ if (html) {
2934
+ let processedHtml = html;
2935
+ const htmlPlugins = [...allPlugins.filter((p) => p.transformIndexHtml), htmlPlugin(config)];
2936
+ for (const p of htmlPlugins) {
2937
+ const result = await p.transformIndexHtml(processedHtml);
2938
+ if (typeof result === "string") {
2939
+ processedHtml = result;
2940
+ } else if (result && "html" in result) {
2941
+ processedHtml = processHtml(result.html, result.tags);
2942
+ } else if (Array.isArray(result)) {
2943
+ processedHtml = processHtml(processedHtml, result);
2944
+ }
2945
+ }
2946
+ processedHtml = injectCssLinks(processedHtml, cssEngine, config);
2947
+ for (const chunk of output) {
2948
+ if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
2949
+ const originalEntry = import_node_path9.default.relative(config.root, chunk.facadeModuleId);
2950
+ processedHtml = processedHtml.replace(
2951
+ new RegExp(`(src=["'])/?(${escapeRegExp(originalEntry)})(["'])`, "g"),
2952
+ `$1${config.base}${chunk.fileName}$3`
2953
+ );
2954
+ }
2955
+ }
2956
+ import_node_fs6.default.writeFileSync(import_node_path9.default.resolve(outDir, "index.html"), processedHtml);
2957
+ }
2958
+ if (!nativeReporter && config.logLevel !== "silent") {
2959
+ reportBuildOutput(output, config, logger);
2960
+ }
2961
+ warnLargeChunks(output, config, logger);
2962
+ return output;
2963
+ }
2964
+ async function buildServerEnvironment(config, name) {
2965
+ const envOptions = config.environments[name];
2966
+ const logger = config.logger;
2967
+ for (const entry of envOptions.entry) {
2968
+ if (!import_node_fs6.default.existsSync(entry)) {
2969
+ throw new Error(`[nasti] environment "${name}" entry not found: ${entry}`);
2970
+ }
2971
+ }
2972
+ const pluginList = resolvePluginList(config, config.plugins, { consumer: envOptions.consumer });
2973
+ const environment = new NastiEnvironment(name, { ...config, plugins: pluginList }, {
2974
+ mode: "build",
2975
+ plugins: pluginList
2976
+ });
2977
+ await environment.init();
2978
+ const rolldownPlugins = [
2979
+ createOxcTransformPlugin(config, environment),
2980
+ ...toRolldownPlugins(environment.plugins)
2981
+ ];
2982
+ const { inputOptions, outputOptions, outDir } = getRolldownOptions(
2983
+ environment,
2984
+ envOptions.entry,
2985
+ rolldownPlugins
2986
+ );
2987
+ if (envOptions.build.emptyOutDir && import_node_fs6.default.existsSync(outDir)) {
2988
+ import_node_fs6.default.rmSync(outDir, { recursive: true, force: true });
2989
+ }
2990
+ import_node_fs6.default.mkdirSync(outDir, { recursive: true });
2991
+ const bundle2 = await (0, import_rolldown.rolldown)(inputOptions);
2992
+ const { output } = await bundle2.write(outputOptions);
2993
+ await bundle2.close();
2994
+ logger.info(
2995
+ import_picocolors4.default.dim(` [${name}] `) + output.map((o) => import_node_path9.default.join(envOptions.build.outDir, o.fileName)).join(import_picocolors4.default.dim(", "))
2996
+ );
2997
+ return output;
2998
+ }
2999
+ function injectCssLinks(html, cssEngine, config) {
3000
+ const cssLinkTags = [];
3001
+ if (cssEngine.singleFileName) {
3002
+ cssLinkTags.push({
3003
+ tag: "link",
3004
+ attrs: { rel: "stylesheet", href: config.base + cssEngine.singleFileName },
3005
+ injectTo: "head"
3006
+ });
3007
+ } else {
3008
+ for (const files of cssEngine.entryCss.values()) {
3009
+ for (const file of files) {
3010
+ cssLinkTags.push({
3011
+ tag: "link",
3012
+ attrs: { rel: "stylesheet", href: config.base + file },
3013
+ injectTo: "head"
3014
+ });
3015
+ }
3016
+ }
3017
+ }
3018
+ return cssLinkTags.length > 0 ? processHtml(html, cssLinkTags) : html;
3019
+ }
3020
+ function escapeRegExp(string) {
3021
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3022
+ }
3023
+ var import_node_path9, import_node_fs6, import_node_module3, import_rolldown, import_picocolors4, debug4, NODE_BUILTINS;
3024
+ var init_build = __esm({
3025
+ "src/build/index.ts"() {
3026
+ "use strict";
3027
+ import_node_path9 = __toESM(require("path"), 1);
3028
+ import_node_fs6 = __toESM(require("fs"), 1);
3029
+ import_node_module3 = require("module");
3030
+ import_rolldown = require("rolldown");
3031
+ init_config();
3032
+ init_builtins();
3033
+ init_environment();
3034
+ init_css_engine();
3035
+ init_html();
3036
+ init_transformer();
3037
+ init_env();
3038
+ init_reporter();
3039
+ init_debug();
3040
+ import_picocolors4 = __toESM(require("picocolors"), 1);
3041
+ debug4 = createDebugger("nasti:build");
3042
+ NODE_BUILTINS = /* @__PURE__ */ new Set([...import_node_module3.builtinModules, ...import_node_module3.builtinModules.map((m) => `node:${m}`)]);
1399
3043
  }
1400
3044
  });
1401
3045
 
@@ -1448,6 +3092,7 @@ var init_ws = __esm({
1448
3092
  var middleware_exports = {};
1449
3093
  __export(middleware_exports, {
1450
3094
  REACT_REFRESH_GLOBAL_PREAMBLE: () => REACT_REFRESH_GLOBAL_PREAMBLE,
3095
+ getReactRefreshRuntimeEsm: () => getReactRefreshRuntimeEsm,
1451
3096
  transformMiddleware: () => transformMiddleware,
1452
3097
  transformRequest: () => transformRequest
1453
3098
  });
@@ -1456,9 +3101,9 @@ function getReactRefreshRuntimeEsm() {
1456
3101
  let cjsPath;
1457
3102
  try {
1458
3103
  const pkgPath = __require.resolve("react-refresh/package.json");
1459
- cjsPath = import_node_path10.default.join(import_node_path10.default.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
3104
+ cjsPath = import_node_path11.default.join(import_node_path11.default.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
1460
3105
  } catch (err) {
1461
- cjsPath = import_node_path10.default.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
3106
+ cjsPath = import_node_path11.default.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
1462
3107
  if (!import_node_fs8.default.existsSync(cjsPath)) {
1463
3108
  const origMsg = err instanceof Error ? err.message : String(err);
1464
3109
  throw new Error(
@@ -1586,7 +3231,11 @@ function transformMiddleware(ctx) {
1586
3231
  return;
1587
3232
  }
1588
3233
  } catch (err) {
1589
- console.error(`[nasti] Transform error: ${url}`, err.message);
3234
+ ctx.config.logger.error(
3235
+ import_picocolors6.default.red(`Transform error: ${url}
3236
+ `) + (err.stack ?? err.message),
3237
+ { timestamp: true, error: err }
3238
+ );
1590
3239
  res.statusCode = 500;
1591
3240
  res.end(`Transform error: ${err.message}`);
1592
3241
  return;
@@ -1615,6 +3264,28 @@ async function transformRequest(url, ctx) {
1615
3264
  return virtual.result;
1616
3265
  }
1617
3266
  }
3267
+ const rawQuery = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
3268
+ if (rawQuery && !/^t=\d+$/.test(rawQuery)) {
3269
+ const loaded = await pluginContainer.load(url);
3270
+ if (loaded != null) {
3271
+ let code2 = typeof loaded === "string" ? loaded : loaded.code;
3272
+ const transformed = await pluginContainer.transform(code2, url);
3273
+ if (transformed != null) {
3274
+ code2 = typeof transformed === "string" ? transformed : transformed.code;
3275
+ }
3276
+ const mod2 = await moduleGraph.ensureEntryFromUrl(url);
3277
+ moduleGraph.registerModule(mod2, cleanReqUrl);
3278
+ code2 = injectImportMetaHot(code2, url);
3279
+ code2 = replaceEnvInCode(code2, ctx.envDefine ?? buildEnvDefine(
3280
+ loadEnv(config.mode, config.root, config.envPrefix),
3281
+ config.mode
3282
+ ));
3283
+ code2 = rewriteImports(code2, config, cleanReqUrl);
3284
+ const transformResult2 = { code: code2 };
3285
+ mod2.transformResult = transformResult2;
3286
+ return transformResult2;
3287
+ }
3288
+ }
1618
3289
  const filePath = resolveUrlToFile(url, config.root);
1619
3290
  if (!filePath || !import_node_fs8.default.existsSync(filePath)) return null;
1620
3291
  const mod = await moduleGraph.ensureEntryFromUrl(url);
@@ -1679,7 +3350,7 @@ async function loadVirtualModule(spec, ctx) {
1679
3350
  loadEnv(config.mode, config.root, config.envPrefix),
1680
3351
  config.mode
1681
3352
  ));
1682
- const anchor = import_node_path10.default.join(config.root, "__nasti_virtual__.ts");
3353
+ const anchor = import_node_path11.default.join(config.root, "__nasti_virtual__.ts");
1683
3354
  code = rewriteImports(code, config, anchor);
1684
3355
  return { id: resolvedId, result: { code } };
1685
3356
  }
@@ -1693,7 +3364,7 @@ async function doBundlePackage(entryFile) {
1693
3364
  const shim = await tryGenerateSubpathShim(entryFile);
1694
3365
  if (shim != null) return shim;
1695
3366
  const { rolldown: rolldown4 } = await import("rolldown");
1696
- const bundle = await rolldown4({
3367
+ const bundle2 = await rolldown4({
1697
3368
  input: entryFile,
1698
3369
  // 仅将其他 npm 包外部化;相对路径(包内部文件)全部内联打包
1699
3370
  external: (id) => {
@@ -1701,8 +3372,8 @@ async function doBundlePackage(entryFile) {
1701
3372
  return true;
1702
3373
  }
1703
3374
  });
1704
- const result = await bundle.generate({ format: "esm", exports: "named" });
1705
- await bundle.close();
3375
+ const result = await bundle2.generate({ format: "esm", exports: "named" });
3376
+ await bundle2.close();
1706
3377
  let code = result.output[0].code;
1707
3378
  code = code.replace(/process\.env\.NODE_ENV/g, '"development"');
1708
3379
  code = code.replace(
@@ -1722,13 +3393,13 @@ async function doBundlePackage(entryFile) {
1722
3393
  return code;
1723
3394
  }
1724
3395
  async function tryGenerateSubpathShim(entryFile) {
1725
- const NM = `${import_node_path10.default.sep}node_modules${import_node_path10.default.sep}`;
3396
+ const NM = `${import_node_path11.default.sep}node_modules${import_node_path11.default.sep}`;
1726
3397
  if (!entryFile.includes(NM)) return null;
1727
3398
  let pkgDir = null;
1728
3399
  let pkgName = null;
1729
- let dir = import_node_path10.default.dirname(entryFile);
3400
+ let dir = import_node_path11.default.dirname(entryFile);
1730
3401
  while (true) {
1731
- const pkgJsonPath = import_node_path10.default.join(dir, "package.json");
3402
+ const pkgJsonPath = import_node_path11.default.join(dir, "package.json");
1732
3403
  if (import_node_fs8.default.existsSync(pkgJsonPath)) {
1733
3404
  try {
1734
3405
  const pkg = JSON.parse(import_node_fs8.default.readFileSync(pkgJsonPath, "utf-8"));
@@ -1740,16 +3411,16 @@ async function tryGenerateSubpathShim(entryFile) {
1740
3411
  } catch {
1741
3412
  }
1742
3413
  }
1743
- const parent = import_node_path10.default.dirname(dir);
3414
+ const parent = import_node_path11.default.dirname(dir);
1744
3415
  if (parent === dir) return null;
1745
3416
  dir = parent;
1746
3417
  if (!dir.includes(NM)) return null;
1747
3418
  }
1748
3419
  if (!pkgDir || !pkgName) return null;
1749
- const entryExt = import_node_path10.default.extname(entryFile);
3420
+ const entryExt = import_node_path11.default.extname(entryFile);
1750
3421
  const mainEntry = pickMainEntryByExtension(pkgDir, entryExt);
1751
3422
  if (!mainEntry) return null;
1752
- if (import_node_path10.default.resolve(mainEntry) === import_node_path10.default.resolve(entryFile)) return null;
3423
+ if (import_node_path11.default.resolve(mainEntry) === import_node_path11.default.resolve(entryFile)) return null;
1753
3424
  let mainNs;
1754
3425
  let subNs;
1755
3426
  try {
@@ -1785,7 +3456,7 @@ async function tryGenerateSubpathShim(entryFile) {
1785
3456
  return lines.join("\n") + "\n";
1786
3457
  }
1787
3458
  function pickMainEntryByExtension(pkgDir, preferredExt) {
1788
- const pkgJsonPath = import_node_path10.default.join(pkgDir, "package.json");
3459
+ const pkgJsonPath = import_node_path11.default.join(pkgDir, "package.json");
1789
3460
  let pkg;
1790
3461
  try {
1791
3462
  pkg = JSON.parse(import_node_fs8.default.readFileSync(pkgJsonPath, "utf-8"));
@@ -1807,13 +3478,13 @@ function pickMainEntryByExtension(pkgDir, preferredExt) {
1807
3478
  if (typeof pkg.module === "string") candidates.push(pkg.module);
1808
3479
  if (typeof pkg.main === "string") candidates.push(pkg.main);
1809
3480
  for (const cand of candidates) {
1810
- if (import_node_path10.default.extname(cand) === preferredExt) {
1811
- const full = import_node_path10.default.resolve(pkgDir, cand);
3481
+ if (import_node_path11.default.extname(cand) === preferredExt) {
3482
+ const full = import_node_path11.default.resolve(pkgDir, cand);
1812
3483
  if (import_node_fs8.default.existsSync(full)) return full;
1813
3484
  }
1814
3485
  }
1815
3486
  for (const cand of candidates) {
1816
- const full = import_node_path10.default.resolve(pkgDir, cand);
3487
+ const full = import_node_path11.default.resolve(pkgDir, cand);
1817
3488
  if (import_node_fs8.default.existsSync(full)) return full;
1818
3489
  }
1819
3490
  return null;
@@ -1839,8 +3510,8 @@ function rewriteExternalRequires(code) {
1839
3510
  }
1840
3511
  async function injectCjsNamedExports(code, entryFile) {
1841
3512
  try {
1842
- const { createRequire: createRequire6 } = await import("module");
1843
- const req = createRequire6(entryFile);
3513
+ const { createRequire: createRequire7 } = await import("module");
3514
+ const req = createRequire7(entryFile);
1844
3515
  const cjsExports = req(entryFile);
1845
3516
  if (!cjsExports || typeof cjsExports !== "object" && typeof cjsExports !== "function" || Array.isArray(cjsExports)) return code;
1846
3517
  const namedKeys = Object.keys(cjsExports).filter(
@@ -1862,11 +3533,11 @@ async function injectCjsNamedExports(code, entryFile) {
1862
3533
  }
1863
3534
  function rewriteImports(code, config, filePath) {
1864
3535
  const root = config.root;
1865
- const fileDir = import_node_path10.default.dirname(filePath);
3536
+ const fileDir = import_node_path11.default.dirname(filePath);
1866
3537
  const aliasEntries = Object.entries(config.resolve.alias).sort(
1867
3538
  ([a], [b]) => b.length - a.length
1868
3539
  );
1869
- const toRootUrl = (abs) => "/" + import_node_path10.default.relative(root, abs).replace(/\\/g, "/");
3540
+ const toRootUrl = (abs) => "/" + import_node_path11.default.relative(root, abs).replace(/\\/g, "/");
1870
3541
  const transformSpec = (spec) => {
1871
3542
  const suffixMatch = spec.match(/[?#].*$/);
1872
3543
  const suffix = suffixMatch ? suffixMatch[0] : "";
@@ -1875,18 +3546,18 @@ function rewriteImports(code, config, filePath) {
1875
3546
  if (baseSpec === key || baseSpec.startsWith(key + "/")) {
1876
3547
  const aliasBase = resolveAliasTarget2(value, root);
1877
3548
  const sub = baseSpec.slice(key.length).replace(/^\//, "");
1878
- const target = sub ? import_node_path10.default.join(aliasBase, sub) : aliasBase;
3549
+ const target = sub ? import_node_path11.default.join(aliasBase, sub) : aliasBase;
1879
3550
  const resolved = tryResolveDiskPath(target);
1880
3551
  return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
1881
3552
  }
1882
3553
  }
1883
3554
  if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
1884
- const target = import_node_path10.default.resolve(fileDir, baseSpec);
3555
+ const target = import_node_path11.default.resolve(fileDir, baseSpec);
1885
3556
  const resolved = tryResolveDiskPath(target);
1886
3557
  return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
1887
3558
  }
1888
3559
  if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
1889
- const target = import_node_path10.default.join(root, baseSpec.replace(/^\//, ""));
3560
+ const target = import_node_path11.default.join(root, baseSpec.replace(/^\//, ""));
1890
3561
  const resolved = tryResolveDiskPath(target);
1891
3562
  return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
1892
3563
  }
@@ -1905,9 +3576,9 @@ function rewriteImports(code, config, filePath) {
1905
3576
  );
1906
3577
  }
1907
3578
  function resolveAliasTarget2(value, root) {
1908
- if (import_node_path10.default.isAbsolute(value) && import_node_fs8.default.existsSync(value)) return value;
1909
- if (value.startsWith("/")) return import_node_path10.default.join(root, value.slice(1));
1910
- return import_node_path10.default.resolve(root, value);
3579
+ if (import_node_path11.default.isAbsolute(value) && import_node_fs8.default.existsSync(value)) return value;
3580
+ if (value.startsWith("/")) return import_node_path11.default.join(root, value.slice(1));
3581
+ return import_node_path11.default.resolve(root, value);
1911
3582
  }
1912
3583
  function tryResolveDiskPath(target) {
1913
3584
  if (import_node_fs8.default.existsSync(target) && import_node_fs8.default.statSync(target).isFile()) return target;
@@ -1917,15 +3588,15 @@ function tryResolveDiskPath(target) {
1917
3588
  }
1918
3589
  if (import_node_fs8.default.existsSync(target) && import_node_fs8.default.statSync(target).isDirectory()) {
1919
3590
  for (const ext of RESOLVE_EXTENSIONS) {
1920
- const idx = import_node_path10.default.join(target, "index" + ext);
3591
+ const idx = import_node_path11.default.join(target, "index" + ext);
1921
3592
  if (import_node_fs8.default.existsSync(idx) && import_node_fs8.default.statSync(idx).isFile()) return idx;
1922
3593
  }
1923
3594
  }
1924
3595
  return null;
1925
3596
  }
1926
3597
  function isUnderRoot(abs, root) {
1927
- const rel = import_node_path10.default.relative(root, abs);
1928
- return !!rel && !rel.startsWith("..") && !import_node_path10.default.isAbsolute(rel);
3598
+ const rel = import_node_path11.default.relative(root, abs);
3599
+ return !!rel && !rel.startsWith("..") && !import_node_path11.default.isAbsolute(rel);
1929
3600
  }
1930
3601
  function resolveNodeModule(root, moduleName) {
1931
3602
  let pkgName;
@@ -1942,17 +3613,17 @@ function resolveNodeModule(root, moduleName) {
1942
3613
  let pkgDir = null;
1943
3614
  let dir = root;
1944
3615
  for (; ; ) {
1945
- const candidate = import_node_path10.default.join(dir, "node_modules", pkgName);
3616
+ const candidate = import_node_path11.default.join(dir, "node_modules", pkgName);
1946
3617
  if (import_node_fs8.default.existsSync(candidate)) {
1947
3618
  pkgDir = candidate;
1948
3619
  break;
1949
3620
  }
1950
- const parent = import_node_path10.default.dirname(dir);
3621
+ const parent = import_node_path11.default.dirname(dir);
1951
3622
  if (parent === dir) break;
1952
3623
  dir = parent;
1953
3624
  }
1954
3625
  if (!pkgDir) return null;
1955
- const pkgJsonPath = import_node_path10.default.join(pkgDir, "package.json");
3626
+ const pkgJsonPath = import_node_path11.default.join(pkgDir, "package.json");
1956
3627
  if (!import_node_fs8.default.existsSync(pkgJsonPath)) return null;
1957
3628
  let pkg;
1958
3629
  try {
@@ -1969,12 +3640,12 @@ function resolveNodeModule(root, moduleName) {
1969
3640
  const subDirs = [""];
1970
3641
  for (const field of ["module", "main"]) {
1971
3642
  if (typeof pkg[field] === "string") {
1972
- const dir2 = import_node_path10.default.dirname(pkg[field]);
3643
+ const dir2 = import_node_path11.default.dirname(pkg[field]);
1973
3644
  if (dir2 && dir2 !== "." && !subDirs.includes(dir2)) subDirs.push(dir2);
1974
3645
  }
1975
3646
  }
1976
3647
  for (const dir2 of subDirs) {
1977
- const direct = import_node_path10.default.join(pkgDir, dir2, subpath);
3648
+ const direct = import_node_path11.default.join(pkgDir, dir2, subpath);
1978
3649
  if (import_node_fs8.default.existsSync(direct) && import_node_fs8.default.statSync(direct).isFile()) return direct;
1979
3650
  for (const ext of RESOLVE_EXTENSIONS) {
1980
3651
  if (import_node_fs8.default.existsSync(direct + ext)) return direct + ext;
@@ -1984,24 +3655,24 @@ function resolveNodeModule(root, moduleName) {
1984
3655
  }
1985
3656
  for (const field of ["module", "jsnext:main", "jsnext", "main"]) {
1986
3657
  if (typeof pkg[field] === "string") {
1987
- const entry = import_node_path10.default.join(pkgDir, pkg[field]);
3658
+ const entry = import_node_path11.default.join(pkgDir, pkg[field]);
1988
3659
  if (import_node_fs8.default.existsSync(entry)) return entry;
1989
3660
  }
1990
3661
  }
1991
- const indexFallback = import_node_path10.default.join(pkgDir, "index.js");
3662
+ const indexFallback = import_node_path11.default.join(pkgDir, "index.js");
1992
3663
  if (import_node_fs8.default.existsSync(indexFallback)) return indexFallback;
1993
3664
  return null;
1994
3665
  }
1995
3666
  function resolvePackageExports(exports2, key, pkgDir) {
1996
3667
  if (typeof exports2 === "string") {
1997
- return key === "." ? import_node_path10.default.join(pkgDir, exports2) : null;
3668
+ return key === "." ? import_node_path11.default.join(pkgDir, exports2) : null;
1998
3669
  }
1999
3670
  const entry = exports2[key];
2000
3671
  if (entry === void 0) return null;
2001
3672
  return resolveExportValue(entry, pkgDir);
2002
3673
  }
2003
3674
  function resolveExportValue(value, pkgDir) {
2004
- if (typeof value === "string") return import_node_path10.default.join(pkgDir, value);
3675
+ if (typeof value === "string") return import_node_path11.default.join(pkgDir, value);
2005
3676
  if (Array.isArray(value)) {
2006
3677
  for (const item of value) {
2007
3678
  const r = resolveExportValue(item, pkgDir);
@@ -2025,7 +3696,7 @@ function resolveUrlToFile(url, root) {
2025
3696
  const moduleName = cleanUrl.slice("/@modules/".length);
2026
3697
  return resolveNodeModule(root, moduleName);
2027
3698
  }
2028
- const filePath = import_node_path10.default.resolve(root, cleanUrl.replace(/^\//, ""));
3699
+ const filePath = import_node_path11.default.resolve(root, cleanUrl.replace(/^\//, ""));
2029
3700
  if (import_node_fs8.default.existsSync(filePath) && import_node_fs8.default.statSync(filePath).isFile()) {
2030
3701
  return filePath;
2031
3702
  }
@@ -2034,7 +3705,7 @@ function resolveUrlToFile(url, root) {
2034
3705
  if (import_node_fs8.default.existsSync(withExt)) return withExt;
2035
3706
  }
2036
3707
  for (const ext of RESOLVE_EXTENSIONS) {
2037
- const indexFile = import_node_path10.default.join(filePath, "index" + ext);
3708
+ const indexFile = import_node_path11.default.join(filePath, "index" + ext);
2038
3709
  if (import_node_fs8.default.existsSync(indexFile)) return indexFile;
2039
3710
  }
2040
3711
  return null;
@@ -2043,7 +3714,7 @@ function isModuleRequest(url) {
2043
3714
  const cleanUrl = url.split("?")[0];
2044
3715
  if (/\.(ts|tsx|jsx|js|mjs|vue|css|json)$/.test(cleanUrl)) return true;
2045
3716
  if (cleanUrl.startsWith("/@modules/")) return true;
2046
- if (!import_node_path10.default.extname(cleanUrl)) return true;
3717
+ if (!import_node_path11.default.extname(cleanUrl)) return true;
2047
3718
  return false;
2048
3719
  }
2049
3720
  function getHmrClientCode() {
@@ -2174,20 +3845,21 @@ export function createHotContext(ownerPath) {
2174
3845
  }
2175
3846
  `;
2176
3847
  }
2177
- var import_node_path10, import_node_fs8, import_node_module4, import_node_url3, import_meta, __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
3848
+ var import_node_path11, import_node_fs8, import_node_module5, import_node_url3, import_picocolors6, import_meta, __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
2178
3849
  var init_middleware = __esm({
2179
3850
  "src/server/middleware.ts"() {
2180
3851
  "use strict";
2181
- import_node_path10 = __toESM(require("path"), 1);
3852
+ import_node_path11 = __toESM(require("path"), 1);
2182
3853
  import_node_fs8 = __toESM(require("fs"), 1);
2183
- import_node_module4 = require("module");
3854
+ import_node_module5 = require("module");
2184
3855
  import_node_url3 = require("url");
3856
+ import_picocolors6 = __toESM(require("picocolors"), 1);
2185
3857
  init_transformer();
2186
3858
  init_html();
2187
3859
  init_env();
2188
3860
  import_meta = {};
2189
- __dirname_esm = import_node_path10.default.dirname((0, import_node_url3.fileURLToPath)(import_meta.url));
2190
- __require = (0, import_node_module4.createRequire)(import_meta.url);
3861
+ __dirname_esm = import_node_path11.default.dirname((0, import_node_url3.fileURLToPath)(import_meta.url));
3862
+ __require = (0, import_node_module5.createRequire)(import_meta.url);
2191
3863
  __refreshRuntimeCache = null;
2192
3864
  REACT_REFRESH_GLOBAL_PREAMBLE = `
2193
3865
  import RefreshRuntime from "/@react-refresh";
@@ -2206,7 +3878,9 @@ window.__vite_plugin_react_preamble_installed__ = true;
2206
3878
  // src/server/hmr.ts
2207
3879
  async function handleFileChange(file, server) {
2208
3880
  const { moduleGraph, ws, config } = server;
2209
- const relativePath = "/" + import_node_path11.default.relative(config.root, file);
3881
+ const logger = config.logger;
3882
+ const relativePath = "/" + import_node_path12.default.relative(config.root, file);
3883
+ const shortFile = import_node_path12.default.relative(config.root, file);
2210
3884
  const mods = moduleGraph.getModulesByFile(file);
2211
3885
  if (!mods || mods.size === 0) {
2212
3886
  return;
@@ -2234,6 +3908,7 @@ async function handleFileChange(file, server) {
2234
3908
  for (const affected of affectedModules) {
2235
3909
  const boundaries = moduleGraph.getHmrBoundaries(affected);
2236
3910
  if (boundaries.length === 0) {
3911
+ logger.info(import_picocolors7.default.green("page reload ") + import_picocolors7.default.dim(shortFile), { timestamp: true });
2237
3912
  ws.send({ type: "full-reload", path: relativePath });
2238
3913
  return;
2239
3914
  }
@@ -2248,15 +3923,679 @@ async function handleFileChange(file, server) {
2248
3923
  }
2249
3924
  }
2250
3925
  if (updates.length > 0) {
3926
+ logger.info(
3927
+ updates.map((u) => import_picocolors7.default.green("hmr update ") + import_picocolors7.default.dim(u.path)).join("\n"),
3928
+ { timestamp: true }
3929
+ );
2251
3930
  ws.send({ type: "update", updates });
2252
3931
  }
2253
3932
  }
2254
- var import_node_path11, import_node_fs9;
3933
+ var import_node_path12, import_node_fs9, import_picocolors7;
2255
3934
  var init_hmr = __esm({
2256
3935
  "src/server/hmr.ts"() {
2257
3936
  "use strict";
2258
- import_node_path11 = __toESM(require("path"), 1);
3937
+ import_node_path12 = __toESM(require("path"), 1);
2259
3938
  import_node_fs9 = __toESM(require("fs"), 1);
3939
+ import_picocolors7 = __toESM(require("picocolors"), 1);
3940
+ }
3941
+ });
3942
+
3943
+ // src/server/runnable-environment.ts
3944
+ var runnable_environment_exports = {};
3945
+ __export(runnable_environment_exports, {
3946
+ NastiModuleRunner: () => NastiModuleRunner,
3947
+ createModuleRunner: () => createModuleRunner
3948
+ });
3949
+ function createModuleRunner(environment) {
3950
+ if (environment.consumer !== "server") {
3951
+ throw new Error(
3952
+ `[nasti] module runner requires a server-consumer environment (got "${environment.name}" / ${environment.consumer})`
3953
+ );
3954
+ }
3955
+ return new NastiModuleRunner(environment);
3956
+ }
3957
+ var import_node_path13, import_node_fs10, import_node_module6, import_node_url4, debug5, NODE_BUILTINS3, NastiModuleRunner, AsyncFunction;
3958
+ var init_runnable_environment = __esm({
3959
+ "src/server/runnable-environment.ts"() {
3960
+ "use strict";
3961
+ import_node_path13 = __toESM(require("path"), 1);
3962
+ import_node_fs10 = __toESM(require("fs"), 1);
3963
+ import_node_module6 = require("module");
3964
+ import_node_url4 = require("url");
3965
+ init_transformer();
3966
+ init_env();
3967
+ init_debug();
3968
+ debug5 = createDebugger("nasti:ssr");
3969
+ NODE_BUILTINS3 = /* @__PURE__ */ new Set([...import_node_module6.builtinModules, ...import_node_module6.builtinModules.map((m) => `node:${m}`)]);
3970
+ NastiModuleRunner = class {
3971
+ environment;
3972
+ config;
3973
+ cache = /* @__PURE__ */ new Map();
3974
+ envDefine;
3975
+ require;
3976
+ constructor(environment) {
3977
+ this.environment = environment;
3978
+ this.config = environment.config;
3979
+ this.envDefine = buildEnvDefine(
3980
+ loadEnv(this.config.mode, this.config.root, this.config.envPrefix),
3981
+ this.config.mode,
3982
+ ssrDefineOverrides(environment.consumer)
3983
+ );
3984
+ this.require = (0, import_node_module6.createRequire)(import_node_path13.default.join(this.config.root, "package.json"));
3985
+ const handlers = {
3986
+ fetchModule: async (id, importer) => this.fetchModule(id, importer),
3987
+ getBuiltins: () => [/^node:/, ...import_node_module6.builtinModules]
3988
+ };
3989
+ environment.hot.setInvokeHandler?.(handlers);
3990
+ }
3991
+ /** 入口:加载并执行一个模块(url 为根相对或绝对路径) */
3992
+ async import(rawUrl) {
3993
+ const id = this.resolveToId(rawUrl);
3994
+ return this.instantiate(id);
3995
+ }
3996
+ /** 文件变更时按文件失效(含其所属的虚拟子模块) */
3997
+ invalidateFile(file) {
3998
+ for (const key of [...this.cache.keys()]) {
3999
+ if (key === file || key.startsWith(file + "?")) {
4000
+ this.cache.delete(key);
4001
+ }
4002
+ }
4003
+ }
4004
+ invalidateAll() {
4005
+ this.cache.clear();
4006
+ }
4007
+ resolveToId(rawUrl) {
4008
+ if (import_node_path13.default.isAbsolute(rawUrl) && import_node_fs10.default.existsSync(rawUrl.split("?")[0])) return rawUrl;
4009
+ const clean = rawUrl.replace(/^\//, "");
4010
+ return import_node_path13.default.resolve(this.config.root, clean);
4011
+ }
4012
+ /**
4013
+ * fetchModule(invoke 契约方法):环境管线产出 runner 可执行代码。
4014
+ * resolve(插件 resolveId → 文件系统)→ load/读盘 → 插件 transform →
4015
+ * oxc(TS/JSX)→ moduleRunnerTransform。
4016
+ */
4017
+ async fetchModule(id, importer) {
4018
+ if (NODE_BUILTINS3.has(id)) return { externalize: id };
4019
+ if (!id.startsWith(".") && !import_node_path13.default.isAbsolute(id) && !id.startsWith("\0")) {
4020
+ return { externalize: id };
4021
+ }
4022
+ const container = this.environment.pluginContainer;
4023
+ let resolvedId = id;
4024
+ if (id.startsWith(".") && importer) {
4025
+ const resolved = await container.resolveId(id, importer);
4026
+ resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id : import_node_path13.default.resolve(import_node_path13.default.dirname(importer.split("?")[0]), id);
4027
+ }
4028
+ resolvedId = this.completeExtension(resolvedId);
4029
+ const cleanId = resolvedId.split("?")[0];
4030
+ let code;
4031
+ const loaded = await container.load(resolvedId);
4032
+ if (loaded != null) {
4033
+ code = typeof loaded === "string" ? loaded : loaded.code;
4034
+ } else if (import_node_fs10.default.existsSync(cleanId)) {
4035
+ code = import_node_fs10.default.readFileSync(cleanId, "utf-8");
4036
+ } else {
4037
+ throw new Error(`[nasti:ssr] cannot load module: ${resolvedId}`);
4038
+ }
4039
+ const transformed = await container.transform(code, resolvedId);
4040
+ if (transformed != null) {
4041
+ code = typeof transformed === "string" ? transformed : transformed.code;
4042
+ }
4043
+ if (shouldTransform(cleanId)) {
4044
+ const result = transformCode(cleanId, code, {
4045
+ sourcemap: false,
4046
+ jsxRuntime: "automatic",
4047
+ jsxImportSource: this.config.framework === "vue" ? "vue" : "react"
4048
+ });
4049
+ code = result.code;
4050
+ }
4051
+ code = replaceEnvInCode(code, this.envDefine);
4052
+ let moduleRunnerTransform;
4053
+ try {
4054
+ ;
4055
+ ({ moduleRunnerTransform } = await import("rolldown/experimental"));
4056
+ } catch (err) {
4057
+ throw new Error(
4058
+ `[nasti:ssr] rolldown/experimental moduleRunnerTransform unavailable (installed rolldown incompatible?): ${err.message}`
4059
+ );
4060
+ }
4061
+ const runnerResult = await moduleRunnerTransform(resolvedId, code);
4062
+ debug5?.(`fetchModule ${resolvedId} (${runnerResult.deps?.length ?? 0} deps)`);
4063
+ return { id: resolvedId, code: runnerResult.code };
4064
+ }
4065
+ completeExtension(id) {
4066
+ const clean = id.split("?")[0];
4067
+ const query = id.includes("?") ? id.slice(id.indexOf("?")) : "";
4068
+ if (import_node_fs10.default.existsSync(clean) && import_node_fs10.default.statSync(clean).isFile()) return id;
4069
+ const jsMatch = clean.match(/^(.*)\.([mc]?)jsx?$/);
4070
+ if (jsMatch) {
4071
+ for (const tsExt of [`.${jsMatch[2]}ts`, `.${jsMatch[2]}tsx`]) {
4072
+ if (import_node_fs10.default.existsSync(jsMatch[1] + tsExt)) return jsMatch[1] + tsExt + query;
4073
+ }
4074
+ }
4075
+ for (const ext of this.config.resolve.extensions) {
4076
+ if (import_node_fs10.default.existsSync(clean + ext)) return clean + ext + query;
4077
+ }
4078
+ for (const ext of this.config.resolve.extensions) {
4079
+ const indexPath = import_node_path13.default.join(clean, `index${ext}`);
4080
+ if (import_node_fs10.default.existsSync(indexPath)) return indexPath;
4081
+ }
4082
+ return id;
4083
+ }
4084
+ async instantiate(id) {
4085
+ const cached2 = this.cache.get(id);
4086
+ if (cached2) return cached2.promise ?? Promise.resolve(cached2.exports);
4087
+ const entry = { exports: {}, promise: null };
4088
+ this.cache.set(id, entry);
4089
+ entry.promise = this.evaluate(id, entry).then(() => {
4090
+ entry.promise = null;
4091
+ return entry.exports;
4092
+ }).catch((err) => {
4093
+ this.cache.delete(id);
4094
+ throw err;
4095
+ });
4096
+ return entry.promise;
4097
+ }
4098
+ async evaluate(id, entry) {
4099
+ const fetched = await this.fetchModule(id);
4100
+ if ("externalize" in fetched) {
4101
+ const spec = fetched.externalize;
4102
+ const mod = await this.importExternal(spec);
4103
+ entry.exports = mod;
4104
+ return;
4105
+ }
4106
+ const ssrImport = async (dep) => {
4107
+ if (NODE_BUILTINS3.has(dep) || !dep.startsWith(".") && !import_node_path13.default.isAbsolute(dep) && !dep.startsWith("\0")) {
4108
+ return this.importExternal(dep);
4109
+ }
4110
+ const depId = dep.startsWith(".") ? this.completeExtension(import_node_path13.default.resolve(import_node_path13.default.dirname(fetched.id.split("?")[0]), dep)) : this.completeExtension(dep);
4111
+ return this.instantiate(depId);
4112
+ };
4113
+ const ssrExportAll = (sourceModule) => {
4114
+ for (const key of Object.keys(sourceModule)) {
4115
+ if (key !== "default" && !(key in entry.exports)) {
4116
+ Object.defineProperty(entry.exports, key, {
4117
+ enumerable: true,
4118
+ configurable: true,
4119
+ get: () => sourceModule[key]
4120
+ });
4121
+ }
4122
+ }
4123
+ };
4124
+ const importMeta = {
4125
+ url: (0, import_node_url4.pathToFileURL)(fetched.id.split("?")[0]).href,
4126
+ env: { SSR: true, MODE: this.config.mode, DEV: this.config.mode !== "production", PROD: this.config.mode === "production" },
4127
+ hot: void 0
4128
+ };
4129
+ const fn = new AsyncFunction(
4130
+ "__vite_ssr_exports__",
4131
+ "__vite_ssr_import__",
4132
+ "__vite_ssr_dynamic_import__",
4133
+ "__vite_ssr_exportAll__",
4134
+ "__vite_ssr_import_meta__",
4135
+ `"use strict";${fetched.code}
4136
+ //# sourceURL=${fetched.id}`
4137
+ );
4138
+ await fn(entry.exports, ssrImport, ssrImport, ssrExportAll, importMeta);
4139
+ }
4140
+ async importExternal(spec) {
4141
+ try {
4142
+ return await (spec.startsWith("node:") || !import_node_path13.default.isAbsolute(spec) ? import(this.resolveExternalSpecifier(spec)) : import((0, import_node_url4.pathToFileURL)(spec).href));
4143
+ } catch (err) {
4144
+ throw new Error(`[nasti:ssr] failed to import external "${spec}": ${err.message}`);
4145
+ }
4146
+ }
4147
+ /** bare specifier → 项目 node_modules 的绝对 URL(避免相对 Nasti 自身解析) */
4148
+ resolveExternalSpecifier(spec) {
4149
+ if (spec.startsWith("node:")) return spec;
4150
+ if (NODE_BUILTINS3.has(spec)) return `node:${spec}`;
4151
+ try {
4152
+ return (0, import_node_url4.pathToFileURL)(this.require.resolve(spec)).href;
4153
+ } catch {
4154
+ return spec;
4155
+ }
4156
+ }
4157
+ };
4158
+ AsyncFunction = Object.getPrototypeOf(async function() {
4159
+ }).constructor;
4160
+ }
4161
+ });
4162
+
4163
+ // src/server/bundled/dev-engine.ts
4164
+ var dev_engine_exports = {};
4165
+ __export(dev_engine_exports, {
4166
+ createBundledDevServer: () => createBundledDevServer
4167
+ });
4168
+ async function createBundledDevServer(opts) {
4169
+ const { config, clientEnv, httpServer } = opts;
4170
+ const logger = config.logger;
4171
+ let devFn;
4172
+ let refreshWrapperFn = null;
4173
+ try {
4174
+ const experimental = await import("rolldown/experimental");
4175
+ devFn = experimental.dev;
4176
+ if (typeof devFn !== "function") throw new Error("dev() export missing");
4177
+ if (typeof experimental.viteReactRefreshWrapperPlugin === "function") {
4178
+ refreshWrapperFn = experimental.viteReactRefreshWrapperPlugin;
4179
+ }
4180
+ } catch (err) {
4181
+ throw new Error(
4182
+ `[nasti] experimental.bundledDev requires rolldown's experimental dev() API (locked to the installed rc; got: ${err.message}). Remove --bundle / experimental.bundledDev to use the default unbundled dev server.`
4183
+ );
4184
+ }
4185
+ const html = await readHtmlFile(config.root);
4186
+ const entryPoints = resolveClientEntries(config, html);
4187
+ if (entryPoints.length === 0) {
4188
+ throw new Error("No entry point found. Add a <script> tag to index.html or create src/main.ts");
4189
+ }
4190
+ const memoryFiles = new MemoryFiles();
4191
+ const patches = new MemoryFiles();
4192
+ const entryFileNames = /* @__PURE__ */ new Map();
4193
+ const bundledClients = /* @__PURE__ */ new Map();
4194
+ const useReactRefresh = config.framework !== "vue" && refreshWrapperFn != null;
4195
+ const rolldownPlugins = [
4196
+ ...useReactRefresh ? [
4197
+ createReactRefreshRuntimePlugin(entryPoints),
4198
+ createBundledOxcRefreshPlugin()
4199
+ ] : [],
4200
+ ...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins)),
4201
+ ...useReactRefresh ? [
4202
+ refreshWrapperFn({
4203
+ cwd: config.root,
4204
+ include: [/\.[jt]sx(\?.*)?$/],
4205
+ exclude: [/node_modules/],
4206
+ jsxImportSource: "react",
4207
+ reactRefreshHost: ""
4208
+ })
4209
+ ] : []
4210
+ ];
4211
+ const { inputOptions, outputOptions } = getRolldownOptions(clientEnv, entryPoints, rolldownPlugins);
4212
+ let fullReloadTimer = null;
4213
+ const scheduleFullReload = () => {
4214
+ if (fullReloadTimer) clearTimeout(fullReloadTimer);
4215
+ fullReloadTimer = setTimeout(() => {
4216
+ logger.info(import_picocolors8.default.green("page reload ") + import_picocolors8.default.dim("(bundled)"), { timestamp: true });
4217
+ broadcast({ type: "hmr:reload" });
4218
+ }, 30);
4219
+ };
4220
+ const broadcast = (payload) => {
4221
+ const data = JSON.stringify(payload);
4222
+ for (const ws of bundledClients.values()) {
4223
+ if (ws.readyState === 1) ws.send(data);
4224
+ }
4225
+ };
4226
+ const sendTo = (clientId, payload) => {
4227
+ const ws = bundledClients.get(clientId);
4228
+ if (ws && ws.readyState === 1) ws.send(JSON.stringify(payload));
4229
+ };
4230
+ async function processUpdates(updates, changedFiles) {
4231
+ let needsLatestOutput = false;
4232
+ for (const { clientId, update } of updates) {
4233
+ if (update.type === "Noop") continue;
4234
+ if (update.type === "FullReload") {
4235
+ debug6?.(`full reload for ${clientId}: ${update.reason ?? ""}`);
4236
+ needsLatestOutput = true;
4237
+ continue;
4238
+ }
4239
+ const patchPath = `__nasti_patch/${update.filename}`;
4240
+ patches.set(patchPath, update.code + "\n;export {}");
4241
+ if (update.sourcemap && update.sourcemapFilename) {
4242
+ patches.set(`__nasti_patch/${update.sourcemapFilename}`, update.sourcemap);
4243
+ }
4244
+ const url = `/${patchPath}`;
4245
+ logger.info(
4246
+ import_picocolors8.default.green("hmr update ") + import_picocolors8.default.dim(changedFiles.map((f) => import_node_path14.default.relative(config.root, f)).join(", ")),
4247
+ { timestamp: true }
4248
+ );
4249
+ sendTo(clientId, { type: "hmr:update", path: url, url });
4250
+ }
4251
+ if (needsLatestOutput) {
4252
+ await engine.ensureLatestBuildOutput();
4253
+ scheduleFullReload();
4254
+ }
4255
+ }
4256
+ const engine = await devFn(
4257
+ {
4258
+ ...inputOptions,
4259
+ cwd: config.root,
4260
+ // Rolldown bug 规避:inlineConst 与 dev patch 机制冲突(vitejs/vite#21843)
4261
+ optimization: { ...inputOptions.optimization, inlineConst: false },
4262
+ experimental: {
4263
+ ...inputOptions.experimental,
4264
+ devMode: {
4265
+ lazy: true,
4266
+ // 默认 DevRuntime 把 ws 地址烤进 bundle:指向 Nasti dev server 本身
4267
+ //(端口被占自动 +1 时 HMR ws 会失联 —— 已知限制,产物仍可服务)
4268
+ host: config.server.host === true ? "localhost" : config.server.host || "localhost",
4269
+ port: config.server.port
4270
+ }
4271
+ }
4272
+ },
4273
+ {
4274
+ ...outputOptions,
4275
+ entryFileNames: "assets/[name].js",
4276
+ chunkFileNames: "assets/[name]-[hash].js",
4277
+ minify: false,
4278
+ sourcemap: true
4279
+ },
4280
+ {
4281
+ watch: { skipWrite: true },
4282
+ rebuildStrategy: "auto",
4283
+ onOutput(result) {
4284
+ if (result instanceof Error) {
4285
+ logger.error(import_picocolors8.default.red(`[bundled] build error: ${result.message}`), { error: result });
4286
+ return;
4287
+ }
4288
+ for (const file of result.output) {
4289
+ const content = file.type === "chunk" ? file.code : file.source;
4290
+ if (content != null) memoryFiles.set(file.fileName, content);
4291
+ if (file.type === "chunk" && file.isEntry && file.facadeModuleId) {
4292
+ entryFileNames.set(file.facadeModuleId, file.fileName);
4293
+ }
4294
+ if (file.type === "chunk" && file.map) {
4295
+ memoryFiles.set(`${file.fileName}.map`, JSON.stringify(file.map));
4296
+ }
4297
+ }
4298
+ debug6?.(`bundle output refreshed (${result.output.length} files)`);
4299
+ },
4300
+ async onHmrUpdates(result) {
4301
+ if (result instanceof Error) {
4302
+ logger.error(import_picocolors8.default.red(`[bundled] hmr error: ${result.message}`), { error: result });
4303
+ broadcast({ type: "error", err: { message: result.message, stack: result.stack } });
4304
+ return;
4305
+ }
4306
+ const { updates, changedFiles } = result;
4307
+ debug6?.(
4308
+ `onHmrUpdates(engine watcher): ${changedFiles.length} changed, ${updates.length} updates`
4309
+ );
4310
+ if (changedFiles.length === 0) return;
4311
+ await processUpdates(updates, changedFiles);
4312
+ }
4313
+ }
4314
+ );
4315
+ await engine.run();
4316
+ await engine.ensureCurrentBuildFinish();
4317
+ logger.info(import_picocolors8.default.dim(` bundled dev engine ready (${entryPoints.length} entries, in-memory)`));
4318
+ const wss = new import_ws2.WebSocketServer({ noServer: true });
4319
+ httpServer.on("upgrade", (req, socket, head) => {
4320
+ if (req.headers["sec-websocket-protocol"] === "nasti-hmr") return;
4321
+ const url = new URL(req.url ?? "/", "http://localhost");
4322
+ const clientId = url.searchParams.get("clientId");
4323
+ if (!clientId) return;
4324
+ wss.handleUpgrade(req, socket, head, (ws) => {
4325
+ bundledClients.set(clientId, ws);
4326
+ debug6?.(`bundled client connected: ${clientId}`);
4327
+ ws.send(JSON.stringify({ type: "connected" }));
4328
+ ws.on("message", async (raw) => {
4329
+ try {
4330
+ const msg = JSON.parse(String(raw));
4331
+ if (msg.type === "hmr:module-registered" && Array.isArray(msg.modules)) {
4332
+ await engine.registerModules(clientId, msg.modules);
4333
+ debug6?.(`registered ${msg.modules.length} modules for ${clientId}`);
4334
+ } else if (msg.type === "hmr:invalidate") {
4335
+ scheduleFullReload();
4336
+ }
4337
+ } catch (err) {
4338
+ debug6?.(`bundled ws message error: ${err.message}`);
4339
+ }
4340
+ });
4341
+ ws.on("close", () => {
4342
+ bundledClients.delete(clientId);
4343
+ engine.removeClient(clientId).catch((err) => debug6?.(`removeClient failed for ${clientId}: ${err?.message ?? err}`));
4344
+ });
4345
+ });
4346
+ });
4347
+ const middleware = (req, res, next) => {
4348
+ void (async () => {
4349
+ const rawUrl = req.url ?? "/";
4350
+ const url = new URL(rawUrl, "http://localhost");
4351
+ const pathname = decodeURIComponent(url.pathname);
4352
+ if (pathname === "/@vite/lazy" || pathname === "/@nasti/lazy") {
4353
+ const id = url.searchParams.get("id");
4354
+ const clientId = url.searchParams.get("clientId");
4355
+ if (!id || !clientId) {
4356
+ res.statusCode = 400;
4357
+ res.end("// [nasti] lazy endpoint requires id & clientId");
4358
+ return;
4359
+ }
4360
+ const code = await engine.compileEntry(id, clientId);
4361
+ res.setHeader("Content-Type", "application/javascript");
4362
+ res.setHeader("Cache-Control", "no-store");
4363
+ res.end(code + "\n;export {}");
4364
+ return;
4365
+ }
4366
+ const patchHit = patches.get(pathname.replace(/^\//, ""));
4367
+ if (patchHit) {
4368
+ res.setHeader("Content-Type", "application/javascript");
4369
+ res.setHeader("Cache-Control", "no-store");
4370
+ res.end(patchHit.content);
4371
+ return;
4372
+ }
4373
+ const fileName = pathname.replace(/^\//, "");
4374
+ const hit = memoryFiles.get(fileName);
4375
+ if (hit) {
4376
+ if (req.headers["if-none-match"] === hit.etag) {
4377
+ res.statusCode = 304;
4378
+ res.end();
4379
+ return;
4380
+ }
4381
+ res.setHeader("ETag", hit.etag);
4382
+ res.setHeader("Content-Type", MIME_TYPES[import_node_path14.default.extname(fileName)] ?? "application/octet-stream");
4383
+ res.setHeader("Cache-Control", "no-cache");
4384
+ res.end(hit.content);
4385
+ return;
4386
+ }
4387
+ if (pathname === "/" || pathname.endsWith(".html")) {
4388
+ const rawHtml = await readHtmlFile(config.root);
4389
+ if (rawHtml) {
4390
+ res.setHeader("Content-Type", "text/html");
4391
+ res.setHeader("Cache-Control", "no-store");
4392
+ res.end(await renderBundledIndexHtml(rawHtml, config, entryFileNames));
4393
+ return;
4394
+ }
4395
+ }
4396
+ next();
4397
+ })().catch((err) => {
4398
+ config.logger.error(import_picocolors8.default.red(`[bundled] ${err.message}`), { error: err });
4399
+ res.statusCode = 500;
4400
+ res.end(`[nasti bundled] ${err.message}`);
4401
+ });
4402
+ };
4403
+ return {
4404
+ middleware,
4405
+ async close() {
4406
+ if (fullReloadTimer) clearTimeout(fullReloadTimer);
4407
+ wss.close();
4408
+ await engine.close();
4409
+ }
4410
+ };
4411
+ }
4412
+ function stripCatchAllLoad(plugins) {
4413
+ return plugins.map(
4414
+ (p) => p?.name === "nasti:resolve" ? { ...p, load: void 0 } : p
4415
+ );
4416
+ }
4417
+ function createReactRefreshRuntimePlugin(entryPoints) {
4418
+ const entryIds = new Set(entryPoints.map((p) => import_node_path14.default.resolve(p)));
4419
+ return {
4420
+ name: "nasti:bundled-react-refresh",
4421
+ resolveId(source) {
4422
+ if (source === REFRESH_RUNTIME_URL) return REFRESH_RUNTIME_URL;
4423
+ if (source === PREAMBLE_SPEC) return RESOLVED_PREAMBLE_ID;
4424
+ return null;
4425
+ },
4426
+ load(id) {
4427
+ if (id === REFRESH_RUNTIME_URL) {
4428
+ return { code: getReactRefreshRuntimeEsm() + WRAPPER_RUNTIME_HELPERS, moduleType: "js" };
4429
+ }
4430
+ if (id === RESOLVED_PREAMBLE_ID) {
4431
+ return { code: BUNDLED_PREAMBLE_CODE, moduleType: "js" };
4432
+ }
4433
+ return null;
4434
+ },
4435
+ transform(code, id) {
4436
+ if (!entryIds.has(import_node_path14.default.resolve(id.split("?")[0]))) return null;
4437
+ return { code: `import ${JSON.stringify(PREAMBLE_SPEC)};
4438
+ ${code}`, map: null };
4439
+ }
4440
+ };
4441
+ }
4442
+ function createBundledOxcRefreshPlugin() {
4443
+ return {
4444
+ name: "nasti:bundled-oxc-refresh",
4445
+ transform(code, id) {
4446
+ const clean = id.split("?")[0];
4447
+ if (!/\.[jt]sx$/.test(clean) || clean.includes("/node_modules/")) return null;
4448
+ const result = transformCode(clean, code, {
4449
+ sourcemap: true,
4450
+ jsxRuntime: "automatic",
4451
+ jsxImportSource: "react",
4452
+ reactRefresh: true
4453
+ });
4454
+ return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
4455
+ }
4456
+ };
4457
+ }
4458
+ async function renderBundledIndexHtml(html, config, entryFileNames) {
4459
+ let processed = html;
4460
+ for (const plugin of config.plugins) {
4461
+ if (!plugin.transformIndexHtml || plugin.name === "nasti:html") continue;
4462
+ const result = await plugin.transformIndexHtml(processed);
4463
+ if (typeof result === "string") {
4464
+ processed = result;
4465
+ } else if (result && "html" in result) {
4466
+ processed = processHtml(result.html, result.tags);
4467
+ } else if (Array.isArray(result)) {
4468
+ processed = processHtml(processed, result);
4469
+ }
4470
+ }
4471
+ for (const [facadeModuleId, fileName] of entryFileNames) {
4472
+ const originalEntry = import_node_path14.default.relative(config.root, facadeModuleId);
4473
+ processed = processed.replace(
4474
+ new RegExp(`(src=["'])/?(${originalEntry.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})(["'])`, "g"),
4475
+ `$1/${fileName}$3`
4476
+ );
4477
+ }
4478
+ return processed;
4479
+ }
4480
+ var import_node_path14, import_node_crypto3, import_ws2, import_picocolors8, debug6, MIME_TYPES, MemoryFiles, PREAMBLE_SPEC, RESOLVED_PREAMBLE_ID, REFRESH_RUNTIME_URL, BUNDLED_PREAMBLE_CODE, WRAPPER_RUNTIME_HELPERS;
4481
+ var init_dev_engine = __esm({
4482
+ "src/server/bundled/dev-engine.ts"() {
4483
+ "use strict";
4484
+ import_node_path14 = __toESM(require("path"), 1);
4485
+ import_node_crypto3 = __toESM(require("crypto"), 1);
4486
+ import_ws2 = require("ws");
4487
+ import_picocolors8 = __toESM(require("picocolors"), 1);
4488
+ init_build();
4489
+ init_html();
4490
+ init_transformer();
4491
+ init_middleware();
4492
+ init_debug();
4493
+ debug6 = createDebugger("nasti:bundled");
4494
+ MIME_TYPES = {
4495
+ ".js": "application/javascript",
4496
+ ".mjs": "application/javascript",
4497
+ ".css": "text/css",
4498
+ ".html": "text/html",
4499
+ ".json": "application/json",
4500
+ ".map": "application/json",
4501
+ ".svg": "image/svg+xml",
4502
+ ".png": "image/png",
4503
+ ".jpg": "image/jpeg",
4504
+ ".wasm": "application/wasm"
4505
+ };
4506
+ MemoryFiles = class {
4507
+ files = /* @__PURE__ */ new Map();
4508
+ set(fileName, content) {
4509
+ const etag = `"${import_node_crypto3.default.createHash("sha1").update(content).digest("base64").slice(0, 27)}"`;
4510
+ this.files.set(fileName, { content, etag });
4511
+ }
4512
+ get(fileName) {
4513
+ return this.files.get(fileName);
4514
+ }
4515
+ clear() {
4516
+ this.files.clear();
4517
+ }
4518
+ };
4519
+ PREAMBLE_SPEC = "nasti:react-preamble";
4520
+ RESOLVED_PREAMBLE_ID = "\0nasti:react-preamble";
4521
+ REFRESH_RUNTIME_URL = "/@react-refresh";
4522
+ BUNDLED_PREAMBLE_CODE = `
4523
+ import __rt from ${JSON.stringify(REFRESH_RUNTIME_URL)};
4524
+ __rt.injectIntoGlobalHook(window);
4525
+ window.$RefreshReg$ = () => {};
4526
+ window.$RefreshSig$ = () => (type) => type;
4527
+ window.__vite_plugin_react_preamble_installed__ = true;
4528
+ `;
4529
+ WRAPPER_RUNTIME_HELPERS = `
4530
+ // \u2500\u2500 viteReactRefreshWrapperPlugin \u8FD0\u884C\u65F6\u5951\u7EA6\uFF08@vitejs/plugin-react \u540C\u6B3E\uFF09\u2500\u2500
4531
+ function __isPlainObject(obj) {
4532
+ return Object.prototype.toString.call(obj) === '[object Object]' &&
4533
+ (obj.constructor === Object || obj.constructor === undefined);
4534
+ }
4535
+ function __isCompoundComponent(type) {
4536
+ if (!__isPlainObject(type)) return false;
4537
+ for (const key in type) {
4538
+ if (!isLikelyComponentType(type[key])) return false;
4539
+ }
4540
+ return true;
4541
+ }
4542
+ export function registerExportsForReactRefresh(filename, moduleExports) {
4543
+ for (const key in moduleExports) {
4544
+ if (key === '__esModule') continue;
4545
+ const exportValue = moduleExports[key];
4546
+ if (isLikelyComponentType(exportValue)) {
4547
+ register(exportValue, filename + ' export ' + key);
4548
+ } else if (__isCompoundComponent(exportValue)) {
4549
+ for (const subKey in exportValue) {
4550
+ register(exportValue[subKey], filename + ' export ' + key + '-' + subKey);
4551
+ }
4552
+ }
4553
+ }
4554
+ }
4555
+ let __enqueueTimer;
4556
+ const __hooks = [];
4557
+ window.__registerBeforePerformReactRefresh = (cb) => { __hooks.push(cb); };
4558
+ function __enqueueUpdate() {
4559
+ clearTimeout(__enqueueTimer);
4560
+ __enqueueTimer = setTimeout(async () => {
4561
+ if (__hooks.length) await Promise.all(__hooks.map((cb) => cb()));
4562
+ performReactRefresh();
4563
+ }, 16);
4564
+ }
4565
+ function __predicateOnExport(ignoredExports, moduleExports, predicate) {
4566
+ for (const key in moduleExports) {
4567
+ if (ignoredExports.includes(key)) continue;
4568
+ if (!predicate(key, moduleExports[key])) return key;
4569
+ }
4570
+ return true;
4571
+ }
4572
+ export function validateRefreshBoundaryAndEnqueueUpdate(id, prevExports, nextExports) {
4573
+ const ignoredExports = window.__getReactRefreshIgnoredExports?.({ id }) ?? [];
4574
+ if (__predicateOnExport(ignoredExports, prevExports, (key) => key in nextExports) !== true) {
4575
+ return 'Could not Fast Refresh (export removed)';
4576
+ }
4577
+ if (__predicateOnExport(ignoredExports, nextExports, (key) => key in prevExports) !== true) {
4578
+ return 'Could not Fast Refresh (new export)';
4579
+ }
4580
+ let hasExports = false;
4581
+ const allExportsAreComponentsOrUnchanged = __predicateOnExport(
4582
+ ignoredExports,
4583
+ nextExports,
4584
+ (key, value) => {
4585
+ hasExports = true;
4586
+ if (isLikelyComponentType(value)) return true;
4587
+ if (__isCompoundComponent(value)) return true;
4588
+ return prevExports[key] === nextExports[key];
4589
+ },
4590
+ );
4591
+ if (hasExports && allExportsAreComponentsOrUnchanged === true) {
4592
+ __enqueueUpdate();
4593
+ } else {
4594
+ return 'Could not Fast Refresh ("' + allExportsAreComponentsOrUnchanged + '" export is incompatible)';
4595
+ }
4596
+ }
4597
+ export const __hmr_import = (module) => import(/* @vite-ignore */ module);
4598
+ `;
2260
4599
  }
2261
4600
  });
2262
4601
 
@@ -2266,38 +4605,71 @@ __export(server_exports, {
2266
4605
  createServer: () => createServer
2267
4606
  });
2268
4607
  async function createServer(inlineConfig = {}) {
4608
+ const startTime = performance.now();
2269
4609
  const config = await resolveConfig(inlineConfig, "serve");
2270
- const allPlugins = [
2271
- ...config.framework === "vue" ? [vuePlugin(config)] : [],
2272
- resolvePlugin(config),
2273
- cssPlugin(config),
2274
- assetsPlugin(config),
2275
- htmlPlugin(config),
2276
- ...config.plugins
2277
- ];
4610
+ const logger = config.logger;
4611
+ const allPlugins = resolvePluginList(config, config.plugins);
2278
4612
  const configWithPlugins = { ...config, plugins: allPlugins };
2279
- const moduleGraph = new ModuleGraph();
2280
- const pluginContainer = new PluginContainer(configWithPlugins);
2281
4613
  const app = (0, import_connect.default)();
4614
+ const httpServer = import_node_http.default.createServer(app);
4615
+ const ws = createWebSocketServer(httpServer);
4616
+ const clientEnv = new NastiEnvironment("client", configWithPlugins, {
4617
+ hot: createWsHotChannel(ws),
4618
+ mode: "dev",
4619
+ plugins: allPlugins
4620
+ });
4621
+ await clientEnv.init();
4622
+ const environments = { client: clientEnv };
4623
+ for (const name of Object.keys(config.environments)) {
4624
+ if (name === "client") continue;
4625
+ const consumer = config.environments[name].consumer;
4626
+ const envPlugins = resolvePluginList(config, config.plugins, { consumer });
4627
+ environments[name] = new NastiEnvironment(name, { ...config, plugins: envPlugins }, {
4628
+ mode: "dev",
4629
+ plugins: envPlugins
4630
+ });
4631
+ }
4632
+ let ssrRunner = null;
4633
+ async function getSsrRunner() {
4634
+ if (ssrRunner) return ssrRunner;
4635
+ const ssrEnv = environments.ssr;
4636
+ if (!ssrEnv) {
4637
+ throw new Error('[nasti] no "ssr" environment configured (config.environments.ssr)');
4638
+ }
4639
+ await ssrEnv.init();
4640
+ const { createModuleRunner: createModuleRunner2 } = await Promise.resolve().then(() => (init_runnable_environment(), runnable_environment_exports));
4641
+ ssrRunner = createModuleRunner2(ssrEnv);
4642
+ return ssrRunner;
4643
+ }
4644
+ const moduleGraph = clientEnv.moduleGraph;
4645
+ const pluginContainer = clientEnv.pluginContainer;
4646
+ let bundledServer = null;
4647
+ if (config.experimental.bundledDev) {
4648
+ const { createBundledDevServer: createBundledDevServer2 } = await Promise.resolve().then(() => (init_dev_engine(), dev_engine_exports));
4649
+ bundledServer = await createBundledDevServer2({
4650
+ config: configWithPlugins,
4651
+ clientEnv,
4652
+ httpServer
4653
+ });
4654
+ app.use(bundledServer.middleware);
4655
+ }
2282
4656
  app.use(transformMiddleware({
2283
4657
  config: configWithPlugins,
2284
4658
  pluginContainer,
2285
4659
  moduleGraph
2286
4660
  }));
2287
- const publicDir = import_node_path12.default.resolve(config.root, "public");
4661
+ const publicDir = import_node_path15.default.resolve(config.root, "public");
2288
4662
  app.use((0, import_sirv.default)(publicDir, { dev: true, etag: true }));
2289
4663
  app.use((0, import_sirv.default)(config.root, { dev: true, etag: true }));
2290
- const httpServer = import_node_http.default.createServer(app);
2291
- const ws = createWebSocketServer(httpServer);
2292
4664
  const ignoredSegments = /* @__PURE__ */ new Set(["node_modules", ".git", ".nasti"]);
2293
- const outDirAbs = import_node_path12.default.resolve(config.root, config.build.outDir);
4665
+ const outDirAbs = import_node_path15.default.resolve(config.root, config.build.outDir);
2294
4666
  const watcher = (0, import_chokidar.watch)(config.root, {
2295
4667
  ignored: (filePath) => {
2296
4668
  if (filePath === config.root) return false;
2297
- if (filePath === outDirAbs || filePath.startsWith(outDirAbs + import_node_path12.default.sep)) return true;
2298
- const rel = import_node_path12.default.relative(config.root, filePath);
2299
- if (!rel || rel.startsWith("..") || import_node_path12.default.isAbsolute(rel)) return false;
2300
- for (const seg of rel.split(import_node_path12.default.sep)) {
4669
+ if (filePath === outDirAbs || filePath.startsWith(outDirAbs + import_node_path15.default.sep)) return true;
4670
+ const rel = import_node_path15.default.relative(config.root, filePath);
4671
+ if (!rel || rel.startsWith("..") || import_node_path15.default.isAbsolute(rel)) return false;
4672
+ for (const seg of rel.split(import_node_path15.default.sep)) {
2301
4673
  if (ignoredSegments.has(seg)) return true;
2302
4674
  }
2303
4675
  return false;
@@ -2306,9 +4678,11 @@ async function createServer(inlineConfig = {}) {
2306
4678
  });
2307
4679
  let server;
2308
4680
  watcher.on("change", (file) => {
4681
+ ssrRunner?.invalidateFile(file);
2309
4682
  handleFileChange(file, server);
2310
4683
  });
2311
4684
  watcher.on("add", (file) => {
4685
+ ssrRunner?.invalidateFile(file);
2312
4686
  handleFileChange(file, server);
2313
4687
  });
2314
4688
  server = {
@@ -2317,6 +4691,7 @@ async function createServer(inlineConfig = {}) {
2317
4691
  moduleGraph,
2318
4692
  watcher,
2319
4693
  ws,
4694
+ environments,
2320
4695
  async listen(port) {
2321
4696
  const finalPort = port ?? config.server.port;
2322
4697
  const host = config.server.host === true ? "0.0.0.0" : config.server.host;
@@ -2326,23 +4701,27 @@ async function createServer(inlineConfig = {}) {
2326
4701
  const onListening = () => {
2327
4702
  const actualPort = httpServer.address()?.port ?? currentPort;
2328
4703
  config.server.port = actualPort;
2329
- const localUrl = `http://localhost:${actualPort}`;
2330
- const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
2331
- console.log();
2332
- console.log(import_picocolors3.default.cyan(" nasti dev server") + import_picocolors3.default.dim(` v${"1.7.1"}`));
2333
- console.log();
2334
- console.log(` ${import_picocolors3.default.green(">")} Local: ${import_picocolors3.default.cyan(localUrl)}`);
2335
- if (networkUrl) {
2336
- console.log(` ${import_picocolors3.default.green(">")} Network: ${import_picocolors3.default.cyan(networkUrl)}`);
2337
- }
2338
- console.log();
4704
+ const localUrl = `http://localhost:${actualPort}/`;
4705
+ const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}/` : null;
4706
+ logger.clearScreen("info");
4707
+ const readyIn = Math.ceil(performance.now() - startTime);
4708
+ logger.info(
4709
+ `
4710
+ ${import_picocolors9.default.cyan(import_picocolors9.default.bold("NASTI"))} ${import_picocolors9.default.cyan(`v${"2.0.0"}`)} ${import_picocolors9.default.dim("ready in")} ${import_picocolors9.default.bold(readyIn)} ${import_picocolors9.default.dim("ms")}
4711
+ `
4712
+ );
4713
+ printServerUrls(
4714
+ { local: [localUrl], network: networkUrl ? [networkUrl] : [] },
4715
+ logger.info
4716
+ );
4717
+ logger.info("");
2339
4718
  resolve(server);
2340
4719
  };
2341
4720
  httpServer.on("listening", onListening);
2342
4721
  httpServer.on("error", (err) => {
2343
4722
  if (err.code === "EADDRINUSE") {
2344
4723
  currentPort++;
2345
- console.log(import_picocolors3.default.yellow(`Port ${currentPort - 1} is in use, trying ${currentPort}...`));
4724
+ logger.info(import_picocolors9.default.yellow(`Port ${currentPort - 1} is in use, trying ${currentPort}...`));
2346
4725
  httpServer.listen(currentPort, host);
2347
4726
  } else {
2348
4727
  reject(err);
@@ -2355,8 +4734,13 @@ async function createServer(inlineConfig = {}) {
2355
4734
  const { transformRequest: transformRequest2 } = await Promise.resolve().then(() => (init_middleware(), middleware_exports));
2356
4735
  return transformRequest2(url, { config: configWithPlugins, pluginContainer, moduleGraph });
2357
4736
  },
4737
+ async ssrLoadModule(url) {
4738
+ const runner = await getSsrRunner();
4739
+ return runner.import(url);
4740
+ },
2358
4741
  async close() {
2359
4742
  await pluginContainer.buildEnd();
4743
+ await bundledServer?.close();
2360
4744
  watcher.close();
2361
4745
  ws.close();
2362
4746
  httpServer.close();
@@ -2385,41 +4769,49 @@ function getNetworkAddress() {
2385
4769
  }
2386
4770
  return "localhost";
2387
4771
  }
2388
- var import_node_http, import_node_path12, import_node_os, import_connect, import_sirv, import_chokidar, import_picocolors3;
4772
+ var import_node_http, import_node_path15, import_node_os, import_connect, import_sirv, import_chokidar, import_picocolors9;
2389
4773
  var init_server = __esm({
2390
4774
  "src/server/index.ts"() {
2391
4775
  "use strict";
2392
4776
  import_node_http = __toESM(require("http"), 1);
2393
- import_node_path12 = __toESM(require("path"), 1);
4777
+ import_node_path15 = __toESM(require("path"), 1);
2394
4778
  import_node_os = __toESM(require("os"), 1);
2395
4779
  import_connect = __toESM(require("connect"), 1);
2396
4780
  import_sirv = __toESM(require("sirv"), 1);
2397
4781
  import_chokidar = require("chokidar");
2398
- import_picocolors3 = __toESM(require("picocolors"), 1);
4782
+ import_picocolors9 = __toESM(require("picocolors"), 1);
2399
4783
  init_config();
2400
- init_plugin_container();
2401
- init_module_graph();
4784
+ init_environment();
4785
+ init_hot_channel();
4786
+ init_logger();
2402
4787
  init_ws();
2403
4788
  init_middleware();
2404
4789
  init_hmr();
2405
- init_resolve();
2406
- init_css();
2407
- init_assets();
2408
- init_vue();
2409
- init_html();
4790
+ init_builtins();
2410
4791
  }
2411
4792
  });
2412
4793
 
2413
4794
  // src/index.ts
2414
4795
  var src_exports = {};
2415
4796
  __export(src_exports, {
4797
+ LogLevels: () => LogLevels,
4798
+ NastiEnvironment: () => NastiEnvironment,
2416
4799
  build: () => build,
2417
4800
  buildElectron: () => buildElectron,
4801
+ buildEnvDefine: () => buildEnvDefine,
4802
+ createDebugger: () => createDebugger,
4803
+ createLogger: () => createLogger,
4804
+ createNoopHotChannel: () => createNoopHotChannel,
2418
4805
  createServer: () => createServer,
4806
+ createWsHotChannel: () => createWsHotChannel,
2419
4807
  defineConfig: () => defineConfig,
2420
4808
  electronPlugin: () => electronPlugin,
4809
+ loadEnv: () => loadEnv,
2421
4810
  monacoEditorPlugin: () => monacoEditorPlugin,
4811
+ printServerUrls: () => printServerUrls,
2422
4812
  resolveConfig: () => resolveConfig,
4813
+ resolveEnvironmentPlugins: () => resolveEnvironmentPlugins,
4814
+ ssrDefineOverrides: () => ssrDefineOverrides,
2423
4815
  startElectronDev: () => startElectronDev
2424
4816
  });
2425
4817
  module.exports = __toCommonJS(src_exports);
@@ -2427,18 +4819,18 @@ init_config();
2427
4819
  init_build();
2428
4820
 
2429
4821
  // src/build/electron.ts
2430
- var import_node_path9 = __toESM(require("path"), 1);
4822
+ var import_node_path10 = __toESM(require("path"), 1);
2431
4823
  var import_node_fs7 = __toESM(require("fs"), 1);
2432
4824
  var import_rolldown2 = require("rolldown");
2433
- var import_picocolors2 = __toESM(require("picocolors"), 1);
4825
+ var import_picocolors5 = __toESM(require("picocolors"), 1);
2434
4826
  init_config();
2435
4827
  init_resolve();
2436
4828
 
2437
4829
  // src/plugins/electron.ts
2438
- var import_node_module3 = require("module");
2439
- var NODE_BUILTINS = /* @__PURE__ */ new Set([
2440
- ...import_node_module3.builtinModules,
2441
- ...import_node_module3.builtinModules.map((m) => `node:${m}`)
4830
+ var import_node_module4 = require("module");
4831
+ var NODE_BUILTINS2 = /* @__PURE__ */ new Set([
4832
+ ...import_node_module4.builtinModules,
4833
+ ...import_node_module4.builtinModules.map((m) => `node:${m}`)
2442
4834
  ]);
2443
4835
  var ELECTRON_MODULES = /* @__PURE__ */ new Set([
2444
4836
  "electron",
@@ -2449,7 +4841,7 @@ var ELECTRON_MODULES = /* @__PURE__ */ new Set([
2449
4841
  function electronPlugin(config) {
2450
4842
  const external = /* @__PURE__ */ new Set([
2451
4843
  ...ELECTRON_MODULES,
2452
- ...NODE_BUILTINS,
4844
+ ...NODE_BUILTINS2,
2453
4845
  ...config.electron.external ?? []
2454
4846
  ]);
2455
4847
  return {
@@ -2474,16 +4866,16 @@ async function buildElectron(inlineConfig = {}) {
2474
4866
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
2475
4867
  const startTime = performance.now();
2476
4868
  assertElectronVersion(config);
2477
- console.log(import_picocolors2.default.cyan("\n\u26A1 nasti build (electron)") + import_picocolors2.default.dim(` v${"1.7.1"}`));
2478
- console.log(import_picocolors2.default.dim(` root: ${config.root}`));
2479
- console.log(import_picocolors2.default.dim(` mode: ${config.mode}`));
2480
- console.log(import_picocolors2.default.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
2481
- const outDir = import_node_path9.default.resolve(config.root, config.build.outDir);
4869
+ console.log(import_picocolors5.default.cyan("\n\u26A1 nasti build (electron)") + import_picocolors5.default.dim(` v${"2.0.0"}`));
4870
+ console.log(import_picocolors5.default.dim(` root: ${config.root}`));
4871
+ console.log(import_picocolors5.default.dim(` mode: ${config.mode}`));
4872
+ console.log(import_picocolors5.default.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
4873
+ const outDir = import_node_path10.default.resolve(config.root, config.build.outDir);
2482
4874
  if (config.build.emptyOutDir && import_node_fs7.default.existsSync(outDir)) {
2483
4875
  import_node_fs7.default.rmSync(outDir, { recursive: true, force: true });
2484
4876
  }
2485
4877
  import_node_fs7.default.mkdirSync(outDir, { recursive: true });
2486
- const rendererOutDir = import_node_path9.default.join(outDir, "renderer");
4878
+ const rendererOutDir = import_node_path10.default.join(outDir, "renderer");
2487
4879
  const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
2488
4880
  await build2({
2489
4881
  ...inlineConfig,
@@ -2494,7 +4886,7 @@ async function buildElectron(inlineConfig = {}) {
2494
4886
  emptyOutDir: false
2495
4887
  }
2496
4888
  });
2497
- const mainEntry = import_node_path9.default.resolve(config.root, config.electron.main);
4889
+ const mainEntry = import_node_path10.default.resolve(config.root, config.electron.main);
2498
4890
  if (!import_node_fs7.default.existsSync(mainEntry)) {
2499
4891
  throw new Error(
2500
4892
  `Electron main entry not found: ${config.electron.main}
@@ -2510,10 +4902,10 @@ async function buildElectron(inlineConfig = {}) {
2510
4902
  const preloadFiles = [];
2511
4903
  for (const entry of preloadEntries) {
2512
4904
  if (!import_node_fs7.default.existsSync(entry)) {
2513
- console.warn(import_picocolors2.default.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
4905
+ console.warn(import_picocolors5.default.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
2514
4906
  continue;
2515
4907
  }
2516
- const base = import_node_path9.default.basename(entry).replace(/\.[^.]+$/, "");
4908
+ const base = import_node_path10.default.basename(entry).replace(/\.[^.]+$/, "");
2517
4909
  const out = outFileName(outDir, base, config.electron.preloadFormat);
2518
4910
  await bundleNode(config, entry, {
2519
4911
  outFile: out,
@@ -2523,12 +4915,12 @@ async function buildElectron(inlineConfig = {}) {
2523
4915
  preloadFiles.push(out);
2524
4916
  }
2525
4917
  const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
2526
- console.log(import_picocolors2.default.green(`
4918
+ console.log(import_picocolors5.default.green(`
2527
4919
  \u2713 Electron build complete in ${elapsed}s`));
2528
- console.log(import_picocolors2.default.dim(` renderer: ${import_node_path9.default.relative(config.root, rendererOutDir)}/`));
2529
- console.log(import_picocolors2.default.dim(` main: ${import_node_path9.default.relative(config.root, mainFile)}`));
4920
+ console.log(import_picocolors5.default.dim(` renderer: ${import_node_path10.default.relative(config.root, rendererOutDir)}/`));
4921
+ console.log(import_picocolors5.default.dim(` main: ${import_node_path10.default.relative(config.root, mainFile)}`));
2530
4922
  for (const pf of preloadFiles) {
2531
- console.log(import_picocolors2.default.dim(` preload: ${import_node_path9.default.relative(config.root, pf)}`));
4923
+ console.log(import_picocolors5.default.dim(` preload: ${import_node_path10.default.relative(config.root, pf)}`));
2532
4924
  }
2533
4925
  console.log();
2534
4926
  return { rendererOutDir, mainFile, preloadFiles };
@@ -2554,15 +4946,15 @@ async function bundleNode(config, entry, opts) {
2554
4946
  };
2555
4947
  const { output: userOutput, transform: userTransform, ...restInputOptions } = config.build.rolldownOptions;
2556
4948
  const mergedDefine = { ...userTransform?.define ?? {}, ...envDefine };
2557
- const bundle = await (0, import_rolldown2.rolldown)({
4949
+ const bundle2 = await (0, import_rolldown2.rolldown)({
2558
4950
  ...restInputOptions,
2559
4951
  input: entry,
2560
4952
  platform: "node",
2561
4953
  transform: { ...userTransform, define: mergedDefine },
2562
4954
  plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
2563
4955
  });
2564
- import_node_fs7.default.mkdirSync(import_node_path9.default.dirname(opts.outFile), { recursive: true });
2565
- await bundle.write({
4956
+ import_node_fs7.default.mkdirSync(import_node_path10.default.dirname(opts.outFile), { recursive: true });
4957
+ await bundle2.write({
2566
4958
  sourcemap: !!config.build.sourcemap,
2567
4959
  minify: !!config.build.minify,
2568
4960
  // 允许用户微调 output;但主进程 / preload 的单文件约束由下方键强制保证
@@ -2571,24 +4963,24 @@ async function bundleNode(config, entry, opts) {
2571
4963
  format: opts.format === "cjs" ? "cjs" : "esm",
2572
4964
  codeSplitting: false
2573
4965
  });
2574
- await bundle.close();
2575
- console.log(import_picocolors2.default.dim(` \u2713 ${opts.label} \u2192 ${import_node_path9.default.relative(config.root, opts.outFile)}`));
4966
+ await bundle2.close();
4967
+ console.log(import_picocolors5.default.dim(` \u2713 ${opts.label} \u2192 ${import_node_path10.default.relative(config.root, opts.outFile)}`));
2576
4968
  return opts.outFile;
2577
4969
  }
2578
4970
  function outFileName(outDir, base, format) {
2579
4971
  const ext = format === "cjs" ? ".cjs" : ".mjs";
2580
- return import_node_path9.default.join(outDir, base + ext);
4972
+ return import_node_path10.default.join(outDir, base + ext);
2581
4973
  }
2582
4974
  function normalizePreload(preload, root) {
2583
4975
  const list = Array.isArray(preload) ? preload : preload ? [preload] : [];
2584
- return list.map((p) => import_node_path9.default.resolve(root, p));
4976
+ return list.map((p) => import_node_path10.default.resolve(root, p));
2585
4977
  }
2586
4978
  function assertElectronVersion(config) {
2587
4979
  const min = config.electron.minVersion;
2588
4980
  const installed = detectInstalledElectron(config.root);
2589
4981
  if (installed && installed < min) {
2590
4982
  console.warn(
2591
- import_picocolors2.default.yellow(
4983
+ import_picocolors5.default.yellow(
2592
4984
  ` \u26A0 \u68C0\u6D4B\u5230 Electron ${installed}\uFF0CNasti \u8981\u6C42 \u2265 ${min}\u3002\u65E7\u7248\u672C\u53EF\u80FD\u7F3A\u5C11 ESM \u4E3B\u8FDB\u7A0B\u652F\u6301\u3002`
2593
4985
  )
2594
4986
  );
@@ -2596,7 +4988,7 @@ function assertElectronVersion(config) {
2596
4988
  }
2597
4989
  function detectInstalledElectron(root) {
2598
4990
  try {
2599
- const pkgPath = import_node_path9.default.resolve(root, "node_modules/electron/package.json");
4991
+ const pkgPath = import_node_path10.default.resolve(root, "node_modules/electron/package.json");
2600
4992
  if (!import_node_fs7.default.existsSync(pkgPath)) return null;
2601
4993
  const pkg = JSON.parse(import_node_fs7.default.readFileSync(pkgPath, "utf-8"));
2602
4994
  const major = parseInt(String(pkg.version).split(".")[0], 10);
@@ -2610,12 +5002,12 @@ function detectInstalledElectron(root) {
2610
5002
  init_server();
2611
5003
 
2612
5004
  // src/server/electron-dev.ts
2613
- var import_node_path13 = __toESM(require("path"), 1);
2614
- var import_node_fs10 = __toESM(require("fs"), 1);
2615
- var import_node_module5 = require("module");
5005
+ var import_node_path16 = __toESM(require("path"), 1);
5006
+ var import_node_fs11 = __toESM(require("fs"), 1);
5007
+ var import_node_module7 = require("module");
2616
5008
  var import_node_child_process = require("child_process");
2617
5009
  var import_chokidar2 = __toESM(require("chokidar"), 1);
2618
- var import_picocolors4 = __toESM(require("picocolors"), 1);
5010
+ var import_picocolors10 = __toESM(require("picocolors"), 1);
2619
5011
  init_config();
2620
5012
  var import_rolldown3 = require("rolldown");
2621
5013
  init_resolve();
@@ -2625,17 +5017,17 @@ async function startElectronDev(inlineConfig = {}) {
2625
5017
  const { noSpawn, ...rest } = inlineConfig;
2626
5018
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
2627
5019
  warnElectronVersion(config);
2628
- console.log(import_picocolors4.default.cyan("\n\u26A1 nasti electron dev") + import_picocolors4.default.dim(` v${"1.7.1"}`));
5020
+ console.log(import_picocolors10.default.cyan("\n\u26A1 nasti electron dev") + import_picocolors10.default.dim(` v${"2.0.0"}`));
2629
5021
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
2630
5022
  const server = await createServer2({ ...rest, target: "electron" });
2631
5023
  await server.listen();
2632
5024
  const devUrl = `http://localhost:${server.config.server.port}/`;
2633
- console.log(import_picocolors4.default.dim(` renderer: ${devUrl}`));
2634
- const stageDir = import_node_path13.default.resolve(config.root, ".nasti");
2635
- import_node_fs10.default.mkdirSync(stageDir, { recursive: true });
2636
- const mainEntry = import_node_path13.default.resolve(config.root, config.electron.main);
5025
+ console.log(import_picocolors10.default.dim(` renderer: ${devUrl}`));
5026
+ const stageDir = import_node_path16.default.resolve(config.root, ".nasti");
5027
+ import_node_fs11.default.mkdirSync(stageDir, { recursive: true });
5028
+ const mainEntry = import_node_path16.default.resolve(config.root, config.electron.main);
2637
5029
  const preloadEntries = normalizePreload(config.electron.preload, config.root);
2638
- const builtMainFile = import_node_path13.default.join(stageDir, "main" + extFor(config.electron.mainFormat));
5030
+ const builtMainFile = import_node_path16.default.join(stageDir, "main" + extFor(config.electron.mainFormat));
2639
5031
  const builtPreloadFiles = [];
2640
5032
  const compileAll = async () => {
2641
5033
  await compileNode(config, mainEntry, {
@@ -2645,9 +5037,9 @@ async function startElectronDev(inlineConfig = {}) {
2645
5037
  });
2646
5038
  builtPreloadFiles.length = 0;
2647
5039
  for (const entry of preloadEntries) {
2648
- if (!import_node_fs10.default.existsSync(entry)) continue;
2649
- const base = import_node_path13.default.basename(entry).replace(/\.[^.]+$/, "");
2650
- const out = import_node_path13.default.join(stageDir, base + extFor(config.electron.preloadFormat));
5040
+ if (!import_node_fs11.default.existsSync(entry)) continue;
5041
+ const base = import_node_path16.default.basename(entry).replace(/\.[^.]+$/, "");
5042
+ const out = import_node_path16.default.join(stageDir, base + extFor(config.electron.preloadFormat));
2651
5043
  await compileNode(config, entry, {
2652
5044
  outFile: out,
2653
5045
  format: config.electron.preloadFormat,
@@ -2658,13 +5050,13 @@ async function startElectronDev(inlineConfig = {}) {
2658
5050
  };
2659
5051
  await compileAll();
2660
5052
  if (noSpawn) {
2661
- console.log(import_picocolors4.default.dim(" (noSpawn) \u5DF2\u7F16\u8BD1\u4E3B/preload\uFF0C\u8DF3\u8FC7\u542F\u52A8 Electron\u3002"));
5053
+ console.log(import_picocolors10.default.dim(" (noSpawn) \u5DF2\u7F16\u8BD1\u4E3B/preload\uFF0C\u8DF3\u8FC7\u542F\u52A8 Electron\u3002"));
2662
5054
  return;
2663
5055
  }
2664
5056
  const electronBin = resolveElectronBinary(config);
2665
5057
  if (!electronBin) {
2666
5058
  console.warn(
2667
- import_picocolors4.default.yellow(
5059
+ import_picocolors10.default.yellow(
2668
5060
  " \u26A0 \u672A\u627E\u5230 Electron \u53EF\u6267\u884C\u6587\u4EF6\uFF0C\u8BF7\u5148\u5B89\u88C5\uFF1Anpm install -D electron\n \u5DF2\u7F16\u8BD1\u4E3B/preload \u81F3 .nasti/\uFF0C\u53EF\u624B\u52A8\u8FD0\u884C\u3002"
2669
5061
  )
2670
5062
  );
@@ -2679,14 +5071,14 @@ async function startElectronDev(inlineConfig = {}) {
2679
5071
  });
2680
5072
  child.on("exit", (code) => {
2681
5073
  if (code !== null && child && child.__nastiKilled !== true) {
2682
- console.log(import_picocolors4.default.dim(` Electron exited (${code}).`));
5074
+ console.log(import_picocolors10.default.dim(` Electron exited (${code}).`));
2683
5075
  process.exit(code ?? 0);
2684
5076
  }
2685
5077
  });
2686
5078
  };
2687
5079
  spawnElectron();
2688
5080
  if (config.electron.autoRestart) {
2689
- const watchTargets = [mainEntry, ...preloadEntries].filter(import_node_fs10.default.existsSync);
5081
+ const watchTargets = [mainEntry, ...preloadEntries].filter(import_node_fs11.default.existsSync);
2690
5082
  const watcher = import_chokidar2.default.watch(watchTargets, { ignoreInitial: true });
2691
5083
  let restarting = null;
2692
5084
  let pending = false;
@@ -2698,7 +5090,7 @@ async function startElectronDev(inlineConfig = {}) {
2698
5090
  restarting = (async () => {
2699
5091
  do {
2700
5092
  pending = false;
2701
- console.log(import_picocolors4.default.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
5093
+ console.log(import_picocolors10.default.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
2702
5094
  if (child && !child.killed) {
2703
5095
  ;
2704
5096
  child.__nastiKilled = true;
@@ -2716,7 +5108,7 @@ async function startElectronDev(inlineConfig = {}) {
2716
5108
  await compileAll();
2717
5109
  spawnElectron();
2718
5110
  } catch (e) {
2719
- console.warn(import_picocolors4.default.yellow(` \u26A0 \u91CD\u542F\u7F16\u8BD1\u5931\u8D25\uFF0C\u4FDD\u7559\u4E0A\u4E00\u6B21\u8FDB\u7A0B: ${e.message}`));
5111
+ console.warn(import_picocolors10.default.yellow(` \u26A0 \u91CD\u542F\u7F16\u8BD1\u5931\u8D25\uFF0C\u4FDD\u7559\u4E0A\u4E00\u6B21\u8FDB\u7A0B: ${e.message}`));
2720
5112
  }
2721
5113
  } while (pending);
2722
5114
  restarting = null;
@@ -2756,14 +5148,14 @@ async function compileNode(config, entry, opts) {
2756
5148
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
2757
5149
  }
2758
5150
  };
2759
- const bundle = await (0, import_rolldown3.rolldown)({
5151
+ const bundle2 = await (0, import_rolldown3.rolldown)({
2760
5152
  input: entry,
2761
5153
  transform: { define: envDefine },
2762
5154
  platform: "node",
2763
5155
  plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
2764
5156
  });
2765
- import_node_fs10.default.mkdirSync(import_node_path13.default.dirname(opts.outFile), { recursive: true });
2766
- await bundle.write({
5157
+ import_node_fs11.default.mkdirSync(import_node_path16.default.dirname(opts.outFile), { recursive: true });
5158
+ await bundle2.write({
2767
5159
  file: opts.outFile,
2768
5160
  format: opts.format === "cjs" ? "cjs" : "esm",
2769
5161
  sourcemap: false,
@@ -2772,17 +5164,17 @@ async function compileNode(config, entry, opts) {
2772
5164
  // 同样语义(单 chunk、内联 dynamic import)
2773
5165
  codeSplitting: false
2774
5166
  });
2775
- await bundle.close();
5167
+ await bundle2.close();
2776
5168
  }
2777
5169
  function resolveElectronBinary(config) {
2778
- if (config.electron.electronPath && import_node_fs10.default.existsSync(config.electron.electronPath)) {
5170
+ if (config.electron.electronPath && import_node_fs11.default.existsSync(config.electron.electronPath)) {
2779
5171
  return config.electron.electronPath;
2780
5172
  }
2781
5173
  try {
2782
- const require2 = (0, import_node_module5.createRequire)(import_node_path13.default.resolve(config.root, "package.json"));
5174
+ const require2 = (0, import_node_module7.createRequire)(import_node_path16.default.resolve(config.root, "package.json"));
2783
5175
  const pathFile = require2.resolve("electron");
2784
5176
  const electronModule = require2(pathFile);
2785
- if (typeof electronModule === "string" && import_node_fs10.default.existsSync(electronModule)) {
5177
+ if (typeof electronModule === "string" && import_node_fs11.default.existsSync(electronModule)) {
2786
5178
  return electronModule;
2787
5179
  }
2788
5180
  } catch {
@@ -2793,7 +5185,7 @@ function warnElectronVersion(config) {
2793
5185
  const installed = detectInstalledElectron(config.root);
2794
5186
  if (installed === null) {
2795
5187
  console.warn(
2796
- import_picocolors4.default.yellow(
5188
+ import_picocolors10.default.yellow(
2797
5189
  ` \u26A0 \u672A\u68C0\u6D4B\u5230 Electron\uFF0C\u8BF7\u5B89\u88C5\uFF1Anpm install -D electron@^${config.electron.minVersion}`
2798
5190
  )
2799
5191
  );
@@ -2801,7 +5193,7 @@ function warnElectronVersion(config) {
2801
5193
  }
2802
5194
  if (installed < config.electron.minVersion) {
2803
5195
  console.warn(
2804
- import_picocolors4.default.yellow(
5196
+ import_picocolors10.default.yellow(
2805
5197
  ` \u26A0 Electron ${installed} \u4F4E\u4E8E Nasti \u8981\u6C42\u7684 ${config.electron.minVersion}\uFF0C\u67D0\u4E9B\u7279\u6027\uFF08\u5982 ESM \u4E3B\u8FDB\u7A0B\uFF09\u4E0D\u53EF\u7528\u3002`
2806
5198
  )
2807
5199
  );
@@ -2809,10 +5201,10 @@ function warnElectronVersion(config) {
2809
5201
  }
2810
5202
 
2811
5203
  // src/plugins/monaco-editor.ts
2812
- var import_node_path14 = __toESM(require("path"), 1);
2813
- var import_node_fs11 = __toESM(require("fs"), 1);
2814
- var import_node_crypto3 = __toESM(require("crypto"), 1);
2815
- var import_node_module6 = require("module");
5204
+ var import_node_path17 = __toESM(require("path"), 1);
5205
+ var import_node_fs12 = __toESM(require("fs"), 1);
5206
+ var import_node_crypto4 = __toESM(require("crypto"), 1);
5207
+ var import_node_module8 = require("module");
2816
5208
  var DEFAULT_WORKERS = {
2817
5209
  editorWorkerService: "monaco-editor/esm/vs/editor/editor.worker",
2818
5210
  css: "monaco-editor/esm/vs/language/css/css.worker",
@@ -2831,9 +5223,9 @@ function normalizePublicPath(p) {
2831
5223
  }
2832
5224
  function readMonacoVersion(root) {
2833
5225
  try {
2834
- const require2 = (0, import_node_module6.createRequire)(import_node_path14.default.resolve(root, "package.json"));
5226
+ const require2 = (0, import_node_module8.createRequire)(import_node_path17.default.resolve(root, "package.json"));
2835
5227
  const pkgJsonPath = require2.resolve("monaco-editor/package.json", { paths: [root] });
2836
- const pkg = JSON.parse(import_node_fs11.default.readFileSync(pkgJsonPath, "utf-8"));
5228
+ const pkg = JSON.parse(import_node_fs12.default.readFileSync(pkgJsonPath, "utf-8"));
2837
5229
  return typeof pkg.version === "string" ? pkg.version : "unknown";
2838
5230
  } catch {
2839
5231
  return "unknown";
@@ -2853,32 +5245,32 @@ function monacoEditorPlugin(options = {}) {
2853
5245
  let cacheDir = "";
2854
5246
  const building = /* @__PURE__ */ new Map();
2855
5247
  async function buildWorker(worker) {
2856
- const cacheFile = import_node_path14.default.join(cacheDir, `${worker.label}.worker.js`);
2857
- if (import_node_fs11.default.existsSync(cacheFile)) return cacheFile;
5248
+ const cacheFile = import_node_path17.default.join(cacheDir, `${worker.label}.worker.js`);
5249
+ if (import_node_fs12.default.existsSync(cacheFile)) return cacheFile;
2858
5250
  const existing = building.get(worker.label);
2859
5251
  if (existing) return existing;
2860
5252
  const task = (async () => {
2861
5253
  const { rolldown: rolldown4 } = await import("rolldown");
2862
- const require2 = (0, import_node_module6.createRequire)(import_node_path14.default.resolve(resolvedConfig.root, "package.json"));
5254
+ const require2 = (0, import_node_module8.createRequire)(import_node_path17.default.resolve(resolvedConfig.root, "package.json"));
2863
5255
  let entry;
2864
5256
  try {
2865
5257
  entry = require2.resolve(worker.entry, { paths: [resolvedConfig.root] });
2866
5258
  } catch {
2867
5259
  entry = require2.resolve(worker.entry + ".js", { paths: [resolvedConfig.root] });
2868
5260
  }
2869
- import_node_fs11.default.mkdirSync(cacheDir, { recursive: true });
2870
- const bundle = await rolldown4({
5261
+ import_node_fs12.default.mkdirSync(cacheDir, { recursive: true });
5262
+ const bundle2 = await rolldown4({
2871
5263
  input: entry,
2872
5264
  platform: "browser"
2873
5265
  });
2874
- await bundle.write({
5266
+ await bundle2.write({
2875
5267
  file: cacheFile,
2876
5268
  format: "iife",
2877
5269
  sourcemap: false,
2878
5270
  minify: true,
2879
5271
  codeSplitting: false
2880
5272
  });
2881
- await bundle.close();
5273
+ await bundle2.close();
2882
5274
  return cacheFile;
2883
5275
  })();
2884
5276
  building.set(worker.label, task);
@@ -2925,13 +5317,13 @@ function monacoEditorPlugin(options = {}) {
2925
5317
  configResolved(config) {
2926
5318
  resolvedConfig = config;
2927
5319
  const version = readMonacoVersion(config.root);
2928
- const key = import_node_crypto3.default.createHash("sha1").update(version + "|" + publicPath).digest("hex").slice(0, 8);
2929
- cacheDir = import_node_path14.default.resolve(config.root, "node_modules/.nasti/monaco", key);
5320
+ const key = import_node_crypto4.default.createHash("sha1").update(version + "|" + publicPath).digest("hex").slice(0, 8);
5321
+ cacheDir = import_node_path17.default.resolve(config.root, "node_modules/.nasti/monaco", key);
2930
5322
  },
2931
5323
  async configureServer(server) {
2932
5324
  const shouldBuild = !isCDN(publicPath) || forceBuildCDN;
2933
5325
  const watcher = server.watcher;
2934
- const monacoDir = import_node_path14.default.resolve(resolvedConfig.root, "node_modules/monaco-editor");
5326
+ const monacoDir = import_node_path17.default.resolve(resolvedConfig.root, "node_modules/monaco-editor");
2935
5327
  try {
2936
5328
  watcher?.unwatch?.(monacoDir);
2937
5329
  } catch {
@@ -2961,7 +5353,7 @@ function monacoEditorPlugin(options = {}) {
2961
5353
  const file = await buildWorker(worker);
2962
5354
  res.setHeader("Content-Type", "application/javascript; charset=utf-8");
2963
5355
  res.setHeader("Cache-Control", "public, max-age=604800, immutable");
2964
- import_node_fs11.default.createReadStream(file).pipe(res);
5356
+ import_node_fs12.default.createReadStream(file).pipe(res);
2965
5357
  } catch (e) {
2966
5358
  res.statusCode = 500;
2967
5359
  res.end(`Monaco worker build failed: ${e.message}`);
@@ -2996,16 +5388,16 @@ self.monaco = monaco;`,
2996
5388
  resolvedConfig.root,
2997
5389
  resolvedConfig.build.outDir,
2998
5390
  resolvedConfig.base
2999
- ) : isCDN(publicPath) ? import_node_path14.default.resolve(resolvedConfig.root, resolvedConfig.build.outDir, "monaco") : import_node_path14.default.resolve(
5391
+ ) : isCDN(publicPath) ? import_node_path17.default.resolve(resolvedConfig.root, resolvedConfig.build.outDir, "monaco") : import_node_path17.default.resolve(
3000
5392
  resolvedConfig.root,
3001
5393
  resolvedConfig.build.outDir,
3002
5394
  publicPath.replace(/^\//, "")
3003
5395
  );
3004
- import_node_fs11.default.mkdirSync(outDir, { recursive: true });
5396
+ import_node_fs12.default.mkdirSync(outDir, { recursive: true });
3005
5397
  for (const worker of workers) {
3006
5398
  try {
3007
5399
  const cacheFile = await buildWorker(worker);
3008
- import_node_fs11.default.copyFileSync(cacheFile, import_node_path14.default.join(outDir, `${worker.label}.worker.js`));
5400
+ import_node_fs12.default.copyFileSync(cacheFile, import_node_path17.default.join(outDir, `${worker.label}.worker.js`));
3009
5401
  } catch (e) {
3010
5402
  throw new Error(
3011
5403
  `[nasti:monaco-editor] worker build failed for "${worker.label}": ${e.message}
@@ -3016,15 +5408,33 @@ ${e.stack || ""}`
3016
5408
  }
3017
5409
  };
3018
5410
  }
5411
+
5412
+ // src/index.ts
5413
+ init_environment();
5414
+ init_hot_channel();
5415
+ init_logger();
5416
+ init_debug();
5417
+ init_env();
3019
5418
  // Annotate the CommonJS export names for ESM import in node:
3020
5419
  0 && (module.exports = {
5420
+ LogLevels,
5421
+ NastiEnvironment,
3021
5422
  build,
3022
5423
  buildElectron,
5424
+ buildEnvDefine,
5425
+ createDebugger,
5426
+ createLogger,
5427
+ createNoopHotChannel,
3023
5428
  createServer,
5429
+ createWsHotChannel,
3024
5430
  defineConfig,
3025
5431
  electronPlugin,
5432
+ loadEnv,
3026
5433
  monacoEditorPlugin,
5434
+ printServerUrls,
3027
5435
  resolveConfig,
5436
+ resolveEnvironmentPlugins,
5437
+ ssrDefineOverrides,
3028
5438
  startElectronDev
3029
5439
  });
3030
5440
  //# sourceMappingURL=index.cjs.map