@nasti-toolchain/nasti 1.5.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -161,6 +161,14 @@ async function resolveConfig(inlineConfig = {}, command) {
161
161
  return p.apply === command;
162
162
  });
163
163
  resolved.plugins = filteredPlugins;
164
+ if (resolved.target === "electron") {
165
+ const autoExternal = detectNativeDeps(root);
166
+ if (autoExternal.length > 0) {
167
+ const current = new Set(resolved.electron.external ?? []);
168
+ for (const dep of autoExternal) current.add(dep);
169
+ resolved.electron.external = [...current];
170
+ }
171
+ }
164
172
  for (const plugin of resolved.plugins) {
165
173
  if (plugin.configResolved) {
166
174
  await plugin.configResolved(resolved);
@@ -168,6 +176,73 @@ async function resolveConfig(inlineConfig = {}, command) {
168
176
  }
169
177
  return resolved;
170
178
  }
179
+ function detectNativeDeps(root) {
180
+ const result = /* @__PURE__ */ new Set();
181
+ const pkgJsonPath = path.resolve(root, "package.json");
182
+ if (!fs.existsSync(pkgJsonPath)) return [];
183
+ let pkg;
184
+ try {
185
+ pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
186
+ } catch {
187
+ return [];
188
+ }
189
+ const deps = {
190
+ ...pkg.dependencies ?? {},
191
+ ...pkg.optionalDependencies ?? {}
192
+ };
193
+ const KNOWN_NATIVE = /* @__PURE__ */ new Set([
194
+ "node-pty",
195
+ "better-sqlite3",
196
+ "sharp",
197
+ "serialport",
198
+ "@vscode/tree-sitter-wasm",
199
+ "keytar",
200
+ "nodegit",
201
+ "sqlite3",
202
+ "fsevents"
203
+ ]);
204
+ for (const dep of Object.keys(deps)) {
205
+ if (KNOWN_NATIVE.has(dep)) {
206
+ result.add(dep);
207
+ continue;
208
+ }
209
+ const depDir = path.resolve(root, "node_modules", dep);
210
+ if (!fs.existsSync(depDir)) continue;
211
+ if (fs.existsSync(path.join(depDir, "binding.gyp"))) {
212
+ result.add(dep);
213
+ continue;
214
+ }
215
+ const subPkg = path.join(depDir, "package.json");
216
+ if (fs.existsSync(subPkg)) {
217
+ try {
218
+ const sub = JSON.parse(fs.readFileSync(subPkg, "utf-8"));
219
+ if (sub.gypfile === true || sub.binary?.module_name) {
220
+ result.add(dep);
221
+ continue;
222
+ }
223
+ } catch {
224
+ }
225
+ }
226
+ if (hasDotNodeFile(depDir)) {
227
+ result.add(dep);
228
+ }
229
+ }
230
+ return [...result];
231
+ }
232
+ function hasDotNodeFile(dir, depth = 0) {
233
+ if (depth > 3) return false;
234
+ try {
235
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
236
+ for (const e of entries) {
237
+ if (e.isFile() && e.name.endsWith(".node")) return true;
238
+ if (e.isDirectory() && (e.name === "build" || e.name === "prebuilds" || e.name === "Release")) {
239
+ if (hasDotNodeFile(path.join(dir, e.name), depth + 1)) return true;
240
+ }
241
+ }
242
+ } catch {
243
+ }
244
+ return false;
245
+ }
171
246
  function deepMerge(target, source) {
172
247
  const result = { ...target };
173
248
  for (const key of Object.keys(source)) {
@@ -520,6 +595,15 @@ function htmlPlugin(config) {
520
595
  transformIndexHtml(html) {
521
596
  const tags = [];
522
597
  if (config.command === "serve") {
598
+ const isReactLike = config.framework === "react" || config.framework === "auto";
599
+ if (isReactLike) {
600
+ tags.push({
601
+ tag: "script",
602
+ attrs: { type: "module" },
603
+ children: REACT_REFRESH_HTML_PREAMBLE,
604
+ injectTo: "head-prepend"
605
+ });
606
+ }
523
607
  tags.push({
524
608
  tag: "script",
525
609
  attrs: { type: "module", src: "/@nasti/client" },
@@ -570,9 +654,17 @@ async function readHtmlFile(root) {
570
654
  if (!fs2.existsSync(htmlPath)) return null;
571
655
  return fs2.readFileSync(htmlPath, "utf-8");
572
656
  }
657
+ var REACT_REFRESH_HTML_PREAMBLE;
573
658
  var init_html = __esm({
574
659
  "src/plugins/html.ts"() {
575
660
  "use strict";
661
+ REACT_REFRESH_HTML_PREAMBLE = `
662
+ import RefreshRuntime from "/@react-refresh";
663
+ RefreshRuntime.injectIntoGlobalHook(window);
664
+ window.$RefreshReg$ = () => {};
665
+ window.$RefreshSig$ = () => (type) => type;
666
+ window.__vite_plugin_react_preamble_installed__ = true;
667
+ `.trim();
576
668
  }
577
669
  });
578
670
 
@@ -640,11 +732,93 @@ var init_env = __esm({
640
732
  // src/server/middleware.ts
641
733
  var middleware_exports = {};
642
734
  __export(middleware_exports, {
735
+ REACT_REFRESH_GLOBAL_PREAMBLE: () => REACT_REFRESH_GLOBAL_PREAMBLE,
643
736
  transformMiddleware: () => transformMiddleware,
644
737
  transformRequest: () => transformRequest
645
738
  });
646
739
  import path4 from "path";
647
740
  import fs4 from "fs";
741
+ import { createRequire } from "module";
742
+ import { fileURLToPath } from "url";
743
+ function getReactRefreshRuntimeEsm() {
744
+ if (__refreshRuntimeCache) return __refreshRuntimeCache;
745
+ let cjsPath;
746
+ try {
747
+ const pkgPath = __require.resolve("react-refresh/package.json");
748
+ cjsPath = path4.join(path4.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
749
+ } catch (err) {
750
+ cjsPath = path4.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
751
+ if (!fs4.existsSync(cjsPath)) {
752
+ const origMsg = err instanceof Error ? err.message : String(err);
753
+ throw new Error(
754
+ `[nasti] Missing dependency "react-refresh". Install it with: npm install react-refresh
755
+ Original resolve error: ${origMsg}`
756
+ );
757
+ }
758
+ }
759
+ const cjsSource = fs4.readFileSync(cjsPath, "utf-8");
760
+ __refreshRuntimeCache = `// Wrapped react-refresh runtime -> ESM
761
+ const exports = {};
762
+ const module = { exports };
763
+ const process = { env: { NODE_ENV: 'development' } };
764
+ ${cjsSource}
765
+ const __rt = module.exports;
766
+ export const injectIntoGlobalHook = __rt.injectIntoGlobalHook;
767
+ export const register = __rt.register;
768
+ export const createSignatureFunctionForTransform = __rt.createSignatureFunctionForTransform;
769
+ export const performReactRefresh = __rt.performReactRefresh;
770
+ export const isLikelyComponentType = __rt.isLikelyComponentType;
771
+ export const hasUnrecoverableErrors = __rt.hasUnrecoverableErrors;
772
+ export const setSignature = __rt.setSignature;
773
+ export const getFamilyByID = __rt.getFamilyByID;
774
+ export const getFamilyByType = __rt.getFamilyByType;
775
+ export const findAffectedHostInstances = __rt.findAffectedHostInstances;
776
+ export const collectCustomHooksForSignature = __rt.collectCustomHooksForSignature;
777
+ export default __rt;
778
+ `;
779
+ return __refreshRuntimeCache;
780
+ }
781
+ function buildReactRefreshWrapper(moduleUrl, transformedCode) {
782
+ const urlLit = JSON.stringify(moduleUrl);
783
+ const userCode = transformedCode.replace(/\bimport\.meta\.hot\b/g, "__nasti_hot__");
784
+ return `import * as RefreshRuntime from "/@react-refresh";
785
+ import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
786
+ const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
787
+
788
+ if (!window.__vite_plugin_react_preamble_installed__) {
789
+ throw new Error("[nasti] React Fast Refresh preamble missing. Make sure nasti:html is wired with framework: 'react'.");
790
+ }
791
+
792
+ const prevRefreshReg = window.$RefreshReg$;
793
+ const prevRefreshSig = window.$RefreshSig$;
794
+ window.$RefreshReg$ = (type, id) => {
795
+ RefreshRuntime.register(type, ${urlLit} + " " + id);
796
+ };
797
+ window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
798
+
799
+ ${userCode}
800
+
801
+ window.$RefreshReg$ = prevRefreshReg;
802
+ window.$RefreshSig$ = prevRefreshSig;
803
+
804
+ if (__nasti_hot__) {
805
+ __nasti_hot__.accept(() => {
806
+ clearTimeout(window.__nasti_refresh_timer__);
807
+ window.__nasti_refresh_timer__ = setTimeout(() => {
808
+ RefreshRuntime.performReactRefresh();
809
+ }, 30);
810
+ });
811
+ }
812
+ `;
813
+ }
814
+ function injectImportMetaHot(code, moduleUrl) {
815
+ if (!/\bimport\.meta\.hot\b/.test(code)) return code;
816
+ const urlLit = JSON.stringify(moduleUrl);
817
+ const header = `import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
818
+ const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
819
+ `;
820
+ return header + code.replace(/\bimport\.meta\.hot\b/g, "__nasti_hot__");
821
+ }
648
822
  function transformMiddleware(ctx) {
649
823
  ctx.envDefine = buildEnvDefine(
650
824
  loadEnv(ctx.config.mode, ctx.config.root, ctx.config.envPrefix),
@@ -718,7 +892,7 @@ async function transformRequest(url, ctx) {
718
892
  return cached.transformResult;
719
893
  }
720
894
  if (cleanReqUrl === "/@react-refresh") {
721
- return { code: REACT_REFRESH_RUNTIME };
895
+ return { code: getReactRefreshRuntimeEsm() };
722
896
  }
723
897
  const filePath = resolveUrlToFile(url, config.root);
724
898
  if (!filePath || !fs4.existsSync(filePath)) return null;
@@ -735,6 +909,8 @@ async function transformRequest(url, ctx) {
735
909
  if (pluginResult) {
736
910
  code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
737
911
  }
912
+ const stableUrl = cleanReqUrl;
913
+ let wrappedWithRefresh = false;
738
914
  if (shouldTransform(filePath)) {
739
915
  const isJsx = /\.[jt]sx$/.test(filePath);
740
916
  const useRefresh = isJsx && config.framework !== "vue";
@@ -746,9 +922,14 @@ async function transformRequest(url, ctx) {
746
922
  });
747
923
  code = result.code;
748
924
  if (useRefresh) {
749
- code = REACT_REFRESH_PREAMBLE + code + REACT_REFRESH_FOOTER;
925
+ code = buildReactRefreshWrapper(stableUrl, code);
926
+ wrappedWithRefresh = true;
927
+ mod.isSelfAccepting = true;
750
928
  }
751
929
  }
930
+ if (!wrappedWithRefresh) {
931
+ code = injectImportMetaHot(code, stableUrl);
932
+ }
752
933
  const envDefine = ctx.envDefine ?? buildEnvDefine(
753
934
  loadEnv(config.mode, config.root, config.envPrefix),
754
935
  config.mode
@@ -816,8 +997,8 @@ function rewriteExternalRequires(code) {
816
997
  }
817
998
  async function injectCjsNamedExports(code, entryFile) {
818
999
  try {
819
- const { createRequire: createRequire3 } = await import("module");
820
- const req = createRequire3(entryFile);
1000
+ const { createRequire: createRequire4 } = await import("module");
1001
+ const req = createRequire4(entryFile);
821
1002
  const cjsExports = req(entryFile);
822
1003
  if (!cjsExports || typeof cjsExports !== "object" && typeof cjsExports !== "function" || Array.isArray(cjsExports)) return code;
823
1004
  const namedKeys = Object.keys(cjsExports).filter(
@@ -980,12 +1161,15 @@ function getHmrClientCode() {
980
1161
  // Nasti HMR Client
981
1162
  const socket = new WebSocket(\`ws://\${location.host}\`, 'nasti-hmr');
982
1163
  const hotModulesMap = new Map();
1164
+ const disposeMap = new Map();
1165
+ const pruneMap = new Map();
983
1166
 
984
1167
  socket.addEventListener('message', ({ data }) => {
985
1168
  const payload = JSON.parse(data);
986
1169
  switch (payload.type) {
987
1170
  case 'connected':
988
1171
  console.log('[nasti] connected.');
1172
+ clearErrorOverlay();
989
1173
  break;
990
1174
  case 'update':
991
1175
  payload.updates.forEach((update) => {
@@ -995,11 +1179,18 @@ socket.addEventListener('message', ({ data }) => {
995
1179
  updateCss(update.path);
996
1180
  }
997
1181
  });
1182
+ clearErrorOverlay();
998
1183
  break;
999
1184
  case 'full-reload':
1000
1185
  console.log('[nasti] full reload');
1001
1186
  location.reload();
1002
1187
  break;
1188
+ case 'prune':
1189
+ payload.paths.forEach((p) => {
1190
+ const cb = pruneMap.get(p);
1191
+ if (cb) cb();
1192
+ });
1193
+ break;
1003
1194
  case 'error':
1004
1195
  console.error('[nasti] error:', payload.err.message);
1005
1196
  showErrorOverlay(payload.err);
@@ -1007,14 +1198,23 @@ socket.addEventListener('message', ({ data }) => {
1007
1198
  }
1008
1199
  });
1009
1200
 
1201
+ // \u81EA\u52A8\u91CD\u8FDE\uFF08\u65AD\u7EBF\u65F6\u6307\u6570\u9000\u907F\uFF09
1202
+ let reconnectTimer = 0;
1203
+ socket.addEventListener('close', () => {
1204
+ clearTimeout(reconnectTimer);
1205
+ reconnectTimer = setTimeout(() => location.reload(), 1000);
1206
+ });
1207
+
1010
1208
  async function fetchUpdate(update) {
1011
1209
  const mod = hotModulesMap.get(update.path);
1210
+ // \u5148\u8DD1 dispose\uFF08\u7ED9\u6A21\u5757\u673A\u4F1A\u6E05\u7406\u526F\u4F5C\u7528\uFF09
1211
+ const dispose = disposeMap.get(update.path);
1212
+ if (dispose) dispose();
1213
+
1214
+ const newMod = await import(update.acceptedPath + '?t=' + update.timestamp);
1012
1215
  if (mod) {
1013
- const newMod = await import(update.acceptedPath + '?t=' + update.timestamp);
1014
- mod.callbacks.forEach((cb) => cb(newMod));
1015
- } else {
1016
- // \u6CA1\u6709\u6CE8\u518C hot \u56DE\u8C03\uFF0C\u5C1D\u8BD5\u91CD\u65B0 import
1017
- await import(update.path + '?t=' + update.timestamp);
1216
+ // \u590D\u5236\u56DE\u8C03\u6570\u7EC4\u907F\u514D\u56DE\u8C03\u5185\u90E8\u53C8\u4FEE\u6539 hotModulesMap \u9020\u6210\u8FED\u4EE3\u5F02\u5E38
1217
+ [...mod.callbacks].forEach((cb) => cb(newMod));
1018
1218
  }
1019
1219
  }
1020
1220
 
@@ -1027,7 +1227,13 @@ function updateCss(path) {
1027
1227
  }
1028
1228
  }
1029
1229
 
1230
+ function clearErrorOverlay() {
1231
+ const el = document.getElementById('nasti-error-overlay');
1232
+ if (el) el.remove();
1233
+ }
1234
+
1030
1235
  function showErrorOverlay(err) {
1236
+ clearErrorOverlay();
1031
1237
  const overlay = document.createElement('div');
1032
1238
  overlay.id = 'nasti-error-overlay';
1033
1239
  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;';
@@ -1046,59 +1252,55 @@ function showErrorOverlay(err) {
1046
1252
  document.body.appendChild(overlay);
1047
1253
  }
1048
1254
 
1049
- // import.meta.hot API
1050
- const createHotContext = (ownerPath) => ({
1051
- accept(deps, callback) {
1052
- if (typeof deps === 'function' || !deps) {
1053
- // self-accepting
1054
- const callbacks = hotModulesMap.get(ownerPath)?.callbacks || [];
1055
- callbacks.push(deps || (() => {}));
1056
- hotModulesMap.set(ownerPath, { callbacks });
1057
- }
1058
- },
1059
- prune(callback) {
1060
- // \u6A21\u5757\u88AB\u79FB\u9664\u65F6\u6267\u884C
1061
- },
1062
- dispose(callback) {
1063
- // \u6A21\u5757\u66F4\u65B0\u524D\u6267\u884C\u6E05\u7406
1064
- },
1065
- invalidate() {
1066
- location.reload();
1067
- },
1068
- data: {},
1069
- });
1070
-
1071
- // \u66B4\u9732\u7ED9\u6A21\u5757\u4F7F\u7528
1072
- if (!window.__nasti_hot_map) window.__nasti_hot_map = new Map();
1073
- window.__NASTI_HMR__ = { createHotContext };
1255
+ /**
1256
+ * \u751F\u6210 import.meta.hot \u7684 hot context\u3002
1257
+ * \u5173\u952E\u7EA6\u675F\uFF1A\u540C\u4E00 ownerPath \u7684 accept \u56DE\u8C03\u5FC5\u987B\u66FF\u6362\uFF08\u4E0D\u662F append\uFF09\u3002
1258
+ * \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
1259
+ * \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
1260
+ */
1261
+ export function createHotContext(ownerPath) {
1262
+ return {
1263
+ accept(deps, callback) {
1264
+ // \u81EA\u63A5\u53D7: hot.accept() \u6216 hot.accept(callback)
1265
+ if (typeof deps === 'function' || deps === undefined) {
1266
+ hotModulesMap.set(ownerPath, { callbacks: [deps || (() => {})] });
1267
+ return;
1268
+ }
1269
+ // \u4F9D\u8D56\u63A5\u53D7: hot.accept(deps, callback)\uFF0C\u591A\u6B21\u8C03\u7528\u8FFD\u52A0
1270
+ const existing = hotModulesMap.get(ownerPath)?.callbacks ?? [];
1271
+ hotModulesMap.set(ownerPath, { callbacks: [...existing, callback] });
1272
+ },
1273
+ prune(callback) {
1274
+ pruneMap.set(ownerPath, callback);
1275
+ },
1276
+ dispose(callback) {
1277
+ disposeMap.set(ownerPath, callback);
1278
+ },
1279
+ invalidate() {
1280
+ location.reload();
1281
+ },
1282
+ data: {},
1283
+ };
1284
+ }
1074
1285
  `;
1075
1286
  }
1076
- var REACT_REFRESH_RUNTIME, REACT_REFRESH_PREAMBLE, REACT_REFRESH_FOOTER, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
1287
+ var __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
1077
1288
  var init_middleware = __esm({
1078
1289
  "src/server/middleware.ts"() {
1079
1290
  "use strict";
1080
1291
  init_transformer();
1081
1292
  init_html();
1082
1293
  init_env();
1083
- REACT_REFRESH_RUNTIME = `
1084
- export function createSignatureFunctionForTransform() {
1085
- return function(type, key, forceReset, getCustomHooks) { return type; };
1086
- }
1087
- export function register(type, id) {}
1088
- export default { createSignatureFunctionForTransform, register };
1089
- `;
1090
- REACT_REFRESH_PREAMBLE = `
1091
- import RefreshRuntime from '/@react-refresh';
1092
- if (!window.$RefreshReg$) {
1093
- window.$RefreshReg$ = (type, id) => RefreshRuntime.register(type, import.meta.url + ' ' + id);
1094
- window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
1095
- }
1096
- `;
1097
- REACT_REFRESH_FOOTER = `
1098
- if (import.meta.hot) {
1099
- import.meta.hot.accept();
1100
- }
1101
- `;
1294
+ __dirname_esm = path4.dirname(fileURLToPath(import.meta.url));
1295
+ __require = createRequire(import.meta.url);
1296
+ __refreshRuntimeCache = null;
1297
+ REACT_REFRESH_GLOBAL_PREAMBLE = `
1298
+ import RefreshRuntime from "/@react-refresh";
1299
+ RefreshRuntime.injectIntoGlobalHook(window);
1300
+ window.$RefreshReg$ = () => {};
1301
+ window.$RefreshSig$ = () => (type) => type;
1302
+ window.__vite_plugin_react_preamble_installed__ = true;
1303
+ `.trim();
1102
1304
  esmBundleCache = /* @__PURE__ */ new Map();
1103
1305
  VALID_IDENT = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
1104
1306
  RESOLVE_EXTENSIONS = [".tsx", ".ts", ".jsx", ".js", ".mjs", ".json", ".vue"];
@@ -1165,10 +1367,10 @@ var init_hmr = __esm({
1165
1367
  // src/plugins/resolve.ts
1166
1368
  import path6 from "path";
1167
1369
  import fs6 from "fs";
1168
- import { createRequire } from "module";
1370
+ import { createRequire as createRequire2 } from "module";
1169
1371
  function resolvePlugin(config) {
1170
1372
  const { alias, extensions } = config.resolve;
1171
- const require2 = createRequire(path6.resolve(config.root, "package.json"));
1373
+ const require2 = createRequire2(path6.resolve(config.root, "package.json"));
1172
1374
  return {
1173
1375
  name: "nasti:resolve",
1174
1376
  enforce: "pre",
@@ -1435,7 +1637,7 @@ async function createServer(inlineConfig = {}) {
1435
1637
  const localUrl = `http://localhost:${actualPort}`;
1436
1638
  const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
1437
1639
  console.log();
1438
- console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.5.0"}`));
1640
+ console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.5.2"}`));
1439
1641
  console.log();
1440
1642
  console.log(` ${pc.green(">")} Local: ${pc.cyan(localUrl)}`);
1441
1643
  if (networkUrl) {
@@ -1558,7 +1760,7 @@ import pc2 from "picocolors";
1558
1760
  async function build(inlineConfig = {}) {
1559
1761
  const config = await resolveConfig(inlineConfig, "build");
1560
1762
  const startTime = performance.now();
1561
- console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.5.0"}`));
1763
+ console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.5.2"}`));
1562
1764
  console.log(pc2.dim(` root: ${config.root}`));
1563
1765
  console.log(pc2.dim(` mode: ${config.mode}`));
1564
1766
  const outDir = path10.resolve(config.root, config.build.outDir);
@@ -1718,7 +1920,7 @@ async function buildElectron(inlineConfig = {}) {
1718
1920
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
1719
1921
  const startTime = performance.now();
1720
1922
  assertElectronVersion(config);
1721
- console.log(pc3.cyan("\n\u26A1 nasti build (electron)") + pc3.dim(` v${"1.5.0"}`));
1923
+ console.log(pc3.cyan("\n\u26A1 nasti build (electron)") + pc3.dim(` v${"1.5.2"}`));
1722
1924
  console.log(pc3.dim(` root: ${config.root}`));
1723
1925
  console.log(pc3.dim(` mode: ${config.mode}`));
1724
1926
  console.log(pc3.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
@@ -1863,7 +2065,7 @@ __export(electron_dev_exports, {
1863
2065
  });
1864
2066
  import path12 from "path";
1865
2067
  import fs10 from "fs";
1866
- import { createRequire as createRequire2 } from "module";
2068
+ import { createRequire as createRequire3 } from "module";
1867
2069
  import { spawn } from "child_process";
1868
2070
  import chokidar from "chokidar";
1869
2071
  import pc4 from "picocolors";
@@ -1872,7 +2074,7 @@ async function startElectronDev(inlineConfig = {}) {
1872
2074
  const { noSpawn, ...rest } = inlineConfig;
1873
2075
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
1874
2076
  warnElectronVersion(config);
1875
- console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.5.0"}`));
2077
+ console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.5.2"}`));
1876
2078
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
1877
2079
  const server = await createServer2({ ...rest, target: "electron" });
1878
2080
  await server.listen();
@@ -1936,11 +2138,16 @@ async function startElectronDev(inlineConfig = {}) {
1936
2138
  const watchTargets = [mainEntry, ...preloadEntries].filter(fs10.existsSync);
1937
2139
  const watcher = chokidar.watch(watchTargets, { ignoreInitial: true });
1938
2140
  let restarting = null;
1939
- watcher.on("all", async () => {
1940
- if (restarting) return;
2141
+ let pending = false;
2142
+ const restart = async () => {
2143
+ if (restarting) {
2144
+ pending = true;
2145
+ return;
2146
+ }
1941
2147
  restarting = (async () => {
1942
- console.log(pc4.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
1943
- try {
2148
+ do {
2149
+ pending = false;
2150
+ console.log(pc4.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
1944
2151
  if (child && !child.killed) {
1945
2152
  ;
1946
2153
  child.__nastiKilled = true;
@@ -1954,12 +2161,24 @@ async function startElectronDev(inlineConfig = {}) {
1954
2161
  dying.kill();
1955
2162
  });
1956
2163
  }
1957
- await compileAll();
1958
- spawnElectron();
1959
- } finally {
1960
- restarting = null;
1961
- }
2164
+ try {
2165
+ await compileAll();
2166
+ spawnElectron();
2167
+ } catch (e) {
2168
+ console.warn(pc4.yellow(` \u26A0 \u91CD\u542F\u7F16\u8BD1\u5931\u8D25\uFF0C\u4FDD\u7559\u4E0A\u4E00\u6B21\u8FDB\u7A0B: ${e.message}`));
2169
+ }
2170
+ } while (pending);
2171
+ restarting = null;
1962
2172
  })();
2173
+ return restarting;
2174
+ };
2175
+ let debounceTimer = null;
2176
+ watcher.on("all", () => {
2177
+ if (debounceTimer) clearTimeout(debounceTimer);
2178
+ debounceTimer = setTimeout(() => {
2179
+ debounceTimer = null;
2180
+ void restart();
2181
+ }, 80);
1963
2182
  });
1964
2183
  }
1965
2184
  }
@@ -2007,7 +2226,7 @@ function resolveElectronBinary(config) {
2007
2226
  return config.electron.electronPath;
2008
2227
  }
2009
2228
  try {
2010
- const require2 = createRequire2(path12.resolve(config.root, "package.json"));
2229
+ const require2 = createRequire3(path12.resolve(config.root, "package.json"));
2011
2230
  const pathFile = require2.resolve("electron");
2012
2231
  const electronModule = require2(pathFile);
2013
2232
  if (typeof electronModule === "string" && fs10.existsSync(electronModule)) {
@@ -2180,6 +2399,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
2180
2399
  }
2181
2400
  });
2182
2401
  cli.help();
2183
- cli.version("1.5.0");
2402
+ cli.version("1.5.2");
2184
2403
  cli.parse();
2185
2404
  //# sourceMappingURL=cli.js.map