@nasti-toolchain/nasti 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -164,6 +164,14 @@ async function resolveConfig(inlineConfig = {}, command) {
164
164
  return p.apply === command;
165
165
  });
166
166
  resolved.plugins = filteredPlugins;
167
+ if (resolved.target === "electron") {
168
+ const autoExternal = detectNativeDeps(root);
169
+ if (autoExternal.length > 0) {
170
+ const current = new Set(resolved.electron.external ?? []);
171
+ for (const dep of autoExternal) current.add(dep);
172
+ resolved.electron.external = [...current];
173
+ }
174
+ }
167
175
  for (const plugin of resolved.plugins) {
168
176
  if (plugin.configResolved) {
169
177
  await plugin.configResolved(resolved);
@@ -171,6 +179,73 @@ async function resolveConfig(inlineConfig = {}, command) {
171
179
  }
172
180
  return resolved;
173
181
  }
182
+ function detectNativeDeps(root) {
183
+ const result = /* @__PURE__ */ new Set();
184
+ const pkgJsonPath = path.resolve(root, "package.json");
185
+ if (!fs.existsSync(pkgJsonPath)) return [];
186
+ let pkg;
187
+ try {
188
+ pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
189
+ } catch {
190
+ return [];
191
+ }
192
+ const deps = {
193
+ ...pkg.dependencies ?? {},
194
+ ...pkg.optionalDependencies ?? {}
195
+ };
196
+ const KNOWN_NATIVE = /* @__PURE__ */ new Set([
197
+ "node-pty",
198
+ "better-sqlite3",
199
+ "sharp",
200
+ "serialport",
201
+ "@vscode/tree-sitter-wasm",
202
+ "keytar",
203
+ "nodegit",
204
+ "sqlite3",
205
+ "fsevents"
206
+ ]);
207
+ for (const dep of Object.keys(deps)) {
208
+ if (KNOWN_NATIVE.has(dep)) {
209
+ result.add(dep);
210
+ continue;
211
+ }
212
+ const depDir = path.resolve(root, "node_modules", dep);
213
+ if (!fs.existsSync(depDir)) continue;
214
+ if (fs.existsSync(path.join(depDir, "binding.gyp"))) {
215
+ result.add(dep);
216
+ continue;
217
+ }
218
+ const subPkg = path.join(depDir, "package.json");
219
+ if (fs.existsSync(subPkg)) {
220
+ try {
221
+ const sub = JSON.parse(fs.readFileSync(subPkg, "utf-8"));
222
+ if (sub.gypfile === true || sub.binary?.module_name) {
223
+ result.add(dep);
224
+ continue;
225
+ }
226
+ } catch {
227
+ }
228
+ }
229
+ if (hasDotNodeFile(depDir)) {
230
+ result.add(dep);
231
+ }
232
+ }
233
+ return [...result];
234
+ }
235
+ function hasDotNodeFile(dir, depth = 0) {
236
+ if (depth > 3) return false;
237
+ try {
238
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
239
+ for (const e of entries) {
240
+ if (e.isFile() && e.name.endsWith(".node")) return true;
241
+ if (e.isDirectory() && (e.name === "build" || e.name === "prebuilds" || e.name === "Release")) {
242
+ if (hasDotNodeFile(path.join(dir, e.name), depth + 1)) return true;
243
+ }
244
+ }
245
+ } catch {
246
+ }
247
+ return false;
248
+ }
174
249
  function deepMerge(target, source) {
175
250
  const result = { ...target };
176
251
  for (const key of Object.keys(source)) {
@@ -415,6 +490,15 @@ function htmlPlugin(config) {
415
490
  transformIndexHtml(html) {
416
491
  const tags = [];
417
492
  if (config.command === "serve") {
493
+ const isReactLike = config.framework === "react" || config.framework === "auto";
494
+ if (isReactLike) {
495
+ tags.push({
496
+ tag: "script",
497
+ attrs: { type: "module" },
498
+ children: REACT_REFRESH_HTML_PREAMBLE,
499
+ injectTo: "head-prepend"
500
+ });
501
+ }
418
502
  tags.push({
419
503
  tag: "script",
420
504
  attrs: { type: "module", src: "/@nasti/client" },
@@ -465,9 +549,17 @@ async function readHtmlFile(root) {
465
549
  if (!fs4.existsSync(htmlPath)) return null;
466
550
  return fs4.readFileSync(htmlPath, "utf-8");
467
551
  }
552
+ var REACT_REFRESH_HTML_PREAMBLE;
468
553
  var init_html = __esm({
469
554
  "src/plugins/html.ts"() {
470
555
  "use strict";
556
+ REACT_REFRESH_HTML_PREAMBLE = `
557
+ import RefreshRuntime from "/@react-refresh";
558
+ RefreshRuntime.injectIntoGlobalHook(window);
559
+ window.$RefreshReg$ = () => {};
560
+ window.$RefreshSig$ = () => (type) => type;
561
+ window.__vite_plugin_react_preamble_installed__ = true;
562
+ `.trim();
471
563
  }
472
564
  });
473
565
 
@@ -701,7 +793,7 @@ import pc from "picocolors";
701
793
  async function build(inlineConfig = {}) {
702
794
  const config = await resolveConfig(inlineConfig, "build");
703
795
  const startTime = performance.now();
704
- console.log(pc.cyan("\n\u{1F528} nasti build") + pc.dim(` v${"1.5.0"}`));
796
+ console.log(pc.cyan("\n\u{1F528} nasti build") + pc.dim(` v${"1.5.1"}`));
705
797
  console.log(pc.dim(` root: ${config.root}`));
706
798
  console.log(pc.dim(` mode: ${config.mode}`));
707
799
  const outDir = path7.resolve(config.root, config.build.outDir);
@@ -1005,11 +1097,85 @@ var init_ws = __esm({
1005
1097
  // src/server/middleware.ts
1006
1098
  var middleware_exports = {};
1007
1099
  __export(middleware_exports, {
1100
+ REACT_REFRESH_GLOBAL_PREAMBLE: () => REACT_REFRESH_GLOBAL_PREAMBLE,
1008
1101
  transformMiddleware: () => transformMiddleware,
1009
1102
  transformRequest: () => transformRequest
1010
1103
  });
1011
1104
  import path9 from "path";
1012
1105
  import fs8 from "fs";
1106
+ import { createRequire as createRequire2 } from "module";
1107
+ import { fileURLToPath } from "url";
1108
+ function getReactRefreshRuntimeEsm() {
1109
+ if (__refreshRuntimeCache) return __refreshRuntimeCache;
1110
+ let cjsPath;
1111
+ try {
1112
+ cjsPath = __require.resolve("react-refresh/cjs/react-refresh-runtime.development.js");
1113
+ } catch {
1114
+ cjsPath = path9.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
1115
+ }
1116
+ const cjsSource = fs8.readFileSync(cjsPath, "utf-8");
1117
+ __refreshRuntimeCache = `// Wrapped react-refresh runtime -> ESM
1118
+ const exports = {};
1119
+ const module = { exports };
1120
+ const process = { env: { NODE_ENV: 'development' } };
1121
+ ${cjsSource}
1122
+ const __rt = module.exports;
1123
+ export const injectIntoGlobalHook = __rt.injectIntoGlobalHook;
1124
+ export const register = __rt.register;
1125
+ export const createSignatureFunctionForTransform = __rt.createSignatureFunctionForTransform;
1126
+ export const performReactRefresh = __rt.performReactRefresh;
1127
+ export const isLikelyComponentType = __rt.isLikelyComponentType;
1128
+ export const hasUnrecoverableErrors = __rt.hasUnrecoverableErrors;
1129
+ export const setSignature = __rt.setSignature;
1130
+ export const getFamilyByID = __rt.getFamilyByID;
1131
+ export const getFamilyByType = __rt.getFamilyByType;
1132
+ export const findAffectedHostInstances = __rt.findAffectedHostInstances;
1133
+ export const collectCustomHooksForSignature = __rt.collectCustomHooksForSignature;
1134
+ export default __rt;
1135
+ `;
1136
+ return __refreshRuntimeCache;
1137
+ }
1138
+ function buildReactRefreshWrapper(moduleUrl, transformedCode) {
1139
+ const urlLit = JSON.stringify(moduleUrl);
1140
+ const userCode = transformedCode.replace(/\bimport\.meta\.hot\b/g, "__nasti_hot__");
1141
+ return `import * as RefreshRuntime from "/@react-refresh";
1142
+ import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
1143
+ const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
1144
+
1145
+ if (!window.__vite_plugin_react_preamble_installed__) {
1146
+ throw new Error("[nasti] React Fast Refresh preamble missing. Make sure nasti:html is wired with framework: 'react'.");
1147
+ }
1148
+
1149
+ const prevRefreshReg = window.$RefreshReg$;
1150
+ const prevRefreshSig = window.$RefreshSig$;
1151
+ window.$RefreshReg$ = (type, id) => {
1152
+ RefreshRuntime.register(type, ${urlLit} + " " + id);
1153
+ };
1154
+ window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
1155
+
1156
+ ${userCode}
1157
+
1158
+ window.$RefreshReg$ = prevRefreshReg;
1159
+ window.$RefreshSig$ = prevRefreshSig;
1160
+
1161
+ if (__nasti_hot__) {
1162
+ __nasti_hot__.accept(() => {
1163
+ clearTimeout(window.__nasti_refresh_timer__);
1164
+ window.__nasti_refresh_timer__ = setTimeout(() => {
1165
+ RefreshRuntime.performReactRefresh();
1166
+ }, 30);
1167
+ });
1168
+ }
1169
+ `;
1170
+ }
1171
+ function injectImportMetaHot(code, moduleUrl) {
1172
+ if (!/\bimport\.meta\.hot\b/.test(code)) return code;
1173
+ const urlLit = JSON.stringify(moduleUrl);
1174
+ const header = `import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
1175
+ const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
1176
+ `;
1177
+ return header + code.replace(/\bimport\.meta\.hot\b/g, "__nasti_hot__");
1178
+ }
1013
1179
  function transformMiddleware(ctx) {
1014
1180
  ctx.envDefine = buildEnvDefine(
1015
1181
  loadEnv(ctx.config.mode, ctx.config.root, ctx.config.envPrefix),
@@ -1083,7 +1249,7 @@ async function transformRequest(url, ctx) {
1083
1249
  return cached.transformResult;
1084
1250
  }
1085
1251
  if (cleanReqUrl === "/@react-refresh") {
1086
- return { code: REACT_REFRESH_RUNTIME };
1252
+ return { code: getReactRefreshRuntimeEsm() };
1087
1253
  }
1088
1254
  const filePath = resolveUrlToFile(url, config.root);
1089
1255
  if (!filePath || !fs8.existsSync(filePath)) return null;
@@ -1100,6 +1266,8 @@ async function transformRequest(url, ctx) {
1100
1266
  if (pluginResult) {
1101
1267
  code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
1102
1268
  }
1269
+ const stableUrl = cleanReqUrl;
1270
+ let wrappedWithRefresh = false;
1103
1271
  if (shouldTransform(filePath)) {
1104
1272
  const isJsx = /\.[jt]sx$/.test(filePath);
1105
1273
  const useRefresh = isJsx && config.framework !== "vue";
@@ -1111,9 +1279,14 @@ async function transformRequest(url, ctx) {
1111
1279
  });
1112
1280
  code = result.code;
1113
1281
  if (useRefresh) {
1114
- code = REACT_REFRESH_PREAMBLE + code + REACT_REFRESH_FOOTER;
1282
+ code = buildReactRefreshWrapper(stableUrl, code);
1283
+ wrappedWithRefresh = true;
1284
+ mod.isSelfAccepting = true;
1115
1285
  }
1116
1286
  }
1287
+ if (!wrappedWithRefresh) {
1288
+ code = injectImportMetaHot(code, stableUrl);
1289
+ }
1117
1290
  const envDefine = ctx.envDefine ?? buildEnvDefine(
1118
1291
  loadEnv(config.mode, config.root, config.envPrefix),
1119
1292
  config.mode
@@ -1181,8 +1354,8 @@ function rewriteExternalRequires(code) {
1181
1354
  }
1182
1355
  async function injectCjsNamedExports(code, entryFile) {
1183
1356
  try {
1184
- const { createRequire: createRequire4 } = await import("module");
1185
- const req = createRequire4(entryFile);
1357
+ const { createRequire: createRequire5 } = await import("module");
1358
+ const req = createRequire5(entryFile);
1186
1359
  const cjsExports = req(entryFile);
1187
1360
  if (!cjsExports || typeof cjsExports !== "object" && typeof cjsExports !== "function" || Array.isArray(cjsExports)) return code;
1188
1361
  const namedKeys = Object.keys(cjsExports).filter(
@@ -1345,12 +1518,15 @@ function getHmrClientCode() {
1345
1518
  // Nasti HMR Client
1346
1519
  const socket = new WebSocket(\`ws://\${location.host}\`, 'nasti-hmr');
1347
1520
  const hotModulesMap = new Map();
1521
+ const disposeMap = new Map();
1522
+ const pruneMap = new Map();
1348
1523
 
1349
1524
  socket.addEventListener('message', ({ data }) => {
1350
1525
  const payload = JSON.parse(data);
1351
1526
  switch (payload.type) {
1352
1527
  case 'connected':
1353
1528
  console.log('[nasti] connected.');
1529
+ clearErrorOverlay();
1354
1530
  break;
1355
1531
  case 'update':
1356
1532
  payload.updates.forEach((update) => {
@@ -1360,11 +1536,18 @@ socket.addEventListener('message', ({ data }) => {
1360
1536
  updateCss(update.path);
1361
1537
  }
1362
1538
  });
1539
+ clearErrorOverlay();
1363
1540
  break;
1364
1541
  case 'full-reload':
1365
1542
  console.log('[nasti] full reload');
1366
1543
  location.reload();
1367
1544
  break;
1545
+ case 'prune':
1546
+ payload.paths.forEach((p) => {
1547
+ const cb = pruneMap.get(p);
1548
+ if (cb) cb();
1549
+ });
1550
+ break;
1368
1551
  case 'error':
1369
1552
  console.error('[nasti] error:', payload.err.message);
1370
1553
  showErrorOverlay(payload.err);
@@ -1372,14 +1555,23 @@ socket.addEventListener('message', ({ data }) => {
1372
1555
  }
1373
1556
  });
1374
1557
 
1558
+ // \u81EA\u52A8\u91CD\u8FDE\uFF08\u65AD\u7EBF\u65F6\u6307\u6570\u9000\u907F\uFF09
1559
+ let reconnectTimer = 0;
1560
+ socket.addEventListener('close', () => {
1561
+ clearTimeout(reconnectTimer);
1562
+ reconnectTimer = setTimeout(() => location.reload(), 1000);
1563
+ });
1564
+
1375
1565
  async function fetchUpdate(update) {
1376
1566
  const mod = hotModulesMap.get(update.path);
1567
+ // \u5148\u8DD1 dispose\uFF08\u7ED9\u6A21\u5757\u673A\u4F1A\u6E05\u7406\u526F\u4F5C\u7528\uFF09
1568
+ const dispose = disposeMap.get(update.path);
1569
+ if (dispose) dispose();
1570
+
1571
+ const newMod = await import(update.acceptedPath + '?t=' + update.timestamp);
1377
1572
  if (mod) {
1378
- const newMod = await import(update.acceptedPath + '?t=' + update.timestamp);
1379
- mod.callbacks.forEach((cb) => cb(newMod));
1380
- } else {
1381
- // \u6CA1\u6709\u6CE8\u518C hot \u56DE\u8C03\uFF0C\u5C1D\u8BD5\u91CD\u65B0 import
1382
- await import(update.path + '?t=' + update.timestamp);
1573
+ // \u590D\u5236\u56DE\u8C03\u6570\u7EC4\u907F\u514D\u56DE\u8C03\u5185\u90E8\u53C8\u4FEE\u6539 hotModulesMap \u9020\u6210\u8FED\u4EE3\u5F02\u5E38
1574
+ [...mod.callbacks].forEach((cb) => cb(newMod));
1383
1575
  }
1384
1576
  }
1385
1577
 
@@ -1392,7 +1584,13 @@ function updateCss(path) {
1392
1584
  }
1393
1585
  }
1394
1586
 
1587
+ function clearErrorOverlay() {
1588
+ const el = document.getElementById('nasti-error-overlay');
1589
+ if (el) el.remove();
1590
+ }
1591
+
1395
1592
  function showErrorOverlay(err) {
1593
+ clearErrorOverlay();
1396
1594
  const overlay = document.createElement('div');
1397
1595
  overlay.id = 'nasti-error-overlay';
1398
1596
  overlay.style.cssText = 'position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,0.85);color:#fff;font-family:monospace;padding:2rem;overflow:auto;';
@@ -1411,59 +1609,55 @@ function showErrorOverlay(err) {
1411
1609
  document.body.appendChild(overlay);
1412
1610
  }
1413
1611
 
1414
- // import.meta.hot API
1415
- const createHotContext = (ownerPath) => ({
1416
- accept(deps, callback) {
1417
- if (typeof deps === 'function' || !deps) {
1418
- // self-accepting
1419
- const callbacks = hotModulesMap.get(ownerPath)?.callbacks || [];
1420
- callbacks.push(deps || (() => {}));
1421
- hotModulesMap.set(ownerPath, { callbacks });
1422
- }
1423
- },
1424
- prune(callback) {
1425
- // \u6A21\u5757\u88AB\u79FB\u9664\u65F6\u6267\u884C
1426
- },
1427
- dispose(callback) {
1428
- // \u6A21\u5757\u66F4\u65B0\u524D\u6267\u884C\u6E05\u7406
1429
- },
1430
- invalidate() {
1431
- location.reload();
1432
- },
1433
- data: {},
1434
- });
1435
-
1436
- // \u66B4\u9732\u7ED9\u6A21\u5757\u4F7F\u7528
1437
- if (!window.__nasti_hot_map) window.__nasti_hot_map = new Map();
1438
- window.__NASTI_HMR__ = { createHotContext };
1612
+ /**
1613
+ * \u751F\u6210 import.meta.hot \u7684 hot context\u3002
1614
+ * \u5173\u952E\u7EA6\u675F\uFF1A\u540C\u4E00 ownerPath \u7684 accept \u56DE\u8C03\u5FC5\u987B\u66FF\u6362\uFF08\u4E0D\u662F append\uFF09\u3002
1615
+ * \u6BCF\u6B21\u6A21\u5757\u91CD\u65B0 import \u90FD\u4F1A\u8C03\u7528 createHotContext\uFF0C\u65E7\u56DE\u8C03\u4F1A\u88AB fetchUpdate \u8C03\u7528\u540E\u7ACB\u5373\u88AB\u65B0 import
1616
+ * \u91CC\u7684 accept \u66FF\u6362\u3002\u4E0D\u66FF\u6362\u7684\u8BDD\u6BCF\u7F16\u8F91\u4E00\u6B21\u5C31\u591A\u4E00\u4E2A\u56DE\u8C03\uFF0C\u8D8A\u8DD1\u8D8A\u6162\u3002
1617
+ */
1618
+ export function createHotContext(ownerPath) {
1619
+ return {
1620
+ accept(deps, callback) {
1621
+ // \u81EA\u63A5\u53D7: hot.accept() \u6216 hot.accept(callback)
1622
+ if (typeof deps === 'function' || deps === undefined) {
1623
+ hotModulesMap.set(ownerPath, { callbacks: [deps || (() => {})] });
1624
+ return;
1625
+ }
1626
+ // \u4F9D\u8D56\u63A5\u53D7: hot.accept(deps, callback)\uFF0C\u591A\u6B21\u8C03\u7528\u8FFD\u52A0
1627
+ const existing = hotModulesMap.get(ownerPath)?.callbacks ?? [];
1628
+ hotModulesMap.set(ownerPath, { callbacks: [...existing, callback] });
1629
+ },
1630
+ prune(callback) {
1631
+ pruneMap.set(ownerPath, callback);
1632
+ },
1633
+ dispose(callback) {
1634
+ disposeMap.set(ownerPath, callback);
1635
+ },
1636
+ invalidate() {
1637
+ location.reload();
1638
+ },
1639
+ data: {},
1640
+ };
1641
+ }
1439
1642
  `;
1440
1643
  }
1441
- var REACT_REFRESH_RUNTIME, REACT_REFRESH_PREAMBLE, REACT_REFRESH_FOOTER, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
1644
+ var __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
1442
1645
  var init_middleware = __esm({
1443
1646
  "src/server/middleware.ts"() {
1444
1647
  "use strict";
1445
1648
  init_transformer();
1446
1649
  init_html();
1447
1650
  init_env();
1448
- REACT_REFRESH_RUNTIME = `
1449
- export function createSignatureFunctionForTransform() {
1450
- return function(type, key, forceReset, getCustomHooks) { return type; };
1451
- }
1452
- export function register(type, id) {}
1453
- export default { createSignatureFunctionForTransform, register };
1454
- `;
1455
- REACT_REFRESH_PREAMBLE = `
1456
- import RefreshRuntime from '/@react-refresh';
1457
- if (!window.$RefreshReg$) {
1458
- window.$RefreshReg$ = (type, id) => RefreshRuntime.register(type, import.meta.url + ' ' + id);
1459
- window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
1460
- }
1461
- `;
1462
- REACT_REFRESH_FOOTER = `
1463
- if (import.meta.hot) {
1464
- import.meta.hot.accept();
1465
- }
1466
- `;
1651
+ __dirname_esm = path9.dirname(fileURLToPath(import.meta.url));
1652
+ __require = createRequire2(import.meta.url);
1653
+ __refreshRuntimeCache = null;
1654
+ REACT_REFRESH_GLOBAL_PREAMBLE = `
1655
+ import RefreshRuntime from "/@react-refresh";
1656
+ RefreshRuntime.injectIntoGlobalHook(window);
1657
+ window.$RefreshReg$ = () => {};
1658
+ window.$RefreshSig$ = () => (type) => type;
1659
+ window.__vite_plugin_react_preamble_installed__ = true;
1660
+ `.trim();
1467
1661
  esmBundleCache = /* @__PURE__ */ new Map();
1468
1662
  VALID_IDENT = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
1469
1663
  RESOLVE_EXTENSIONS = [".tsx", ".ts", ".jsx", ".js", ".mjs", ".json", ".vue"];
@@ -1595,7 +1789,7 @@ async function createServer(inlineConfig = {}) {
1595
1789
  const localUrl = `http://localhost:${actualPort}`;
1596
1790
  const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
1597
1791
  console.log();
1598
- console.log(pc3.cyan(" nasti dev server") + pc3.dim(` v${"1.5.0"}`));
1792
+ console.log(pc3.cyan(" nasti dev server") + pc3.dim(` v${"1.5.1"}`));
1599
1793
  console.log();
1600
1794
  console.log(` ${pc3.green(">")} Local: ${pc3.cyan(localUrl)}`);
1601
1795
  if (networkUrl) {
@@ -1719,7 +1913,7 @@ async function buildElectron(inlineConfig = {}) {
1719
1913
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
1720
1914
  const startTime = performance.now();
1721
1915
  assertElectronVersion(config);
1722
- console.log(pc2.cyan("\n\u26A1 nasti build (electron)") + pc2.dim(` v${"1.5.0"}`));
1916
+ console.log(pc2.cyan("\n\u26A1 nasti build (electron)") + pc2.dim(` v${"1.5.1"}`));
1723
1917
  console.log(pc2.dim(` root: ${config.root}`));
1724
1918
  console.log(pc2.dim(` mode: ${config.mode}`));
1725
1919
  console.log(pc2.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
@@ -1854,7 +2048,7 @@ init_server();
1854
2048
  init_config();
1855
2049
  import path12 from "path";
1856
2050
  import fs10 from "fs";
1857
- import { createRequire as createRequire2 } from "module";
2051
+ import { createRequire as createRequire3 } from "module";
1858
2052
  import { spawn } from "child_process";
1859
2053
  import chokidar from "chokidar";
1860
2054
  import pc4 from "picocolors";
@@ -1866,7 +2060,7 @@ async function startElectronDev(inlineConfig = {}) {
1866
2060
  const { noSpawn, ...rest } = inlineConfig;
1867
2061
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
1868
2062
  warnElectronVersion(config);
1869
- console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.5.0"}`));
2063
+ console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.5.1"}`));
1870
2064
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
1871
2065
  const server = await createServer2({ ...rest, target: "electron" });
1872
2066
  await server.listen();
@@ -1930,11 +2124,16 @@ async function startElectronDev(inlineConfig = {}) {
1930
2124
  const watchTargets = [mainEntry, ...preloadEntries].filter(fs10.existsSync);
1931
2125
  const watcher = chokidar.watch(watchTargets, { ignoreInitial: true });
1932
2126
  let restarting = null;
1933
- watcher.on("all", async () => {
1934
- if (restarting) return;
2127
+ let pending = false;
2128
+ const restart = async () => {
2129
+ if (restarting) {
2130
+ pending = true;
2131
+ return;
2132
+ }
1935
2133
  restarting = (async () => {
1936
- console.log(pc4.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
1937
- try {
2134
+ do {
2135
+ pending = false;
2136
+ console.log(pc4.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
1938
2137
  if (child && !child.killed) {
1939
2138
  ;
1940
2139
  child.__nastiKilled = true;
@@ -1948,12 +2147,24 @@ async function startElectronDev(inlineConfig = {}) {
1948
2147
  dying.kill();
1949
2148
  });
1950
2149
  }
1951
- await compileAll();
1952
- spawnElectron();
1953
- } finally {
1954
- restarting = null;
1955
- }
2150
+ try {
2151
+ await compileAll();
2152
+ spawnElectron();
2153
+ } catch (e) {
2154
+ console.warn(pc4.yellow(` \u26A0 \u91CD\u542F\u7F16\u8BD1\u5931\u8D25\uFF0C\u4FDD\u7559\u4E0A\u4E00\u6B21\u8FDB\u7A0B: ${e.message}`));
2155
+ }
2156
+ } while (pending);
2157
+ restarting = null;
1956
2158
  })();
2159
+ return restarting;
2160
+ };
2161
+ let debounceTimer = null;
2162
+ watcher.on("all", () => {
2163
+ if (debounceTimer) clearTimeout(debounceTimer);
2164
+ debounceTimer = setTimeout(() => {
2165
+ debounceTimer = null;
2166
+ void restart();
2167
+ }, 80);
1957
2168
  });
1958
2169
  }
1959
2170
  }
@@ -2001,7 +2212,7 @@ function resolveElectronBinary(config) {
2001
2212
  return config.electron.electronPath;
2002
2213
  }
2003
2214
  try {
2004
- const require2 = createRequire2(path12.resolve(config.root, "package.json"));
2215
+ const require2 = createRequire3(path12.resolve(config.root, "package.json"));
2005
2216
  const pathFile = require2.resolve("electron");
2006
2217
  const electronModule = require2(pathFile);
2007
2218
  if (typeof electronModule === "string" && fs10.existsSync(electronModule)) {
@@ -2034,7 +2245,7 @@ function warnElectronVersion(config) {
2034
2245
  import path13 from "path";
2035
2246
  import fs11 from "fs";
2036
2247
  import crypto2 from "crypto";
2037
- import { createRequire as createRequire3 } from "module";
2248
+ import { createRequire as createRequire4 } from "module";
2038
2249
  var DEFAULT_WORKERS = {
2039
2250
  editorWorkerService: "monaco-editor/esm/vs/editor/editor.worker",
2040
2251
  css: "monaco-editor/esm/vs/language/css/css.worker",
@@ -2053,7 +2264,7 @@ function normalizePublicPath(p) {
2053
2264
  }
2054
2265
  function readMonacoVersion(root) {
2055
2266
  try {
2056
- const require2 = createRequire3(path13.resolve(root, "package.json"));
2267
+ const require2 = createRequire4(path13.resolve(root, "package.json"));
2057
2268
  const pkgJsonPath = require2.resolve("monaco-editor/package.json", { paths: [root] });
2058
2269
  const pkg = JSON.parse(fs11.readFileSync(pkgJsonPath, "utf-8"));
2059
2270
  return typeof pkg.version === "string" ? pkg.version : "unknown";
@@ -2081,7 +2292,7 @@ function monacoEditorPlugin(options = {}) {
2081
2292
  if (existing) return existing;
2082
2293
  const task = (async () => {
2083
2294
  const { rolldown: rolldown4 } = await import("rolldown");
2084
- const require2 = createRequire3(path13.resolve(resolvedConfig.root, "package.json"));
2295
+ const require2 = createRequire4(path13.resolve(resolvedConfig.root, "package.json"));
2085
2296
  let entry;
2086
2297
  try {
2087
2298
  entry = require2.resolve(worker.entry, { paths: [resolvedConfig.root] });