@nasti-toolchain/nasti 1.4.1 → 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",
@@ -1417,15 +1611,6 @@ async function createServer(inlineConfig = {}) {
1417
1611
  watcher.on("add", (file) => {
1418
1612
  handleFileChange(file, server);
1419
1613
  });
1420
- const postMiddlewares = [];
1421
- for (const plugin of allPlugins) {
1422
- if (plugin.configureServer) {
1423
- const result = await plugin.configureServer(server);
1424
- if (typeof result === "function") {
1425
- postMiddlewares.push(result);
1426
- }
1427
- }
1428
- }
1429
1614
  server = {
1430
1615
  config: configWithPlugins,
1431
1616
  middlewares: app,
@@ -1444,7 +1629,7 @@ async function createServer(inlineConfig = {}) {
1444
1629
  const localUrl = `http://localhost:${actualPort}`;
1445
1630
  const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
1446
1631
  console.log();
1447
- console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.4.1"}`));
1632
+ console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.5.1"}`));
1448
1633
  console.log();
1449
1634
  console.log(` ${pc.green(">")} Local: ${pc.cyan(localUrl)}`);
1450
1635
  if (networkUrl) {
@@ -1477,6 +1662,16 @@ async function createServer(inlineConfig = {}) {
1477
1662
  httpServer.close();
1478
1663
  }
1479
1664
  };
1665
+ const postMiddlewares = [];
1666
+ for (const plugin of allPlugins) {
1667
+ if (plugin.configureServer) {
1668
+ const result = await plugin.configureServer(server);
1669
+ if (typeof result === "function") {
1670
+ postMiddlewares.push(result);
1671
+ }
1672
+ }
1673
+ }
1674
+ for (const run of postMiddlewares) run();
1480
1675
  return server;
1481
1676
  }
1482
1677
  function getNetworkAddress() {
@@ -1557,7 +1752,7 @@ import pc2 from "picocolors";
1557
1752
  async function build(inlineConfig = {}) {
1558
1753
  const config = await resolveConfig(inlineConfig, "build");
1559
1754
  const startTime = performance.now();
1560
- console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.4.1"}`));
1755
+ console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.5.1"}`));
1561
1756
  console.log(pc2.dim(` root: ${config.root}`));
1562
1757
  console.log(pc2.dim(` mode: ${config.mode}`));
1563
1758
  const outDir = path10.resolve(config.root, config.build.outDir);
@@ -1717,7 +1912,7 @@ async function buildElectron(inlineConfig = {}) {
1717
1912
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
1718
1913
  const startTime = performance.now();
1719
1914
  assertElectronVersion(config);
1720
- console.log(pc3.cyan("\n\u26A1 nasti build (electron)") + pc3.dim(` v${"1.4.1"}`));
1915
+ console.log(pc3.cyan("\n\u26A1 nasti build (electron)") + pc3.dim(` v${"1.5.1"}`));
1721
1916
  console.log(pc3.dim(` root: ${config.root}`));
1722
1917
  console.log(pc3.dim(` mode: ${config.mode}`));
1723
1918
  console.log(pc3.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
@@ -1862,7 +2057,7 @@ __export(electron_dev_exports, {
1862
2057
  });
1863
2058
  import path12 from "path";
1864
2059
  import fs10 from "fs";
1865
- import { createRequire as createRequire2 } from "module";
2060
+ import { createRequire as createRequire3 } from "module";
1866
2061
  import { spawn } from "child_process";
1867
2062
  import chokidar from "chokidar";
1868
2063
  import pc4 from "picocolors";
@@ -1871,7 +2066,7 @@ async function startElectronDev(inlineConfig = {}) {
1871
2066
  const { noSpawn, ...rest } = inlineConfig;
1872
2067
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
1873
2068
  warnElectronVersion(config);
1874
- console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.4.1"}`));
2069
+ console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.5.1"}`));
1875
2070
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
1876
2071
  const server = await createServer2({ ...rest, target: "electron" });
1877
2072
  await server.listen();
@@ -1935,11 +2130,16 @@ async function startElectronDev(inlineConfig = {}) {
1935
2130
  const watchTargets = [mainEntry, ...preloadEntries].filter(fs10.existsSync);
1936
2131
  const watcher = chokidar.watch(watchTargets, { ignoreInitial: true });
1937
2132
  let restarting = null;
1938
- watcher.on("all", async () => {
1939
- if (restarting) return;
2133
+ let pending = false;
2134
+ const restart = async () => {
2135
+ if (restarting) {
2136
+ pending = true;
2137
+ return;
2138
+ }
1940
2139
  restarting = (async () => {
1941
- console.log(pc4.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
1942
- try {
2140
+ do {
2141
+ pending = false;
2142
+ console.log(pc4.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
1943
2143
  if (child && !child.killed) {
1944
2144
  ;
1945
2145
  child.__nastiKilled = true;
@@ -1953,12 +2153,24 @@ async function startElectronDev(inlineConfig = {}) {
1953
2153
  dying.kill();
1954
2154
  });
1955
2155
  }
1956
- await compileAll();
1957
- spawnElectron();
1958
- } finally {
1959
- restarting = null;
1960
- }
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;
1961
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);
1962
2174
  });
1963
2175
  }
1964
2176
  }
@@ -2006,7 +2218,7 @@ function resolveElectronBinary(config) {
2006
2218
  return config.electron.electronPath;
2007
2219
  }
2008
2220
  try {
2009
- const require2 = createRequire2(path12.resolve(config.root, "package.json"));
2221
+ const require2 = createRequire3(path12.resolve(config.root, "package.json"));
2010
2222
  const pathFile = require2.resolve("electron");
2011
2223
  const electronModule = require2(pathFile);
2012
2224
  if (typeof electronModule === "string" && fs10.existsSync(electronModule)) {
@@ -2179,6 +2391,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
2179
2391
  }
2180
2392
  });
2181
2393
  cli.help();
2182
- cli.version("1.4.1");
2394
+ cli.version("1.5.1");
2183
2395
  cli.parse();
2184
2396
  //# sourceMappingURL=cli.js.map