@neuxnet/neux-cli 0.2.7 → 0.2.8

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/core/web.js +44 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuxnet/neux-cli",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Standalone CLI and Node API for Neux mini program build, pack, preview, and CI automation.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/core/web.js CHANGED
@@ -192,6 +192,10 @@ export function liveReloadScript() {
192
192
  return `<script>
193
193
  (() => {
194
194
  const source = new EventSource('/__dimina_live_reload');
195
+ let hotUpdateQueue = Promise.resolve();
196
+ let hotUpdateRecoveryTimer = null;
197
+ let hotUpdateRecoveryActive = false;
198
+ let reloadRequested = false;
195
199
  const refreshStylesheets = (doc, timestamp) => {
196
200
  if (!doc) return;
197
201
  for (const link of doc.querySelectorAll('link[rel="stylesheet"][href]')) {
@@ -209,36 +213,66 @@ export function liveReloadScript() {
209
213
  } catch {}
210
214
  }
211
215
  };
216
+ const requestReload = () => {
217
+ if (reloadRequested) return;
218
+ reloadRequested = true;
219
+ window.location.reload();
220
+ };
221
+ const armHotUpdateRecovery = () => {
222
+ hotUpdateRecoveryActive = true;
223
+ clearTimeout(hotUpdateRecoveryTimer);
224
+ hotUpdateRecoveryTimer = setTimeout(() => {
225
+ hotUpdateRecoveryActive = false;
226
+ }, 2000);
227
+ };
228
+ const isDomPatchError = (value) => {
229
+ const message = value?.message || value?.reason?.message || value?.reason || value;
230
+ return /(?:insertBefore|appendChild|removeChild|parentNode)/.test(String(message || ''));
231
+ };
232
+ const recoverFromAsyncHotUpdateError = (event) => {
233
+ if (hotUpdateRecoveryActive && isDomPatchError(event?.error || event)) {
234
+ requestReload();
235
+ }
236
+ };
237
+ window.addEventListener('error', recoverFromAsyncHotUpdateError);
238
+ window.addEventListener('unhandledrejection', recoverFromAsyncHotUpdateError);
212
239
  const applyHotUpdate = (handler, payload) => {
240
+ armHotUpdateRecovery();
213
241
  try {
214
242
  if (typeof handler !== 'function') {
215
- window.location.reload();
243
+ requestReload();
216
244
  return;
217
245
  }
218
246
  const result = handler(payload);
219
247
  if (result && typeof result.then === 'function') {
220
- result.then((handled) => {
221
- if (handled === false || handled == null) window.location.reload();
222
- }).catch(() => window.location.reload());
223
- return;
248
+ return result.then((handled) => {
249
+ if (handled === false || handled == null) requestReload();
250
+ }).catch(() => requestReload());
224
251
  }
225
252
  if (result === false || result == null) {
226
- window.location.reload();
253
+ requestReload();
227
254
  }
255
+ return result;
228
256
  } catch {
229
- window.location.reload();
257
+ requestReload();
230
258
  }
231
259
  };
260
+ const enqueueHotUpdate = (handler, payload) => {
261
+ hotUpdateQueue = hotUpdateQueue
262
+ .then(() => applyHotUpdate(handler, payload))
263
+ .catch(() => requestReload());
264
+ return hotUpdateQueue;
265
+ };
232
266
  source.addEventListener('style-update', refreshAllStylesheets);
233
267
  source.addEventListener('view-update', (event) => {
234
268
  const payload = JSON.parse(event.data || '{}');
235
- applyHotUpdate(window.__diminaHotUpdateView, payload);
269
+ enqueueHotUpdate(window.__diminaHotUpdateView, payload);
236
270
  });
237
271
  source.addEventListener('logic-update', (event) => {
238
272
  const payload = JSON.parse(event.data || '{}');
239
- applyHotUpdate(window.__diminaHotUpdateLogic, payload);
273
+ enqueueHotUpdate(window.__diminaHotUpdateLogic, payload);
240
274
  });
241
- source.addEventListener('reload', () => location.reload());
275
+ source.addEventListener('reload', requestReload);
242
276
  })();
243
277
  </script>`
244
278
  }