@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/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,85 @@ 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
+ cjsPath = __require.resolve("react-refresh/cjs/react-refresh-runtime.development.js");
748
+ } catch {
749
+ cjsPath = path4.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
750
+ }
751
+ const cjsSource = fs4.readFileSync(cjsPath, "utf-8");
752
+ __refreshRuntimeCache = `// Wrapped react-refresh runtime -> ESM
753
+ const exports = {};
754
+ const module = { exports };
755
+ const process = { env: { NODE_ENV: 'development' } };
756
+ ${cjsSource}
757
+ const __rt = module.exports;
758
+ export const injectIntoGlobalHook = __rt.injectIntoGlobalHook;
759
+ export const register = __rt.register;
760
+ export const createSignatureFunctionForTransform = __rt.createSignatureFunctionForTransform;
761
+ export const performReactRefresh = __rt.performReactRefresh;
762
+ export const isLikelyComponentType = __rt.isLikelyComponentType;
763
+ export const hasUnrecoverableErrors = __rt.hasUnrecoverableErrors;
764
+ export const setSignature = __rt.setSignature;
765
+ export const getFamilyByID = __rt.getFamilyByID;
766
+ export const getFamilyByType = __rt.getFamilyByType;
767
+ export const findAffectedHostInstances = __rt.findAffectedHostInstances;
768
+ export const collectCustomHooksForSignature = __rt.collectCustomHooksForSignature;
769
+ export default __rt;
770
+ `;
771
+ return __refreshRuntimeCache;
772
+ }
773
+ function buildReactRefreshWrapper(moduleUrl, transformedCode) {
774
+ const urlLit = JSON.stringify(moduleUrl);
775
+ const userCode = transformedCode.replace(/\bimport\.meta\.hot\b/g, "__nasti_hot__");
776
+ return `import * as RefreshRuntime from "/@react-refresh";
777
+ import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
778
+ const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
779
+
780
+ if (!window.__vite_plugin_react_preamble_installed__) {
781
+ throw new Error("[nasti] React Fast Refresh preamble missing. Make sure nasti:html is wired with framework: 'react'.");
782
+ }
783
+
784
+ const prevRefreshReg = window.$RefreshReg$;
785
+ const prevRefreshSig = window.$RefreshSig$;
786
+ window.$RefreshReg$ = (type, id) => {
787
+ RefreshRuntime.register(type, ${urlLit} + " " + id);
788
+ };
789
+ window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
790
+
791
+ ${userCode}
792
+
793
+ window.$RefreshReg$ = prevRefreshReg;
794
+ window.$RefreshSig$ = prevRefreshSig;
795
+
796
+ if (__nasti_hot__) {
797
+ __nasti_hot__.accept(() => {
798
+ clearTimeout(window.__nasti_refresh_timer__);
799
+ window.__nasti_refresh_timer__ = setTimeout(() => {
800
+ RefreshRuntime.performReactRefresh();
801
+ }, 30);
802
+ });
803
+ }
804
+ `;
805
+ }
806
+ function injectImportMetaHot(code, moduleUrl) {
807
+ if (!/\bimport\.meta\.hot\b/.test(code)) return code;
808
+ const urlLit = JSON.stringify(moduleUrl);
809
+ const header = `import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
810
+ const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
811
+ `;
812
+ return header + code.replace(/\bimport\.meta\.hot\b/g, "__nasti_hot__");
813
+ }
648
814
  function transformMiddleware(ctx) {
649
815
  ctx.envDefine = buildEnvDefine(
650
816
  loadEnv(ctx.config.mode, ctx.config.root, ctx.config.envPrefix),
@@ -718,7 +884,7 @@ async function transformRequest(url, ctx) {
718
884
  return cached.transformResult;
719
885
  }
720
886
  if (cleanReqUrl === "/@react-refresh") {
721
- return { code: REACT_REFRESH_RUNTIME };
887
+ return { code: getReactRefreshRuntimeEsm() };
722
888
  }
723
889
  const filePath = resolveUrlToFile(url, config.root);
724
890
  if (!filePath || !fs4.existsSync(filePath)) return null;
@@ -735,6 +901,8 @@ async function transformRequest(url, ctx) {
735
901
  if (pluginResult) {
736
902
  code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
737
903
  }
904
+ const stableUrl = cleanReqUrl;
905
+ let wrappedWithRefresh = false;
738
906
  if (shouldTransform(filePath)) {
739
907
  const isJsx = /\.[jt]sx$/.test(filePath);
740
908
  const useRefresh = isJsx && config.framework !== "vue";
@@ -746,9 +914,14 @@ async function transformRequest(url, ctx) {
746
914
  });
747
915
  code = result.code;
748
916
  if (useRefresh) {
749
- code = REACT_REFRESH_PREAMBLE + code + REACT_REFRESH_FOOTER;
917
+ code = buildReactRefreshWrapper(stableUrl, code);
918
+ wrappedWithRefresh = true;
919
+ mod.isSelfAccepting = true;
750
920
  }
751
921
  }
922
+ if (!wrappedWithRefresh) {
923
+ code = injectImportMetaHot(code, stableUrl);
924
+ }
752
925
  const envDefine = ctx.envDefine ?? buildEnvDefine(
753
926
  loadEnv(config.mode, config.root, config.envPrefix),
754
927
  config.mode
@@ -816,8 +989,8 @@ function rewriteExternalRequires(code) {
816
989
  }
817
990
  async function injectCjsNamedExports(code, entryFile) {
818
991
  try {
819
- const { createRequire: createRequire3 } = await import("module");
820
- const req = createRequire3(entryFile);
992
+ const { createRequire: createRequire4 } = await import("module");
993
+ const req = createRequire4(entryFile);
821
994
  const cjsExports = req(entryFile);
822
995
  if (!cjsExports || typeof cjsExports !== "object" && typeof cjsExports !== "function" || Array.isArray(cjsExports)) return code;
823
996
  const namedKeys = Object.keys(cjsExports).filter(
@@ -980,12 +1153,15 @@ function getHmrClientCode() {
980
1153
  // Nasti HMR Client
981
1154
  const socket = new WebSocket(\`ws://\${location.host}\`, 'nasti-hmr');
982
1155
  const hotModulesMap = new Map();
1156
+ const disposeMap = new Map();
1157
+ const pruneMap = new Map();
983
1158
 
984
1159
  socket.addEventListener('message', ({ data }) => {
985
1160
  const payload = JSON.parse(data);
986
1161
  switch (payload.type) {
987
1162
  case 'connected':
988
1163
  console.log('[nasti] connected.');
1164
+ clearErrorOverlay();
989
1165
  break;
990
1166
  case 'update':
991
1167
  payload.updates.forEach((update) => {
@@ -995,11 +1171,18 @@ socket.addEventListener('message', ({ data }) => {
995
1171
  updateCss(update.path);
996
1172
  }
997
1173
  });
1174
+ clearErrorOverlay();
998
1175
  break;
999
1176
  case 'full-reload':
1000
1177
  console.log('[nasti] full reload');
1001
1178
  location.reload();
1002
1179
  break;
1180
+ case 'prune':
1181
+ payload.paths.forEach((p) => {
1182
+ const cb = pruneMap.get(p);
1183
+ if (cb) cb();
1184
+ });
1185
+ break;
1003
1186
  case 'error':
1004
1187
  console.error('[nasti] error:', payload.err.message);
1005
1188
  showErrorOverlay(payload.err);
@@ -1007,14 +1190,23 @@ socket.addEventListener('message', ({ data }) => {
1007
1190
  }
1008
1191
  });
1009
1192
 
1193
+ // \u81EA\u52A8\u91CD\u8FDE\uFF08\u65AD\u7EBF\u65F6\u6307\u6570\u9000\u907F\uFF09
1194
+ let reconnectTimer = 0;
1195
+ socket.addEventListener('close', () => {
1196
+ clearTimeout(reconnectTimer);
1197
+ reconnectTimer = setTimeout(() => location.reload(), 1000);
1198
+ });
1199
+
1010
1200
  async function fetchUpdate(update) {
1011
1201
  const mod = hotModulesMap.get(update.path);
1202
+ // \u5148\u8DD1 dispose\uFF08\u7ED9\u6A21\u5757\u673A\u4F1A\u6E05\u7406\u526F\u4F5C\u7528\uFF09
1203
+ const dispose = disposeMap.get(update.path);
1204
+ if (dispose) dispose();
1205
+
1206
+ const newMod = await import(update.acceptedPath + '?t=' + update.timestamp);
1012
1207
  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);
1208
+ // \u590D\u5236\u56DE\u8C03\u6570\u7EC4\u907F\u514D\u56DE\u8C03\u5185\u90E8\u53C8\u4FEE\u6539 hotModulesMap \u9020\u6210\u8FED\u4EE3\u5F02\u5E38
1209
+ [...mod.callbacks].forEach((cb) => cb(newMod));
1018
1210
  }
1019
1211
  }
1020
1212
 
@@ -1027,7 +1219,13 @@ function updateCss(path) {
1027
1219
  }
1028
1220
  }
1029
1221
 
1222
+ function clearErrorOverlay() {
1223
+ const el = document.getElementById('nasti-error-overlay');
1224
+ if (el) el.remove();
1225
+ }
1226
+
1030
1227
  function showErrorOverlay(err) {
1228
+ clearErrorOverlay();
1031
1229
  const overlay = document.createElement('div');
1032
1230
  overlay.id = 'nasti-error-overlay';
1033
1231
  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 +1244,55 @@ function showErrorOverlay(err) {
1046
1244
  document.body.appendChild(overlay);
1047
1245
  }
1048
1246
 
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 };
1247
+ /**
1248
+ * \u751F\u6210 import.meta.hot \u7684 hot context\u3002
1249
+ * \u5173\u952E\u7EA6\u675F\uFF1A\u540C\u4E00 ownerPath \u7684 accept \u56DE\u8C03\u5FC5\u987B\u66FF\u6362\uFF08\u4E0D\u662F append\uFF09\u3002
1250
+ * \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
1251
+ * \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
1252
+ */
1253
+ export function createHotContext(ownerPath) {
1254
+ return {
1255
+ accept(deps, callback) {
1256
+ // \u81EA\u63A5\u53D7: hot.accept() \u6216 hot.accept(callback)
1257
+ if (typeof deps === 'function' || deps === undefined) {
1258
+ hotModulesMap.set(ownerPath, { callbacks: [deps || (() => {})] });
1259
+ return;
1260
+ }
1261
+ // \u4F9D\u8D56\u63A5\u53D7: hot.accept(deps, callback)\uFF0C\u591A\u6B21\u8C03\u7528\u8FFD\u52A0
1262
+ const existing = hotModulesMap.get(ownerPath)?.callbacks ?? [];
1263
+ hotModulesMap.set(ownerPath, { callbacks: [...existing, callback] });
1264
+ },
1265
+ prune(callback) {
1266
+ pruneMap.set(ownerPath, callback);
1267
+ },
1268
+ dispose(callback) {
1269
+ disposeMap.set(ownerPath, callback);
1270
+ },
1271
+ invalidate() {
1272
+ location.reload();
1273
+ },
1274
+ data: {},
1275
+ };
1276
+ }
1074
1277
  `;
1075
1278
  }
1076
- var REACT_REFRESH_RUNTIME, REACT_REFRESH_PREAMBLE, REACT_REFRESH_FOOTER, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
1279
+ var __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
1077
1280
  var init_middleware = __esm({
1078
1281
  "src/server/middleware.ts"() {
1079
1282
  "use strict";
1080
1283
  init_transformer();
1081
1284
  init_html();
1082
1285
  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
- `;
1286
+ __dirname_esm = path4.dirname(fileURLToPath(import.meta.url));
1287
+ __require = createRequire(import.meta.url);
1288
+ __refreshRuntimeCache = null;
1289
+ REACT_REFRESH_GLOBAL_PREAMBLE = `
1290
+ import RefreshRuntime from "/@react-refresh";
1291
+ RefreshRuntime.injectIntoGlobalHook(window);
1292
+ window.$RefreshReg$ = () => {};
1293
+ window.$RefreshSig$ = () => (type) => type;
1294
+ window.__vite_plugin_react_preamble_installed__ = true;
1295
+ `.trim();
1102
1296
  esmBundleCache = /* @__PURE__ */ new Map();
1103
1297
  VALID_IDENT = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
1104
1298
  RESOLVE_EXTENSIONS = [".tsx", ".ts", ".jsx", ".js", ".mjs", ".json", ".vue"];
@@ -1165,10 +1359,10 @@ var init_hmr = __esm({
1165
1359
  // src/plugins/resolve.ts
1166
1360
  import path6 from "path";
1167
1361
  import fs6 from "fs";
1168
- import { createRequire } from "module";
1362
+ import { createRequire as createRequire2 } from "module";
1169
1363
  function resolvePlugin(config) {
1170
1364
  const { alias, extensions } = config.resolve;
1171
- const require2 = createRequire(path6.resolve(config.root, "package.json"));
1365
+ const require2 = createRequire2(path6.resolve(config.root, "package.json"));
1172
1366
  return {
1173
1367
  name: "nasti:resolve",
1174
1368
  enforce: "pre",
@@ -1435,7 +1629,7 @@ async function createServer(inlineConfig = {}) {
1435
1629
  const localUrl = `http://localhost:${actualPort}`;
1436
1630
  const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
1437
1631
  console.log();
1438
- console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.5.0"}`));
1632
+ console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.5.1"}`));
1439
1633
  console.log();
1440
1634
  console.log(` ${pc.green(">")} Local: ${pc.cyan(localUrl)}`);
1441
1635
  if (networkUrl) {
@@ -1558,7 +1752,7 @@ import pc2 from "picocolors";
1558
1752
  async function build(inlineConfig = {}) {
1559
1753
  const config = await resolveConfig(inlineConfig, "build");
1560
1754
  const startTime = performance.now();
1561
- console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.5.0"}`));
1755
+ console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.5.1"}`));
1562
1756
  console.log(pc2.dim(` root: ${config.root}`));
1563
1757
  console.log(pc2.dim(` mode: ${config.mode}`));
1564
1758
  const outDir = path10.resolve(config.root, config.build.outDir);
@@ -1718,7 +1912,7 @@ async function buildElectron(inlineConfig = {}) {
1718
1912
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
1719
1913
  const startTime = performance.now();
1720
1914
  assertElectronVersion(config);
1721
- console.log(pc3.cyan("\n\u26A1 nasti build (electron)") + pc3.dim(` v${"1.5.0"}`));
1915
+ console.log(pc3.cyan("\n\u26A1 nasti build (electron)") + pc3.dim(` v${"1.5.1"}`));
1722
1916
  console.log(pc3.dim(` root: ${config.root}`));
1723
1917
  console.log(pc3.dim(` mode: ${config.mode}`));
1724
1918
  console.log(pc3.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
@@ -1863,7 +2057,7 @@ __export(electron_dev_exports, {
1863
2057
  });
1864
2058
  import path12 from "path";
1865
2059
  import fs10 from "fs";
1866
- import { createRequire as createRequire2 } from "module";
2060
+ import { createRequire as createRequire3 } from "module";
1867
2061
  import { spawn } from "child_process";
1868
2062
  import chokidar from "chokidar";
1869
2063
  import pc4 from "picocolors";
@@ -1872,7 +2066,7 @@ async function startElectronDev(inlineConfig = {}) {
1872
2066
  const { noSpawn, ...rest } = inlineConfig;
1873
2067
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
1874
2068
  warnElectronVersion(config);
1875
- console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.5.0"}`));
2069
+ console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.5.1"}`));
1876
2070
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
1877
2071
  const server = await createServer2({ ...rest, target: "electron" });
1878
2072
  await server.listen();
@@ -1936,11 +2130,16 @@ async function startElectronDev(inlineConfig = {}) {
1936
2130
  const watchTargets = [mainEntry, ...preloadEntries].filter(fs10.existsSync);
1937
2131
  const watcher = chokidar.watch(watchTargets, { ignoreInitial: true });
1938
2132
  let restarting = null;
1939
- watcher.on("all", async () => {
1940
- if (restarting) return;
2133
+ let pending = false;
2134
+ const restart = async () => {
2135
+ if (restarting) {
2136
+ pending = true;
2137
+ return;
2138
+ }
1941
2139
  restarting = (async () => {
1942
- console.log(pc4.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
1943
- try {
2140
+ do {
2141
+ pending = false;
2142
+ console.log(pc4.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
1944
2143
  if (child && !child.killed) {
1945
2144
  ;
1946
2145
  child.__nastiKilled = true;
@@ -1954,12 +2153,24 @@ async function startElectronDev(inlineConfig = {}) {
1954
2153
  dying.kill();
1955
2154
  });
1956
2155
  }
1957
- await compileAll();
1958
- spawnElectron();
1959
- } finally {
1960
- restarting = null;
1961
- }
2156
+ try {
2157
+ await compileAll();
2158
+ spawnElectron();
2159
+ } catch (e) {
2160
+ console.warn(pc4.yellow(` \u26A0 \u91CD\u542F\u7F16\u8BD1\u5931\u8D25\uFF0C\u4FDD\u7559\u4E0A\u4E00\u6B21\u8FDB\u7A0B: ${e.message}`));
2161
+ }
2162
+ } while (pending);
2163
+ restarting = null;
1962
2164
  })();
2165
+ return restarting;
2166
+ };
2167
+ let debounceTimer = null;
2168
+ watcher.on("all", () => {
2169
+ if (debounceTimer) clearTimeout(debounceTimer);
2170
+ debounceTimer = setTimeout(() => {
2171
+ debounceTimer = null;
2172
+ void restart();
2173
+ }, 80);
1963
2174
  });
1964
2175
  }
1965
2176
  }
@@ -2007,7 +2218,7 @@ function resolveElectronBinary(config) {
2007
2218
  return config.electron.electronPath;
2008
2219
  }
2009
2220
  try {
2010
- const require2 = createRequire2(path12.resolve(config.root, "package.json"));
2221
+ const require2 = createRequire3(path12.resolve(config.root, "package.json"));
2011
2222
  const pathFile = require2.resolve("electron");
2012
2223
  const electronModule = require2(pathFile);
2013
2224
  if (typeof electronModule === "string" && fs10.existsSync(electronModule)) {
@@ -2180,6 +2391,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
2180
2391
  }
2181
2392
  });
2182
2393
  cli.help();
2183
- cli.version("1.5.0");
2394
+ cli.version("1.5.1");
2184
2395
  cli.parse();
2185
2396
  //# sourceMappingURL=cli.js.map