@useavalon/avalon 0.1.8 → 0.1.10

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.
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Adapter registry for managing framework-specific HMR adapters
3
+ */
4
+ export class AdapterRegistry {
5
+ adapters = new Map();
6
+ /**
7
+ * Register a framework-specific HMR adapter
8
+ *
9
+ * @param framework - Framework name (case-insensitive)
10
+ * @param adapter - The adapter implementation
11
+ * @throws Error if adapter is invalid or already registered
12
+ *
13
+ * Requirements: 2.1-2.7
14
+ */
15
+ register(framework, adapter) {
16
+ const normalizedName = framework.toLowerCase();
17
+ // Validate adapter
18
+ if (!adapter) {
19
+ throw new Error(`Cannot register null/undefined adapter for framework: ${framework}`);
20
+ }
21
+ if (!adapter.name) {
22
+ throw new Error(`Adapter for framework ${framework} must have a name property`);
23
+ }
24
+ if (typeof adapter.canHandle !== "function") {
25
+ throw new Error(`Adapter for framework ${framework} must implement canHandle method`);
26
+ }
27
+ if (typeof adapter.preserveState !== "function") {
28
+ throw new Error(`Adapter for framework ${framework} must implement preserveState method`);
29
+ }
30
+ if (typeof adapter.update !== "function") {
31
+ throw new Error(`Adapter for framework ${framework} must implement update method`);
32
+ }
33
+ if (typeof adapter.restoreState !== "function") {
34
+ throw new Error(`Adapter for framework ${framework} must implement restoreState method`);
35
+ }
36
+ if (typeof adapter.handleError !== "function") {
37
+ throw new Error(`Adapter for framework ${framework} must implement handleError method`);
38
+ }
39
+ // Check if already registered
40
+ if (this.adapters.has(normalizedName)) {
41
+ console.warn(`Overwriting existing HMR adapter for framework: ${framework}`);
42
+ }
43
+ this.adapters.set(normalizedName, adapter);
44
+ }
45
+ /**
46
+ * Get an adapter for a specific framework
47
+ *
48
+ * @param framework - Framework name (case-insensitive)
49
+ * @returns The adapter or undefined if not found
50
+ */
51
+ get(framework) {
52
+ return this.adapters.get(framework.toLowerCase());
53
+ }
54
+ /**
55
+ * Check if an adapter is registered for a framework
56
+ *
57
+ * @param framework - Framework name (case-insensitive)
58
+ * @returns true if adapter is registered
59
+ */
60
+ has(framework) {
61
+ return this.adapters.has(framework.toLowerCase());
62
+ }
63
+ /**
64
+ * Get all registered framework names
65
+ *
66
+ * @returns Array of registered framework names
67
+ */
68
+ getRegisteredFrameworks() {
69
+ return Array.from(this.adapters.keys());
70
+ }
71
+ /**
72
+ * Find an adapter that can handle a specific component
73
+ *
74
+ * Iterates through all registered adapters and returns the first one
75
+ * that can handle the component.
76
+ *
77
+ * @param component - The component to check
78
+ * @returns The adapter that can handle the component, or undefined
79
+ */
80
+ findAdapter(component) {
81
+ for (const adapter of this.adapters.values()) {
82
+ if (adapter.canHandle(component)) {
83
+ return adapter;
84
+ }
85
+ }
86
+ return undefined;
87
+ }
88
+ /**
89
+ * Unregister an adapter
90
+ *
91
+ * @param framework - Framework name (case-insensitive)
92
+ * @returns true if adapter was removed, false if not found
93
+ */
94
+ unregister(framework) {
95
+ const normalizedName = framework.toLowerCase();
96
+ const removed = this.adapters.delete(normalizedName);
97
+ return removed;
98
+ }
99
+ /**
100
+ * Clear all registered adapters
101
+ */
102
+ clear() {
103
+ this.adapters.clear();
104
+ }
105
+ /**
106
+ * Get the number of registered adapters
107
+ */
108
+ get size() {
109
+ return this.adapters.size;
110
+ }
111
+ }
112
+ /**
113
+ * Base adapter class with common functionality
114
+ *
115
+ * Framework-specific adapters can extend this class to inherit common behavior
116
+ * and only override framework-specific methods.
117
+ */
118
+ export class BaseFrameworkAdapter {
119
+ /**
120
+ * Default state preservation implementation
121
+ * Captures DOM state (scroll, focus, form values)
122
+ *
123
+ * Subclasses should override to add framework-specific state
124
+ */
125
+ preserveState(island) {
126
+ try {
127
+ const snapshot = {
128
+ framework: this.name,
129
+ timestamp: Date.now(),
130
+ data: {},
131
+ dom: this.captureDOMState(island)
132
+ };
133
+ return snapshot;
134
+ } catch (error) {
135
+ console.warn(`Failed to preserve state for ${this.name}:`, error);
136
+ return null;
137
+ }
138
+ }
139
+ /**
140
+ * Default state restoration implementation
141
+ * Restores DOM state (scroll, focus, form values)
142
+ *
143
+ * Subclasses should override to add framework-specific state restoration
144
+ */
145
+ restoreState(island, state) {
146
+ try {
147
+ if (state.dom) {
148
+ this.restoreDOMState(island, state.dom);
149
+ }
150
+ } catch (error) {
151
+ console.warn(`Failed to restore state for ${this.name}:`, error);
152
+ }
153
+ }
154
+ /**
155
+ * Default error handling implementation
156
+ * Shows error indicator and preserves SSR HTML
157
+ */
158
+ handleError(island, error) {
159
+ console.error(`HMR error in ${this.name} island:`, error);
160
+ // Add error indicator
161
+ const errorIndicator = document.createElement("div");
162
+ errorIndicator.className = "hmr-error-indicator";
163
+ errorIndicator.style.cssText = `
164
+ position: absolute;
165
+ top: 0;
166
+ left: 0;
167
+ right: 0;
168
+ background: #ff4444;
169
+ color: white;
170
+ padding: 8px;
171
+ font-size: 12px;
172
+ font-family: monospace;
173
+ z-index: 10000;
174
+ border-bottom: 2px solid #cc0000;
175
+ `;
176
+ errorIndicator.textContent = `HMR Error: ${error.message}`;
177
+ // Remove existing error indicators
178
+ const existing = island.querySelector(".hmr-error-indicator");
179
+ if (existing) {
180
+ existing.remove();
181
+ }
182
+ island.style.position = "relative";
183
+ island.insertBefore(errorIndicator, island.firstChild);
184
+ // Mark island as having error
185
+ island.setAttribute("data-hmr-error", "true");
186
+ island.setAttribute("data-hmr-error-message", error.message);
187
+ }
188
+ /**
189
+ * Capture DOM state (scroll, focus, form values)
190
+ */
191
+ captureDOMState(island) {
192
+ const dom = {};
193
+ // Capture scroll position
194
+ const scrollableElements = island.querySelectorAll("[data-preserve-scroll]");
195
+ if (scrollableElements.length > 0 || island.scrollTop > 0 || island.scrollLeft > 0) {
196
+ dom.scrollPosition = {
197
+ x: island.scrollLeft,
198
+ y: island.scrollTop
199
+ };
200
+ }
201
+ // Capture focused element
202
+ const activeElement = document.activeElement;
203
+ if (activeElement && island.contains(activeElement)) {
204
+ const selector = this.getElementSelector(activeElement);
205
+ if (selector) {
206
+ dom.focusedElement = selector;
207
+ }
208
+ }
209
+ // Capture form values
210
+ const formElements = island.querySelectorAll("input, textarea, select");
211
+ if (formElements.length > 0) {
212
+ dom.formValues = {};
213
+ formElements.forEach((element, index) => {
214
+ const input = element;
215
+ const name = input.name || input.id || `element-${index}`;
216
+ if (input.type === "checkbox" || input.type === "radio") {
217
+ dom.formValues[name] = input.checked;
218
+ } else {
219
+ dom.formValues[name] = input.value;
220
+ }
221
+ });
222
+ }
223
+ return dom;
224
+ }
225
+ /**
226
+ * Restore DOM state (scroll, focus, form values)
227
+ */
228
+ restoreDOMState(island, dom) {
229
+ if (!dom) return;
230
+ // Restore scroll position
231
+ if (dom.scrollPosition) {
232
+ island.scrollLeft = dom.scrollPosition.x;
233
+ island.scrollTop = dom.scrollPosition.y;
234
+ }
235
+ // Restore focused element
236
+ if (dom.focusedElement) {
237
+ try {
238
+ const element = island.querySelector(dom.focusedElement);
239
+ if (element && typeof element.focus === "function") {
240
+ element.focus();
241
+ }
242
+ } catch (error) {
243
+ console.warn("Failed to restore focus:", error);
244
+ }
245
+ }
246
+ // Restore form values
247
+ if (dom.formValues) {
248
+ const formElements = island.querySelectorAll("input, textarea, select");
249
+ formElements.forEach((element, index) => {
250
+ const input = element;
251
+ const name = input.name || input.id || `element-${index}`;
252
+ const value = dom.formValues[name];
253
+ if (value !== undefined) {
254
+ if (input.type === "checkbox" || input.type === "radio") {
255
+ input.checked = value;
256
+ } else {
257
+ input.value = value;
258
+ }
259
+ }
260
+ });
261
+ }
262
+ }
263
+ /**
264
+ * Get a CSS selector for an element
265
+ */
266
+ getElementSelector(element) {
267
+ if (element.id) {
268
+ return `#${element.id}`;
269
+ }
270
+ // Check if element has name attribute (for form elements)
271
+ const nameAttr = element.getAttribute("name");
272
+ if (nameAttr) {
273
+ return `[name="${nameAttr}"]`;
274
+ }
275
+ // Fallback to nth-child selector
276
+ const parent = element.parentElement;
277
+ if (parent) {
278
+ const index = Array.from(parent.children).indexOf(element);
279
+ return `${element.tagName.toLowerCase()}:nth-child(${index + 1})`;
280
+ }
281
+ return null;
282
+ }
283
+ }
@@ -0,0 +1,274 @@
1
+ /**
2
+ * HMR Coordinator
3
+ *
4
+ * Central orchestrator for all HMR operations in Avalon.
5
+ * Integrates with Vite's HMR API and coordinates island updates across frameworks.
6
+ */
7
+ /// <reference lib="dom" />
8
+ /// <reference lib="dom.iterable" />
9
+ import { AdapterRegistry } from "./framework-adapter.js";
10
+ import { getCSSHMRHandler } from "./css-hmr-handler.js";
11
+ /**
12
+ * HMR Coordinator class
13
+ * Manages HMR lifecycle and coordinates updates across islands
14
+ */
15
+ export class HMRCoordinator {
16
+ registry = new AdapterRegistry();
17
+ stateSnapshots = new Map();
18
+ updateQueue = new Set();
19
+ isProcessing = false;
20
+ /**
21
+ * Initialize the HMR coordinator
22
+ * Sets up Vite HMR listeners and accepts updates
23
+ */
24
+ initialize() {
25
+ // @ts-ignore - Vite HMR is available in browser context
26
+ if (!import.meta.hot) {
27
+ return;
28
+ }
29
+ // @ts-ignore - Vite HMR API
30
+ import.meta.hot.accept();
31
+ // @ts-ignore - Vite HMR event types
32
+ import.meta.hot.on("vite:beforeUpdate", (payload) => {
33
+ this.handleUpdate(payload);
34
+ });
35
+ // @ts-ignore - Vite HMR event types
36
+ import.meta.hot.on("vite:beforeFullReload", () => {
37
+ this.handleBeforeFullReload();
38
+ });
39
+ // @ts-ignore - Vite HMR event types
40
+ import.meta.hot.on("vite:error", (payload) => {
41
+ console.error("[HMR] error:", payload);
42
+ this.handleError(payload);
43
+ });
44
+ document.addEventListener("hmr-update-required", (event) => {
45
+ const customEvent = event;
46
+ const { src, reason } = customEvent.detail;
47
+ if (reason === "css-module-update") {
48
+ this.updateQueue.add(this.normalizePath(src));
49
+ if (!this.isProcessing) {
50
+ this.processUpdateQueue().catch((error) => {
51
+ console.error("[HMR] Failed to process CSS module update:", error);
52
+ });
53
+ }
54
+ }
55
+ });
56
+ }
57
+ registerAdapter(framework, adapter) {
58
+ this.registry.register(framework, adapter);
59
+ }
60
+ getRegistry() {
61
+ return this.registry;
62
+ }
63
+ async handleUpdate(payload) {
64
+ if (payload.type !== "update" || !payload.updates) {
65
+ return;
66
+ }
67
+ const cssUpdates = [];
68
+ const jsUpdates = [];
69
+ for (const update of payload.updates) {
70
+ if (update.type === "css-update") {
71
+ cssUpdates.push(update);
72
+ } else {
73
+ jsUpdates.push(update);
74
+ }
75
+ }
76
+ this.processCSSUpdates(cssUpdates);
77
+ this.queueJSUpdates(jsUpdates);
78
+ if (!this.isProcessing && this.updateQueue.size > 0) {
79
+ await this.processUpdateQueue();
80
+ }
81
+ }
82
+ processCSSUpdates(cssUpdates) {
83
+ if (cssUpdates.length === 0) return;
84
+ const cssHandler = getCSSHMRHandler();
85
+ for (const cssUpdate of cssUpdates) {
86
+ try {
87
+ cssHandler.handleCSSUpdate(cssUpdate);
88
+ } catch (error) {
89
+ console.error("[HMR] CSS update failed:", error);
90
+ }
91
+ }
92
+ }
93
+ queueJSUpdates(jsUpdates) {
94
+ for (const update of jsUpdates) {
95
+ const normalizedPath = this.normalizePath(update.path || update.acceptedPath);
96
+ if (this.isIslandModule(normalizedPath)) {
97
+ this.updateQueue.add(normalizedPath);
98
+ }
99
+ }
100
+ }
101
+ async processUpdateQueue() {
102
+ if (this.updateQueue.size === 0) return;
103
+ this.isProcessing = true;
104
+ try {
105
+ const paths = Array.from(this.updateQueue);
106
+ this.updateQueue.clear();
107
+ for (const path of paths) {
108
+ const islands = this.findAffectedIslands(path);
109
+ for (const island of islands) {
110
+ try {
111
+ await this.updateIsland(island);
112
+ } catch (error) {
113
+ console.error("[HMR] Failed to update island:", error);
114
+ }
115
+ }
116
+ }
117
+ } finally {
118
+ this.isProcessing = false;
119
+ }
120
+ }
121
+ findAffectedIslands(modulePath) {
122
+ const islands = [];
123
+ const normalizedPath = this.normalizePath(modulePath);
124
+ const allIslands = document.querySelectorAll("[data-src]");
125
+ for (const island of allIslands) {
126
+ const src = island.dataset.src;
127
+ if (!src) continue;
128
+ const normalizedSrc = this.normalizePath(src);
129
+ const isMatch = normalizedSrc === normalizedPath || normalizedSrc.endsWith(normalizedPath) || normalizedPath.endsWith(normalizedSrc) || normalizedSrc.split("/").pop() === normalizedPath.split("/").pop();
130
+ if (isMatch) {
131
+ islands.push(island);
132
+ }
133
+ }
134
+ return islands;
135
+ }
136
+ async updateIsland(island) {
137
+ const framework = island.dataset.framework;
138
+ const src = island.dataset.src;
139
+ const propsAttr = island.dataset.props;
140
+ if (!framework || !src) {
141
+ console.warn("[HMR] Island missing framework or src attribute", island);
142
+ return;
143
+ }
144
+ const adapter = this.registry.get(framework.toLowerCase());
145
+ if (!adapter) {
146
+ console.warn(`[HMR] No adapter registered for framework: ${framework}`);
147
+ return;
148
+ }
149
+ try {
150
+ const props = propsAttr ? JSON.parse(propsAttr) : {};
151
+ const state = adapter.preserveState(island);
152
+ if (state) {
153
+ this.stateSnapshots.set(this.getIslandId(island), state);
154
+ }
155
+ delete island.dataset.hydrated;
156
+ delete island.dataset.hydrationStatus;
157
+ island.querySelector(".hydration-error-indicator, .hmr-error-indicator")?.remove();
158
+ const timestamp = Date.now();
159
+ const freshSrc = src.includes("?") ? `${src}&t=${timestamp}` : `${src}?t=${timestamp}`;
160
+ const componentModule = await import(
161
+ /* @vite-ignore */
162
+ freshSrc
163
+ );
164
+ const Component = this.resolveComponent(componentModule, src);
165
+ await adapter.update(island, Component, props);
166
+ if (state) {
167
+ adapter.restoreState(island, state);
168
+ this.stateSnapshots.delete(this.getIslandId(island));
169
+ }
170
+ island.dataset.hydrated = "true";
171
+ island.dispatchEvent(new CustomEvent("hmr-update", {
172
+ detail: {
173
+ framework,
174
+ src,
175
+ timestamp: Date.now(),
176
+ success: true
177
+ },
178
+ bubbles: true
179
+ }));
180
+ } catch (error) {
181
+ console.error(`[HMR] Failed to update ${framework} island ${src}:`, error);
182
+ adapter.handleError(island, error);
183
+ island.dispatchEvent(new CustomEvent("hmr-error", {
184
+ detail: {
185
+ framework,
186
+ src,
187
+ error: error.message,
188
+ timestamp: Date.now()
189
+ },
190
+ bubbles: true
191
+ }));
192
+ throw error;
193
+ }
194
+ }
195
+ resolveComponent(componentModule, src) {
196
+ if (componentModule.default) return componentModule.default;
197
+ for (const key of Object.keys(componentModule)) {
198
+ if (key === "default") continue;
199
+ const value = componentModule[key];
200
+ if (typeof value === "function" && value.prototype) {
201
+ return value;
202
+ }
203
+ }
204
+ throw new Error(`Component ${src} has no default export`);
205
+ }
206
+ handleBeforeFullReload() {
207
+ const islands = document.querySelectorAll("[data-hydrated=\"true\"]");
208
+ const states = {};
209
+ for (const island of islands) {
210
+ const framework = island.dataset.framework;
211
+ const src = island.dataset.src;
212
+ if (!framework || !src) continue;
213
+ const adapter = this.registry.get(framework.toLowerCase());
214
+ if (!adapter) continue;
215
+ const state = adapter.preserveState(island);
216
+ if (state) {
217
+ states[src] = state;
218
+ }
219
+ }
220
+ try {
221
+ sessionStorage.setItem("__avalon_hmr_states__", JSON.stringify(states));
222
+ } catch (error) {
223
+ console.warn("[HMR] Failed to save states:", error);
224
+ }
225
+ }
226
+ handleError(payload) {
227
+ const error = new Error(payload.err.message);
228
+ error.stack = payload.err.stack;
229
+ console.error("[HMR] Error:", error);
230
+ if (globalThis.window !== undefined) {
231
+ // @ts-ignore - dynamic import of JS file
232
+ import("./hmr-error-overlay.js").then(({ showHMRErrorOverlay }) => {
233
+ showHMRErrorOverlay({
234
+ framework: "unknown",
235
+ src: "unknown",
236
+ error,
237
+ filePath: payload.err.id || payload.err.loc?.file || "unknown",
238
+ line: payload.err.loc?.line,
239
+ column: payload.err.loc?.column
240
+ });
241
+ }).catch(() => {
242
+ console.error("[HMR] Failed to show error overlay");
243
+ });
244
+ }
245
+ }
246
+ normalizePath(path) {
247
+ return path.replaceAll("\\", "/").replace(/^\//, "").replace(/\?.*$/, "").replace(/#.*$/, "").replace(/^src\//, "");
248
+ }
249
+ isIslandModule(path) {
250
+ return path.includes("/islands/") || path.includes("\\islands\\");
251
+ }
252
+ getIslandId(island) {
253
+ const src = island.dataset.src ?? "";
254
+ const framework = island.dataset.framework ?? "";
255
+ const index = Array.from(document.querySelectorAll(`[data-src="${src}"]`)).indexOf(island);
256
+ return `${framework}:${src}:${index}`;
257
+ }
258
+ }
259
+ /**
260
+ * Global HMR coordinator instance
261
+ */
262
+ let coordinatorInstance = null;
263
+ export function getHMRCoordinator() {
264
+ coordinatorInstance ??= new HMRCoordinator();
265
+ return coordinatorInstance;
266
+ }
267
+ export function initializeHMR() {
268
+ // @ts-ignore - Vite HMR is available in browser context
269
+ if (!import.meta.hot) {
270
+ return;
271
+ }
272
+ const coordinator = getHMRCoordinator();
273
+ coordinator.initialize();
274
+ }
@@ -608,7 +608,7 @@ if (import.meta.hot) {
608
608
  import.meta.hot.accept();
609
609
 
610
610
  // Lazy HMR adapter registration - only load adapters for frameworks used on the page
611
- import('./hmr-coordinator.ts')
611
+ import('./hmr-coordinator.js')
612
612
  .then(async ({ initializeHMR, getHMRCoordinator }) => {
613
613
  initializeHMR();
614
614
 
@@ -623,13 +623,13 @@ if (import.meta.hot) {
623
623
 
624
624
  // Only register adapters for frameworks that are used
625
625
  const adapterLoaders = {
626
- react: () => import('./adapters/react-adapter.ts').then(m => m.reactAdapter),
627
- preact: () => import('./adapters/preact-adapter.ts').then(m => m.preactAdapter),
628
- vue: () => import('./adapters/vue-adapter.ts').then(m => m.vueAdapter),
629
- svelte: () => import('./adapters/svelte-adapter.ts').then(m => m.svelteAdapter),
630
- solid: () => import('./adapters/solid-adapter.ts').then(m => m.solidAdapter),
631
- lit: () => import('./adapters/lit-adapter.ts').then(m => m.litAdapter),
632
- qwik: () => import('./adapters/qwik-adapter.ts').then(m => m.qwikAdapter),
626
+ react: () => import('./adapters/react-adapter.js').then(m => m.reactAdapter),
627
+ preact: () => import('./adapters/preact-adapter.js').then(m => m.preactAdapter),
628
+ vue: () => import('./adapters/vue-adapter.js').then(m => m.vueAdapter),
629
+ svelte: () => import('./adapters/svelte-adapter.js').then(m => m.svelteAdapter),
630
+ solid: () => import('./adapters/solid-adapter.js').then(m => m.solidAdapter),
631
+ lit: () => import('./adapters/lit-adapter.js').then(m => m.litAdapter),
632
+ qwik: () => import('./adapters/qwik-adapter.js').then(m => m.qwikAdapter),
633
633
  };
634
634
 
635
635
  for (const framework of usedFrameworks) {
@@ -282,10 +282,12 @@ export async function avalon(config?: AvalonPluginConfig): Promise<PluginOption[
282
282
  enforce: "pre",
283
283
 
284
284
  config() {
285
- // @useavalon packages ship raw .ts source. Mark them as noExternal so
286
- // Vite processes them through the transform pipeline (SSR).
287
- // For client-side, Vite's built-in OXC plugin handles .ts stripping
288
- // and sets moduleType: 'js' automatically.
285
+ // @useavalon packages ship raw .ts source for SSR (handled by our
286
+ // transform hook below) and pre-compiled .js for client-side code.
287
+ // Client .js files are excluded from OXC by default (/\.js$/), so
288
+ // integration plugins' jsx: 'automatic' config doesn't affect them.
289
+ // noExternal ensures Vite processes @useavalon packages through the
290
+ // SSR transform pipeline instead of treating them as external CJS.
289
291
  return {
290
292
  ssr: {
291
293
  noExternal: [/^@useavalon\//],
@@ -318,6 +320,27 @@ export async function avalon(config?: AvalonPluginConfig): Promise<PluginOption[
318
320
  return null;
319
321
  },
320
322
 
323
+ async transform(code: string, id: string) {
324
+ // For SSR: strip TypeScript from @useavalon packages ourselves.
325
+ // Integration plugins (react, preact) set jsx: 'automatic' which Vite's
326
+ // OXC applies to all files — causing "Invalid jsx option" errors on
327
+ // plain .ts files during SSR. We intercept and strip TS without JSX config.
328
+ // For client-side: main.js imports pre-compiled .js files that OXC
329
+ // skips entirely (default exclude: /\.js$/), avoiding the jsx conflict.
330
+ if (
331
+ this.environment?.config?.consumer === 'server' &&
332
+ id.includes('@useavalon/') &&
333
+ /\.tsx?$/.test(id)
334
+ ) {
335
+ const { transform: oxcTransform } = await import('oxc-transform');
336
+ const result = await oxcTransform(id, code, {
337
+ sourcemap: true,
338
+ typescript: { onlyRemoveTypeImports: false },
339
+ });
340
+ return { code: result.code, map: result.map, moduleType: 'js' };
341
+ }
342
+ },
343
+
321
344
  async buildStart() {
322
345
  await runAutoDiscovery(resolvedConfig, viteConfig?.root, activeIntegrations);
323
346
  runValidation(resolvedConfig, activeIntegrations);