@absolutejs/absolute 0.19.0-beta.130 → 0.19.0-beta.131
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/.absolutejs/tsconfig.tsbuildinfo +1 -1
- package/dist/build.js +8 -7
- package/dist/build.js.map +3 -3
- package/dist/dev/client/constants.ts +25 -0
- package/dist/dev/client/cssUtils.ts +305 -0
- package/dist/dev/client/domDiff.ts +225 -0
- package/dist/dev/client/domState.ts +420 -0
- package/dist/dev/client/domTracker.ts +60 -0
- package/dist/dev/client/errorOverlay.ts +183 -0
- package/dist/dev/client/frameworkDetect.ts +62 -0
- package/dist/dev/client/handlers/angular.ts +551 -0
- package/dist/dev/client/handlers/angularRuntime.ts +205 -0
- package/dist/dev/client/handlers/html.ts +361 -0
- package/dist/dev/client/handlers/htmx.ts +274 -0
- package/dist/dev/client/handlers/react.ts +107 -0
- package/dist/dev/client/handlers/rebuild.ts +152 -0
- package/dist/dev/client/handlers/svelte.ts +328 -0
- package/dist/dev/client/handlers/vue.ts +266 -0
- package/dist/dev/client/headPatch.ts +232 -0
- package/dist/dev/client/hmrClient.ts +250 -0
- package/dist/dev/client/moduleVersions.ts +61 -0
- package/dist/dev/client/reactRefreshSetup.ts +34 -0
- package/dist/index.js +8 -7
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/* Head element patching for HMR updates (title, meta, favicon, etc.) */
|
|
2
|
+
|
|
3
|
+
const getLinkElementKey = (elem: Element) => {
|
|
4
|
+
const rel = (elem.getAttribute('rel') || '').toLowerCase();
|
|
5
|
+
if (rel === 'icon' || rel === 'shortcut icon' || rel === 'apple-touch-icon')
|
|
6
|
+
return `link:icon:${rel}`;
|
|
7
|
+
if (rel === 'stylesheet') return null;
|
|
8
|
+
if (rel === 'preconnect')
|
|
9
|
+
return `link:preconnect:${elem.getAttribute('href') || ''}`;
|
|
10
|
+
if (rel === 'preload')
|
|
11
|
+
return `link:preload:${elem.getAttribute('href') || ''}`;
|
|
12
|
+
if (rel === 'canonical') return 'link:canonical';
|
|
13
|
+
if (rel === 'dns-prefetch')
|
|
14
|
+
return `link:dns-prefetch:${elem.getAttribute('href') || ''}`;
|
|
15
|
+
|
|
16
|
+
return null;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const getHeadElementKey = (elem: Element) => {
|
|
20
|
+
const tag = elem.tagName.toLowerCase();
|
|
21
|
+
|
|
22
|
+
if (tag === 'title') return 'title';
|
|
23
|
+
if (tag === 'meta' && elem.hasAttribute('charset')) return 'meta:charset';
|
|
24
|
+
if (tag === 'meta' && elem.hasAttribute('name'))
|
|
25
|
+
return `meta:name:${elem.getAttribute('name')}`;
|
|
26
|
+
if (tag === 'meta' && elem.hasAttribute('property'))
|
|
27
|
+
return `meta:property:${elem.getAttribute('property')}`;
|
|
28
|
+
if (tag === 'meta' && elem.hasAttribute('http-equiv'))
|
|
29
|
+
return `meta:http-equiv:${elem.getAttribute('http-equiv')}`;
|
|
30
|
+
|
|
31
|
+
if (tag === 'link') return getLinkElementKey(elem);
|
|
32
|
+
|
|
33
|
+
if (tag === 'script' && elem.hasAttribute('data-hmr-id'))
|
|
34
|
+
return `script:hmr:${elem.getAttribute('data-hmr-id')}`;
|
|
35
|
+
if (tag === 'script') return null;
|
|
36
|
+
if (tag === 'base') return 'base';
|
|
37
|
+
|
|
38
|
+
return null;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const shouldPreserveElement = (elem: Element) => {
|
|
42
|
+
if (elem.hasAttribute('data-hmr-import-map')) return true;
|
|
43
|
+
if (elem.hasAttribute('data-hmr-client')) return true;
|
|
44
|
+
if (elem.hasAttribute('data-react-refresh-setup')) return true;
|
|
45
|
+
|
|
46
|
+
const attrs = Array.from(elem.attributes);
|
|
47
|
+
for (let idx = 0; idx < attrs.length; idx++) {
|
|
48
|
+
if (attrs[idx]?.name.startsWith('data-hmr-')) return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (elem.tagName === 'SCRIPT') {
|
|
52
|
+
const src = elem.getAttribute('src') || '';
|
|
53
|
+
if (src.includes('htmx.min.js') || src.includes('htmx.js')) return true;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return false;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const updateTitleElement = (oldEl: Element, newEl: Element) => {
|
|
60
|
+
const newTitle = newEl.textContent || '';
|
|
61
|
+
if (oldEl.textContent === newTitle) return;
|
|
62
|
+
oldEl.textContent = newTitle;
|
|
63
|
+
document.title = newTitle;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const updateMetaElement = (oldEl: Element, newEl: Element) => {
|
|
67
|
+
const newContent = newEl.getAttribute('content');
|
|
68
|
+
const oldContent = oldEl.getAttribute('content');
|
|
69
|
+
if (oldContent !== newContent && newContent !== null) {
|
|
70
|
+
oldEl.setAttribute('content', newContent);
|
|
71
|
+
}
|
|
72
|
+
if (!newEl.hasAttribute('charset')) return;
|
|
73
|
+
const newCharset = newEl.getAttribute('charset');
|
|
74
|
+
if (oldEl.getAttribute('charset') !== newCharset && newCharset !== null) {
|
|
75
|
+
oldEl.setAttribute('charset', newCharset);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const updateFaviconHref = (
|
|
80
|
+
oldEl: Element,
|
|
81
|
+
newHref: string,
|
|
82
|
+
oldHref: string
|
|
83
|
+
) => {
|
|
84
|
+
const [oldBase] = oldHref.split('?');
|
|
85
|
+
const [newBase] = newHref.split('?');
|
|
86
|
+
if (oldBase === newBase) return;
|
|
87
|
+
const cacheBustedHref = `${
|
|
88
|
+
newHref + (newHref.includes('?') ? '&' : '?')
|
|
89
|
+
}t=${Date.now()}`;
|
|
90
|
+
oldEl.setAttribute('href', cacheBustedHref);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const updateLinkElement = (oldEl: Element, newEl: Element) => {
|
|
94
|
+
const rel = (oldEl.getAttribute('rel') || '').toLowerCase();
|
|
95
|
+
const newHref = newEl.getAttribute('href');
|
|
96
|
+
const oldHref = oldEl.getAttribute('href');
|
|
97
|
+
|
|
98
|
+
const isIcon =
|
|
99
|
+
rel === 'icon' || rel === 'shortcut icon' || rel === 'apple-touch-icon';
|
|
100
|
+
|
|
101
|
+
if (isIcon && newHref && oldHref) {
|
|
102
|
+
updateFaviconHref(oldEl, newHref, oldHref);
|
|
103
|
+
} else if (!isIcon && newHref && oldHref !== newHref) {
|
|
104
|
+
oldEl.setAttribute('href', newHref);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const attrsToCheck = ['type', 'sizes', 'crossorigin', 'as', 'media'];
|
|
108
|
+
attrsToCheck.forEach((attr) => {
|
|
109
|
+
const newVal = newEl.getAttribute(attr);
|
|
110
|
+
const oldVal = oldEl.getAttribute(attr);
|
|
111
|
+
if (newVal !== null && oldVal !== newVal) {
|
|
112
|
+
oldEl.setAttribute(attr, newVal);
|
|
113
|
+
} else if (newVal === null && oldVal !== null) {
|
|
114
|
+
oldEl.removeAttribute(attr);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const updateBaseElement = (oldEl: Element, newEl: Element) => {
|
|
120
|
+
const newHref = newEl.getAttribute('href');
|
|
121
|
+
const newTarget = newEl.getAttribute('target');
|
|
122
|
+
if (newHref && oldEl.getAttribute('href') !== newHref) {
|
|
123
|
+
oldEl.setAttribute('href', newHref);
|
|
124
|
+
}
|
|
125
|
+
if (newTarget && oldEl.getAttribute('target') !== newTarget) {
|
|
126
|
+
oldEl.setAttribute('target', newTarget);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const updateHeadElement = (oldEl: Element, newEl: Element) => {
|
|
131
|
+
const tag = oldEl.tagName.toLowerCase();
|
|
132
|
+
|
|
133
|
+
if (tag === 'title') {
|
|
134
|
+
updateTitleElement(oldEl, newEl);
|
|
135
|
+
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (tag === 'meta') {
|
|
140
|
+
updateMetaElement(oldEl, newEl);
|
|
141
|
+
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (tag === 'link') {
|
|
146
|
+
updateLinkElement(oldEl, newEl);
|
|
147
|
+
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (tag === 'base') {
|
|
152
|
+
updateBaseElement(oldEl, newEl);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const addHeadElement = (newEl: Element) => {
|
|
157
|
+
const clone = document.createElement(newEl.tagName.toLowerCase());
|
|
158
|
+
for (const attr of Array.from(newEl.attributes)) {
|
|
159
|
+
clone.setAttribute(attr.name, attr.value);
|
|
160
|
+
}
|
|
161
|
+
clone.textContent = newEl.textContent;
|
|
162
|
+
clone.setAttribute('data-hmr-source', 'patched');
|
|
163
|
+
|
|
164
|
+
const tag = newEl.tagName.toLowerCase();
|
|
165
|
+
const { head } = document;
|
|
166
|
+
let insertBefore: Node | null = null;
|
|
167
|
+
|
|
168
|
+
if (tag === 'title') {
|
|
169
|
+
insertBefore = head.firstChild;
|
|
170
|
+
} else if (tag === 'meta') {
|
|
171
|
+
const firstLink = head.querySelector('link');
|
|
172
|
+
const firstScript = head.querySelector('script');
|
|
173
|
+
insertBefore = firstLink || firstScript;
|
|
174
|
+
} else if (tag === 'link') {
|
|
175
|
+
const firstScript = head.querySelector('script');
|
|
176
|
+
insertBefore = firstScript;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (insertBefore) {
|
|
180
|
+
head.insertBefore(clone, insertBefore);
|
|
181
|
+
} else {
|
|
182
|
+
head.appendChild(clone);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const removeStaleElement = (existingEl: Element) => {
|
|
187
|
+
if (shouldPreserveElement(existingEl)) return;
|
|
188
|
+
const tag = existingEl.tagName.toLowerCase();
|
|
189
|
+
const rel = existingEl.getAttribute('rel') || '';
|
|
190
|
+
if (tag === 'link' && rel === 'stylesheet') return;
|
|
191
|
+
existingEl.remove();
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export const patchHeadInPlace = (newHeadHTML: string) => {
|
|
195
|
+
if (!newHeadHTML) return;
|
|
196
|
+
|
|
197
|
+
const tempDiv = document.createElement('div');
|
|
198
|
+
tempDiv.innerHTML = newHeadHTML;
|
|
199
|
+
|
|
200
|
+
const existingMap = new Map<string, Element>();
|
|
201
|
+
const newMap = new Map<string, Element>();
|
|
202
|
+
|
|
203
|
+
Array.from(document.head.children).forEach((elem) => {
|
|
204
|
+
if (shouldPreserveElement(elem)) return;
|
|
205
|
+
const key = getHeadElementKey(elem);
|
|
206
|
+
if (key) {
|
|
207
|
+
existingMap.set(key, elem);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
Array.from(tempDiv.children).forEach((elem) => {
|
|
212
|
+
const key = getHeadElementKey(elem);
|
|
213
|
+
if (key) {
|
|
214
|
+
newMap.set(key, elem);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
newMap.forEach((newEl, key) => {
|
|
219
|
+
const existingEl = existingMap.get(key);
|
|
220
|
+
if (existingEl) {
|
|
221
|
+
updateHeadElement(existingEl, newEl);
|
|
222
|
+
} else {
|
|
223
|
+
addHeadElement(newEl);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
existingMap.forEach((existingEl, key) => {
|
|
228
|
+
if (!newMap.has(key)) {
|
|
229
|
+
removeStaleElement(existingEl);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
};
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/* AbsoluteJS HMR Client - Entry point
|
|
2
|
+
Initializes WebSocket connection, dispatches messages to framework handlers */
|
|
3
|
+
|
|
4
|
+
import { hmrState } from '../../../types/client';
|
|
5
|
+
import {
|
|
6
|
+
HMR_UPDATE_TIMEOUT_MS,
|
|
7
|
+
MAX_RECONNECT_ATTEMPTS,
|
|
8
|
+
PING_INTERVAL_MS,
|
|
9
|
+
RECONNECT_INITIAL_DELAY_MS,
|
|
10
|
+
RECONNECT_POLL_INTERVAL_MS,
|
|
11
|
+
WEBSOCKET_NORMAL_CLOSURE
|
|
12
|
+
} from './constants';
|
|
13
|
+
import { detectCurrentFramework } from './frameworkDetect';
|
|
14
|
+
import { hideErrorOverlay, showErrorOverlay } from './errorOverlay';
|
|
15
|
+
import { handleAngularUpdate } from './handlers/angular';
|
|
16
|
+
import { handleReactUpdate } from './handlers/react';
|
|
17
|
+
import { handleHTMLUpdate, handleScriptUpdate } from './handlers/html';
|
|
18
|
+
import { handleHTMXUpdate } from './handlers/htmx';
|
|
19
|
+
import { handleSvelteUpdate } from './handlers/svelte';
|
|
20
|
+
import { handleVueUpdate } from './handlers/vue';
|
|
21
|
+
import { reloadCSSStylesheets } from './cssUtils';
|
|
22
|
+
import {
|
|
23
|
+
handleFullReload,
|
|
24
|
+
handleManifest,
|
|
25
|
+
handleModuleUpdate,
|
|
26
|
+
handleRebuildComplete,
|
|
27
|
+
handleRebuildError
|
|
28
|
+
} from './handlers/rebuild';
|
|
29
|
+
|
|
30
|
+
// Initialize HMR globals
|
|
31
|
+
if (typeof window !== 'undefined') {
|
|
32
|
+
if (!window.__HMR_MANIFEST__) {
|
|
33
|
+
window.__HMR_MANIFEST__ = {};
|
|
34
|
+
}
|
|
35
|
+
if (!window.__HMR_MODULE_UPDATES__) {
|
|
36
|
+
window.__HMR_MODULE_UPDATES__ = [];
|
|
37
|
+
}
|
|
38
|
+
if (!window.__HMR_MODULE_VERSIONS__) {
|
|
39
|
+
window.__HMR_MODULE_VERSIONS__ = {};
|
|
40
|
+
}
|
|
41
|
+
if (!window.__HMR_SERVER_VERSIONS__) {
|
|
42
|
+
window.__HMR_SERVER_VERSIONS__ = {};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Catch uncaught runtime errors and show the error overlay
|
|
47
|
+
window.addEventListener('error', (evt) => {
|
|
48
|
+
if (!evt.error) return;
|
|
49
|
+
showErrorOverlay({
|
|
50
|
+
framework: detectCurrentFramework() || undefined,
|
|
51
|
+
kind: 'runtime',
|
|
52
|
+
message:
|
|
53
|
+
evt.error instanceof Error
|
|
54
|
+
? evt.error.stack || evt.error.message
|
|
55
|
+
: String(evt.error)
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
window.addEventListener('unhandledrejection', (evt) => {
|
|
60
|
+
if (!evt.reason) return;
|
|
61
|
+
showErrorOverlay({
|
|
62
|
+
framework: detectCurrentFramework() || undefined,
|
|
63
|
+
kind: 'runtime',
|
|
64
|
+
message:
|
|
65
|
+
evt.reason instanceof Error
|
|
66
|
+
? evt.reason.stack || evt.reason.message
|
|
67
|
+
: String(evt.reason)
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const hmrUpdateTypes = new Set([
|
|
72
|
+
'angular-update',
|
|
73
|
+
'react-update',
|
|
74
|
+
'html-update',
|
|
75
|
+
'htmx-update',
|
|
76
|
+
'vue-update',
|
|
77
|
+
'svelte-update',
|
|
78
|
+
'style-update',
|
|
79
|
+
'module-update',
|
|
80
|
+
'rebuild-start'
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
const handleHMRMessage = (message: any) => {
|
|
85
|
+
if (hmrUpdateTypes.has(message.type)) {
|
|
86
|
+
hmrState.isHMRUpdating = true;
|
|
87
|
+
setTimeout(() => {
|
|
88
|
+
hmrState.isHMRUpdating = false;
|
|
89
|
+
}, HMR_UPDATE_TIMEOUT_MS);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
switch (message.type) {
|
|
93
|
+
case 'manifest':
|
|
94
|
+
handleManifest(message);
|
|
95
|
+
break;
|
|
96
|
+
case 'rebuild-start':
|
|
97
|
+
break;
|
|
98
|
+
case 'rebuild-complete':
|
|
99
|
+
handleRebuildComplete(message);
|
|
100
|
+
break;
|
|
101
|
+
case 'framework-update':
|
|
102
|
+
break;
|
|
103
|
+
case 'module-update':
|
|
104
|
+
hideErrorOverlay();
|
|
105
|
+
handleModuleUpdate(message);
|
|
106
|
+
break;
|
|
107
|
+
case 'react-update':
|
|
108
|
+
handleReactUpdate(message);
|
|
109
|
+
break;
|
|
110
|
+
case 'script-update':
|
|
111
|
+
hideErrorOverlay();
|
|
112
|
+
handleScriptUpdate(message);
|
|
113
|
+
break;
|
|
114
|
+
case 'html-update':
|
|
115
|
+
hideErrorOverlay();
|
|
116
|
+
handleHTMLUpdate(message);
|
|
117
|
+
break;
|
|
118
|
+
case 'htmx-update':
|
|
119
|
+
hideErrorOverlay();
|
|
120
|
+
handleHTMXUpdate(message);
|
|
121
|
+
break;
|
|
122
|
+
case 'svelte-update':
|
|
123
|
+
hideErrorOverlay();
|
|
124
|
+
handleSvelteUpdate(message);
|
|
125
|
+
break;
|
|
126
|
+
case 'vue-update':
|
|
127
|
+
hideErrorOverlay();
|
|
128
|
+
handleVueUpdate(message);
|
|
129
|
+
break;
|
|
130
|
+
case 'angular-update':
|
|
131
|
+
hideErrorOverlay();
|
|
132
|
+
handleAngularUpdate(message);
|
|
133
|
+
break;
|
|
134
|
+
case 'rebuild-error':
|
|
135
|
+
handleRebuildError(message);
|
|
136
|
+
break;
|
|
137
|
+
case 'full-reload':
|
|
138
|
+
handleFullReload();
|
|
139
|
+
break;
|
|
140
|
+
case 'pong':
|
|
141
|
+
break;
|
|
142
|
+
case 'style-update':
|
|
143
|
+
reloadCSSStylesheets(message.data.manifest);
|
|
144
|
+
break;
|
|
145
|
+
default:
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Prevent multiple WebSocket connections
|
|
151
|
+
if (!(window.__HMR_WS__ && window.__HMR_WS__.readyState === WebSocket.OPEN)) {
|
|
152
|
+
// Determine WebSocket URL
|
|
153
|
+
const wsHost = location.hostname;
|
|
154
|
+
const wsPort =
|
|
155
|
+
location.port || (location.protocol === 'https:' ? '443' : '80');
|
|
156
|
+
const wsProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
|
|
157
|
+
const wsUrl = `${wsProtocol}://${wsHost}:${wsPort}/hmr`;
|
|
158
|
+
|
|
159
|
+
const wsc = new WebSocket(wsUrl);
|
|
160
|
+
window.__HMR_WS__ = wsc;
|
|
161
|
+
|
|
162
|
+
wsc.onopen = function () {
|
|
163
|
+
hmrState.isConnected = true;
|
|
164
|
+
sessionStorage.setItem('__HMR_CONNECTED__', 'true');
|
|
165
|
+
|
|
166
|
+
const currentFramework = detectCurrentFramework();
|
|
167
|
+
wsc.send(
|
|
168
|
+
JSON.stringify({
|
|
169
|
+
framework: currentFramework,
|
|
170
|
+
type: 'ready'
|
|
171
|
+
})
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
if (hmrState.reconnectTimeout) {
|
|
175
|
+
clearTimeout(hmrState.reconnectTimeout);
|
|
176
|
+
hmrState.reconnectTimeout = null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
hmrState.pingInterval = setInterval(() => {
|
|
180
|
+
if (wsc.readyState === WebSocket.OPEN && hmrState.isConnected) {
|
|
181
|
+
wsc.send(JSON.stringify({ type: 'ping' }));
|
|
182
|
+
}
|
|
183
|
+
}, PING_INTERVAL_MS);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
wsc.onmessage = function (event: MessageEvent) {
|
|
187
|
+
let message;
|
|
188
|
+
try {
|
|
189
|
+
message = JSON.parse(event.data);
|
|
190
|
+
} catch {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
handleHMRMessage(message);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
wsc.onclose = function (event: CloseEvent) {
|
|
198
|
+
hmrState.isConnected = false;
|
|
199
|
+
|
|
200
|
+
if (hmrState.pingInterval) {
|
|
201
|
+
clearInterval(hmrState.pingInterval);
|
|
202
|
+
hmrState.pingInterval = null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (event.code !== WEBSOCKET_NORMAL_CLOSURE) {
|
|
206
|
+
let attempts = 0;
|
|
207
|
+
hmrState.reconnectTimeout = setTimeout(function pollServer() {
|
|
208
|
+
attempts++;
|
|
209
|
+
if (attempts > MAX_RECONNECT_ATTEMPTS) return;
|
|
210
|
+
|
|
211
|
+
fetch('/hmr-status', { cache: 'no-store' })
|
|
212
|
+
.then((res) => {
|
|
213
|
+
if (res.ok) {
|
|
214
|
+
window.location.reload();
|
|
215
|
+
} else {
|
|
216
|
+
hmrState.reconnectTimeout = setTimeout(
|
|
217
|
+
pollServer,
|
|
218
|
+
RECONNECT_POLL_INTERVAL_MS
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return undefined;
|
|
223
|
+
})
|
|
224
|
+
.catch(() => {
|
|
225
|
+
hmrState.reconnectTimeout = setTimeout(
|
|
226
|
+
pollServer,
|
|
227
|
+
RECONNECT_POLL_INTERVAL_MS
|
|
228
|
+
);
|
|
229
|
+
});
|
|
230
|
+
}, RECONNECT_INITIAL_DELAY_MS);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
wsc.onerror = function () {
|
|
235
|
+
hmrState.isConnected = false;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
window.addEventListener('beforeunload', () => {
|
|
239
|
+
if (hmrState.isHMRUpdating) {
|
|
240
|
+
if (hmrState.pingInterval) clearInterval(hmrState.pingInterval);
|
|
241
|
+
if (hmrState.reconnectTimeout)
|
|
242
|
+
clearTimeout(hmrState.reconnectTimeout);
|
|
243
|
+
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (hmrState.pingInterval) clearInterval(hmrState.pingInterval);
|
|
248
|
+
if (hmrState.reconnectTimeout) clearTimeout(hmrState.reconnectTimeout);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/* Module version validation and sync */
|
|
2
|
+
|
|
3
|
+
export const checkModuleVersions = (
|
|
4
|
+
serverVersions: Record<string, number> | undefined,
|
|
5
|
+
clientVersions: Record<string, number> | undefined
|
|
6
|
+
) => {
|
|
7
|
+
if (!serverVersions || !clientVersions) {
|
|
8
|
+
return { needsSync: false, stale: [] };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const stale = Object.entries(serverVersions)
|
|
12
|
+
.filter(([modulePath, serverVersion]) => {
|
|
13
|
+
const clientVersion = clientVersions[modulePath];
|
|
14
|
+
|
|
15
|
+
return clientVersion === undefined || clientVersion < serverVersion;
|
|
16
|
+
})
|
|
17
|
+
.map(([modulePath]) => modulePath);
|
|
18
|
+
|
|
19
|
+
return { needsSync: stale.length > 0, stale };
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const resolveManifestPath = (
|
|
23
|
+
modulePath: string,
|
|
24
|
+
manifest: Record<string, string> | undefined
|
|
25
|
+
) => {
|
|
26
|
+
if (!manifest) {
|
|
27
|
+
return modulePath;
|
|
28
|
+
}
|
|
29
|
+
for (const key of Object.keys(manifest)) {
|
|
30
|
+
const path = manifest[key] ?? modulePath;
|
|
31
|
+
if (path === modulePath || path.includes(modulePath)) {
|
|
32
|
+
return path;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return modulePath;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const prefetchModules = (
|
|
40
|
+
modulePaths: string[],
|
|
41
|
+
manifest: Record<string, string> | undefined
|
|
42
|
+
) => {
|
|
43
|
+
const prefetchPromises: Promise<unknown>[] = [];
|
|
44
|
+
|
|
45
|
+
for (const modulePath of modulePaths) {
|
|
46
|
+
const manifestPath = resolveManifestPath(modulePath, manifest);
|
|
47
|
+
|
|
48
|
+
const cacheBuster = `?t=${Date.now()}`;
|
|
49
|
+
const fullPath = manifestPath.startsWith('/')
|
|
50
|
+
? manifestPath + cacheBuster
|
|
51
|
+
: `/${manifestPath}${cacheBuster}`;
|
|
52
|
+
|
|
53
|
+
prefetchPromises.push(
|
|
54
|
+
import(fullPath).catch(() => {
|
|
55
|
+
/* ignore */
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return Promise.all(prefetchPromises);
|
|
61
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* React Refresh runtime setup — must be imported before any component modules.
|
|
2
|
+
Bun's reactFastRefresh flag injects $RefreshSig$/$RefreshReg$ calls into
|
|
3
|
+
component code. This module ensures those globals exist before components
|
|
4
|
+
initialize.
|
|
5
|
+
|
|
6
|
+
IMPORTANT: This module is idempotent. On HMR re-import the existing runtime
|
|
7
|
+
is preserved so new component registrations feed into the SAME RefreshRuntime
|
|
8
|
+
instance that owns the current React tree. */
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
11
|
+
// @ts-ignore — react-refresh has no type declarations
|
|
12
|
+
import RefreshRuntime from 'react-refresh/runtime';
|
|
13
|
+
|
|
14
|
+
if (!window.$RefreshRuntime$) {
|
|
15
|
+
RefreshRuntime.injectIntoGlobalHook(window);
|
|
16
|
+
window.$RefreshRuntime$ = RefreshRuntime;
|
|
17
|
+
window.$RefreshReg$ = (type: unknown, id: string) =>
|
|
18
|
+
RefreshRuntime.register(type, id);
|
|
19
|
+
window.$RefreshSig$ = () =>
|
|
20
|
+
RefreshRuntime.createSignatureFunctionForTransform();
|
|
21
|
+
|
|
22
|
+
// Replay buffered registrations from the bootstrap script.
|
|
23
|
+
// The SSR HTML injects a buffering $RefreshReg$ that captures
|
|
24
|
+
// registrations before the runtime is ready.
|
|
25
|
+
const buffer = (window as unknown as Record<string, unknown>)
|
|
26
|
+
.__REFRESH_BUFFER__ as Array<[unknown, string]> | undefined;
|
|
27
|
+
if (buffer) {
|
|
28
|
+
for (const [type, id] of buffer) {
|
|
29
|
+
RefreshRuntime.register(type, id);
|
|
30
|
+
}
|
|
31
|
+
(window as unknown as Record<string, unknown>).__REFRESH_BUFFER__ =
|
|
32
|
+
undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -9944,7 +9944,7 @@ ${lanes.join(`
|
|
|
9944
9944
|
return process.memoryUsage().heapUsed;
|
|
9945
9945
|
},
|
|
9946
9946
|
getFileSize(path) {
|
|
9947
|
-
const stat2 =
|
|
9947
|
+
const stat2 = statSync(path);
|
|
9948
9948
|
if (stat2 == null ? undefined : stat2.isFile()) {
|
|
9949
9949
|
return stat2.size;
|
|
9950
9950
|
}
|
|
@@ -9987,7 +9987,7 @@ ${lanes.join(`
|
|
|
9987
9987
|
}
|
|
9988
9988
|
};
|
|
9989
9989
|
return nodeSystem;
|
|
9990
|
-
function
|
|
9990
|
+
function statSync(path) {
|
|
9991
9991
|
try {
|
|
9992
9992
|
return _fs.statSync(path, statSyncOptions);
|
|
9993
9993
|
} catch {
|
|
@@ -10039,7 +10039,7 @@ ${lanes.join(`
|
|
|
10039
10039
|
activeSession.post("Profiler.stop", (err, { profile }) => {
|
|
10040
10040
|
var _a;
|
|
10041
10041
|
if (!err) {
|
|
10042
|
-
if ((_a =
|
|
10042
|
+
if ((_a = statSync(profilePath)) == null ? undefined : _a.isDirectory()) {
|
|
10043
10043
|
profilePath = _path.join(profilePath, `${(/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-")}+P${process.pid}.cpuprofile`);
|
|
10044
10044
|
}
|
|
10045
10045
|
try {
|
|
@@ -10148,7 +10148,7 @@ ${lanes.join(`
|
|
|
10148
10148
|
let stat2;
|
|
10149
10149
|
if (typeof dirent === "string" || dirent.isSymbolicLink()) {
|
|
10150
10150
|
const name = combinePaths(path, entry);
|
|
10151
|
-
stat2 =
|
|
10151
|
+
stat2 = statSync(name);
|
|
10152
10152
|
if (!stat2) {
|
|
10153
10153
|
continue;
|
|
10154
10154
|
}
|
|
@@ -10172,7 +10172,7 @@ ${lanes.join(`
|
|
|
10172
10172
|
return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames2, process.cwd(), depth, getAccessibleFileSystemEntries, realpath);
|
|
10173
10173
|
}
|
|
10174
10174
|
function fileSystemEntryExists(path, entryKind) {
|
|
10175
|
-
const stat2 =
|
|
10175
|
+
const stat2 = statSync(path);
|
|
10176
10176
|
if (!stat2) {
|
|
10177
10177
|
return false;
|
|
10178
10178
|
}
|
|
@@ -10206,7 +10206,7 @@ ${lanes.join(`
|
|
|
10206
10206
|
}
|
|
10207
10207
|
function getModifiedTime3(path) {
|
|
10208
10208
|
var _a;
|
|
10209
|
-
return (_a =
|
|
10209
|
+
return (_a = statSync(path)) == null ? undefined : _a.mtime;
|
|
10210
10210
|
}
|
|
10211
10211
|
function setModifiedTime(path, time) {
|
|
10212
10212
|
try {
|
|
@@ -171247,6 +171247,7 @@ import {
|
|
|
171247
171247
|
mkdirSync as mkdirSync8,
|
|
171248
171248
|
readFileSync as readFileSync5,
|
|
171249
171249
|
rmSync,
|
|
171250
|
+
statSync,
|
|
171250
171251
|
writeFileSync as writeFileSync3
|
|
171251
171252
|
} from "fs";
|
|
171252
171253
|
import { basename as basename5, dirname as dirname6, join as join13, relative as relative7, resolve as resolve11 } from "path";
|
|
@@ -205722,5 +205723,5 @@ export {
|
|
|
205722
205723
|
ANGULAR_INIT_TIMEOUT_MS
|
|
205723
205724
|
};
|
|
205724
205725
|
|
|
205725
|
-
//# debugId=
|
|
205726
|
+
//# debugId=A4B0380C43D3114264756E2164756E21
|
|
205726
205727
|
//# sourceMappingURL=index.js.map
|