@vizejs/vite-plugin 0.424.10 → 0.426.0

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,4111 @@
1
+ import { a as vizeConfigStore } from "./config-PP6EAmWc.mjs";
2
+ import { n as resolveSharedConfig } from "./shared-config-dMxrrTkb.mjs";
3
+ import { n as registerResolvedVizeConfig, r as unregisterResolvedVizeConfig } from "./config-bridge-Dv6U7_RC.mjs";
4
+ import { createRequire } from "node:module";
5
+ import crypto, { createHash } from "node:crypto";
6
+ import * as native from "@vizejs/native";
7
+ import { applyViteDefineReplacements, buildInspectorGraph, chunkVitePrecompileFiles, classifyVitePluginRequest, createViteBareImportBases, createViteBareImportCandidates, createViteVirtualId, detectViteHmrUpdateType, diffVitePrecompileFiles, generateViteHmrCode, hasViteHmrChanges, isViteBareSpecifier, normalizeViteCssModuleFilename, normalizeViteDevMiddlewareUrl, normalizeVitePrecompileBatchSize, normalizeViteRequireBase, normalizeViteResolvedVuePath, resolveViteAliasRequest, resolveViteCssImports, resolveViteRelativeImport, resolveViteVuePath, rewriteViteDynamicTemplateImports, rewriteViteImportMetaGlobBase, rewriteViteStaticAssetUrls, scopeViteCssForPipeline, shouldApplyViteDefineInVirtualModule, splitViteIdQuery, toViteBrowserImportPrefix, transformViteCssVarsForPipeline } from "@vizejs/native";
8
+ import { parseSync } from "oxc-parser";
9
+ import path from "node:path";
10
+ import fs from "node:fs";
11
+ import { glob } from "tinyglobby";
12
+ import zlib from "node:zlib";
13
+ import { pathToFileURL } from "node:url";
14
+ import * as vite from "vite";
15
+ //#region src/hmr.ts
16
+ function hasHmrChanges(prev, next) {
17
+ if (!prev) return true;
18
+ return hasViteHmrChanges(toHmrHashes(prev), toHmrHashes(next)) || runtimeFingerprint(prev) !== runtimeFingerprint(next) || styleFingerprint(prev) !== styleFingerprint(next);
19
+ }
20
+ /**
21
+ * Detect the type of HMR update needed based on content hash changes.
22
+ *
23
+ * @param prev - Previously compiled module (undefined if first compile)
24
+ * @param next - Newly compiled module
25
+ * @returns The type of HMR update needed
26
+ */
27
+ function detectHmrUpdateType(prev, next) {
28
+ if (!prev) return detectViteHmrUpdateType(void 0, toHmrHashes(next));
29
+ if (prev.scriptHash !== next.scriptHash) return "full-reload";
30
+ if (prev.templateHash !== next.templateHash) return "template-only";
31
+ if (prev.styleHash !== next.styleHash) return "style-only";
32
+ if (runtimeFingerprint(prev) !== runtimeFingerprint(next)) return "full-reload";
33
+ if (styleFingerprint(prev) !== styleFingerprint(next)) return "style-only";
34
+ return "full-reload";
35
+ }
36
+ /**
37
+ * Generate HMR-aware code output based on update type.
38
+ */
39
+ function generateHmrCode(scopeId, updateType) {
40
+ return generateViteHmrCode(scopeId, updateType);
41
+ }
42
+ function toHmrHashes(module) {
43
+ return module ? {
44
+ scriptHash: module.scriptHash,
45
+ templateHash: module.templateHash,
46
+ styleHash: module.styleHash
47
+ } : void 0;
48
+ }
49
+ function runtimeFingerprint(module) {
50
+ return JSON.stringify({
51
+ code: module.code,
52
+ scopeId: module.scopeId,
53
+ hasScoped: module.hasScoped,
54
+ macroArtifacts: module.macroArtifacts?.map((artifact) => ({
55
+ kind: artifact.kind,
56
+ name: artifact.name,
57
+ source: artifact.source,
58
+ content: artifact.content,
59
+ moduleCode: artifact.moduleCode,
60
+ start: artifact.start,
61
+ end: artifact.end
62
+ })),
63
+ styles: module.styles?.map((style) => ({
64
+ lang: style.lang,
65
+ scoped: style.scoped,
66
+ module: style.module,
67
+ index: style.index
68
+ })),
69
+ dependencies: [...module.dependencies ?? []].sort()
70
+ });
71
+ }
72
+ function styleFingerprint(module) {
73
+ return JSON.stringify({
74
+ css: module.css,
75
+ styles: module.styles?.map((style) => ({
76
+ index: style.index,
77
+ content: style.content
78
+ }))
79
+ });
80
+ }
81
+ //#endregion
82
+ //#region src/utils/module-output.ts
83
+ const OUTPUT_PARSE_ID = "vize-output.tsx";
84
+ const SFC_MAIN_NAME = "_sfc_main";
85
+ const EXPORT_DEFAULT = "export default";
86
+ function isNode(value) {
87
+ return value != null && typeof value === "object" && typeof value.type === "string";
88
+ }
89
+ function getNodeStart(node) {
90
+ return typeof node?.start === "number" ? node.start : null;
91
+ }
92
+ function getNodeEnd(node) {
93
+ return typeof node?.end === "number" ? node.end : null;
94
+ }
95
+ function getNodeName(node) {
96
+ return isNode(node) && typeof node.name === "string" ? node.name : null;
97
+ }
98
+ function isSfcMainDefaultExport(defaultExport) {
99
+ return isIdentifierNamed(isNode(defaultExport?.declaration) ? defaultExport.declaration : null, SFC_MAIN_NAME);
100
+ }
101
+ function parseProgram(code) {
102
+ try {
103
+ const result = parseSync(OUTPUT_PARSE_ID, code);
104
+ if (result != null && typeof result === "object") {
105
+ const errors = result.errors;
106
+ if (Array.isArray(errors) && errors.length > 0) return null;
107
+ const program = result.program;
108
+ if (isNode(program)) return program;
109
+ }
110
+ return isNode(result) ? result : null;
111
+ } catch {
112
+ return null;
113
+ }
114
+ }
115
+ function getProgramBody(program) {
116
+ if (!program || !Array.isArray(program.body)) return [];
117
+ return program.body.filter(isNode);
118
+ }
119
+ function isIdentifierNamed(node, name) {
120
+ return getNodeName(node) === name;
121
+ }
122
+ function getVariableDeclarationNames(statement) {
123
+ return (Array.isArray(statement.declarations) ? statement.declarations : []).filter(isNode).map((declaration) => isNode(declaration.id) ? getNodeName(declaration.id) : null).filter((name) => name != null);
124
+ }
125
+ function getExportedNames(statement) {
126
+ const declaration = isNode(statement.declaration) ? statement.declaration : null;
127
+ const names = [];
128
+ if (declaration?.type === "FunctionDeclaration" || declaration?.type === "ClassDeclaration") {
129
+ const name = isNode(declaration.id) ? getNodeName(declaration.id) : null;
130
+ if (name) names.push(name);
131
+ }
132
+ if (declaration?.type === "VariableDeclaration") names.push(...getVariableDeclarationNames(declaration));
133
+ const specifiers = Array.isArray(statement.specifiers) ? statement.specifiers : [];
134
+ for (const specifier of specifiers) {
135
+ if (!isNode(specifier)) continue;
136
+ const exported = isNode(specifier.exported) ? specifier.exported : null;
137
+ const local = isNode(specifier.local) ? specifier.local : null;
138
+ const name = getNodeName(exported) ?? getNodeName(local);
139
+ if (name) names.push(name);
140
+ }
141
+ return names;
142
+ }
143
+ function findDefaultExport(program) {
144
+ return getProgramBody(program).find((statement) => statement.type === "ExportDefaultDeclaration") ?? null;
145
+ }
146
+ function analyzeFastDefaultOutput(code) {
147
+ if (code.includes(SFC_MAIN_NAME) || code.includes("export function render") || code.includes("export function ssrRender") || code.includes("export {")) return null;
148
+ const defaultExportStart = code.indexOf(EXPORT_DEFAULT);
149
+ if (defaultExportStart === -1 || defaultExportStart !== code.lastIndexOf(EXPORT_DEFAULT)) return null;
150
+ const before = defaultExportStart === 0 ? "\n" : code[defaultExportStart - 1];
151
+ if (!before || !/\s|;/.test(before)) return null;
152
+ return {
153
+ hasDefaultExport: true,
154
+ hasSfcMainDefined: false,
155
+ hasNamedRenderExport: false,
156
+ hasNamedSsrRenderExport: false,
157
+ defaultExportStart,
158
+ defaultExportKeywordEnd: defaultExportStart + 14,
159
+ defaultExportEnd: null,
160
+ defaultExportIsSfcMain: false
161
+ };
162
+ }
163
+ function getExportDefaultKeywordEnd(code, defaultExport) {
164
+ const exportStart = getNodeStart(defaultExport);
165
+ if (exportStart == null) return null;
166
+ const match = /^export\s+default\b/.exec(code.slice(exportStart));
167
+ return match ? exportStart + match[0].length : null;
168
+ }
169
+ function analyzeModuleOutput(code) {
170
+ const fastOutput = analyzeFastDefaultOutput(code);
171
+ if (fastOutput) return fastOutput;
172
+ const program = parseProgram(code);
173
+ const body = getProgramBody(program);
174
+ const defaultExport = findDefaultExport(program);
175
+ const defaultExportStart = getNodeStart(defaultExport);
176
+ const defaultExportKeywordEnd = defaultExport ? getExportDefaultKeywordEnd(code, defaultExport) : null;
177
+ const exportedNames = body.filter((statement) => statement.type === "ExportNamedDeclaration").flatMap(getExportedNames);
178
+ return {
179
+ hasDefaultExport: defaultExport != null,
180
+ hasSfcMainDefined: body.some((statement) => {
181
+ return statement.type === "VariableDeclaration" && getVariableDeclarationNames(statement).includes(SFC_MAIN_NAME);
182
+ }),
183
+ hasNamedRenderExport: exportedNames.includes("render"),
184
+ hasNamedSsrRenderExport: exportedNames.includes("ssrRender"),
185
+ defaultExportKeywordEnd,
186
+ defaultExportStart,
187
+ defaultExportEnd: getNodeEnd(defaultExport),
188
+ defaultExportIsSfcMain: isSfcMainDefaultExport(defaultExport)
189
+ };
190
+ }
191
+ function rewriteDefaultExportToSfcMain(code, moduleInfo = {
192
+ defaultExportKeywordEnd: null,
193
+ defaultExportStart: null
194
+ }) {
195
+ let exportStart = moduleInfo.defaultExportStart;
196
+ let keywordEnd = moduleInfo.defaultExportKeywordEnd;
197
+ if (exportStart == null || keywordEnd == null) {
198
+ const defaultExport = findDefaultExport(parseProgram(code));
199
+ exportStart = getNodeStart(defaultExport);
200
+ keywordEnd = defaultExport ? getExportDefaultKeywordEnd(code, defaultExport) : null;
201
+ }
202
+ if (exportStart == null || keywordEnd == null) return code;
203
+ return `${code.slice(0, exportStart)}const ${SFC_MAIN_NAME} =${code.slice(keywordEnd)}`;
204
+ }
205
+ /**
206
+ * Locate `export default _sfc_main` when the caller has no analysis to hand.
207
+ *
208
+ * The string test is a sound pre-filter: the AST check below only succeeds when
209
+ * the default export's declaration *is* the `_sfc_main` identifier, which cannot
210
+ * happen unless that name occurs in the module.
211
+ */
212
+ function findSfcMainDefaultExport(code) {
213
+ if (!code.includes(SFC_MAIN_NAME)) return {
214
+ defaultExportStart: null,
215
+ defaultExportEnd: null,
216
+ defaultExportIsSfcMain: false
217
+ };
218
+ const defaultExport = findDefaultExport(parseProgram(code));
219
+ return {
220
+ defaultExportStart: getNodeStart(defaultExport),
221
+ defaultExportEnd: getNodeEnd(defaultExport),
222
+ defaultExportIsSfcMain: isSfcMainDefaultExport(defaultExport)
223
+ };
224
+ }
225
+ function insertBeforeSfcMainDefaultExport(code, insertion, options = {}) {
226
+ const { defaultExportStart: exportStart, defaultExportEnd: exportEnd, defaultExportIsSfcMain } = options.moduleInfo ?? findSfcMainDefaultExport(code);
227
+ if (!defaultExportIsSfcMain || exportStart == null) return code;
228
+ if (options.normalizeSemicolon && exportEnd != null) {
229
+ const suffixStart = code[exportEnd] === ";" ? exportEnd + 1 : exportEnd;
230
+ return `${code.slice(0, exportStart)}${insertion}\nexport default ${SFC_MAIN_NAME};${code.slice(suffixStart)}`;
231
+ }
232
+ return `${code.slice(0, exportStart)}${insertion}\n${code.slice(exportStart)}`;
233
+ }
234
+ //#endregion
235
+ //#region src/utils/source-map.ts
236
+ function isSourceMapV3(value) {
237
+ if (value === null || typeof value !== "object") return false;
238
+ const map = value;
239
+ return map.version === 3 && Array.isArray(map.sources) && Array.isArray(map.names) && typeof map.mappings === "string";
240
+ }
241
+ /**
242
+ * Parse a compiler-produced map, or `null` when there is nothing usable.
243
+ *
244
+ * A malformed map is worse than no map — Vite would chain garbage into the
245
+ * bundle's map — so anything that is not a v3 document is dropped.
246
+ */
247
+ function parseSourceMap(json) {
248
+ if (!json) return null;
249
+ let parsed;
250
+ try {
251
+ parsed = JSON.parse(json);
252
+ } catch {
253
+ return null;
254
+ }
255
+ return isSourceMapV3(parsed) ? parsed : null;
256
+ }
257
+ function countNewlines(text) {
258
+ let total = 0;
259
+ for (let index = text.indexOf("\n"); index !== -1; index = text.indexOf("\n", index + 1)) total++;
260
+ return total;
261
+ }
262
+ /**
263
+ * Insert `count` unmapped generated lines at generated line `atLine`.
264
+ *
265
+ * Returns the map unchanged when the insertion lands past the last mapped line,
266
+ * because nothing after it needs moving.
267
+ */
268
+ function shiftMappedLines(map, atLine, count) {
269
+ if (count <= 0) return map;
270
+ const groups = map.mappings.split(";");
271
+ if (atLine >= groups.length) return map;
272
+ const shifted = [
273
+ ...groups.slice(0, atLine),
274
+ ...Array(count).fill(""),
275
+ ...groups.slice(atLine)
276
+ ];
277
+ return {
278
+ ...map,
279
+ mappings: shifted.join(";")
280
+ };
281
+ }
282
+ /**
283
+ * A module's code and the map that describes it, edited together.
284
+ *
285
+ * Every write goes through {@link edit}, so the map is corrected in the same
286
+ * step that changes the code and the two cannot drift.
287
+ */
288
+ var MappedModule = class {
289
+ code;
290
+ map;
291
+ constructor(code, map) {
292
+ this.code = code;
293
+ this.map = map;
294
+ }
295
+ /** Replace the module with `next`, realigning the map to the new line layout. */
296
+ edit(next) {
297
+ const previous = this.code;
298
+ this.code = next;
299
+ if (this.map === null || next === previous) return;
300
+ const limit = Math.min(previous.length, next.length);
301
+ let prefix = 0;
302
+ while (prefix < limit && previous.charCodeAt(prefix) === next.charCodeAt(prefix)) prefix++;
303
+ let suffix = 0;
304
+ while (suffix < limit - prefix && previous.charCodeAt(previous.length - 1 - suffix) === next.charCodeAt(next.length - 1 - suffix)) suffix++;
305
+ const removed = previous.slice(prefix, previous.length - suffix);
306
+ const addedLines = countNewlines(next.slice(prefix, next.length - suffix)) - countNewlines(removed);
307
+ if (addedLines === 0) return;
308
+ if (addedLines < 0) {
309
+ this.map = null;
310
+ return;
311
+ }
312
+ const editLine = countNewlines(previous.slice(0, prefix));
313
+ const startsAtLineStart = prefix === 0 || previous.charCodeAt(prefix - 1) === 10;
314
+ this.map = shiftMappedLines(this.map, startsAtLineStart ? editLine : editLine + 1, addedLines);
315
+ }
316
+ };
317
+ //#endregion
318
+ //#region src/utils/css.ts
319
+ function scopeCssForPipeline(css, scopeId) {
320
+ return scopeViteCssForPipeline(css, scopeId);
321
+ }
322
+ function transformCssVarsForPipeline(css, scopeId) {
323
+ return transformViteCssVarsForPipeline(css, scopeId);
324
+ }
325
+ /**
326
+ * Resolve CSS @import statements by inlining the imported files,
327
+ * then resolve @custom-media definitions within the combined CSS.
328
+ */
329
+ function resolveCssImports(css, importer, aliasRules, isDev, devUrlBase) {
330
+ return resolveViteCssImports(css, importer, aliasRules.map(toNativeCssAliasRule), isDev, devUrlBase);
331
+ }
332
+ function toNativeCssAliasRule(rule) {
333
+ return typeof rule.find === "string" ? {
334
+ find: rule.find,
335
+ replacement: rule.replacement,
336
+ isRegex: false
337
+ } : {
338
+ find: rule.find.source,
339
+ replacement: rule.replacement,
340
+ isRegex: true,
341
+ flags: rule.find.flags.replace(/[gy]/g, "")
342
+ };
343
+ }
344
+ //#endregion
345
+ //#region src/utils/filter.ts
346
+ /**
347
+ * Defaults the filter falls back to, and what the `vite:vue` shim reports
348
+ * through `api.include` / `api.exclude` when neither is configured (#3227).
349
+ *
350
+ * `DEFAULT_INCLUDE_PATTERN` is `@vitejs/plugin-vue`'s own default.
351
+ * `DEFAULT_EXCLUDE_PATTERN` has no upstream counterpart — plugin-vue leaves
352
+ * `exclude` undefined — so the shim reports the pattern Vize actually filters
353
+ * on rather than an upstream-shaped `undefined` it does not honor.
354
+ */
355
+ const DEFAULT_INCLUDE_PATTERN = /\.vue$/;
356
+ const DEFAULT_EXCLUDE_PATTERN = /node_modules/;
357
+ function createFilter(include, exclude) {
358
+ const includePatterns = include ? Array.isArray(include) ? include : [include] : [DEFAULT_INCLUDE_PATTERN];
359
+ const excludePatterns = exclude ? Array.isArray(exclude) ? exclude : [exclude] : [DEFAULT_EXCLUDE_PATTERN];
360
+ return (id) => {
361
+ const matchInclude = includePatterns.some((pattern) => matchesFilterPattern(pattern, id));
362
+ const matchExclude = excludePatterns.some((pattern) => matchesFilterPattern(pattern, id));
363
+ return matchInclude && !matchExclude;
364
+ };
365
+ }
366
+ const GLOB_META = /[*?]/;
367
+ function matchesFilterPattern(pattern, id) {
368
+ if (typeof pattern === "string") return matchesStringFilter(pattern, id);
369
+ pattern.lastIndex = 0;
370
+ const matched = pattern.test(id);
371
+ pattern.lastIndex = 0;
372
+ return matched;
373
+ }
374
+ function matchesStringFilter(pattern, id) {
375
+ const normalizedId = normalizeFilterPath(id);
376
+ const normalizedPattern = normalizeFilterPath(pattern);
377
+ if (!GLOB_META.test(normalizedPattern)) return normalizedId.includes(normalizedPattern);
378
+ return stringGlobToRegExp(normalizedPattern).test(normalizedId);
379
+ }
380
+ function normalizeFilterPath(value) {
381
+ return value.replace(/\\/g, "/");
382
+ }
383
+ function stringGlobToRegExp(pattern) {
384
+ const absolute = pattern.startsWith("/");
385
+ let body = absolute ? pattern : stripRelativePrefix(pattern);
386
+ let descendantSuffix = false;
387
+ if (body.endsWith("/**")) {
388
+ body = body.slice(0, -3);
389
+ descendantSuffix = true;
390
+ }
391
+ const prefix = absolute ? "^" : "(?:^|/)";
392
+ const suffix = descendantSuffix ? "(?:/.*)?$" : "$";
393
+ return new RegExp(`${prefix}${globBodyToRegExp(body)}${suffix}`);
394
+ }
395
+ function stripRelativePrefix(pattern) {
396
+ let rest = pattern;
397
+ while (rest.startsWith("../")) rest = rest.slice(3);
398
+ while (rest.startsWith("./")) rest = rest.slice(2);
399
+ return rest;
400
+ }
401
+ function globBodyToRegExp(pattern) {
402
+ let source = "";
403
+ for (let i = 0; i < pattern.length;) {
404
+ const char = pattern[i];
405
+ if (char === "*") {
406
+ if (pattern[i + 1] === "*") if (pattern[i + 2] === "/") {
407
+ source += "(?:.*\\/)?";
408
+ i += 3;
409
+ } else {
410
+ source += ".*";
411
+ i += 2;
412
+ }
413
+ else {
414
+ source += "[^/]*";
415
+ i += 1;
416
+ }
417
+ continue;
418
+ }
419
+ if (char === "?") {
420
+ source += "[^/]";
421
+ i += 1;
422
+ continue;
423
+ }
424
+ source += escapeRegExp(char);
425
+ i += 1;
426
+ }
427
+ return source;
428
+ }
429
+ function escapeRegExp(char) {
430
+ return "\\^$+?.()|[]{}".includes(char) ? `\\${char}` : char;
431
+ }
432
+ //#endregion
433
+ //#region src/utils/index.ts
434
+ /** Known CSS preprocessor languages that must be delegated to Vite */
435
+ const PREPROCESSOR_LANGS = new Set([
436
+ "scss",
437
+ "sass",
438
+ "less",
439
+ "stylus",
440
+ "styl"
441
+ ]);
442
+ /** Check if a style block requires Vite's preprocessor pipeline */
443
+ function needsPreprocessor(block) {
444
+ return block.lang !== null && PREPROCESSOR_LANGS.has(block.lang);
445
+ }
446
+ /** Check if a style block uses CSS Modules */
447
+ function isCssModule(block) {
448
+ return block.module !== false;
449
+ }
450
+ function needsCssPipeline(block) {
451
+ return block.content.includes("@apply");
452
+ }
453
+ function styleVirtualSuffix(block) {
454
+ const lang = block.lang ?? "css";
455
+ return block.module !== false ? `.module.${lang}` : `.${lang}`;
456
+ }
457
+ function createStyleImportUrl(filePath, params, block) {
458
+ return `${filePath}?${params.toString()}${styleVirtualSuffix(block)}`;
459
+ }
460
+ /**
461
+ * Check if any style blocks in the compiled module require delegation to
462
+ * Vite's CSS pipeline (preprocessor, CSS Modules, or PostCSS transforms).
463
+ */
464
+ function hasDelegatedStyles(compiled) {
465
+ if (!compiled.styles) return false;
466
+ return compiled.styles.some((s) => needsPreprocessor(s) || isCssModule(s) || needsCssPipeline(s));
467
+ }
468
+ function supportsTemplateOnlyHmr(output) {
469
+ return /(?:^|\n)(?:_sfc_main|__sfc__)\.render\s*=\s*render\b/m.test(output);
470
+ }
471
+ /**
472
+ * Prepend a runtime `<style>` injection for plain CSS to a module's output.
473
+ *
474
+ * This is the same inline-CSS path plain SFC `<style>` blocks use in
475
+ * {@link generateOutput}: a guarded `document.createElement('style')` keyed by a
476
+ * stable id so the rule is injected once and idempotently. `styleKey` seeds the
477
+ * element id. Used for both SFC plain CSS and JSX `<style scoped>` CSS (#1495,
478
+ * #1533), whose content is already scope-rewritten by the compiler.
479
+ */
480
+ function prependInlineStyleInjection(output, css, styleKey) {
481
+ return `
482
+ export const __vize_css__ = ${JSON.stringify(css)};
483
+ const __vize_css_id__ = ${JSON.stringify(`vize-style-${styleKey}`)};
484
+ (function() {
485
+ if (typeof document !== 'undefined') {
486
+ let style = document.getElementById(__vize_css_id__);
487
+ if (!style) {
488
+ style = document.createElement('style');
489
+ style.id = __vize_css_id__;
490
+ style.textContent = __vize_css__;
491
+ document.head.appendChild(style);
492
+ } else {
493
+ style.textContent = __vize_css__;
494
+ }
495
+ }
496
+ })();
497
+ ${output}`;
498
+ }
499
+ function insertAfterStaticImports(output, imports) {
500
+ let insertAt = 0;
501
+ for (const match of output.matchAll(/^import\b[^\n]*(?:\r?\n|$)/gm)) insertAt = (match.index ?? 0) + match[0].length;
502
+ if (insertAt === 0) return `${imports}\n${output}`;
503
+ return `${output.slice(0, insertAt)}${imports}\n${output.slice(insertAt)}`;
504
+ }
505
+ function generateScopeId(filename) {
506
+ return createHash("sha256").update(filename).digest("hex").slice(0, 8);
507
+ }
508
+ /**
509
+ * Whether the SFC's `<style>` blocks are handed to Vite as virtual imports.
510
+ *
511
+ * Some blocks require Vite's CSS pipeline (preprocessor or CSS Modules), and a
512
+ * production client build routes plain CSS through it too so nesting,
513
+ * minification, and chunk ownership still apply. In both cases the blocks are
514
+ * emitted as imports and `compiled.css` is not used.
515
+ */
516
+ function usesStyleImports(compiled, options) {
517
+ return !!options.filePath && !!compiled.styles?.length && (options.customElement || hasDelegatedStyles(compiled) || !options.ssr && options.isProduction && !!options.extractCss);
518
+ }
519
+ /**
520
+ * Whether `generateOutput` will embed `compiled.css` in the module.
521
+ *
522
+ * The only consumer of `compiled.css` is the inline `<style>` injection, so this
523
+ * is also the only case in which resolving the CSS's `@import`s affects the
524
+ * output. Callers that would otherwise resolve `compiled.css` eagerly consult
525
+ * this first, which keeps the condition in one place instead of duplicating
526
+ * `generateOutput`'s branch structure at the call site.
527
+ *
528
+ * That guard matters because resolving `@import`s reads and inlines files and
529
+ * crosses the native boundary with the whole stylesheet. A production client
530
+ * build hands plain `<style>` blocks to Vite as virtual imports and an SSR build
531
+ * emits no CSS at all, so in both cases the resolved text was previously built
532
+ * and discarded, once per styled SFC on every build (270 discarded calls on the
533
+ * 300-file bench corpus).
534
+ */
535
+ function embedsInlineCss(compiled, options) {
536
+ return !usesStyleImports(compiled, options) && !options.customElement && !options.ssr && !!compiled.css && !(options.isProduction && !!options.extractCss);
537
+ }
538
+ function generateOutput(compiled, options) {
539
+ return generateOutputWithMap(compiled, options).code;
540
+ }
541
+ /**
542
+ * `generateOutput` plus the source map that describes the module it returns.
543
+ *
544
+ * The compiler's map (`compiled.map`) describes `compiled.code`; every rewrite
545
+ * below goes through {@link MappedModule}, which realigns the map to the lines
546
+ * it inserts, so the returned map describes the returned code (#3399). `map` is
547
+ * `null` when the compiler produced none.
548
+ */
549
+ function generateOutputWithMap(compiled, options) {
550
+ const { customElement, isProduction, isDev, ssr, hmrUpdateType, extractCss, filePath } = options;
551
+ const emitted = new MappedModule(compiled.code, parseSourceMap(compiled.map));
552
+ const moduleInfo = compiled.moduleShape ?? analyzeModuleOutput(emitted.code);
553
+ const hasExportDefault = moduleInfo.hasDefaultExport;
554
+ const hasNamedRenderExport = moduleInfo.hasNamedRenderExport;
555
+ const hasNamedSsrRenderExport = moduleInfo.hasNamedSsrRenderExport;
556
+ const hasSfcMainDefined = moduleInfo.hasSfcMainDefined;
557
+ if (hasExportDefault && !hasSfcMainDefined) {
558
+ emitted.edit(rewriteDefaultExportToSfcMain(emitted.code, moduleInfo));
559
+ if (compiled.hasScoped && compiled.scopeId) emitted.edit(`${emitted.code}\n_sfc_main.__scopeId = "data-v-${compiled.scopeId}";`);
560
+ emitted.edit(`${emitted.code}\nexport default _sfc_main;`);
561
+ } else if (hasExportDefault && hasSfcMainDefined) {
562
+ if (compiled.hasScoped && compiled.scopeId) emitted.edit(insertBeforeSfcMainDefaultExport(emitted.code, `_sfc_main.__scopeId = "data-v-${compiled.scopeId}";`, { moduleInfo }));
563
+ } else if (!hasExportDefault && !hasSfcMainDefined && hasNamedRenderExport) {
564
+ emitted.edit(`${emitted.code}\nconst _sfc_main = {};`);
565
+ if (compiled.hasScoped && compiled.scopeId) emitted.edit(`${emitted.code}\n_sfc_main.__scopeId = "data-v-${compiled.scopeId}";`);
566
+ emitted.edit(`${emitted.code}\n_sfc_main.render = render;`);
567
+ emitted.edit(`${emitted.code}\nexport default _sfc_main;`);
568
+ } else if (!hasExportDefault && !hasSfcMainDefined && hasNamedSsrRenderExport) {
569
+ emitted.edit(`${emitted.code}\nconst _sfc_main = {};`);
570
+ if (compiled.hasScoped && compiled.scopeId) emitted.edit(`${emitted.code}\n_sfc_main.__scopeId = "data-v-${compiled.scopeId}";`);
571
+ emitted.edit(`${emitted.code}\n_sfc_main.ssrRender = ssrRender;`);
572
+ emitted.edit(`${emitted.code}\nexport default _sfc_main;`);
573
+ }
574
+ if (usesStyleImports(compiled, options)) {
575
+ const styleImports = [];
576
+ const cssModuleImports = [];
577
+ const customElementStyleBindings = [];
578
+ for (const block of compiled.styles) {
579
+ const lang = block.lang ?? "css";
580
+ const params = new URLSearchParams();
581
+ params.set("vue", "");
582
+ params.set("type", "style");
583
+ params.set("index", String(block.index));
584
+ if (block.scoped) params.set("scoped", `data-v-${compiled.scopeId}`);
585
+ params.set("lang", lang);
586
+ if (customElement) {
587
+ if (isCssModule(block)) throw new Error("<style module> is not supported in custom element mode");
588
+ params.set("inline", "");
589
+ const bindingName = `_style_${block.index}`;
590
+ const importUrl = createStyleImportUrl(filePath, params, block);
591
+ styleImports.push(`import ${bindingName} from ${JSON.stringify(importUrl)};`);
592
+ customElementStyleBindings.push(bindingName);
593
+ } else if (isCssModule(block)) {
594
+ const bindingName = typeof block.module === "string" ? block.module : "$style";
595
+ params.set("module", typeof block.module === "string" ? block.module : "");
596
+ const importUrl = createStyleImportUrl(filePath, params, block);
597
+ cssModuleImports.push(`import ${bindingName} from ${JSON.stringify(importUrl)};`);
598
+ } else {
599
+ const importUrl = createStyleImportUrl(filePath, params, block);
600
+ styleImports.push(`import ${JSON.stringify(importUrl)};`);
601
+ }
602
+ }
603
+ const allImports = [...styleImports, ...cssModuleImports].join("\n");
604
+ if (allImports) emitted.edit(insertAfterStaticImports(emitted.code, allImports));
605
+ if (customElementStyleBindings.length > 0) emitted.edit(insertBeforeSfcMainDefaultExport(emitted.code, `_sfc_main.styles = [${customElementStyleBindings.join(", ")}];`, { normalizeSemicolon: true }));
606
+ else if (cssModuleImports.length > 0) {
607
+ const moduleBindings = [];
608
+ for (const block of compiled.styles) if (isCssModule(block)) {
609
+ const bindingName = typeof block.module === "string" ? block.module : "$style";
610
+ moduleBindings.push({
611
+ name: bindingName,
612
+ bindingName
613
+ });
614
+ }
615
+ const cssModuleSetup = moduleBindings.map((m) => `_sfc_main.__cssModules = _sfc_main.__cssModules || {};\n_sfc_main.__cssModules[${JSON.stringify(m.name)}] = ${m.bindingName};`).join("\n");
616
+ emitted.edit(insertBeforeSfcMainDefaultExport(emitted.code, cssModuleSetup, { normalizeSemicolon: true }));
617
+ }
618
+ } else if (!ssr && compiled.css && !(isProduction && extractCss)) emitted.edit(prependInlineStyleInjection(emitted.code, compiled.css, compiled.scopeId));
619
+ if (!isProduction && isDev && hasExportDefault) {
620
+ const effectiveHmrUpdateType = hmrUpdateType === "template-only" && !supportsTemplateOnlyHmr(emitted.code) ? "full-reload" : hmrUpdateType ?? "full-reload";
621
+ emitted.edit(`${emitted.code}${generateHmrCode(compiled.scopeId, effectiveHmrUpdateType)}`);
622
+ }
623
+ return {
624
+ code: emitted.code,
625
+ map: emitted.map
626
+ };
627
+ }
628
+ const RESOLVED_CSS_MODULE = "\0vize:all-styles.css";
629
+ /** Check if a module ID is a vize-compiled virtual module */
630
+ function isVizeVirtual(id) {
631
+ return classifyVitePluginRequest(id).isVizeVirtual;
632
+ }
633
+ function isVizeSsrVirtual(id) {
634
+ return classifyVitePluginRequest(id).isVizeSsrVirtual;
635
+ }
636
+ /** Create a virtual module ID from a real .vue file path */
637
+ function toVirtualId(realPath, ssr = false) {
638
+ return createViteVirtualId(realPath, ssr);
639
+ }
640
+ function toPluginVisibleVirtualId(realPath, ssr = false, querySuffix = "") {
641
+ const params = new URLSearchParams(querySuffix.startsWith("?") ? querySuffix.slice(1) : "");
642
+ params.delete("vue");
643
+ params.delete("vize");
644
+ params.delete("vize-ssr");
645
+ const rest = params.toString();
646
+ return `${realPath}.ts?vue&${ssr ? "vize-ssr" : "vize"}${rest ? `&${rest}` : ""}`;
647
+ }
648
+ /**
649
+ * String pre-gate for {@link fromPluginVisibleVirtualId}, so ordinary module IDs
650
+ * never cross the native boundary (#3427).
651
+ *
652
+ * A non-null result requires `request.path` to end with `.vue.ts` or `.vue.tsx`
653
+ * and `request.querySuffix` to be non-empty. `request.path` is `id` up to the
654
+ * first `?` and `querySuffix` is non-empty exactly when that `?` exists, so both
655
+ * conditions imply these two substring tests. The tests are strictly weaker, so
656
+ * everything the old code accepted still reaches the classifier.
657
+ */
658
+ function mayBePluginVisibleVirtualId(id) {
659
+ return !id.startsWith("\0") && id.includes(".vue.ts") && id.includes("?");
660
+ }
661
+ function fromPluginVisibleVirtualId(id) {
662
+ if (!mayBePluginVisibleVirtualId(id)) return null;
663
+ const request = classifyVitePluginRequest(id);
664
+ if (!isPluginVisibleVueVirtualPath(request.path) || !request.querySuffix) return null;
665
+ const params = new URLSearchParams(request.querySuffix.slice(1));
666
+ if (!params.has("vue") || !params.has("vize") && !params.has("vize-ssr")) return null;
667
+ return stripPluginVisibleVueVirtualSuffix(stripFsPrefix(request.path));
668
+ }
669
+ /**
670
+ * The `path` a second `classifyVitePluginRequest(request.normalizedFsId ?? id)`
671
+ * used to recompute (#3427).
672
+ *
673
+ * `normalizedFsId` is `Some` exactly when the pre-`?` path starts with `/@fs`,
674
+ * and its value is that path with the four-byte prefix removed plus the original
675
+ * query suffix. Re-splitting that at the first `?` therefore yields the path
676
+ * without the prefix — and when `normalizedFsId` is `undefined` the second call
677
+ * classified `id` itself and yielded `request.path` unchanged.
678
+ */
679
+ function stripFsPrefix(path) {
680
+ return path.startsWith("/@fs") ? path.slice(4) : path;
681
+ }
682
+ function isPluginVisibleVueVirtualPath(path) {
683
+ return path.endsWith(".vue.ts") || path.endsWith(".vue.tsx");
684
+ }
685
+ function stripPluginVisibleVueVirtualSuffix(path) {
686
+ if (path.endsWith(".vue.tsx")) return path.slice(0, -4);
687
+ return path.endsWith(".vue.ts") ? path.slice(0, -3) : path;
688
+ }
689
+ function isPluginVisibleSsrVirtualId(id) {
690
+ const request = classifyVitePluginRequest(id);
691
+ return request.querySuffix ? new URLSearchParams(request.querySuffix.slice(1)).has("vize-ssr") : false;
692
+ }
693
+ function toBrowserImportPrefix(replacement) {
694
+ return toViteBrowserImportPrefix(replacement);
695
+ }
696
+ //#endregion
697
+ //#region src/transform.ts
698
+ /**
699
+ * Code transformation utilities for Vize.
700
+ *
701
+ * Handles static asset URL rewriting, Vite define replacements, and
702
+ * provides the debug logger.
703
+ */
704
+ /**
705
+ * Rewrite static asset URLs in compiled template output.
706
+ *
707
+ * Transforms property values like `src: "@/assets/logo.svg"` into import
708
+ * statements hoisted to the top of the module, so Vite's module resolution
709
+ * pipeline handles alias expansion and asset hashing in both dev and build.
710
+ */
711
+ function rewriteStaticAssetUrls(code, aliasRules) {
712
+ if (aliasRules.length === 0 || !code.includes("src")) return code;
713
+ return rewriteViteStaticAssetUrls(code, aliasRules);
714
+ }
715
+ function rewriteDynamicTemplateImports(code, aliasRules) {
716
+ if (!code.includes("import(") || !code.includes("`")) return code;
717
+ return rewriteViteDynamicTemplateImports(code, aliasRules);
718
+ }
719
+ function rewriteImportMetaGlobBase(code, importer, root) {
720
+ if (!code.includes("import.meta.glob")) return code;
721
+ return rewriteViteImportMetaGlobBase(code, importer, root);
722
+ }
723
+ function shouldApplyDefineInVirtualModule(key) {
724
+ return shouldApplyViteDefineInVirtualModule(key);
725
+ }
726
+ /**
727
+ * Apply Vite define replacements to code.
728
+ * Replaces keys like `import.meta.vfFeatures.photoSection` with their values.
729
+ * Uses word-boundary-aware matching to avoid replacing inside strings or partial matches.
730
+ */
731
+ function applyDefineReplacements(code, defines) {
732
+ return applyViteDefineReplacements(code, Object.entries(defines).map(([key, value]) => ({
733
+ key,
734
+ value
735
+ })));
736
+ }
737
+ function createLogger(debug) {
738
+ return {
739
+ log: (...args) => debug && console.log("[vize]", ...args),
740
+ info: (...args) => console.log("[vize]", ...args),
741
+ warn: (...args) => console.warn("[vize]", ...args),
742
+ error: (...args) => console.error("[vize]", ...args)
743
+ };
744
+ }
745
+ //#endregion
746
+ //#region src/plugin/plugin-vue-options.ts
747
+ const PLUGIN_VUE_COMPAT_VERSION = "6.0.7";
748
+ const DEFAULT_CUSTOM_ELEMENT_PATTERN = /\.ce\.vue$/;
749
+ function booleanCompilerOption(value) {
750
+ return typeof value === "boolean" ? value : void 0;
751
+ }
752
+ function resolvePluginVueCompileOptions(options) {
753
+ const compilerOptions = options.template?.compilerOptions;
754
+ const resolved = { styleTrim: options.style?.trim ?? true };
755
+ const templateCacheHandlers = booleanCompilerOption(compilerOptions?.cacheHandlers);
756
+ const templateComments = booleanCompilerOption(compilerOptions?.comments);
757
+ const templateHoistStatic = booleanCompilerOption(compilerOptions?.hoistStatic);
758
+ const templatePrefixIdentifiers = booleanCompilerOption(compilerOptions?.prefixIdentifiers);
759
+ if (templateCacheHandlers !== void 0) resolved.templateCacheHandlers = templateCacheHandlers;
760
+ if (templateComments !== void 0) resolved.templateComments = templateComments;
761
+ if (templateHoistStatic !== void 0) resolved.templateHoistStatic = templateHoistStatic;
762
+ if (templatePrefixIdentifiers !== void 0) resolved.templatePrefixIdentifiers = templatePrefixIdentifiers;
763
+ return resolved;
764
+ }
765
+ function resolveCustomElementOption(options) {
766
+ const featureCustomElement = options.features?.customElement;
767
+ if (featureCustomElement) return featureCustomElement;
768
+ if (options.customElement !== void 0) return options.customElement;
769
+ return DEFAULT_CUSTOM_ELEMENT_PATTERN;
770
+ }
771
+ function isPluginVueCustomElement(options, filePath) {
772
+ const customElement = resolveCustomElementOption(options);
773
+ if (typeof customElement === "boolean") return customElement;
774
+ return createFilter(customElement, void 0)(filePath);
775
+ }
776
+ //#endregion
777
+ //#region src/plugin/precompile.ts
778
+ const DEFAULT_PRECOMPILE_IGNORE_PATTERNS = [
779
+ "node_modules/**",
780
+ "**/node_modules/**",
781
+ "dist/**",
782
+ "**/dist/**",
783
+ ".git/**",
784
+ "**/.git/**",
785
+ ".nuxt/**",
786
+ "**/.nuxt/**",
787
+ ".output/**",
788
+ "**/.output/**",
789
+ ".nitro/**",
790
+ "**/.nitro/**",
791
+ "coverage/**",
792
+ "**/coverage/**"
793
+ ];
794
+ function isPrecompileSfcPath(path) {
795
+ return path.endsWith(".vue");
796
+ }
797
+ function diffPrecompileFiles(files, currentMetadata, previousMetadata) {
798
+ return diffVitePrecompileFiles([...files], toNativePrecompileMetadataEntries(currentMetadata), toNativePrecompileMetadataEntries(previousMetadata));
799
+ }
800
+ function normalizePrecompileBatchSize(value) {
801
+ return normalizeVitePrecompileBatchSize(value);
802
+ }
803
+ function chunkPrecompileFiles(files, batchSize, options = {}) {
804
+ return chunkVitePrecompileFiles([...files], batchSize, {
805
+ maxBytes: options.maxBytes,
806
+ metadata: options.metadata ? toNativePrecompileMetadataEntries(options.metadata) : void 0
807
+ });
808
+ }
809
+ function toNativePrecompileMetadataEntries(metadata) {
810
+ const entries = [];
811
+ for (const [path, value] of metadata) entries.push({
812
+ path,
813
+ mtimeMs: value.mtimeMs,
814
+ size: value.size
815
+ });
816
+ return entries;
817
+ }
818
+ //#endregion
819
+ //#region src/plugin/state.ts
820
+ function getEnvironmentCache(state, ssr) {
821
+ return ssr ? state.ssrCache : state.cache;
822
+ }
823
+ function getCompileOptionsForRequest(state, ssr) {
824
+ const options = {
825
+ sourceMap: state.mergedOptions?.sourceMap ?? (!state.isProduction || !!state.viteBuildSourcemap),
826
+ ssr,
827
+ vapor: !ssr && (state.mergedOptions?.vapor ?? false),
828
+ customRenderer: state.mergedOptions?.customRenderer ?? false,
829
+ templateSyntax: state.mergedOptions?.templateSyntax ?? "standard",
830
+ ...resolvePluginVueCompileOptions(state.mergedOptions ?? {})
831
+ };
832
+ if (state.mergedOptions?.customElements !== void 0) options.customElements = state.mergedOptions.customElements;
833
+ if (state.mergedOptions?.mode !== void 0) options.mode = state.mergedOptions.mode;
834
+ if (state.mergedOptions?.runtimeModuleName !== void 0) options.runtimeModuleName = state.mergedOptions.runtimeModuleName;
835
+ if (state.mergedOptions?.runtimeGlobalName !== void 0) options.runtimeGlobalName = state.mergedOptions.runtimeGlobalName;
836
+ if (state.mergedOptions?.vueVersion !== void 0) options.vueVersion = state.mergedOptions.vueVersion;
837
+ if (state.mergedOptions?.experimentalInTagComments) options.experimentalInTagComments = true;
838
+ if (state.mergedOptions?.experimentalPatternedTemplate) options.experimentalPatternedTemplate = true;
839
+ if (state.mergedOptions?.experimentalSelfComponent) options.experimentalSelfComponent = true;
840
+ if (state.mergedOptions?.experimentalStrictSlotChildren) options.experimentalStrictSlotChildren = true;
841
+ if (state.mergedOptions?.experimentalServerScript) options.experimentalServerScript = true;
842
+ return options;
843
+ }
844
+ function syncCollectedCssForFile(state, filePath, compiled) {
845
+ if (!compiled || !state.extractCss) return;
846
+ if (compiled.styles?.length) {
847
+ state.collectedCss.delete(filePath);
848
+ return;
849
+ }
850
+ if (compiled.css && !hasDelegatedStyles(compiled)) state.collectedCss.set(filePath, resolveCssImports(compiled.css, filePath, state.cssAliasRules, false));
851
+ else state.collectedCss.delete(filePath);
852
+ }
853
+ function shouldExtractCssForRequest(state, ssr) {
854
+ return state.isProduction && !ssr;
855
+ }
856
+ function clearBuildCaches(state) {
857
+ state.cache.clear();
858
+ state.ssrCache.clear();
859
+ state.collectedCss.clear();
860
+ state.precompileMetadata.clear();
861
+ state.pendingHmrUpdateTypes.clear();
862
+ state.viteResolveCache?.clear();
863
+ }
864
+ //#endregion
865
+ //#region src/plugin/compiled-module-cache.ts
866
+ /**
867
+ * Compiled-module caches carrying a reverse index from a `src`-imported
868
+ * dependency to the SFCs that pulled it in.
869
+ *
870
+ * Every hot update has to answer "which SFCs own this changed file?" before it
871
+ * can do anything else, and that answer used to come from a full scan of both
872
+ * caches with a `path.resolve` per dependency per cached file. HMR latency then
873
+ * grew with the number of components in the project, on the interactive path,
874
+ * for every save — including saves of ordinary `.vue` files, because the scan
875
+ * runs before the `.vue` fast path.
876
+ *
877
+ * The index is maintained by overriding `set`/`delete`/`clear` rather than by a
878
+ * second structure updated at each call site. `state.cache` is handed to
879
+ * `compileFile` and `compileBatch`, and is also mutated directly from
880
+ * `precompile-run.ts`, `hmr.ts` and `state.ts`; a structure kept in sync by hand
881
+ * across those would drift the first time a new writer appeared. Subclassing
882
+ * puts the bookkeeping where the mutation is.
883
+ *
884
+ * The keys are `path.resolve`d exactly as the previous scan resolved them, so a
885
+ * dependency recorded as a relative path indexes and looks up identically.
886
+ */
887
+ var CompiledModuleCache = class extends Map {
888
+ #ownersByDependency = /* @__PURE__ */ new Map();
889
+ #dependenciesByOwner = /* @__PURE__ */ new Map();
890
+ /**
891
+ * Deliberately takes no entries: `Map`'s constructor would call the
892
+ * overridden `set` from inside `super()`, before `#ownersByDependency` exists.
893
+ */
894
+ constructor() {
895
+ super();
896
+ }
897
+ set(file, compiled) {
898
+ this.#unindex(file);
899
+ super.set(file, compiled);
900
+ const dependencies = /* @__PURE__ */ new Set();
901
+ for (const dependency of compiled.dependencies ?? []) {
902
+ const key = path.resolve(dependency);
903
+ dependencies.add(key);
904
+ const owners = this.#ownersByDependency.get(key);
905
+ if (owners) owners.add(file);
906
+ else this.#ownersByDependency.set(key, new Set([file]));
907
+ }
908
+ this.#dependenciesByOwner.set(file, dependencies);
909
+ return this;
910
+ }
911
+ delete(file) {
912
+ this.#unindex(file);
913
+ return super.delete(file);
914
+ }
915
+ clear() {
916
+ this.#ownersByDependency.clear();
917
+ this.#dependenciesByOwner.clear();
918
+ super.clear();
919
+ }
920
+ /**
921
+ * Evict a compiled value while retaining the dependency ownership that is
922
+ * required to route another hot update before Vite reloads the owner module.
923
+ * The next `set` reconciles that retained snapshot with the new compilation.
924
+ */
925
+ evict(file) {
926
+ return super.delete(file);
927
+ }
928
+ /** The cached SFCs that `src`-import `resolvedDependency`. */
929
+ ownersOf(resolvedDependency) {
930
+ const owners = this.#ownersByDependency.get(resolvedDependency);
931
+ return owners ? [...owners] : [];
932
+ }
933
+ #unindex(file) {
934
+ for (const dependency of this.#dependenciesByOwner.get(file) ?? []) {
935
+ const owners = this.#ownersByDependency.get(dependency);
936
+ if (!owners) continue;
937
+ owners.delete(file);
938
+ if (owners.size === 0) this.#ownersByDependency.delete(dependency);
939
+ }
940
+ this.#dependenciesByOwner.delete(file);
941
+ }
942
+ };
943
+ /**
944
+ * Invalidate a compiled module without dropping its HMR dependency routing.
945
+ * Hand-built plain Maps retain their historical delete behaviour.
946
+ */
947
+ function evictCompiledModule(cache, file) {
948
+ return cache instanceof CompiledModuleCache ? cache.evict(file) : cache.delete(file);
949
+ }
950
+ /**
951
+ * Owners of `resolvedDependency` in one cache.
952
+ *
953
+ * Plain `Map`s — the hand-built states in unit tests — keep the original linear
954
+ * scan, so an unindexed cache answers exactly what the indexed one does.
955
+ */
956
+ function ownersOfDependency(cache, resolvedDependency) {
957
+ if (cache instanceof CompiledModuleCache) return cache.ownersOf(resolvedDependency);
958
+ const owners = [];
959
+ for (const [file, compiled] of cache) if (compiled.dependencies?.some((dependency) => path.resolve(dependency) === resolvedDependency)) owners.push(file);
960
+ return owners;
961
+ }
962
+ //#endregion
963
+ //#region src/compile-options.ts
964
+ function buildCompileFileOptions(filePath, options) {
965
+ return {
966
+ filename: filePath,
967
+ sourceMap: options.sourceMap,
968
+ ssr: options.ssr,
969
+ vapor: options.vapor,
970
+ customRenderer: options.customRenderer ?? false,
971
+ ...options.customElements === void 0 ? {} : { customElements: options.customElements },
972
+ experimentalInTagComments: options.experimentalInTagComments ?? false,
973
+ experimentalPatternedTemplate: options.experimentalPatternedTemplate ?? false,
974
+ experimentalSelfComponent: options.experimentalSelfComponent ?? false,
975
+ experimentalStrictSlotChildren: options.experimentalStrictSlotChildren ?? false,
976
+ experimentalServerScript: options.experimentalServerScript ?? false,
977
+ scopeId: `data-v-${generateScopeId(filePath)}`,
978
+ styleTrim: options.styleTrim,
979
+ ...options.templateCacheHandlers === void 0 ? {} : { templateCacheHandlers: options.templateCacheHandlers },
980
+ ...options.templateComments === void 0 ? {} : { templateComments: options.templateComments },
981
+ ...options.templateHoistStatic === void 0 ? {} : { templateHoistStatic: options.templateHoistStatic },
982
+ ...options.templatePrefixIdentifiers === void 0 ? {} : { templatePrefixIdentifiers: options.templatePrefixIdentifiers },
983
+ ...options.mode === void 0 ? {} : { mode: options.mode },
984
+ ...options.templateSyntax === void 0 ? {} : { templateSyntax: options.templateSyntax },
985
+ ...options.runtimeModuleName === void 0 ? {} : { runtimeModuleName: options.runtimeModuleName },
986
+ ...options.runtimeGlobalName === void 0 ? {} : { runtimeGlobalName: options.runtimeGlobalName },
987
+ ...options.vueVersion == null ? {} : { vueVersion: String(options.vueVersion) }
988
+ };
989
+ }
990
+ function buildCompileBatchOptions(options) {
991
+ return {
992
+ ssr: options.ssr,
993
+ vapor: options.vapor,
994
+ customRenderer: options.customRenderer ?? false,
995
+ ...options.customElements === void 0 ? {} : { customElements: options.customElements },
996
+ experimentalInTagComments: options.experimentalInTagComments ?? false,
997
+ experimentalPatternedTemplate: options.experimentalPatternedTemplate ?? false,
998
+ experimentalSelfComponent: options.experimentalSelfComponent ?? false,
999
+ experimentalStrictSlotChildren: options.experimentalStrictSlotChildren ?? false,
1000
+ experimentalServerScript: options.experimentalServerScript ?? false,
1001
+ includeStyles: true,
1002
+ includeMacroArtifacts: true,
1003
+ includeHashes: true,
1004
+ includeSourceMap: options.sourceMap,
1005
+ styleTrim: options.styleTrim,
1006
+ ...options.templateCacheHandlers === void 0 ? {} : { templateCacheHandlers: options.templateCacheHandlers },
1007
+ ...options.templateComments === void 0 ? {} : { templateComments: options.templateComments },
1008
+ ...options.templateHoistStatic === void 0 ? {} : { templateHoistStatic: options.templateHoistStatic },
1009
+ ...options.templatePrefixIdentifiers === void 0 ? {} : { templatePrefixIdentifiers: options.templatePrefixIdentifiers },
1010
+ ...options.mode === void 0 ? {} : { mode: options.mode },
1011
+ ...options.templateSyntax === void 0 ? {} : { templateSyntax: options.templateSyntax },
1012
+ ...options.runtimeModuleName === void 0 ? {} : { runtimeModuleName: options.runtimeModuleName },
1013
+ ...options.runtimeGlobalName === void 0 ? {} : { runtimeGlobalName: options.runtimeGlobalName },
1014
+ ...options.vueVersion == null ? {} : { vueVersion: String(options.vueVersion) }
1015
+ };
1016
+ }
1017
+ //#endregion
1018
+ //#region src/compiler.ts
1019
+ const { compileSfc, compileSfcBatchWithResults } = native;
1020
+ const compileJsx = native.compileJsx;
1021
+ var VizeSfcCompileError = class extends Error {
1022
+ filePath;
1023
+ diagnostics;
1024
+ constructor(filePath, diagnostics) {
1025
+ super(formatCompileErrorMessage(filePath, diagnostics));
1026
+ this.name = "VizeSfcCompileError";
1027
+ this.filePath = filePath;
1028
+ this.diagnostics = diagnostics;
1029
+ }
1030
+ };
1031
+ function formatCompileErrorMessage(filePath, diagnostics) {
1032
+ return `[vize] Compilation failed in ${filePath}:\n${diagnostics.map((diagnostic) => ` - ${diagnostic}`).join("\n")}`;
1033
+ }
1034
+ function normalizeStyleBlocks(styles) {
1035
+ if (!styles) return [];
1036
+ return styles.map((block) => ({
1037
+ content: block.content,
1038
+ src: block.src ?? null,
1039
+ lang: block.lang ?? null,
1040
+ scoped: block.scoped,
1041
+ module: block.module ? block.moduleName ?? true : false,
1042
+ index: block.index
1043
+ }));
1044
+ }
1045
+ function resolveRelativeSrc(filePath, src) {
1046
+ return path.isAbsolute(src) ? src : path.resolve(path.dirname(filePath), src);
1047
+ }
1048
+ function readSrcImport(filePath, tag, src) {
1049
+ const resolvedPath = resolveRelativeSrc(filePath, src);
1050
+ try {
1051
+ return {
1052
+ path: resolvedPath,
1053
+ content: fs.readFileSync(resolvedPath, "utf-8")
1054
+ };
1055
+ } catch {
1056
+ throw new Error(`[vize] <${tag} src="${src}"> not found (resolved: ${resolvedPath}) in ${filePath}`);
1057
+ }
1058
+ }
1059
+ function stripSrcAttribute(attrs) {
1060
+ return attrs.replace(/\s*\bsrc\s*=\s*(?:"[^"]*"|'[^']*')/i, "");
1061
+ }
1062
+ function inlineSingleSrcBlock(source, filePath, tag, src, dependencies) {
1063
+ if (!src) return source;
1064
+ const imported = readSrcImport(filePath, tag, src);
1065
+ dependencies.push(imported.path);
1066
+ const pattern = new RegExp(`<${tag}\\b([^>]*)\\bsrc\\s*=\\s*(['"])[^'"]+\\2([^>]*)>[\\s\\S]*?<\\/${tag}>`, "i");
1067
+ return source.replace(pattern, (_match, beforeSrc, _quote, afterSrc) => {
1068
+ return `<${tag}${stripSrcAttribute(`${beforeSrc}${afterSrc}`)}>\n${imported.content}\n</${tag}>`;
1069
+ });
1070
+ }
1071
+ function inlineStyleSrcBlocks(source, filePath, dependencies) {
1072
+ return source.replace(/<style\b([^>]*)\bsrc\s*=\s*(['"])([^'"]+)\2([^>]*)>[\s\S]*?<\/style>/gi, (_match, beforeSrc, _quote, src, afterSrc) => {
1073
+ const imported = readSrcImport(filePath, "style", src);
1074
+ dependencies.push(imported.path);
1075
+ return `<style${stripSrcAttribute(`${beforeSrc}${afterSrc}`)}>\n${imported.content}\n</style>`;
1076
+ });
1077
+ }
1078
+ /**
1079
+ * Cheap necessary condition for an SFC block carrying a `src` attribute.
1080
+ *
1081
+ * `extractSfcSrcInfo` parses a full SFC descriptor, so calling it for every file
1082
+ * costs a second whole-source parse per compile on top of the one the compiler
1083
+ * itself performs -- and block `src` attributes are rare (roughly 4% of files in
1084
+ * a real app). Any `<script src>`/`<template src>`/`<style src>` necessarily
1085
+ * contains `src` followed by `=`, so a source without this substring provably
1086
+ * has nothing to inline and can skip the descriptor parse entirely. False
1087
+ * positives (e.g. `<img src=...>` in a template) simply take the original path.
1088
+ */
1089
+ const SFC_SRC_ATTRIBUTE_HINT = /\bsrc\s*=/i;
1090
+ function resolveSfcSrcImports(filePath, source) {
1091
+ if (!SFC_SRC_ATTRIBUTE_HINT.test(source)) return {
1092
+ source,
1093
+ dependencies: []
1094
+ };
1095
+ const dependencies = [];
1096
+ const srcInfo = native.extractSfcSrcInfo(source, filePath);
1097
+ let resolvedSource = source;
1098
+ resolvedSource = inlineSingleSrcBlock(resolvedSource, filePath, "script", srcInfo.scriptSrc, dependencies);
1099
+ resolvedSource = inlineSingleSrcBlock(resolvedSource, filePath, "template", srcInfo.templateSrc, dependencies);
1100
+ resolvedSource = inlineStyleSrcBlocks(resolvedSource, filePath, dependencies);
1101
+ return {
1102
+ source: resolvedSource,
1103
+ dependencies
1104
+ };
1105
+ }
1106
+ function compileFile(filePath, cache, options, source, diagnostics) {
1107
+ const resolved = resolveSfcSrcImports(filePath, source ?? fs.readFileSync(filePath, "utf-8"));
1108
+ const scopeId = generateScopeId(filePath);
1109
+ const result = compileSfc(resolved.source, buildCompileFileOptions(filePath, options));
1110
+ if (result.errors.length > 0) throw new VizeSfcCompileError(filePath, result.errors);
1111
+ if (result.warnings.length > 0 && (diagnostics?.logWarnings ?? true)) result.warnings.forEach((warning) => {
1112
+ console.warn(`[vize] Warning in ${filePath}: ${warning}`);
1113
+ });
1114
+ const compiled = {
1115
+ code: result.code,
1116
+ ...result.map ? { map: result.map } : {},
1117
+ css: result.css,
1118
+ scopeId,
1119
+ hasScoped: result.hasScoped,
1120
+ templateHash: result.templateHash,
1121
+ styleHash: result.styleHash,
1122
+ scriptHash: result.scriptHash,
1123
+ macroArtifacts: result.macroArtifacts ?? [],
1124
+ styles: normalizeStyleBlocks(result.styles),
1125
+ dependencies: resolved.dependencies
1126
+ };
1127
+ cache.set(filePath, compiled);
1128
+ return compiled;
1129
+ }
1130
+ /**
1131
+ * Compile a `.jsx`/`.tsx` Vue component module to render code through Vize.
1132
+ *
1133
+ * Mirrors `compileFile` for SFCs but routes through the native `compileJsx`
1134
+ * binding. The returned `code` is a self-contained module (the runtime-helper
1135
+ * preamble is included, #1533), and `map` carries a v3 source map when
1136
+ * `sourceMap` is requested. A component's `<style scoped>` CSS is surfaced
1137
+ * (already scope-rewritten) and emitted through the same inline-injection path
1138
+ * plain SFC `<style>` blocks use (#1495, #1533).
1139
+ */
1140
+ function compileJsxModule(filePath, source, options = {}) {
1141
+ const result = compileJsx(source, {
1142
+ filename: filePath,
1143
+ lang: filePath.endsWith(".tsx") ? "tsx" : "jsx",
1144
+ jsxMode: options.jsxMode,
1145
+ jsxCompat: options.jsxCompat,
1146
+ vapor: options.vapor ?? false,
1147
+ sourceMap: options.sourceMap ?? false
1148
+ });
1149
+ if (result.errors.length > 0) throw new VizeSfcCompileError(filePath, result.errors);
1150
+ const css = (result.scopedStyles ?? []).map((style) => style.css).join("\n");
1151
+ let code = result.code;
1152
+ let map = result.map ?? null;
1153
+ if (css && !options.ssr) {
1154
+ const styleKey = result.scopedStyles[0].scopeId.replace(/^data-v-/, "");
1155
+ code = prependInlineStyleInjection(code, css, styleKey);
1156
+ map = null;
1157
+ }
1158
+ return {
1159
+ code,
1160
+ map,
1161
+ warnings: result.warnings
1162
+ };
1163
+ }
1164
+ /**
1165
+ * Batch compile multiple files in parallel using native Rust multithreading.
1166
+ * Returns per-file results with content hashes for HMR.
1167
+ */
1168
+ function compileBatch(files, cache, options) {
1169
+ const dependenciesByPath = /* @__PURE__ */ new Map();
1170
+ const result = compileSfcBatchWithResults(files.map((file) => {
1171
+ const resolved = resolveSfcSrcImports(file.path, file.source);
1172
+ dependenciesByPath.set(file.path, resolved.dependencies);
1173
+ return {
1174
+ path: file.path,
1175
+ source: resolved.source
1176
+ };
1177
+ }), buildCompileBatchOptions(options));
1178
+ for (const fileResult of result.results) {
1179
+ if (fileResult.errors.length === 0) cache.set(fileResult.path, {
1180
+ code: fileResult.code,
1181
+ ...fileResult.map ? { map: fileResult.map } : {},
1182
+ css: fileResult.css,
1183
+ scopeId: fileResult.scopeId,
1184
+ hasScoped: fileResult.hasScoped,
1185
+ templateHash: fileResult.templateHash,
1186
+ styleHash: fileResult.styleHash,
1187
+ scriptHash: fileResult.scriptHash,
1188
+ macroArtifacts: fileResult.macroArtifacts ?? [],
1189
+ styles: normalizeStyleBlocks(fileResult.styles),
1190
+ dependencies: dependenciesByPath.get(fileResult.path) ?? []
1191
+ });
1192
+ if (fileResult.errors.length > 0) console.error(formatCompileErrorMessage(fileResult.path, fileResult.errors));
1193
+ if (fileResult.warnings.length > 0) fileResult.warnings.forEach((warning) => {
1194
+ console.warn(`[vize] Warning in ${fileResult.path}: ${warning}`);
1195
+ });
1196
+ }
1197
+ return result;
1198
+ }
1199
+ /**
1200
+ * SHA-256 of the exact source text handed to the compiler.
1201
+ *
1202
+ * `base64url` rather than hex: the same 256 bits in 43 characters instead of 64,
1203
+ * and the index carries one of these per entry.
1204
+ */
1205
+ function hashPrecompileSource(source) {
1206
+ return crypto.createHash("sha256").update(source, "utf8").digest("base64url");
1207
+ }
1208
+ /** Key-independent JSON: object key order must not change the hash. */
1209
+ function stableStringify(value) {
1210
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
1211
+ if (typeof value === "object" && value !== null) return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`).join(",")}}`;
1212
+ return JSON.stringify(value) ?? "null";
1213
+ }
1214
+ function describeBinary(binary) {
1215
+ try {
1216
+ const stat = fs.statSync(binary);
1217
+ return `${path.basename(binary)}:${stat.size}:${stat.mtimeMs}`;
1218
+ } catch {
1219
+ return `${path.basename(binary)}:unresolved`;
1220
+ }
1221
+ }
1222
+ /**
1223
+ * Identity of the native compiler that produced (or would produce) the output.
1224
+ *
1225
+ * The package version covers releases; the binary's size and mtime cover local
1226
+ * `pnpm --dir npm/native build:debug` rebuilds, which change codegen without
1227
+ * changing any version. Hashing the binary itself would be airtight but costs
1228
+ * hundreds of milliseconds for a >30 MB artifact, so a rebuild is treated as a
1229
+ * new identity — a miss, never a stale hit.
1230
+ */
1231
+ function resolveCompilerIdentity() {
1232
+ const configured = process.env.NAPI_RS_NATIVE_LIBRARY_PATH;
1233
+ try {
1234
+ const manifestPath = createRequire(import.meta.url).resolve("@vizejs/native/package.json");
1235
+ const packageDir = path.dirname(manifestPath);
1236
+ const version = JSON.parse(fs.readFileSync(manifestPath, "utf-8")).version;
1237
+ const binaries = configured ? [configured] : fs.readdirSync(packageDir).filter((name) => name.endsWith(".node")).sort().map((name) => path.join(packageDir, name));
1238
+ return {
1239
+ version: typeof version === "string" ? version : "unknown",
1240
+ binaries: binaries.map(describeBinary)
1241
+ };
1242
+ } catch {
1243
+ return {
1244
+ version: "unresolved",
1245
+ binaries: [configured ?? "unresolved"]
1246
+ };
1247
+ }
1248
+ }
1249
+ /**
1250
+ * Hash of everything outside the source text that changes compiled output.
1251
+ *
1252
+ * `compileOptions` must be the object actually handed to the native batch
1253
+ * compiler, so a newly added compile option cannot be forgotten here.
1254
+ */
1255
+ function computePrecompileCacheKey(compileOptions) {
1256
+ const material = stableStringify({
1257
+ format: 3,
1258
+ compiler: resolveCompilerIdentity(),
1259
+ options: compileOptions
1260
+ });
1261
+ return crypto.createHash("sha256").update(material, "utf8").digest("hex").slice(0, 32);
1262
+ }
1263
+ //#endregion
1264
+ //#region src/plugin/precompile-cache-store.ts
1265
+ /**
1266
+ * On-disk container for the persistent pre-compile cache.
1267
+ *
1268
+ * The first format stored the whole manifest as one JSON document, which meant
1269
+ * every compiled module's `code` went to disk as a JSON-escaped string: ~87% of
1270
+ * the bytes were that one field, and a cold build paid `JSON.stringify` over all
1271
+ * of it while a warm build paid `JSON.parse` back. This container splits the
1272
+ * two concerns instead:
1273
+ *
1274
+ * ```text
1275
+ * <header JSON>\n<compressed index><compressed payload>
1276
+ * ```
1277
+ *
1278
+ * - The **header** is one line of plain JSON naming the format, the cache key,
1279
+ * the codec, and the exact byte length of the two bodies.
1280
+ * - The **index** is a compressed JSON array of `[relativePath, sourceHash,
1281
+ * recordLength]`. Record offsets are *not* stored: they are the running sum of
1282
+ * the lengths, so there is no offset that can point somewhere else.
1283
+ * - The **payload** is the records back to back, each one
1284
+ * `<meta JSON>\n<code utf8><css utf8>\n`. `code` and `css` are raw UTF-8, so
1285
+ * the 90% of the manifest that is compiled output is never escaped, parsed, or
1286
+ * re-quoted -- only sliced out.
1287
+ *
1288
+ * `meta` is `[codeLength, cssLength, everythingElse]`, where `everythingElse` is
1289
+ * the compiled module minus `code`/`css` **by rest destructuring**, not by a
1290
+ * hand-copied field list. A field added to `CompiledModule` later is therefore
1291
+ * carried through automatically instead of being silently dropped.
1292
+ *
1293
+ * Every structural expectation above is re-checked on read and any failure
1294
+ * returns `null`, which the caller treats as "no cache" -- a full recompile.
1295
+ * See `decodePrecompileManifest`.
1296
+ */
1297
+ /** File extension of the container. Not `.json`: it is a header plus two blobs. */
1298
+ const PRECOMPILE_CACHE_EXTENSION = ".vpc";
1299
+ const LF = 10;
1300
+ const NEWLINE = Buffer.from("\n");
1301
+ const EMPTY = Buffer.alloc(0);
1302
+ /**
1303
+ * Whether `module` may be persisted.
1304
+ *
1305
+ * Modules assembled from `src` imports depend on sibling files that this cache
1306
+ * does not hash, so they are recompiled on every cold start instead.
1307
+ */
1308
+ function isPersistablePrecompileModule(module) {
1309
+ return !module.dependencies || module.dependencies.length === 0;
1310
+ }
1311
+ function isCompiledModule(value) {
1312
+ if (value === null || typeof value !== "object") return false;
1313
+ const module = value;
1314
+ if (typeof module.code !== "string" || typeof module.scopeId !== "string") return false;
1315
+ if (typeof module.hasScoped !== "boolean") return false;
1316
+ if (module.css !== void 0 && typeof module.css !== "string") return false;
1317
+ if (module.styles !== void 0 && !Array.isArray(module.styles)) return false;
1318
+ if (module.macroArtifacts !== void 0 && !Array.isArray(module.macroArtifacts)) return false;
1319
+ return isPersistablePrecompileModule(module);
1320
+ }
1321
+ /**
1322
+ * `zstd` when this Node has it, `gzip` otherwise.
1323
+ *
1324
+ * The sync zstd bindings arrived in Node 22.15 / 23.8 and this package supports
1325
+ * Node >= 22, so the codec is detected rather than assumed. Both codecs carry
1326
+ * an integrity check of their own -- zstd with `checksumFlag`, gzip with its
1327
+ * trailing CRC32 -- so bit rot inside either body fails decompression instead of
1328
+ * being decoded into a plausible-looking module.
1329
+ */
1330
+ const hasZstd = typeof zlib.zstdCompressSync === "function" && typeof zlib.zstdDecompressSync === "function";
1331
+ const ZSTD_PARAMS = hasZstd ? { params: { [zlib.constants.ZSTD_c_checksumFlag]: 1 } } : void 0;
1332
+ function compressBody(body) {
1333
+ return hasZstd ? zlib.zstdCompressSync(body, ZSTD_PARAMS) : zlib.gzipSync(body, { level: 1 });
1334
+ }
1335
+ /** `null` for an unknown codec, or one this Node cannot read. */
1336
+ function decompressBody(codec, body) {
1337
+ if (codec === "zstd") return hasZstd ? zlib.zstdDecompressSync(body) : null;
1338
+ if (codec === "gzip") return zlib.gunzipSync(body);
1339
+ return null;
1340
+ }
1341
+ /** `<meta JSON>\n<code><css>\n` -- the trailing LF marks the record boundary. */
1342
+ function encodeRecord(module) {
1343
+ const { code, css, ...rest } = module;
1344
+ const codeBytes = Buffer.from(code, "utf8");
1345
+ const cssBytes = css === void 0 ? null : Buffer.from(css, "utf8");
1346
+ const meta = Buffer.from(JSON.stringify([
1347
+ codeBytes.length,
1348
+ cssBytes === null ? -1 : cssBytes.length,
1349
+ rest
1350
+ ]), "utf8");
1351
+ return Buffer.concat([
1352
+ meta,
1353
+ NEWLINE,
1354
+ codeBytes,
1355
+ cssBytes ?? EMPTY,
1356
+ NEWLINE
1357
+ ]);
1358
+ }
1359
+ /** Serialize the container. Never throws for well-typed entries. */
1360
+ function encodePrecompileManifest(options) {
1361
+ const { key, root, entries } = options;
1362
+ const index = [];
1363
+ const records = [];
1364
+ for (const [file, entry] of entries) {
1365
+ const record = encodeRecord(entry.module);
1366
+ index.push([
1367
+ path.relative(root, file),
1368
+ entry.hash,
1369
+ record.length
1370
+ ]);
1371
+ records.push(record);
1372
+ }
1373
+ const indexBody = compressBody(Buffer.from(JSON.stringify(index), "utf8"));
1374
+ const payloadBody = compressBody(Buffer.concat(records));
1375
+ const header = Buffer.from(JSON.stringify({
1376
+ format: 3,
1377
+ key,
1378
+ codec: hasZstd ? "zstd" : "gzip",
1379
+ index: indexBody.length,
1380
+ payload: payloadBody.length
1381
+ }), "utf8");
1382
+ return Buffer.concat([
1383
+ header,
1384
+ NEWLINE,
1385
+ indexBody,
1386
+ payloadBody
1387
+ ]);
1388
+ }
1389
+ function isByteLength(value) {
1390
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
1391
+ }
1392
+ function isIndexRow(value) {
1393
+ return Array.isArray(value) && value.length === 3 && typeof value[0] === "string" && value[0].length > 0 && typeof value[1] === "string" && value[1].length > 0 && isByteLength(value[2]) && value[2] > 0;
1394
+ }
1395
+ /** Rebuild one module from its payload record, or `null` if the record is not one. */
1396
+ function decodeRecord(record) {
1397
+ if (record.at(-1) !== LF) return null;
1398
+ const metaEnd = record.indexOf(LF);
1399
+ if (metaEnd < 0 || metaEnd >= record.length - 1) return null;
1400
+ let meta;
1401
+ try {
1402
+ meta = JSON.parse(record.toString("utf8", 0, metaEnd));
1403
+ } catch {
1404
+ return null;
1405
+ }
1406
+ if (!Array.isArray(meta) || meta.length !== 3) return null;
1407
+ const [codeLength, cssLength, rest] = meta;
1408
+ if (!isByteLength(codeLength) || typeof cssLength !== "number") return null;
1409
+ if (!isByteLength(cssLength) && cssLength !== -1) return null;
1410
+ const cssBytes = cssLength === -1 ? 0 : cssLength;
1411
+ if (metaEnd + 1 + codeLength + cssBytes + 1 !== record.length) return null;
1412
+ if (typeof rest !== "object" || rest === null || Array.isArray(rest)) return null;
1413
+ if ("code" in rest || "css" in rest) return null;
1414
+ const codeStart = metaEnd + 1;
1415
+ const cssStart = codeStart + codeLength;
1416
+ const module = {
1417
+ ...rest,
1418
+ code: record.toString("utf8", codeStart, cssStart)
1419
+ };
1420
+ if (cssLength !== -1) module.css = record.toString("utf8", cssStart, cssStart + cssLength);
1421
+ return isCompiledModule(module) ? module : null;
1422
+ }
1423
+ /**
1424
+ * Parse the container, or return `null`.
1425
+ *
1426
+ * `null` is indistinguishable from having no cache at all, which is exactly the
1427
+ * safe outcome: recompile everything. Every gate below fails that way --
1428
+ * a missing or unparsable header, a foreign `format` or `key`, a codec this Node
1429
+ * cannot read, body lengths that do not account for the file exactly (a
1430
+ * truncated or partially written container), a body that fails its own
1431
+ * decompression checksum, an index that is not the expected shape, and record
1432
+ * lengths that do not sum to the payload. An individual entry whose record does
1433
+ * not decode into a valid `CompiledModule` is dropped on its own, as in format 1;
1434
+ * because offsets come from the index alone, one bad record cannot shift the
1435
+ * others.
1436
+ */
1437
+ function decodePrecompileManifest(bytes, options) {
1438
+ const { key, root, onReject } = options;
1439
+ const reject = (reason) => {
1440
+ onReject?.(reason);
1441
+ return null;
1442
+ };
1443
+ const headerEnd = bytes.indexOf(LF);
1444
+ if (headerEnd < 0) return reject("no header");
1445
+ let header;
1446
+ try {
1447
+ header = JSON.parse(bytes.toString("utf8", 0, headerEnd));
1448
+ } catch {
1449
+ return reject("unparsable header");
1450
+ }
1451
+ if (typeof header !== "object" || header === null || Array.isArray(header)) return reject("unrecognized header");
1452
+ if (header.format !== 3 || header.key !== key) return reject("foreign format or key");
1453
+ if (!isByteLength(header.index) || !isByteLength(header.payload)) return reject("unrecognized body lengths");
1454
+ const indexStart = headerEnd + 1;
1455
+ const payloadStart = indexStart + header.index;
1456
+ if (payloadStart + header.payload !== bytes.length) return reject("truncated container");
1457
+ let bodies;
1458
+ try {
1459
+ const indexText = decompressBody(header.codec, bytes.subarray(indexStart, payloadStart));
1460
+ const payloadText = decompressBody(header.codec, bytes.subarray(payloadStart));
1461
+ bodies = indexText === null || payloadText === null ? null : [indexText, payloadText];
1462
+ } catch {
1463
+ return reject("corrupt body");
1464
+ }
1465
+ if (bodies === null) return reject(`unsupported codec ${JSON.stringify(header.codec)}`);
1466
+ const [indexText, payload] = bodies;
1467
+ let index;
1468
+ try {
1469
+ index = JSON.parse(indexText.toString("utf8"));
1470
+ } catch {
1471
+ return reject("unparsable index");
1472
+ }
1473
+ if (!Array.isArray(index)) return reject("unrecognized index");
1474
+ const entries = /* @__PURE__ */ new Map();
1475
+ let offset = 0;
1476
+ for (const row of index) {
1477
+ if (!isIndexRow(row)) return reject("unrecognized index row");
1478
+ const [relative, hash, length] = row;
1479
+ const end = offset + length;
1480
+ if (end > payload.length) return reject("index overruns payload");
1481
+ const module = decodeRecord(payload.subarray(offset, end));
1482
+ offset = end;
1483
+ if (module !== null) entries.set(path.resolve(root, relative), {
1484
+ hash,
1485
+ module
1486
+ });
1487
+ }
1488
+ if (offset !== payload.length) return reject("payload not fully described by the index");
1489
+ return entries;
1490
+ }
1491
+ //#endregion
1492
+ //#region src/plugin/precompile-cache.ts
1493
+ /**
1494
+ * Persistent (on-disk) pre-compile cache.
1495
+ *
1496
+ * `state.precompileMetadata` plus `state.cache` already skip recompilation
1497
+ * inside one process, but both are empty on every process start, so `vite
1498
+ * build`, CI, and each dev-server start recompile the whole scan from scratch.
1499
+ * This module backs them with a manifest under
1500
+ * `node_modules/.vize/vite-precompile/` so a cold process can restore the
1501
+ * previous run's output.
1502
+ *
1503
+ * The two invalidation gates -- manifest identity and per-entry source hash --
1504
+ * live in `./precompile-cache-key.ts`, which documents why each one is safe.
1505
+ * Two more gates live in `./precompile-cache-store.ts`, which owns the on-disk
1506
+ * container:
1507
+ *
1508
+ * - **Shape.** Entries are validated before use and dropped individually if
1509
+ * they do not describe a complete `CompiledModule`. The container's own
1510
+ * `format`/`key` are re-checked after parsing, so a manifest reached by any
1511
+ * route other than its key still gets rejected.
1512
+ * - **`src` imports.** SFCs that pull blocks in through `<script src>` /
1513
+ * `<template src>` / `<style src>` are never persisted: their output depends
1514
+ * on files whose content this cache does not hash.
1515
+ *
1516
+ * A missing, truncated, or corrupt manifest degrades to a full recompile: every
1517
+ * read is guarded and any failure yields an empty cache. Writes go through a
1518
+ * sibling temp file and a rename, so an interrupted write cannot be read back.
1519
+ *
1520
+ * Set `VIZE_PRECOMPILE_CACHE=0` to force a full recompile without editing any
1521
+ * config.
1522
+ */
1523
+ /** Manifest location, relative to the Vite root. */
1524
+ const PRECOMPILE_CACHE_DIR = path.join("node_modules", ".vize", "vite-precompile");
1525
+ /** Set to `0`/`false` to force a full recompile without editing the config. */
1526
+ const PRECOMPILE_CACHE_ENV = "VIZE_PRECOMPILE_CACHE";
1527
+ /** Whether the environment forces the cache off. */
1528
+ function isPrecompileCacheDisabledByEnv(env = process.env) {
1529
+ const value = env[PRECOMPILE_CACHE_ENV];
1530
+ return value === "0" || value === "false";
1531
+ }
1532
+ const disabledCache = {
1533
+ file: null,
1534
+ get: () => void 0,
1535
+ set: () => {},
1536
+ delete: () => {},
1537
+ retain: () => {},
1538
+ flush: () => false
1539
+ };
1540
+ /** A cache that never hits and never writes. */
1541
+ function createDisabledPrecompileCache() {
1542
+ return disabledCache;
1543
+ }
1544
+ function openPrecompileCache(options) {
1545
+ const { root, compileOptions, onDiagnostic, env = process.env } = options;
1546
+ if (!root || isPrecompileCacheDisabledByEnv(env)) return createDisabledPrecompileCache();
1547
+ const key = computePrecompileCacheKey(compileOptions);
1548
+ const file = path.join(root, PRECOMPILE_CACHE_DIR, `${key}${PRECOMPILE_CACHE_EXTENSION}`);
1549
+ const entries = readManifestEntries(file, key, root, onDiagnostic);
1550
+ let dirty = false;
1551
+ return {
1552
+ file,
1553
+ get(filePath, sourceHash) {
1554
+ const entry = entries.get(filePath);
1555
+ return entry && entry.hash === sourceHash ? entry.module : void 0;
1556
+ },
1557
+ set(filePath, sourceHash, module) {
1558
+ if (!isPersistablePrecompileModule(module)) {
1559
+ if (entries.delete(filePath)) dirty = true;
1560
+ return;
1561
+ }
1562
+ const existing = entries.get(filePath);
1563
+ if (existing?.hash === sourceHash && existing.module === module) return;
1564
+ entries.set(filePath, {
1565
+ hash: sourceHash,
1566
+ module
1567
+ });
1568
+ dirty = true;
1569
+ },
1570
+ delete(filePath) {
1571
+ if (entries.delete(filePath)) dirty = true;
1572
+ },
1573
+ retain(files) {
1574
+ const keep = files instanceof Set ? files : new Set(files);
1575
+ for (const filePath of entries.keys()) if (!keep.has(filePath)) {
1576
+ entries.delete(filePath);
1577
+ dirty = true;
1578
+ }
1579
+ },
1580
+ flush() {
1581
+ if (!dirty) return false;
1582
+ let container;
1583
+ try {
1584
+ container = encodePrecompileManifest({
1585
+ key,
1586
+ root,
1587
+ entries
1588
+ });
1589
+ } catch (error) {
1590
+ onDiagnostic?.(`Failed to encode pre-compile cache ${file}:`, error);
1591
+ return false;
1592
+ }
1593
+ if (!writeManifest(file, container, onDiagnostic)) return false;
1594
+ removeFormat1Manifests(path.dirname(file));
1595
+ dirty = false;
1596
+ return true;
1597
+ }
1598
+ };
1599
+ }
1600
+ /**
1601
+ * Drop the `.json` manifests format 1 left behind.
1602
+ *
1603
+ * Nothing can read them any more, and they are the reason this change exists:
1604
+ * ~9 KB per SFC, so ~27 MB for a 3000-SFC project sitting in `node_modules`
1605
+ * forever after an upgrade. Only `.json` is removed, which is exactly the set
1606
+ * format 1 wrote; every live manifest is a `.vpc`, and a project legitimately
1607
+ * keeps one per compile-option set. Best effort -- a failure here is not worth
1608
+ * a diagnostic, let alone a failed build.
1609
+ */
1610
+ function removeFormat1Manifests(dir) {
1611
+ try {
1612
+ for (const name of fs.readdirSync(dir)) if (name.endsWith(".json")) fs.rmSync(path.join(dir, name), { force: true });
1613
+ } catch {}
1614
+ }
1615
+ /**
1616
+ * Read the container, or return an empty map.
1617
+ *
1618
+ * A missing, truncated, corrupt, or foreign manifest is indistinguishable from
1619
+ * no cache at all, which is exactly the safe outcome: recompile everything.
1620
+ */
1621
+ function readManifestEntries(file, key, root, onDiagnostic) {
1622
+ let bytes;
1623
+ try {
1624
+ bytes = fs.readFileSync(file);
1625
+ } catch {
1626
+ return /* @__PURE__ */ new Map();
1627
+ }
1628
+ return decodePrecompileManifest(bytes, {
1629
+ key,
1630
+ root,
1631
+ onReject: (reason) => onDiagnostic?.(`Ignoring pre-compile cache ${file}: ${reason}`)
1632
+ }) ?? /* @__PURE__ */ new Map();
1633
+ }
1634
+ /** Write through a sibling temp file so a crash cannot leave a partial manifest. */
1635
+ function writeManifest(file, container, onDiagnostic) {
1636
+ const temp = `${file}.${process.pid}.${crypto.randomBytes(4).toString("hex")}.tmp`;
1637
+ try {
1638
+ fs.mkdirSync(path.dirname(file), { recursive: true });
1639
+ fs.writeFileSync(temp, container);
1640
+ fs.renameSync(temp, file);
1641
+ return true;
1642
+ } catch (error) {
1643
+ try {
1644
+ fs.rmSync(temp, { force: true });
1645
+ } catch {}
1646
+ onDiagnostic?.(`Failed to write pre-compile cache ${file}:`, error);
1647
+ return false;
1648
+ }
1649
+ }
1650
+ //#endregion
1651
+ //#region src/plugin/precompile-run.ts
1652
+ /**
1653
+ * The pre-compilation pass.
1654
+ *
1655
+ * Scans the configured patterns, diffs them against the previous in-process
1656
+ * run, restores whatever the persistent cache can prove is still valid, and
1657
+ * batch-compiles the rest. Extracted from `state.ts` so the state module stays
1658
+ * a state module.
1659
+ */
1660
+ /**
1661
+ * The options the pre-compile batch actually compiles with.
1662
+ *
1663
+ * Also the input to the cache key, so the two can never drift: a new option
1664
+ * that reaches the native compiler reaches the key with it.
1665
+ */
1666
+ function resolvePrecompileBatchOptions(state) {
1667
+ const requestOptions = getCompileOptionsForRequest(state, false);
1668
+ return {
1669
+ sourceMap: requestOptions.sourceMap,
1670
+ ssr: false,
1671
+ vapor: state.mergedOptions.vapor ?? false,
1672
+ mode: state.mergedOptions.mode,
1673
+ customRenderer: state.mergedOptions.customRenderer ?? false,
1674
+ customElements: state.mergedOptions.customElements,
1675
+ templateSyntax: state.mergedOptions.templateSyntax ?? "standard",
1676
+ experimentalInTagComments: state.mergedOptions.experimentalInTagComments ?? false,
1677
+ experimentalPatternedTemplate: state.mergedOptions.experimentalPatternedTemplate ?? false,
1678
+ experimentalSelfComponent: state.mergedOptions.experimentalSelfComponent ?? false,
1679
+ experimentalStrictSlotChildren: state.mergedOptions.experimentalStrictSlotChildren ?? false,
1680
+ experimentalServerScript: state.mergedOptions.experimentalServerScript ?? false,
1681
+ runtimeModuleName: state.mergedOptions.runtimeModuleName,
1682
+ runtimeGlobalName: state.mergedOptions.runtimeGlobalName,
1683
+ vueVersion: state.mergedOptions.vueVersion,
1684
+ styleTrim: requestOptions.styleTrim,
1685
+ templateCacheHandlers: requestOptions.templateCacheHandlers,
1686
+ templateComments: requestOptions.templateComments,
1687
+ templateHoistStatic: requestOptions.templateHoistStatic,
1688
+ templatePrefixIdentifiers: requestOptions.templatePrefixIdentifiers
1689
+ };
1690
+ }
1691
+ function openCacheForRun(state, batchOptions) {
1692
+ if (!state.root) return createDisabledPrecompileCache();
1693
+ return openPrecompileCache({
1694
+ root: state.root,
1695
+ compileOptions: buildCompileBatchOptions(batchOptions),
1696
+ onDiagnostic: (message, error) => error === void 0 ? state.logger.warn(message) : state.logger.warn(message, error)
1697
+ });
1698
+ }
1699
+ /**
1700
+ * Pre-compile all Vue files matching scan patterns.
1701
+ */
1702
+ async function compileAll(state) {
1703
+ const startTime = performance.now();
1704
+ const sfcFiles = (await glob(state.scanPatterns, {
1705
+ cwd: state.root,
1706
+ ignore: state.ignorePatterns,
1707
+ absolute: true,
1708
+ followSymbolicLinks: false
1709
+ })).filter(isPrecompileSfcPath);
1710
+ const currentMetadata = /* @__PURE__ */ new Map();
1711
+ for (const file of sfcFiles) try {
1712
+ const stat = fs.statSync(file);
1713
+ currentMetadata.set(file, {
1714
+ mtimeMs: stat.mtimeMs,
1715
+ size: stat.size
1716
+ });
1717
+ } catch (e) {
1718
+ state.logger.error(`Failed to stat ${file}:`, e);
1719
+ }
1720
+ const { changedFiles, deletedFiles } = diffPrecompileFiles(sfcFiles, currentMetadata, state.precompileMetadata);
1721
+ const cachedFileCount = sfcFiles.length - changedFiles.length;
1722
+ for (const file of deletedFiles) {
1723
+ state.cache.delete(file);
1724
+ state.ssrCache.delete(file);
1725
+ if (state.extractCss) state.collectedCss.delete(file);
1726
+ state.precompileMetadata.delete(file);
1727
+ state.pendingHmrUpdateTypes.delete(file);
1728
+ }
1729
+ state.logger.info(`Pre-compiling ${sfcFiles.length} Vue files... (${changedFiles.length} changed, ${cachedFileCount} cached, ${deletedFiles.length} removed)`);
1730
+ if (changedFiles.length === 0) {
1731
+ const elapsed = (performance.now() - startTime).toFixed(2);
1732
+ state.logger.info(`Pre-compilation complete: cache reused (${elapsed}ms)`);
1733
+ return;
1734
+ }
1735
+ for (const file of changedFiles) {
1736
+ if (state.extractCss) state.collectedCss.delete(file);
1737
+ state.pendingHmrUpdateTypes.delete(file);
1738
+ }
1739
+ const batchOptions = resolvePrecompileBatchOptions(state);
1740
+ const cache = openCacheForRun(state, batchOptions);
1741
+ const cacheEnabled = cache.file !== null;
1742
+ let successCount = 0;
1743
+ let restoredCount = 0;
1744
+ let failedCount = 0;
1745
+ let nativeTimeMs = 0;
1746
+ const precompileFailures = [];
1747
+ const chunks = chunkPrecompileFiles(changedFiles, state.precompileBatchSize, { metadata: currentMetadata });
1748
+ for (const chunk of chunks) {
1749
+ const fileContents = [];
1750
+ const sourceHashes = /* @__PURE__ */ new Map();
1751
+ for (const file of chunk) {
1752
+ let source;
1753
+ try {
1754
+ source = fs.readFileSync(file, "utf-8");
1755
+ } catch (e) {
1756
+ failedCount++;
1757
+ state.cache.delete(file);
1758
+ if (state.extractCss) state.collectedCss.delete(file);
1759
+ state.precompileMetadata.delete(file);
1760
+ cache.delete(file);
1761
+ precompileFailures.push(`[vize] Failed to read ${file}: ${formatUnknownError$2(e)}`);
1762
+ state.logger.error(`Failed to read ${file}:`, e);
1763
+ continue;
1764
+ }
1765
+ const sourceHash = cacheEnabled ? hashPrecompileSource(source) : void 0;
1766
+ const restored = sourceHash === void 0 ? void 0 : cache.get(file, sourceHash);
1767
+ if (restored) {
1768
+ state.cache.set(file, restored);
1769
+ const metadata = currentMetadata.get(file);
1770
+ if (metadata) state.precompileMetadata.set(file, metadata);
1771
+ syncCollectedCssForFile({
1772
+ ...state,
1773
+ extractCss: state.extractCss && !isPluginVueCustomElement(state.mergedOptions, file)
1774
+ }, file, restored);
1775
+ restoredCount++;
1776
+ continue;
1777
+ }
1778
+ if (sourceHash !== void 0) sourceHashes.set(file, sourceHash);
1779
+ fileContents.push({
1780
+ path: file,
1781
+ source
1782
+ });
1783
+ }
1784
+ if (fileContents.length === 0) continue;
1785
+ const result = compileBatch(fileContents, state.cache, batchOptions);
1786
+ const chunkFailedCount = result.results.filter((fileResult) => fileResult.errors.length > 0).length;
1787
+ failedCount += chunkFailedCount;
1788
+ successCount += result.results.length - chunkFailedCount;
1789
+ nativeTimeMs += result.timeMs;
1790
+ for (const fileResult of result.results) {
1791
+ const metadata = currentMetadata.get(fileResult.path);
1792
+ if (fileResult.errors.length > 0) {
1793
+ state.cache.delete(fileResult.path);
1794
+ if (state.extractCss) state.collectedCss.delete(fileResult.path);
1795
+ state.precompileMetadata.delete(fileResult.path);
1796
+ cache.delete(fileResult.path);
1797
+ precompileFailures.push(formatCompileErrorMessage(fileResult.path, fileResult.errors));
1798
+ continue;
1799
+ }
1800
+ if (metadata) state.precompileMetadata.set(fileResult.path, metadata);
1801
+ const compiled = state.cache.get(fileResult.path);
1802
+ const sourceHash = sourceHashes.get(fileResult.path);
1803
+ if (compiled && sourceHash !== void 0) cache.set(fileResult.path, sourceHash, compiled);
1804
+ syncCollectedCssForFile({
1805
+ ...state,
1806
+ extractCss: state.extractCss && !isPluginVueCustomElement(state.mergedOptions, fileResult.path)
1807
+ }, fileResult.path, compiled);
1808
+ }
1809
+ }
1810
+ cache.retain(new Set(sfcFiles));
1811
+ cache.flush();
1812
+ const elapsed = (performance.now() - startTime).toFixed(2);
1813
+ const batchLabel = chunks.length === 1 ? "batch" : "batches";
1814
+ state.logger.info(`Pre-compilation complete: ${successCount} recompiled, ${restoredCount} restored from disk, ${cachedFileCount} reused, ${failedCount} failed (${elapsed}ms, native ${batchLabel}: ${nativeTimeMs.toFixed(2)}ms)`);
1815
+ if (failedCount > 0) {
1816
+ const details = precompileFailures.length > 0 ? `\n\n${precompileFailures.join("\n\n")}` : "";
1817
+ throw new Error(`[vize] Pre-compilation failed for ${failedCount} file(s).${details}`);
1818
+ }
1819
+ }
1820
+ function formatUnknownError$2(error) {
1821
+ return error instanceof Error ? error.message : String(error);
1822
+ }
1823
+ //#endregion
1824
+ //#region src/plugin/importer.ts
1825
+ function isInsidePath(parent, child) {
1826
+ const relative = path.relative(parent, child);
1827
+ return relative === "" || !!relative && !relative.startsWith("..") && !path.isAbsolute(relative);
1828
+ }
1829
+ function normalizeNuxtVirtualImporterPath(importer) {
1830
+ const { request } = splitViteIdQuery(importer);
1831
+ for (const prefix of ["/@id/virtual:nuxt:", "virtual:nuxt:"]) {
1832
+ if (!request.startsWith(prefix)) continue;
1833
+ const encodedPath = request.slice(prefix.length);
1834
+ try {
1835
+ return decodeURIComponent(encodedPath);
1836
+ } catch {
1837
+ return encodedPath;
1838
+ }
1839
+ }
1840
+ return null;
1841
+ }
1842
+ function normalizeImporterFilePath(importer) {
1843
+ const nuxtVirtualPath = normalizeNuxtVirtualImporterPath(importer);
1844
+ if (nuxtVirtualPath) return nuxtVirtualPath;
1845
+ const request = classifyVitePluginRequest(importer);
1846
+ return request.normalizedFsId ?? request.strippedVirtualPath ?? request.vizeVirtualPath ?? request.normalizedVuePath ?? splitViteIdQuery(importer).request;
1847
+ }
1848
+ function isProjectSourceImporter(root, importer) {
1849
+ if (!importer) return false;
1850
+ const importerPath = normalizeImporterFilePath(importer);
1851
+ if (!path.isAbsolute(importerPath)) return false;
1852
+ if (importerPath.split(path.sep).join("/").includes("/node_modules/")) return false;
1853
+ if (isInsidePath(root, importerPath)) return true;
1854
+ try {
1855
+ return isInsidePath(fs.realpathSync(root), fs.realpathSync(importerPath));
1856
+ } catch {
1857
+ return false;
1858
+ }
1859
+ }
1860
+ //#endregion
1861
+ //#region src/plugin/package-imports.ts
1862
+ const PACKAGE_IMPORT_CONDITIONS = [
1863
+ "browser",
1864
+ "import",
1865
+ "module",
1866
+ "default",
1867
+ "node",
1868
+ "require",
1869
+ "types"
1870
+ ];
1871
+ function resolvePackageJsonImportFromVizeImporter(state, id, importer) {
1872
+ const { request, querySuffix } = splitViteIdQuery(id);
1873
+ if (!request.startsWith("#")) return null;
1874
+ const seen = /* @__PURE__ */ new Set();
1875
+ for (const base of createViteBareImportBases(state.root, importer)) {
1876
+ const packageRoot = findPackageScope(base);
1877
+ if (!packageRoot || seen.has(packageRoot)) continue;
1878
+ seen.add(packageRoot);
1879
+ const direct = tryRequireResolve(path.join(packageRoot, "package.json"), request, querySuffix);
1880
+ if (direct) return direct;
1881
+ const imports = readPackageImports(packageRoot);
1882
+ const target = imports ? resolvePackageImportTarget(imports, request) : null;
1883
+ const resolved = target ? resolvePackageImportTargetPath(packageRoot, target, importer, querySuffix) : null;
1884
+ if (resolved) return resolved;
1885
+ }
1886
+ return null;
1887
+ }
1888
+ function findPackageScope(base) {
1889
+ let current = fs.existsSync(base) && fs.statSync(base).isDirectory() ? base : path.dirname(base);
1890
+ while (current !== path.dirname(current)) {
1891
+ if (fs.existsSync(path.join(current, "package.json"))) return current;
1892
+ current = path.dirname(current);
1893
+ }
1894
+ return null;
1895
+ }
1896
+ function tryRequireResolve(base, request, querySuffix) {
1897
+ try {
1898
+ return `${createRequire(base).resolve(request)}${querySuffix}`;
1899
+ } catch {
1900
+ return null;
1901
+ }
1902
+ }
1903
+ function readPackageImports(packageRoot) {
1904
+ try {
1905
+ const json = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf8"));
1906
+ return isPlainObject(json.imports) ? json.imports : null;
1907
+ } catch {
1908
+ return null;
1909
+ }
1910
+ }
1911
+ function resolvePackageImportTarget(imports, request) {
1912
+ const exact = resolveConditionalTarget(imports[request]);
1913
+ if (exact) return exact;
1914
+ let best = null;
1915
+ for (const [key, value] of Object.entries(imports)) {
1916
+ const starIndex = key.indexOf("*");
1917
+ if (starIndex === -1) continue;
1918
+ const prefix = key.slice(0, starIndex);
1919
+ const suffix = key.slice(starIndex + 1);
1920
+ if (!request.startsWith(prefix) || !request.endsWith(suffix)) continue;
1921
+ const target = resolveConditionalTarget(value);
1922
+ if (!target || best && key.length <= best.keyLength) continue;
1923
+ const matched = request.slice(prefix.length, request.length - suffix.length);
1924
+ best = {
1925
+ keyLength: key.length,
1926
+ target: target.replaceAll("*", matched)
1927
+ };
1928
+ }
1929
+ return best?.target ?? null;
1930
+ }
1931
+ function resolveConditionalTarget(value) {
1932
+ if (typeof value === "string") return value;
1933
+ if (Array.isArray(value)) {
1934
+ for (const item of value) {
1935
+ const target = resolveConditionalTarget(item);
1936
+ if (target) return target;
1937
+ }
1938
+ return null;
1939
+ }
1940
+ if (!isPlainObject(value)) return null;
1941
+ for (const condition of PACKAGE_IMPORT_CONDITIONS) {
1942
+ const target = resolveConditionalTarget(value[condition]);
1943
+ if (target) return target;
1944
+ }
1945
+ return null;
1946
+ }
1947
+ function resolvePackageImportTargetPath(packageRoot, target, importer, querySuffix) {
1948
+ const { request } = splitViteIdQuery(target);
1949
+ if (request.startsWith("./")) {
1950
+ const resolved = resolveViteRelativeImport(request, path.join(packageRoot, "package.json"));
1951
+ return resolved && isInsidePackage(packageRoot, resolved) ? `${resolved}${querySuffix}` : null;
1952
+ }
1953
+ if (request.startsWith("../")) return null;
1954
+ if (path.isAbsolute(request)) return fs.existsSync(request) ? `${request}${querySuffix}` : null;
1955
+ return tryRequireResolve(importer, request, querySuffix);
1956
+ }
1957
+ function isPlainObject(value) {
1958
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1959
+ }
1960
+ function isInsidePackage(packageRoot, resolved) {
1961
+ const relative = path.relative(packageRoot, splitViteIdQuery(resolved).request);
1962
+ return relative === "" || !!relative && !relative.startsWith("..") && !path.isAbsolute(relative);
1963
+ }
1964
+ //#endregion
1965
+ //#region src/plugin/resolve-relative-vue.ts
1966
+ function cleanVueSfcImporter(importer, request) {
1967
+ let cleanImporter = request?.normalizedFsId ?? request?.normalizedVuePath ?? importer;
1968
+ if (cleanImporter.startsWith("/@id/__x00__")) cleanImporter = cleanImporter.slice(12);
1969
+ else if (cleanImporter.startsWith("__x00__")) cleanImporter = cleanImporter.slice(7);
1970
+ return classifyVitePluginRequest(cleanImporter).normalizedVuePath;
1971
+ }
1972
+ async function resolveRelativeVueSfcImport(ctx, state, id, cleanImporter, isSsrRequest, isDependencyScan, resolveWithVite) {
1973
+ if (!id.startsWith("./") && !id.startsWith("../")) return null;
1974
+ const { request, querySuffix } = splitViteIdQuery(id);
1975
+ if (!request.endsWith(".vue")) return null;
1976
+ const resolved = await resolveWithVite(ctx, state, id, cleanImporter, { skipSelf: true });
1977
+ if (!resolved) return null;
1978
+ const resolvedRequest = classifyVitePluginRequest(resolved.id);
1979
+ const resolvedPath = resolvedRequest.normalizedFsId ?? resolvedRequest.normalizedVuePath;
1980
+ if (!resolvedPath || !resolvedPath.endsWith(".vue")) return resolved;
1981
+ const effectiveQuery = resolvedRequest.querySuffix || querySuffix;
1982
+ return isDependencyScan ? toVirtualId(resolvedPath, isSsrRequest) : toPluginVisibleVirtualId(resolvedPath, isSsrRequest, effectiveQuery);
1983
+ }
1984
+ //#endregion
1985
+ //#region src/plugin/resolve.ts
1986
+ function resolveVuePath(state, id, importer) {
1987
+ return resolveViteVuePath(state.root, id, importer);
1988
+ }
1989
+ const EMPTY_NATIVE_ALIAS_RULES = [];
1990
+ const VUE_PEER_RUNTIME_PACKAGES = new Set(["vue-router"]);
1991
+ const VUE_PEER_RUNTIME_ESM_ENTRIES = new Map([["vue-router", [
1992
+ "dist/vue-router.mjs",
1993
+ "dist/vue-router.js",
1994
+ "index.mjs",
1995
+ "index.js"
1996
+ ]]]);
1997
+ function getViteResolveCache(state) {
1998
+ return state.viteResolveCache ??= /* @__PURE__ */ new Map();
1999
+ }
2000
+ function createViteResolveCacheKey(id, importer, options, environmentName) {
2001
+ return JSON.stringify([
2002
+ environmentName ?? null,
2003
+ id,
2004
+ importer ?? null,
2005
+ options?.skipSelf ?? false
2006
+ ]);
2007
+ }
2008
+ function resolveWithVite(ctx, state, id, importer, options) {
2009
+ if (state.server !== null) return ctx.resolve(id, importer, options);
2010
+ const cache = getViteResolveCache(state);
2011
+ const key = createViteResolveCacheKey(id, importer, options, ctx.environment?.name);
2012
+ const cached = cache.get(key);
2013
+ if (cached) return cached;
2014
+ const pending = ctx.resolve(id, importer, options).catch((error) => {
2015
+ cache.delete(key);
2016
+ throw error;
2017
+ });
2018
+ cache.set(key, pending);
2019
+ return pending;
2020
+ }
2021
+ function resolveAliasRequest(state, id) {
2022
+ return resolveViteAliasRequest(id, nativeCssAliasRules(state));
2023
+ }
2024
+ function getBarePackageName(id) {
2025
+ if (!isViteBareSpecifier(id)) return null;
2026
+ const segments = id.split("/");
2027
+ if (id.startsWith("@")) return segments.length >= 2 ? `${segments[0]}/${segments[1]}` : null;
2028
+ return segments[0] || null;
2029
+ }
2030
+ function resolveBareImportFromPnpmHoist(request, base) {
2031
+ const packageName = getBarePackageName(request);
2032
+ if (!packageName) return null;
2033
+ let current = path.dirname(base);
2034
+ while (current !== path.dirname(current)) {
2035
+ const directPackage = path.join(current, "node_modules", packageName);
2036
+ if (fs.existsSync(directPackage)) return null;
2037
+ const hoistRoot = path.join(current, "node_modules", ".pnpm", "node_modules");
2038
+ const hoistedPackage = path.join(hoistRoot, packageName);
2039
+ if (fs.existsSync(hoistedPackage)) try {
2040
+ return createRequire(path.join(hoistRoot, "__vize_probe__.js")).resolve(request);
2041
+ } catch {}
2042
+ current = path.dirname(current);
2043
+ }
2044
+ return null;
2045
+ }
2046
+ function resolveBareImportWithNode(state, id, importer) {
2047
+ const { request, querySuffix } = splitViteIdQuery(id);
2048
+ for (const candidate of createViteBareImportBases(state.root, importer)) {
2049
+ const hoisted = resolveBareImportFromPnpmHoist(request, candidate);
2050
+ if (hoisted) return `${hoisted}${querySuffix}`;
2051
+ try {
2052
+ return `${createRequire(candidate).resolve(request)}${querySuffix}`;
2053
+ } catch {}
2054
+ }
2055
+ return null;
2056
+ }
2057
+ function resolveBareImportFromPnpmHoistWithNode(state, id, importer) {
2058
+ const { request, querySuffix } = splitViteIdQuery(id);
2059
+ for (const candidate of createViteBareImportBases(state.root, importer)) {
2060
+ const hoisted = resolveBareImportFromPnpmHoist(request, candidate);
2061
+ if (hoisted) return `${hoisted}${querySuffix}`;
2062
+ }
2063
+ return null;
2064
+ }
2065
+ function resolveBareImportCandidatesWithNode(state, id, importer, resolvedId) {
2066
+ for (const candidate of createViteBareImportCandidates(id, nativeCssAliasRules(state), resolvedId)) {
2067
+ const resolved = resolveBareImportWithNode(state, candidate, importer);
2068
+ if (resolved) return resolved;
2069
+ }
2070
+ return null;
2071
+ }
2072
+ function findPackageRoot(resolvedFile) {
2073
+ let current = path.dirname(resolvedFile);
2074
+ while (current !== path.dirname(current)) {
2075
+ if (fs.existsSync(path.join(current, "package.json"))) return current;
2076
+ current = path.dirname(current);
2077
+ }
2078
+ return null;
2079
+ }
2080
+ function resolvePackageRootWithNode(state, packageName, importer) {
2081
+ const packageJson = resolveBareImportWithNode(state, `${packageName}/package.json`, importer);
2082
+ if (packageJson) return path.dirname(packageJson);
2083
+ const resolvedEntry = resolveBareImportWithNode(state, packageName, importer);
2084
+ return resolvedEntry ? findPackageRoot(resolvedEntry) : null;
2085
+ }
2086
+ function resolveVueBundlerEntryWithNode(state, id, importer) {
2087
+ const { request, querySuffix } = splitViteIdQuery(id);
2088
+ let relativeEntries;
2089
+ if (request === "vue") relativeEntries = [
2090
+ "dist/vue.runtime.esm-bundler.js",
2091
+ "dist/vue.esm-bundler.js",
2092
+ "index.mjs"
2093
+ ];
2094
+ else if (request.startsWith("vue/dist/") && request.endsWith(".js")) relativeEntries = [request.slice(4)];
2095
+ else return null;
2096
+ const packageRoot = resolvePackageRootWithNode(state, "vue", importer);
2097
+ if (!packageRoot) return null;
2098
+ for (const relativeEntry of relativeEntries) {
2099
+ const entry = path.join(packageRoot, relativeEntry);
2100
+ if (fs.existsSync(entry)) return `${entry}${querySuffix}`;
2101
+ }
2102
+ return null;
2103
+ }
2104
+ function resolveVueBundlerEntryFromPnpmHoist(state, id, importer) {
2105
+ const { request, querySuffix } = splitViteIdQuery(id);
2106
+ let relativeEntries;
2107
+ if (request === "vue") relativeEntries = [
2108
+ "dist/vue.runtime.esm-bundler.js",
2109
+ "dist/vue.esm-bundler.js",
2110
+ "index.mjs"
2111
+ ];
2112
+ else if (request.startsWith("vue/dist/") && request.endsWith(".js")) relativeEntries = [request.slice(4)];
2113
+ else return null;
2114
+ const packageJson = resolveBareImportFromPnpmHoistWithNode(state, "vue/package.json", importer);
2115
+ if (!packageJson) return null;
2116
+ const packageRoot = path.dirname(splitViteIdQuery(packageJson).request);
2117
+ for (const relativeEntry of relativeEntries) {
2118
+ const entry = path.join(packageRoot, relativeEntry);
2119
+ if (fs.existsSync(entry)) return `${entry}${querySuffix}`;
2120
+ }
2121
+ return null;
2122
+ }
2123
+ function isVueRuntimeRequest(id) {
2124
+ const request = splitViteIdQuery(id).request;
2125
+ return request === "vue" || request.startsWith("vue/dist/") && request.endsWith(".js");
2126
+ }
2127
+ function isVuePeerRuntimeRequest(id) {
2128
+ const request = splitViteIdQuery(id).request;
2129
+ const packageName = getBarePackageName(request);
2130
+ return packageName ? VUE_PEER_RUNTIME_PACKAGES.has(packageName) : false;
2131
+ }
2132
+ function isProjectVueRuntimeRequest(id) {
2133
+ return isVueRuntimeRequest(id) || isVuePeerRuntimeRequest(id);
2134
+ }
2135
+ function isVueServerRendererRequest(request) {
2136
+ return request === "@vue/server-renderer" || request === "vue/server-renderer" || request.startsWith("vue/dist/") && request.endsWith("/server-renderer");
2137
+ }
2138
+ function resolveVueServerRendererPackageRootWithNode(state, importer) {
2139
+ const packageRoot = resolvePackageRootWithNode(state, "@vue/server-renderer", importer);
2140
+ if (packageRoot) return packageRoot;
2141
+ const vuePackageRoot = resolvePackageRootWithNode(state, "vue", importer);
2142
+ return vuePackageRoot ? resolvePackageRootWithNode(state, "@vue/server-renderer", path.join(vuePackageRoot, "package.json")) : null;
2143
+ }
2144
+ function resolveVueServerRendererBundlerEntryWithNode(state, id, importer) {
2145
+ const { request, querySuffix } = splitViteIdQuery(id);
2146
+ if (querySuffix || !isVueServerRendererRequest(request)) return null;
2147
+ const packageRoot = resolveVueServerRendererPackageRootWithNode(state, importer);
2148
+ if (!packageRoot) return null;
2149
+ for (const relativeEntry of [
2150
+ "dist/server-renderer.esm-bundler.js",
2151
+ "index.mjs",
2152
+ "index.js"
2153
+ ]) {
2154
+ const entry = path.join(packageRoot, relativeEntry);
2155
+ if (fs.existsSync(entry)) return entry;
2156
+ }
2157
+ return null;
2158
+ }
2159
+ function resolveSsrExternalVueRequest(id) {
2160
+ const { request, querySuffix } = splitViteIdQuery(id);
2161
+ if (querySuffix) return null;
2162
+ if (isVueServerRendererRequest(request)) return "vue/server-renderer";
2163
+ if (request === "vue" || request.startsWith("vue/dist/")) return "vue";
2164
+ if (request.startsWith("@vue/")) return request;
2165
+ return null;
2166
+ }
2167
+ function isVuePackageEntry(id) {
2168
+ const { request } = splitViteIdQuery(id);
2169
+ const normalized = request.split(path.sep).join("/");
2170
+ return normalized.endsWith("/node_modules/vue/index.js") || normalized.endsWith("/node_modules/vue/dist/vue.runtime.esm-bundler.js") || normalized.endsWith("/node_modules/vue/dist/vue.esm-bundler.js") || normalized.includes("/node_modules/.pnpm/vue@") || normalized.includes("/node_modules/.pnpm/@vue+");
2171
+ }
2172
+ function isProjectLocalImporter(state, importer) {
2173
+ if (!importer) return false;
2174
+ const importerPath = normalizeImporterFilePath(importer);
2175
+ if (!path.isAbsolute(importerPath)) return false;
2176
+ if (isInsidePath(state.root, importerPath)) return true;
2177
+ try {
2178
+ return isInsidePath(fs.realpathSync(state.root), fs.realpathSync(importerPath));
2179
+ } catch {
2180
+ return false;
2181
+ }
2182
+ }
2183
+ function resolveProjectLocalPnpmVueRuntime(state, resolvedId) {
2184
+ const normalizedResolvedId = normalizeResolvedVuePath(resolvedId) ?? resolvedId;
2185
+ if (!isVuePackageEntry(normalizedResolvedId)) return null;
2186
+ const { request, querySuffix } = splitViteIdQuery(normalizedResolvedId);
2187
+ if (!request.split(path.sep).join("/").includes("/node_modules/.pnpm/")) return null;
2188
+ let realPath = request;
2189
+ try {
2190
+ realPath = fs.realpathSync(request);
2191
+ } catch {}
2192
+ return isInsidePath(state.root, realPath) ? `${realPath}${querySuffix}` : null;
2193
+ }
2194
+ function resolveProjectLocalResolvedPath(state, resolvedId) {
2195
+ const { request, querySuffix } = splitViteIdQuery(resolvedId);
2196
+ if (!path.isAbsolute(request)) return null;
2197
+ let realPath = request;
2198
+ try {
2199
+ realPath = fs.realpathSync(request);
2200
+ } catch {}
2201
+ return isInsidePath(state.root, realPath) ? `${realPath}${querySuffix}` : null;
2202
+ }
2203
+ function resolveVuePeerRuntimeEntryWithNode(state, id, importer) {
2204
+ const { request, querySuffix } = splitViteIdQuery(id);
2205
+ const packageName = getBarePackageName(request);
2206
+ if (!packageName || !VUE_PEER_RUNTIME_PACKAGES.has(packageName)) return null;
2207
+ const packageRoot = resolvePackageRootWithNode(state, packageName, importer);
2208
+ if (!packageRoot || !resolveProjectLocalResolvedPath(state, packageRoot)) return null;
2209
+ if (request === packageName) for (const relativeEntry of VUE_PEER_RUNTIME_ESM_ENTRIES.get(packageName) ?? ["index.mjs"]) {
2210
+ const entry = path.join(packageRoot, relativeEntry);
2211
+ if (fs.existsSync(entry)) return `${entry}${querySuffix}`;
2212
+ }
2213
+ const nodeResolved = resolveBareImportWithNode(state, id, importer);
2214
+ return nodeResolved ? resolveProjectLocalResolvedPath(state, nodeResolved) : null;
2215
+ }
2216
+ function resolveVuePeerRuntimeEntryFromBaseWithNode(state, id, base) {
2217
+ const { request, querySuffix } = splitViteIdQuery(id);
2218
+ const packageName = getBarePackageName(request);
2219
+ if (!packageName || !VUE_PEER_RUNTIME_PACKAGES.has(packageName)) return null;
2220
+ let packageJson;
2221
+ try {
2222
+ packageJson = createRequire(base).resolve(`${packageName}/package.json`);
2223
+ } catch {
2224
+ return null;
2225
+ }
2226
+ const packageRoot = path.dirname(packageJson);
2227
+ if (!resolveProjectLocalResolvedPath(state, packageRoot)) return null;
2228
+ if (request === packageName) for (const relativeEntry of VUE_PEER_RUNTIME_ESM_ENTRIES.get(packageName) ?? ["index.mjs"]) {
2229
+ const entry = path.join(packageRoot, relativeEntry);
2230
+ if (fs.existsSync(entry)) return `${entry}${querySuffix}`;
2231
+ }
2232
+ try {
2233
+ return resolveProjectLocalResolvedPath(state, `${createRequire(base).resolve(request)}${querySuffix}`);
2234
+ } catch {
2235
+ return null;
2236
+ }
2237
+ }
2238
+ function resolveProjectNuxtVuePeerRuntimeEntryWithNode(state, id) {
2239
+ const { request } = splitViteIdQuery(id);
2240
+ if (getBarePackageName(request) !== "vue-router") return null;
2241
+ const nuxtPackageJson = resolveBareImportWithNode(state, "nuxt/package.json", path.join(state.root, "package.json"));
2242
+ if (!nuxtPackageJson) return null;
2243
+ const nuxtPackageRoot = path.dirname(splitViteIdQuery(nuxtPackageJson).request);
2244
+ if (!resolveProjectLocalResolvedPath(state, nuxtPackageRoot)) return null;
2245
+ return resolveVuePeerRuntimeEntryFromBaseWithNode(state, id, path.join(nuxtPackageRoot, "package.json"));
2246
+ }
2247
+ function isOptimizedVueDependency(id) {
2248
+ const { request } = splitViteIdQuery(id);
2249
+ return request.split(path.sep).join("/").includes("/node_modules/.vite/deps/vue.");
2250
+ }
2251
+ const vueResolvableFromRootCache = /* @__PURE__ */ new Map();
2252
+ function isVueResolvableFromRoot(root) {
2253
+ let cached = vueResolvableFromRootCache.get(root);
2254
+ if (cached === void 0) {
2255
+ const rootNodeModules = path.join(root, "node_modules");
2256
+ const directPackageJson = path.join(rootNodeModules, "vue", "package.json");
2257
+ cached = fs.existsSync(directPackageJson);
2258
+ if (!cached) try {
2259
+ createRequire(path.join(root, "__vize_probe__.js")).resolve("vue/package.json");
2260
+ cached = true;
2261
+ } catch {}
2262
+ vueResolvableFromRootCache.set(root, cached);
2263
+ }
2264
+ return cached;
2265
+ }
2266
+ function normalizeResolvedVuePath(id) {
2267
+ return normalizeViteResolvedVuePath(id);
2268
+ }
2269
+ async function resolveProjectVueRuntime(ctx, state, id, importer, isSsrRequest) {
2270
+ if (isSsrRequest || !isProjectVueRuntimeRequest(id) || !isProjectLocalImporter(state, importer)) return null;
2271
+ const isBuild = state.server === null;
2272
+ const viteImporter = normalizeViteRequireBase(importer) ?? importer;
2273
+ if (isVuePeerRuntimeRequest(id)) {
2274
+ const nuxtPeerEntry = resolveProjectNuxtVuePeerRuntimeEntryWithNode(state, id);
2275
+ if (nuxtPeerEntry) {
2276
+ state.logger.log(`resolveId: resolved Nuxt Vue peer runtime ${id} to ${nuxtPeerEntry}`);
2277
+ return nuxtPeerEntry;
2278
+ }
2279
+ if (!isBuild && isProjectSourceImporter(state.root, importer)) {
2280
+ state.logger.log(`resolveId: deferring source Vue peer runtime ${id} to Vite optimizer`);
2281
+ return null;
2282
+ }
2283
+ const projectLocalEntry = resolveVuePeerRuntimeEntryWithNode(state, id, viteImporter);
2284
+ if (projectLocalEntry) {
2285
+ state.logger.log(`resolveId: resolved project-local Vue peer runtime ${id} to ${projectLocalEntry}`);
2286
+ return projectLocalEntry;
2287
+ }
2288
+ return null;
2289
+ }
2290
+ try {
2291
+ const resolved = await resolveWithVite(ctx, state, id, viteImporter, { skipSelf: true });
2292
+ if (resolved && isOptimizedVueDependency(resolved.id)) return null;
2293
+ if (resolved) {
2294
+ const projectLocalEntry = resolveProjectLocalPnpmVueRuntime(state, resolved.id);
2295
+ if (projectLocalEntry) {
2296
+ state.logger.log(`resolveId: resolved project-local Vue runtime to ${projectLocalEntry}`);
2297
+ return projectLocalEntry;
2298
+ }
2299
+ }
2300
+ } catch {}
2301
+ const pnpmHoistedEntry = resolveVueBundlerEntryFromPnpmHoist(state, id, viteImporter);
2302
+ if (pnpmHoistedEntry) {
2303
+ state.logger.log(`resolveId: resolved project pnpm-hoisted Vue runtime to ${pnpmHoistedEntry}`);
2304
+ return pnpmHoistedEntry;
2305
+ }
2306
+ const importerLocalEntry = resolveVueBundlerEntryWithNode(state, id, viteImporter);
2307
+ const projectLocalEntry = importerLocalEntry ? resolveProjectLocalPnpmVueRuntime(state, importerLocalEntry) : null;
2308
+ if (projectLocalEntry) {
2309
+ state.logger.log(`resolveId: resolved importer-local Vue runtime to ${projectLocalEntry}`);
2310
+ return projectLocalEntry;
2311
+ }
2312
+ return null;
2313
+ }
2314
+ function nativeCssAliasRules(state) {
2315
+ return state.cssAliasRules.length === 0 ? EMPTY_NATIVE_ALIAS_RULES : state.cssAliasRules.map(toNativeCssAliasRule);
2316
+ }
2317
+ function isPotentialVizeResolveId(id) {
2318
+ return id.startsWith("\0") || id.startsWith("vize:") || id.startsWith("/@fs") || isProjectVueRuntimeRequest(id) || id === "virtual:vize-styles" || id.endsWith(".vue") || id.includes(".vue?") || /\.vue\.tsx?\?/.test(id) || id.includes("?macro=true") || id.includes("?definePage");
2319
+ }
2320
+ function classifyImporterRequest(importer) {
2321
+ return importer ? classifyVitePluginRequest(importer) : null;
2322
+ }
2323
+ function isPotentialVizeImporter(importer) {
2324
+ if (importer === void 0) return false;
2325
+ if (importer.startsWith("\0") || importer.startsWith("vize:")) return true;
2326
+ return importer.includes(".vue");
2327
+ }
2328
+ function shouldCompileVueSfcRequest(request) {
2329
+ if (!request.isVueSfcPath || request.isVueStyleQuery || request.hasMacroQuery || request.hasDefinePageQuery) return false;
2330
+ if (!request.querySuffix) return true;
2331
+ const params = new URLSearchParams(request.querySuffix.slice(1));
2332
+ if (params.has("raw") || params.has("url") || params.has("worker") || params.has("sharedworker")) return false;
2333
+ return params.has("nuxt_component");
2334
+ }
2335
+ function hasNuxtComponentQuery(request) {
2336
+ if (!request.querySuffix) return false;
2337
+ return new URLSearchParams(request.querySuffix.slice(1)).has("nuxt_component");
2338
+ }
2339
+ async function resolveAliasedVueImport(ctx, state, id, importer, isSsrRequest, handleNodeModules, querySuffix, preserveQueryAsPath, isDependencyScan) {
2340
+ if (path.isAbsolute(id)) return null;
2341
+ const viteResolved = await resolveWithVite(ctx, state, id, normalizeViteRequireBase(importer) ?? importer, { skipSelf: true });
2342
+ const realPath = viteResolved ? normalizeResolvedVuePath(viteResolved.id) : null;
2343
+ if (!realPath) return null;
2344
+ const isResolvedNodeModules = realPath.includes("node_modules");
2345
+ if (!handleNodeModules && preserveQueryAsPath && isResolvedNodeModules) {
2346
+ state.logger.log(`resolveId: skipping resolved node_modules path ${realPath}`);
2347
+ return null;
2348
+ }
2349
+ if (!isResolvedNodeModules && state.filter && !state.filter(realPath)) {
2350
+ state.logger.log(`resolveId: skipping filtered resolved path ${realPath}`);
2351
+ return null;
2352
+ }
2353
+ if (state.cache.has(realPath) || fs.existsSync(realPath)) {
2354
+ state.logger.log(`resolveId: resolved via Vite fallback ${id} to ${realPath}`);
2355
+ return preserveQueryAsPath ? `${realPath}${querySuffix}` : isDependencyScan ? toVirtualId(realPath, isSsrRequest) : toPluginVisibleVirtualId(realPath, isSsrRequest, querySuffix);
2356
+ }
2357
+ return null;
2358
+ }
2359
+ async function resolveIdHook(ctx, state, id, importer, options) {
2360
+ if (!isPotentialVizeResolveId(id) && !isPotentialVizeImporter(importer)) return null;
2361
+ const importerRequest = classifyImporterRequest(importer);
2362
+ const isBuild = state.server === null;
2363
+ const isDependencyScan = !!options?.scan;
2364
+ const isSsrRequest = !!options?.ssr || (importerRequest?.isVizeSsrVirtual ?? false) || (importer ? isPluginVisibleSsrVirtualId(importer) : false);
2365
+ const request = classifyVitePluginRequest(id);
2366
+ const pluginVisibleVirtualPath = fromPluginVisibleVirtualId(id);
2367
+ const projectVueRuntime = await resolveProjectVueRuntime(ctx, state, id, importer, isSsrRequest);
2368
+ if (projectVueRuntime) return projectVueRuntime;
2369
+ if (pluginVisibleVirtualPath) {
2370
+ if (isDependencyScan) return toVirtualId(pluginVisibleVirtualPath, isSsrRequest);
2371
+ return isSsrRequest ? toPluginVisibleVirtualId(pluginVisibleVirtualPath, true, request.querySuffix) : id;
2372
+ }
2373
+ if (id.startsWith("\0")) {
2374
+ if (request.isVizeVirtual) {
2375
+ if (isSsrRequest && !request.isVizeSsrVirtual && request.vizeVirtualPath) return isDependencyScan ? toVirtualId(request.vizeVirtualPath, true) : toPluginVisibleVirtualId(request.vizeVirtualPath, true, request.querySuffix);
2376
+ return id;
2377
+ }
2378
+ if (id.startsWith("\0vize:")) {
2379
+ const rawPath = id.slice(6);
2380
+ const cleanPath = rawPath.endsWith(".ts") ? rawPath.slice(0, -3) : rawPath;
2381
+ if (!cleanPath.endsWith(".vue")) {
2382
+ state.logger.log(`resolveId: redirecting legacy virtual ID to ${cleanPath}`);
2383
+ return cleanPath;
2384
+ }
2385
+ }
2386
+ const cleanPath = id.slice(1);
2387
+ if (cleanPath.startsWith("/") && !cleanPath.endsWith(".vue.ts")) {
2388
+ const { request: pathPart, querySuffix } = splitViteIdQuery(cleanPath);
2389
+ state.logger.log(`resolveId: redirecting \0-prefixed non-vue ID to ${pathPart}${querySuffix}`);
2390
+ const redirected = pathPart + querySuffix;
2391
+ return isBuild ? classifyVitePluginRequest(redirected).normalizedFsId ?? redirected : redirected;
2392
+ }
2393
+ return null;
2394
+ }
2395
+ if (id.startsWith("vize:")) {
2396
+ let realPath = id.slice(5);
2397
+ if (realPath.endsWith(".ts")) realPath = realPath.slice(0, -3);
2398
+ state.logger.log(`resolveId: redirecting stale vize: ID to ${realPath}`);
2399
+ const resolved = await resolveWithVite(ctx, state, realPath, importer, { skipSelf: true });
2400
+ const normalizedFsId = resolved ? classifyVitePluginRequest(resolved.id).normalizedFsId : null;
2401
+ if (resolved && isBuild && normalizedFsId) return {
2402
+ ...resolved,
2403
+ id: normalizedFsId
2404
+ };
2405
+ return resolved;
2406
+ }
2407
+ if (id === "virtual:vize-styles") return RESOLVED_CSS_MODULE;
2408
+ if ((request.hasMacroQuery || request.hasDefinePageQuery) && request.isVueSfcPath) {
2409
+ const resolved = resolveVuePath(state, request.path, importer);
2410
+ if (resolved && fs.existsSync(resolved)) return `\0${resolved}${request.querySuffix}`;
2411
+ }
2412
+ if (request.isVueStyleQuery && request.styleVirtualSuffix) {
2413
+ if (id.includes("vitepress-plugin-llms")) {
2414
+ state.logger.log(`resolveId: skipping vitepress-plugin-llms style import ${id}`);
2415
+ return null;
2416
+ }
2417
+ return `${request.normalizedFsId ?? id}${request.styleVirtualSuffix}`;
2418
+ }
2419
+ if (isBuild && request.normalizedFsId) return request.normalizedFsId;
2420
+ const isMacroImporter = importerRequest?.isMacroVirtualId ?? false;
2421
+ const isVizeVirtualImporter = importerRequest?.isVizeVirtual ?? false;
2422
+ const isVueSfcImporter = importerRequest?.isVueSfcPath ?? false;
2423
+ if (importer && (isVizeVirtualImporter || isMacroImporter || isVueSfcImporter)) {
2424
+ const cleanImporter = isMacroImporter ? importerRequest?.strippedVirtualPath ?? "" : isVizeVirtualImporter ? importerRequest?.vizeVirtualPath ?? "" : cleanVueSfcImporter(importer, importerRequest);
2425
+ state.logger.log(`resolveId from virtual: id=${id}, cleanImporter=${cleanImporter}`);
2426
+ const relativeVueResolved = await resolveRelativeVueSfcImport(ctx, state, id, cleanImporter, isSsrRequest, isDependencyScan, resolveWithVite);
2427
+ if (relativeVueResolved) return relativeVueResolved;
2428
+ if (id.startsWith("#")) {
2429
+ try {
2430
+ const resolved = await resolveWithVite(ctx, state, id, cleanImporter, { skipSelf: true });
2431
+ if (resolved) return resolved;
2432
+ } catch {}
2433
+ return resolvePackageJsonImportFromVizeImporter(state, id, cleanImporter);
2434
+ }
2435
+ if (!id.endsWith(".vue")) {
2436
+ const ssrExternalVueRequest = isSsrRequest ? resolveSsrExternalVueRequest(id) : null;
2437
+ if (ssrExternalVueRequest) {
2438
+ if (!isBuild) {
2439
+ const devSsrVueEntry = ssrExternalVueRequest === "vue/server-renderer" ? resolveVueServerRendererBundlerEntryWithNode(state, id, cleanImporter) : resolveVueBundlerEntryWithNode(state, id, cleanImporter);
2440
+ if (devSsrVueEntry) {
2441
+ state.logger.log(`resolveId: resolved SSR Vue request ${id} to ${devSsrVueEntry}`);
2442
+ return devSsrVueEntry;
2443
+ }
2444
+ }
2445
+ return {
2446
+ id: ssrExternalVueRequest,
2447
+ external: true
2448
+ };
2449
+ }
2450
+ if (!id.startsWith("./") && !id.startsWith("../") && !id.startsWith("/")) {
2451
+ const isVueRuntime = isVueRuntimeRequest(id);
2452
+ const isVuePeerRuntime = isVuePeerRuntimeRequest(id);
2453
+ if (!isBuild && isVuePeerRuntime && isProjectSourceImporter(state.root, importer)) {
2454
+ state.logger.log(`resolveId: deferring source Vue peer runtime ${id} to Vite optimizer`);
2455
+ return null;
2456
+ }
2457
+ if (isVueRuntime && isBuild) {
2458
+ const vueBundlerEntry = resolveVueBundlerEntryWithNode(state, id, cleanImporter);
2459
+ if (vueBundlerEntry) {
2460
+ state.logger.log(`resolveId: resolved Vue runtime to ${vueBundlerEntry}`);
2461
+ return vueBundlerEntry;
2462
+ }
2463
+ }
2464
+ const aliasRequest = resolveAliasRequest(state, id);
2465
+ if (!isVueRuntime && aliasRequest && isViteBareSpecifier(aliasRequest)) {
2466
+ const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter);
2467
+ if (nodeResolved) {
2468
+ state.logger.log(`resolveId: resolved aliased bare ${id} to ${nodeResolved} via Node fallback`);
2469
+ return nodeResolved;
2470
+ }
2471
+ }
2472
+ try {
2473
+ const resolved = await resolveWithVite(ctx, state, id, cleanImporter, { skipSelf: true });
2474
+ if (resolved) {
2475
+ state.logger.log(`resolveId: resolved bare ${id} to ${resolved.id} via Vite resolver`);
2476
+ const normalizedFsId = classifyVitePluginRequest(resolved.id).normalizedFsId;
2477
+ if (isBuild && normalizedFsId) return {
2478
+ ...resolved,
2479
+ id: normalizedFsId
2480
+ };
2481
+ if (isVueRuntime && state.server !== null && !isOptimizedVueDependency(resolved.id)) {
2482
+ const pnpmHoistedEntry = resolveVueBundlerEntryFromPnpmHoist(state, id, cleanImporter);
2483
+ if (pnpmHoistedEntry) {
2484
+ state.logger.log(`resolveId: resolved pnpm-hoisted Vue runtime to ${pnpmHoistedEntry}`);
2485
+ return pnpmHoistedEntry;
2486
+ }
2487
+ const projectLocalEntry = resolveProjectLocalPnpmVueRuntime(state, resolved.id);
2488
+ if (projectLocalEntry) {
2489
+ state.logger.log(`resolveId: resolved project-local Vue runtime to ${projectLocalEntry}`);
2490
+ return projectLocalEntry;
2491
+ }
2492
+ if (isVueResolvableFromRoot(state.root)) {
2493
+ state.logger.log(`resolveId: deferring Vue runtime ${resolved.id} to Vite optimizer`);
2494
+ return null;
2495
+ }
2496
+ const isolatedEntry = resolveVueBundlerEntryWithNode(state, id, cleanImporter) ?? resolved.id;
2497
+ state.logger.log(`resolveId: isolated install — resolved Vue runtime to ${isolatedEntry}`);
2498
+ return isolatedEntry;
2499
+ }
2500
+ if (isVueRuntime && isVuePackageEntry(resolved.id)) {
2501
+ const vueBundlerEntry = resolveVueBundlerEntryWithNode(state, id, cleanImporter);
2502
+ if (vueBundlerEntry) {
2503
+ state.logger.log(`resolveId: resolved Vue runtime to ${vueBundlerEntry}`);
2504
+ return vueBundlerEntry;
2505
+ }
2506
+ return null;
2507
+ }
2508
+ if (isViteBareSpecifier(resolved.id)) {
2509
+ if (isVueRuntime) {
2510
+ const vueBundlerEntry = isBuild || !isVueResolvableFromRoot(state.root) ? resolveVueBundlerEntryWithNode(state, id, cleanImporter) : null;
2511
+ if (vueBundlerEntry) {
2512
+ state.logger.log(`resolveId: resolved Vue runtime to ${vueBundlerEntry}`);
2513
+ return vueBundlerEntry;
2514
+ }
2515
+ state.logger.log(`resolveId: deferring bare Vue runtime ${id} to Vite`);
2516
+ return null;
2517
+ }
2518
+ const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter, resolved.id);
2519
+ if (nodeResolved) {
2520
+ state.logger.log(`resolveId: normalized bare ${id} to ${nodeResolved} via Node fallback`);
2521
+ return nodeResolved;
2522
+ }
2523
+ return null;
2524
+ }
2525
+ return resolved;
2526
+ }
2527
+ } catch {}
2528
+ if (isVueRuntime) {
2529
+ const importerLocalEntry = resolveVueBundlerEntryWithNode(state, id, cleanImporter);
2530
+ const projectLocalEntry = importerLocalEntry ? resolveProjectLocalPnpmVueRuntime(state, importerLocalEntry) : null;
2531
+ if (projectLocalEntry) {
2532
+ state.logger.log(`resolveId: resolved project-local Vue runtime to ${projectLocalEntry}`);
2533
+ return projectLocalEntry;
2534
+ }
2535
+ const vueBundlerEntry = isBuild || !isVueResolvableFromRoot(state.root) ? importerLocalEntry : null;
2536
+ if (vueBundlerEntry) {
2537
+ state.logger.log(`resolveId: resolved Vue runtime to ${vueBundlerEntry}`);
2538
+ return vueBundlerEntry;
2539
+ }
2540
+ state.logger.log(`resolveId: deferring Vue runtime ${id} to Vite`);
2541
+ return null;
2542
+ }
2543
+ const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter);
2544
+ if (nodeResolved) {
2545
+ state.logger.log(`resolveId: resolved bare ${id} to ${nodeResolved} via Node fallback`);
2546
+ return nodeResolved;
2547
+ }
2548
+ if (aliasRequest && aliasRequest !== id && !isViteBareSpecifier(aliasRequest)) {
2549
+ try {
2550
+ const resolved = await resolveWithVite(ctx, state, aliasRequest, cleanImporter, { skipSelf: true });
2551
+ if (resolved) {
2552
+ state.logger.log(`resolveId: resolved aliased bare ${id} to ${resolved.id} via Vite resolver`);
2553
+ const normalizedFsId = classifyVitePluginRequest(resolved.id).normalizedFsId;
2554
+ if (isBuild && normalizedFsId) return {
2555
+ ...resolved,
2556
+ id: normalizedFsId
2557
+ };
2558
+ if (isViteBareSpecifier(resolved.id)) {
2559
+ const nodeResolved = resolveBareImportCandidatesWithNode(state, id, cleanImporter, resolved.id);
2560
+ if (nodeResolved) {
2561
+ state.logger.log(`resolveId: normalized aliased bare ${id} to ${nodeResolved} via Node fallback`);
2562
+ return nodeResolved;
2563
+ }
2564
+ return null;
2565
+ }
2566
+ return resolved;
2567
+ }
2568
+ } catch {}
2569
+ const nodeResolved = resolveBareImportCandidatesWithNode(state, aliasRequest, cleanImporter);
2570
+ if (nodeResolved) {
2571
+ state.logger.log(`resolveId: resolved aliased bare ${id} to ${nodeResolved} via Node fallback`);
2572
+ return nodeResolved;
2573
+ }
2574
+ }
2575
+ return null;
2576
+ }
2577
+ try {
2578
+ const resolved = await resolveWithVite(ctx, state, id, cleanImporter, { skipSelf: true });
2579
+ if (resolved) {
2580
+ state.logger.log(`resolveId: resolved ${id} to ${resolved.id} via Vite resolver`);
2581
+ const normalizedFsId = classifyVitePluginRequest(resolved.id).normalizedFsId;
2582
+ if (isBuild && normalizedFsId) return {
2583
+ ...resolved,
2584
+ id: normalizedFsId
2585
+ };
2586
+ return resolved;
2587
+ }
2588
+ } catch {}
2589
+ if (id.startsWith("./") || id.startsWith("../")) {
2590
+ const resolved = resolveViteRelativeImport(id, cleanImporter);
2591
+ if (resolved) {
2592
+ state.logger.log(`resolveId: resolved relative ${id} to ${resolved}`);
2593
+ return resolved;
2594
+ }
2595
+ }
2596
+ return null;
2597
+ }
2598
+ }
2599
+ if (shouldCompileVueSfcRequest(request)) {
2600
+ const handleNodeModules = state.mergedOptions.handleNodeModulesVue ?? true;
2601
+ const preserveQueryAsPath = hasNuxtComponentQuery(request);
2602
+ const vueRequestPath = request.path;
2603
+ if (!handleNodeModules && preserveQueryAsPath && vueRequestPath.includes("node_modules")) {
2604
+ state.logger.log(`resolveId: skipping node_modules import ${id}`);
2605
+ return null;
2606
+ }
2607
+ const resolved = resolveVuePath(state, vueRequestPath, importer);
2608
+ const fileExists = fs.existsSync(resolved);
2609
+ if (!fileExists) {
2610
+ const aliased = await resolveAliasedVueImport(ctx, state, id, importer, isSsrRequest, handleNodeModules, request.querySuffix, preserveQueryAsPath, isDependencyScan);
2611
+ if (aliased) return aliased;
2612
+ }
2613
+ const isNodeModulesPath = resolved.includes("node_modules");
2614
+ if (!handleNodeModules && preserveQueryAsPath && isNodeModulesPath) {
2615
+ state.logger.log(`resolveId: skipping node_modules path ${resolved}`);
2616
+ return null;
2617
+ }
2618
+ if (state.filter && !isNodeModulesPath && !state.filter(resolved)) {
2619
+ state.logger.log(`resolveId: skipping filtered path ${resolved}`);
2620
+ return null;
2621
+ }
2622
+ const hasCache = state.cache.has(resolved);
2623
+ state.logger.log(`resolveId: id=${id}, resolved=${resolved}, hasCache=${hasCache}, fileExists=${fileExists}, importer=${importer ?? "none"}`);
2624
+ if (hasCache || fileExists) {
2625
+ if (preserveQueryAsPath) return `${resolved}${request.querySuffix}`;
2626
+ return isDependencyScan ? toVirtualId(resolved, isSsrRequest) : toPluginVisibleVirtualId(resolved, isSsrRequest, request.querySuffix);
2627
+ }
2628
+ }
2629
+ return null;
2630
+ }
2631
+ //#endregion
2632
+ //#region src/plugin/load-sfc.ts
2633
+ function shouldLoadVueSfcRequest(request) {
2634
+ if (!request.isVueSfcPath || request.isVueStyleQuery || request.hasMacroQuery || request.hasDefinePageQuery) return false;
2635
+ if (!request.querySuffix) return true;
2636
+ const params = new URLSearchParams(request.querySuffix.slice(1));
2637
+ if (params.has("raw") || params.has("url") || params.has("worker") || params.has("sharedworker")) return false;
2638
+ return params.has("nuxt_component");
2639
+ }
2640
+ function getLoadableVueSfcPath(request) {
2641
+ if (!shouldLoadVueSfcRequest(request)) return null;
2642
+ return classifyVitePluginRequest(request.normalizedFsId ?? request.path).normalizedVuePath;
2643
+ }
2644
+ function shouldLoadCompiledVueSfcPath(state, realPath, hasNuxtComponentQuery = false) {
2645
+ const isNodeModulesPath = realPath.includes("node_modules");
2646
+ if (!(state.mergedOptions.handleNodeModulesVue ?? true) && isNodeModulesPath && hasNuxtComponentQuery) {
2647
+ state.logger.log(`load: skipping node_modules Vue SFC ${realPath}`);
2648
+ return false;
2649
+ }
2650
+ if (!isNodeModulesPath && !state.filter(realPath)) {
2651
+ state.logger.log(`load: skipping filtered Vue SFC ${realPath}`);
2652
+ return false;
2653
+ }
2654
+ return true;
2655
+ }
2656
+ //#endregion
2657
+ //#region src/plugin/ssr-modules.ts
2658
+ /**
2659
+ * Point a compiled SSR module at the `vue/server-renderer` subpath.
2660
+ *
2661
+ * The compiler emits `@vue/server-renderer`, which is not a dependency every
2662
+ * app declares; the subpath re-export always resolves alongside `vue` itself.
2663
+ */
2664
+ function normalizeVueServerRendererImport(code) {
2665
+ return code.replace(/\bfrom\s+(['"])@vue\/server-renderer\1/g, "from \"vue/server-renderer\"");
2666
+ }
2667
+ /**
2668
+ * Marks a module whose registration has already been appended.
2669
+ *
2670
+ * Idempotency cannot key on the helper identifiers: an SFC is free to declare
2671
+ * `__vize_useSSRContext` itself, and skipping registration for it would cost it
2672
+ * its initial stylesheet.
2673
+ */
2674
+ const REGISTRATION_MARKER = "/* @vize-ssr-modules-registered */";
2675
+ /**
2676
+ * Matches the `_sfc_main` component declaration the emitted module carries.
2677
+ *
2678
+ * A bare `\b_sfc_main\b` also matches the identifier inside a string literal or
2679
+ * a comment, and wrapping a component that was never declared is a
2680
+ * `ReferenceError` at render time.
2681
+ */
2682
+ const SFC_MAIN_DECLARATION = /\b(?:const|let|var)\s+_sfc_main\s*=/;
2683
+ /**
2684
+ * Register an SFC in `ssrContext.modules` during SSR, the way
2685
+ * `@vitejs/plugin-vue` does.
2686
+ *
2687
+ * After rendering, `vue-bundle-renderer` intersects `ssrContext.modules` with
2688
+ * the client manifest to decide which stylesheets belong in the document head.
2689
+ * A component that never registers itself contributes no `<link>`, so the
2690
+ * server-rendered markup arrives unstyled and only gains its styles once the
2691
+ * route chunk loads on the client — a flash of unstyled content that never
2692
+ * recovers when JavaScript is disabled (#3868).
2693
+ *
2694
+ * The key must be the module's path relative to the Vite root with POSIX
2695
+ * separators, because that is what the client manifest is keyed on.
2696
+ */
2697
+ function ssrModuleRegistrationCode(filePath, root, helpers = {}) {
2698
+ const moduleId = JSON.stringify(toManifestModuleId(filePath, root));
2699
+ const useSSRContext = helpers.useSSRContext ?? "__vize_useSSRContext";
2700
+ const sfcSetup = helpers.sfcSetup ?? "__vize_sfc_setup";
2701
+ return {
2702
+ prologue: `${REGISTRATION_MARKER}\nimport { useSSRContext as ${useSSRContext} } from "vue";`,
2703
+ epilogue: [
2704
+ `const ${sfcSetup} = _sfc_main.setup;`,
2705
+ `_sfc_main.setup = (props, ctx) => {`,
2706
+ ` const ssrContext = ${useSSRContext}();`,
2707
+ ` (ssrContext.modules || (ssrContext.modules = new Set())).add(${moduleId});`,
2708
+ ` return ${sfcSetup} ? ${sfcSetup}(props, ctx) : undefined;`,
2709
+ `};`
2710
+ ].join("\n")
2711
+ };
2712
+ }
2713
+ /**
2714
+ * The client-manifest key for `filePath`: relative to `root`, POSIX separators.
2715
+ *
2716
+ * A path outside the root keeps its absolute form rather than becoming a `../`
2717
+ * chain, matching how Vite keys modules it cannot root-relativize. Only a real
2718
+ * parent-directory step counts as outside: a filename that merely begins with
2719
+ * `..` still lives in the root and is keyed relative to it.
2720
+ */
2721
+ function toManifestModuleId(filePath, root) {
2722
+ const relative = path.relative(root, filePath).replace(/\\/g, "/");
2723
+ if (!relative || relative === ".." || relative.startsWith("../") || path.isAbsolute(relative)) return filePath.replace(/\\/g, "/");
2724
+ return relative;
2725
+ }
2726
+ /**
2727
+ * Wrap an emitted module with the registration.
2728
+ *
2729
+ * The wrapper is appended, so it closes over whatever `setup` the emitter's own
2730
+ * rewrites left in place, but its `import` is *prepended*. A trailing `import`
2731
+ * is legal ESM, yet it makes the module's last import statement its last line,
2732
+ * and Nuxt's auto-import injection then inserts nothing — a component relying on
2733
+ * an auto-imported composable loses that binding and throws `ReferenceError` at
2734
+ * render time (#3868). Leading the module with the import keeps the import
2735
+ * section where every downstream transform expects to find it.
2736
+ *
2737
+ * `useSSRContext()` throws outside a render, so this is a no-op unless `isSsr`.
2738
+ * Modules without an `_sfc_main` declaration — a render-function-only output, or
2739
+ * a boundary placeholder — have no component object to wrap and are returned
2740
+ * untouched.
2741
+ */
2742
+ function appendSsrModuleRegistration(code, filePath, root, isSsr) {
2743
+ if (!isSsr || !SFC_MAIN_DECLARATION.test(code)) return code;
2744
+ if (code.includes(REGISTRATION_MARKER)) return code;
2745
+ const { prologue, epilogue } = ssrModuleRegistrationCode(filePath, root, {
2746
+ useSSRContext: freeIdentifier("__vize_useSSRContext", code),
2747
+ sfcSetup: freeIdentifier("__vize_sfc_setup", code)
2748
+ });
2749
+ return `${prologue}\n${code}\n${epilogue}`;
2750
+ }
2751
+ /**
2752
+ * `base`, or `base` plus the smallest numeric suffix the module does not use.
2753
+ *
2754
+ * Re-declaring an identifier the SFC already bound is a `SyntaxError`, which
2755
+ * would take down the whole module rather than just its stylesheet.
2756
+ */
2757
+ function freeIdentifier(base, code) {
2758
+ if (!new RegExp(`\\b${base}\\b`).test(code)) return base;
2759
+ for (let suffix = 2;; suffix++) {
2760
+ const candidate = `${base}${suffix}`;
2761
+ if (!new RegExp(`\\b${candidate}\\b`).test(code)) return candidate;
2762
+ }
2763
+ }
2764
+ //#endregion
2765
+ //#region src/plugin/vite-transform.ts
2766
+ function createVirtualTypeScriptTransformer(viteApi) {
2767
+ return async (code, id) => {
2768
+ if (typeof viteApi.transformWithOxc === "function") return viteApi.transformWithOxc(code, id, {
2769
+ lang: "ts",
2770
+ sourcemap: false,
2771
+ target: "esnext"
2772
+ });
2773
+ if (typeof viteApi.transformWithEsbuild === "function") return viteApi.transformWithEsbuild(code, id, {
2774
+ loader: "ts",
2775
+ sourcemap: false,
2776
+ target: "esnext"
2777
+ });
2778
+ throw new Error("Installed Vite does not expose transformWithOxc or transformWithEsbuild");
2779
+ };
2780
+ }
2781
+ /**
2782
+ * Report whether `realPath` names a module Vize's own compiler emitted.
2783
+ *
2784
+ * Vize's Rust emitter guarantees plain JavaScript for every module it produces
2785
+ * (`ensure_javascript_output` at the napi boundary), so re-running Vite's
2786
+ * TypeScript strip over emitter output is a pure re-print. Every emitted module
2787
+ * is recorded in one of the two environment caches, so cache membership is the
2788
+ * cheap, allocation-free proof that the code came from the emitter.
2789
+ *
2790
+ * The probe fails safe: a module the caches do not know about still gets the
2791
+ * strip, which keeps hand-written and malformed virtual modules behaving
2792
+ * exactly as they did before.
2793
+ */
2794
+ function isVizeEmitterOutput(state, realPath) {
2795
+ return state.cache.has(realPath) || state.ssrCache.has(realPath);
2796
+ }
2797
+ const transformVirtualTypeScript = createVirtualTypeScriptTransformer(vite);
2798
+ function getOxcDumpPath(root, realPath) {
2799
+ const dumpDir = path.resolve(root || process.cwd(), "node_modules", ".vize", "oxc-dumps");
2800
+ fs.mkdirSync(dumpDir, { recursive: true });
2801
+ return path.join(dumpDir, `vize-oxc-error-${path.basename(realPath)}.ts`);
2802
+ }
2803
+ function getVirtualModuleDefines(state, ssr) {
2804
+ return {
2805
+ "import.meta.client": ssr ? "false" : "true",
2806
+ "import.meta.server": ssr ? "true" : "false",
2807
+ "import.meta.dev": state.isProduction ? "false" : "true",
2808
+ "import.meta.test": "false",
2809
+ "import.meta.prerender": "false",
2810
+ ...ssr ? state.serverViteDefine : state.clientViteDefine
2811
+ };
2812
+ }
2813
+ function formatUnknownError$1(error) {
2814
+ return error instanceof Error ? error.message : String(error);
2815
+ }
2816
+ async function transformVizeVirtualModule(state, code, realPath, ssr, forceTypeScriptTransform = false) {
2817
+ const needsTsTransform = forceTypeScriptTransform || !isVizeEmitterOutput(state, realPath);
2818
+ try {
2819
+ let transformed = (needsTsTransform ? await transformVirtualTypeScript(code, realPath) : { code }).code;
2820
+ if (transformed.includes("import.meta.")) transformed = applyDefineReplacements(transformed, getVirtualModuleDefines(state, ssr));
2821
+ return transformed === code ? null : {
2822
+ code: transformed,
2823
+ map: null
2824
+ };
2825
+ } catch (e) {
2826
+ state.logger.error(`transformWithOxc failed for ${realPath}:`, e);
2827
+ let dumpPath = null;
2828
+ try {
2829
+ dumpPath = getOxcDumpPath(state.root, realPath);
2830
+ fs.writeFileSync(dumpPath, code, "utf-8");
2831
+ state.logger.error(`Dumped failing code to ${dumpPath}`);
2832
+ } catch (dumpError) {
2833
+ state.logger.error(`Failed to dump failing virtual module for ${realPath}:`, dumpError);
2834
+ }
2835
+ const message = [`[vize] Virtual module transform failed for ${realPath}: ${formatUnknownError$1(e)}`, dumpPath ? `Dumped failing code to ${dumpPath}` : null].filter(Boolean).join("\n");
2836
+ throw new Error(message);
2837
+ }
2838
+ }
2839
+ //#endregion
2840
+ //#region src/plugin/load-style.ts
2841
+ function normalizeStyleVirtualId(id) {
2842
+ const withoutPrefix = id.startsWith("\0") ? id.slice(1) : id;
2843
+ if (!withoutPrefix.includes("?vue")) return id;
2844
+ return withoutPrefix.replace(/\.module\.\w+$/, "").replace(/\.\w+$/, "");
2845
+ }
2846
+ //#endregion
2847
+ //#region src/plugin/load.ts
2848
+ const SERVER_PLACEHOLDER_CODE = `import { createElementBlock, defineComponent } from "vue";
2849
+ export default defineComponent({
2850
+ name: "ServerPlaceholder",
2851
+ render() {
2852
+ return createElementBlock("div");
2853
+ }
2854
+ });
2855
+ `;
2856
+ function getBoundaryPlaceholderCode(realPath, ssr) {
2857
+ const boundaryKind = classifyVitePluginRequest(realPath).boundaryKind;
2858
+ if (ssr && boundaryKind === "client") return SERVER_PLACEHOLDER_CODE;
2859
+ if (!ssr && boundaryKind === "server") return SERVER_PLACEHOLDER_CODE;
2860
+ return null;
2861
+ }
2862
+ function findMacroArtifactModule(state, realPath, ssr, kind) {
2863
+ const cache = getEnvironmentCache(state, ssr);
2864
+ const extractCss = shouldExtractCssForRequest(state, ssr);
2865
+ realPath = classifyVitePluginRequest(realPath).normalizedVuePath;
2866
+ let compiled = cache.get(realPath) ?? state.cache.get(realPath) ?? state.ssrCache.get(realPath);
2867
+ if (!compiled && fs.existsSync(realPath)) {
2868
+ const source = fs.readFileSync(realPath, "utf-8");
2869
+ compiled = compileFile(realPath, cache, getCompileOptionsForRequest(state, ssr), source);
2870
+ }
2871
+ syncCollectedCssForFile({
2872
+ ...state,
2873
+ extractCss
2874
+ }, realPath, compiled);
2875
+ return compiled?.macroArtifacts?.find((artifact) => artifact.kind === kind)?.moduleCode ?? null;
2876
+ }
2877
+ function loadCompiledSfcModule(state, realPath, isSsr, currentBase, loadOptions) {
2878
+ const placeholderCode = getBoundaryPlaceholderCode(realPath, !!loadOptions?.ssr);
2879
+ if (placeholderCode) {
2880
+ state.logger.log(`load: using boundary placeholder for ${realPath}`);
2881
+ return {
2882
+ code: placeholderCode,
2883
+ map: null
2884
+ };
2885
+ }
2886
+ const cache = getEnvironmentCache(state, isSsr);
2887
+ const customElement = isPluginVueCustomElement(state.mergedOptions, realPath);
2888
+ const extractCss = shouldExtractCssForRequest(state, isSsr) && !customElement;
2889
+ let compiled = cache.get(realPath);
2890
+ if (!compiled && fs.existsSync(realPath)) {
2891
+ state.logger.log(`load: on-demand compiling ${realPath}`);
2892
+ compiled = compileFile(realPath, cache, getCompileOptionsForRequest(state, isSsr), void 0, { logWarnings: shouldLogSfcWarnings(state, realPath) });
2893
+ }
2894
+ syncCollectedCssForFile({
2895
+ ...state,
2896
+ extractCss
2897
+ }, realPath, compiled);
2898
+ if (!compiled) return null;
2899
+ for (const watchFile of new Set([realPath, ...compiled.dependencies ?? []])) loadOptions?.addWatchFile?.(watchFile);
2900
+ const hasDelegated = hasDelegatedStyles(compiled);
2901
+ const outputOptions = {
2902
+ isProduction: state.isProduction,
2903
+ isDev: state.server !== null && !isSsr,
2904
+ ssr: isSsr,
2905
+ hmrUpdateType: loadOptions?.ssr ? void 0 : state.pendingHmrUpdateTypes.get(realPath),
2906
+ extractCss,
2907
+ customElement,
2908
+ filePath: realPath
2909
+ };
2910
+ if (compiled.css && !hasDelegated && embedsInlineCss(compiled, outputOptions)) compiled = {
2911
+ ...compiled,
2912
+ css: resolveCssImports(compiled.css, realPath, state.cssAliasRules, state.server !== null, currentBase)
2913
+ };
2914
+ const emitted = generateOutputWithMap(compiled, outputOptions);
2915
+ const rewritten = new MappedModule(isSsr ? normalizeVueServerRendererImport(emitted.code) : emitted.code, emitted.map);
2916
+ rewritten.edit(rewriteDynamicTemplateImports(rewritten.code, state.dynamicImportAliasRules));
2917
+ rewritten.edit(rewriteStaticAssetUrls(rewritten.code, state.dynamicImportAliasRules));
2918
+ rewritten.edit(rewriteImportMetaGlobBase(rewritten.code, realPath, state.root));
2919
+ rewritten.edit(appendSsrModuleRegistration(rewritten.code, realPath, state.root, isSsr));
2920
+ return {
2921
+ code: rewritten.code,
2922
+ map: rewritten.map
2923
+ };
2924
+ }
2925
+ function loadDefinePageArtifact(state, realPath, ssr) {
2926
+ return {
2927
+ code: findMacroArtifactModule(state, realPath, ssr, "vue-router.definePage") ?? "export default {}",
2928
+ map: null
2929
+ };
2930
+ }
2931
+ function loadDefinePageMetaArtifact(state, realPath, ssr) {
2932
+ const code = findMacroArtifactModule(state, realPath, ssr, "nuxt.definePageMeta");
2933
+ return code ? {
2934
+ code,
2935
+ map: null
2936
+ } : null;
2937
+ }
2938
+ function loadHook(state, id, loadOptions) {
2939
+ if (id !== "\0vize:all-styles.css" && !id.startsWith("\0") && !id.includes(".vue")) return null;
2940
+ const request = classifyVitePluginRequest(id);
2941
+ const pluginVisibleVirtualPath = fromPluginVisibleVirtualId(id);
2942
+ const loadableVueSfcPath = getLoadableVueSfcPath(request);
2943
+ const currentBase = loadOptions?.ssr ? state.serverViteBase : state.clientViteBase;
2944
+ if (id === "\0vize:all-styles.css") {
2945
+ let allCss = "";
2946
+ for (const css of state.collectedCss.values()) allCss += allCss ? `\n\n${css}` : css;
2947
+ return allCss;
2948
+ }
2949
+ const styleRequest = classifyVitePluginRequest(normalizeStyleVirtualId(id));
2950
+ if (styleRequest.isVueStyleQuery) {
2951
+ const sourceRequest = classifyVitePluginRequest(styleRequest.path);
2952
+ const realPath = sourceRequest.vizeVirtualPath ?? sourceRequest.normalizedFsId ?? sourceRequest.normalizedVuePath ?? styleRequest.path;
2953
+ const lang = styleRequest.styleLang ?? null;
2954
+ const scoped = styleRequest.styleScoped ?? null;
2955
+ const fallbackCompiled = loadOptions?.ssr ? state.ssrCache.get(realPath) ?? state.cache.get(realPath) : state.cache.get(realPath) ?? state.ssrCache.get(realPath);
2956
+ const blockIndex = styleRequest.styleIndex ?? -1;
2957
+ if (fallbackCompiled?.styles && blockIndex >= 0 && blockIndex < fallbackCompiled.styles.length) {
2958
+ const block = fallbackCompiled.styles[blockIndex];
2959
+ let styleContent = block.content;
2960
+ if (scoped && block.scoped && (!lang || lang === "css")) styleContent = scopeCssForPipeline(styleContent, scoped);
2961
+ styleContent = transformCssVarsForPipeline(styleContent, fallbackCompiled.scopeId);
2962
+ return {
2963
+ code: styleContent,
2964
+ map: null
2965
+ };
2966
+ }
2967
+ if (fallbackCompiled?.css) return resolveCssImports(fallbackCompiled.css, realPath, state.cssAliasRules, state.server !== null, currentBase);
2968
+ return null;
2969
+ }
2970
+ if (id !== "\0vize:all-styles.css" && !id.startsWith("\0") && !pluginVisibleVirtualPath && !loadableVueSfcPath) return null;
2971
+ if (id.startsWith("\0") && request.hasDefinePageQuery) {
2972
+ const realPath = request.strippedVirtualPath ?? "";
2973
+ if (request.isVueSfcPath) return loadDefinePageArtifact(state, realPath, !!loadOptions?.ssr);
2974
+ }
2975
+ if (id.startsWith("\0") && request.hasMacroQuery) {
2976
+ const realPath = request.strippedVirtualPath ?? "";
2977
+ if (request.isVueSfcPath) {
2978
+ const artifactLoad = loadDefinePageMetaArtifact(state, realPath, !!loadOptions?.ssr);
2979
+ if (artifactLoad) return artifactLoad;
2980
+ return {
2981
+ code: "export default {}",
2982
+ map: null
2983
+ };
2984
+ }
2985
+ }
2986
+ if (request.isVizeVirtual || pluginVisibleVirtualPath) {
2987
+ const realPath = request.vizeVirtualPath ?? pluginVisibleVirtualPath ?? "";
2988
+ const isSsr = request.isVizeSsrVirtual || isPluginVisibleSsrVirtualId(id) || !!loadOptions?.ssr;
2989
+ if (!realPath.endsWith(".vue")) {
2990
+ state.logger.log(`load: skipping non-vue virtual module ${realPath}`);
2991
+ return null;
2992
+ }
2993
+ if (!shouldLoadCompiledVueSfcPath(state, realPath)) return null;
2994
+ return loadCompiledSfcModule(state, realPath, isSsr, currentBase, loadOptions);
2995
+ }
2996
+ if (loadableVueSfcPath) {
2997
+ if (!shouldLoadCompiledVueSfcPath(state, loadableVueSfcPath, !!request.querySuffix && new URLSearchParams(request.querySuffix.slice(1)).has("nuxt_component"))) return null;
2998
+ return loadCompiledSfcModule(state, loadableVueSfcPath, !!loadOptions?.ssr, currentBase, loadOptions);
2999
+ }
3000
+ if (id.startsWith("\0")) {
3001
+ const afterPrefix = id.startsWith("\0vize:") ? id.slice(6) : id.slice(1);
3002
+ if (afterPrefix.includes("?commonjs-")) return null;
3003
+ const leakedRequest = classifyVitePluginRequest(afterPrefix);
3004
+ const fsPath = leakedRequest.normalizedFsId ? classifyVitePluginRequest(leakedRequest.normalizedFsId).path : leakedRequest.path;
3005
+ const querySuffix = leakedRequest.querySuffix;
3006
+ if (fsPath.startsWith("/") && fs.existsSync(fsPath) && fs.statSync(fsPath).isFile()) {
3007
+ const importPath = state.server === null ? `${pathToFileURL(fsPath).href}${querySuffix}` : "/@fs" + fsPath + querySuffix;
3008
+ state.logger.log(`load: proxying \0-prefixed file ${id} -> re-export from ${importPath}`);
3009
+ return `export { default } from ${JSON.stringify(importPath)};\nexport * from ${JSON.stringify(importPath)};`;
3010
+ }
3011
+ }
3012
+ return null;
3013
+ }
3014
+ function shouldLogSfcWarnings(state, realPath) {
3015
+ if (!realPath.includes("node_modules")) return true;
3016
+ if ((state.mergedOptions.handleNodeModulesVue ?? true) === false) return false;
3017
+ return state.filter(realPath);
3018
+ }
3019
+ function isJsxComponentPath(path) {
3020
+ return /\.[jt]sx$/.test(path) && !/\.(?:stories|story)\.[jt]sx$/.test(path);
3021
+ }
3022
+ function shouldTransformJsxRequest(state, request) {
3023
+ if (!isJsxComponentPath(request.path)) return false;
3024
+ if (request.querySuffix) {
3025
+ const params = new URLSearchParams(request.querySuffix.slice(1));
3026
+ if (params.has("raw") || params.has("url") || params.has("worker") || params.has("sharedworker")) return false;
3027
+ }
3028
+ if (!state.mergedOptions.include || !state.filter(request.path)) return false;
3029
+ return true;
3030
+ }
3031
+ /**
3032
+ * Route a raw `.jsx`/`.tsx` request through Vize's JSX compiler.
3033
+ *
3034
+ * Returns `undefined` when the request is not a JSX/TSX component (so the
3035
+ * caller falls through to the virtual-module pipeline), or a transform result
3036
+ * otherwise.
3037
+ */
3038
+ function transformJsxRequest(state, code, id, options) {
3039
+ const request = classifyVitePluginRequest(id);
3040
+ if (!shouldTransformJsxRequest(state, request)) return;
3041
+ const realPath = request.normalizedFsId ? classifyVitePluginRequest(request.normalizedFsId).path : request.path;
3042
+ const ssr = options?.ssr ?? false;
3043
+ const sourceMap = getCompileOptionsForRequest(state, ssr).sourceMap;
3044
+ const { code: compiled, map, warnings } = compileJsxModule(realPath, code, {
3045
+ jsxMode: state.mergedOptions.jsxMode,
3046
+ jsxCompat: state.mergedOptions.jsxCompat,
3047
+ vapor: state.mergedOptions.vapor ?? false,
3048
+ ssr,
3049
+ sourceMap
3050
+ });
3051
+ for (const warning of warnings) state.logger.warn(`Warning in ${realPath}: ${warning}`);
3052
+ return {
3053
+ code: compiled,
3054
+ map: map ? JSON.parse(map) : null
3055
+ };
3056
+ }
3057
+ async function transformHook(state, code, id, options) {
3058
+ if (!id.startsWith("\0") && !id.includes(".vue.ts") && !isJsxComponentPath(id)) return null;
3059
+ const pluginVisibleVirtualPath = fromPluginVisibleVirtualId(id);
3060
+ const jsxResult = transformJsxRequest(state, code, id, { ssr: options?.ssr });
3061
+ if (jsxResult !== void 0) return jsxResult;
3062
+ if (!id.startsWith("\0") && !pluginVisibleVirtualPath) return null;
3063
+ const request = classifyVitePluginRequest(id);
3064
+ if (request.isVizeVirtual || request.isMacroVirtualId || pluginVisibleVirtualPath) return transformVizeVirtualModule(state, code, request.isMacroVirtualId ? request.strippedVirtualPath ?? "" : request.vizeVirtualPath ?? pluginVisibleVirtualPath ?? "", options?.ssr ?? false, request.isMacroVirtualId);
3065
+ return null;
3066
+ }
3067
+ //#endregion
3068
+ //#region src/plugin/hmr-module-graph.ts
3069
+ function unique(values) {
3070
+ return [...new Set(values)];
3071
+ }
3072
+ function toViteFsFileId(fileId) {
3073
+ if (!path.isAbsolute(fileId)) return null;
3074
+ const normalized = fileId.replace(/\\/g, "/");
3075
+ return normalized.startsWith("/") ? `/@fs${normalized}` : `/@fs/${normalized}`;
3076
+ }
3077
+ function getVueModuleFileCandidates(vueFile) {
3078
+ const candidates = [
3079
+ toVirtualId(vueFile),
3080
+ toPluginVisibleVirtualId(vueFile),
3081
+ toVirtualId(vueFile, true),
3082
+ toPluginVisibleVirtualId(vueFile, true),
3083
+ toPluginVisibleVirtualId(vueFile).split("?")[0],
3084
+ vueFile
3085
+ ];
3086
+ const viteFsCandidates = candidates.flatMap((candidate) => {
3087
+ const viteFsId = toViteFsFileId(candidate);
3088
+ return viteFsId ? [viteFsId] : [];
3089
+ });
3090
+ return unique([...candidates, ...viteFsCandidates]);
3091
+ }
3092
+ function getStyleModuleFileCandidates(styleId) {
3093
+ return unique([styleId, `${styleId}.css`]);
3094
+ }
3095
+ async function collectModulesByFile(server, fileIds) {
3096
+ const modules = /* @__PURE__ */ new Set();
3097
+ for (const fileId of fileIds) {
3098
+ const add = (module) => {
3099
+ if (module) modules.add(module);
3100
+ };
3101
+ add(server.moduleGraph.getModuleById?.(fileId));
3102
+ if (!fileId.startsWith("\0")) try {
3103
+ add(await server.moduleGraph.getModuleByUrl?.(fileId));
3104
+ } catch {}
3105
+ for (const module of server.moduleGraph.getModulesByFile(fileId) ?? []) add(module);
3106
+ }
3107
+ return modules;
3108
+ }
3109
+ function preferAcceptingClientModules(modules, requireAcceptingClientModule = false) {
3110
+ const accepting = [...modules].filter((module) => {
3111
+ if (isVizeVirtual(module.url)) return !isVizeSsrVirtual(module.url);
3112
+ return fromPluginVisibleVirtualId(module.url) !== null && !isPluginVisibleSsrVirtualId(module.url);
3113
+ });
3114
+ if (accepting.length > 0) return new Set(accepting);
3115
+ return requireAcceptingClientModule ? /* @__PURE__ */ new Set() : modules;
3116
+ }
3117
+ function invalidateModules(server, modules) {
3118
+ for (const module of modules) server.moduleGraph.invalidateModule(module);
3119
+ }
3120
+ //#endregion
3121
+ //#region src/plugin/hmr.ts
3122
+ const VIZE_COMPONENTS_CSS_BASENAME = "vize-components.css";
3123
+ const VIZE_COMPONENTS_CSS_FILE = `assets/${VIZE_COMPONENTS_CSS_BASENAME}`;
3124
+ /**
3125
+ * The cached SFCs that pulled `dependencyFile` in through
3126
+ * `<script src>` / `<template src>` / `<style src>`.
3127
+ *
3128
+ * This runs as the first statement of every hot update, before the `.vue` fast
3129
+ * path, so editing an ordinary SFC pays for it too. It used to walk both caches
3130
+ * end to end with a `path.resolve` per dependency, which made HMR latency grow
3131
+ * with the number of components in the project; the caches now carry a reverse
3132
+ * index that answers it in constant time. See `compiled-module-cache.ts`.
3133
+ */
3134
+ function getVueFilesDependingOn(state, dependencyFile) {
3135
+ const normalizedDependency = path.resolve(dependencyFile);
3136
+ const owners = /* @__PURE__ */ new Set();
3137
+ for (const cache of [state.cache, state.ssrCache]) for (const vueFile of ownersOfDependency(cache, normalizedDependency)) owners.add(vueFile);
3138
+ return [...owners];
3139
+ }
3140
+ async function handleHotUpdateHook(state, ctx, options = {}) {
3141
+ const { file, server, read } = ctx;
3142
+ const clientDependencyOwners = new Set(ownersOfDependency(state.cache, path.resolve(file)));
3143
+ const dependencyOwners = getVueFilesDependingOn(state, file);
3144
+ if (dependencyOwners.length > 0) {
3145
+ const affectedModules = /* @__PURE__ */ new Set();
3146
+ for (const vueFile of dependencyOwners) {
3147
+ const collectedModules = await collectModulesByFile(server, getVueModuleFileCandidates(vueFile));
3148
+ const modules = options.requireAcceptingClientModule ? preferAcceptingClientModules(collectedModules, true) : collectedModules;
3149
+ if (options.requireAcceptingClientModule && modules.size === 0) {
3150
+ if (!options.ensureAcceptingClientModule || !clientDependencyOwners.has(vueFile)) continue;
3151
+ try {
3152
+ const ensured = await options.ensureAcceptingClientModule(vueFile);
3153
+ modules.add(ensured);
3154
+ } catch (error) {
3155
+ state.logger.error(`Failed to restore the client HMR owner for ${vueFile}:`, error);
3156
+ options.onRecompileError?.(error);
3157
+ return;
3158
+ }
3159
+ }
3160
+ evictCompiledModule(state.cache, vueFile);
3161
+ evictCompiledModule(state.ssrCache, vueFile);
3162
+ state.collectedCss.delete(vueFile);
3163
+ state.precompileMetadata.delete(vueFile);
3164
+ state.pendingHmrUpdateTypes.set(vueFile, "full-reload");
3165
+ for (const module of modules) {
3166
+ server.moduleGraph.invalidateModule(module);
3167
+ affectedModules.add(module);
3168
+ }
3169
+ state.logger.log(`Invalidated ${path.relative(state.root, vueFile)} because ${path.relative(state.root, file)} changed`);
3170
+ }
3171
+ return [...affectedModules];
3172
+ }
3173
+ if (file.endsWith(".vue") && state.filter(file)) try {
3174
+ const initialModules = options.requireAcceptingClientModule ? preferAcceptingClientModules(await collectModulesByFile(server, getVueModuleFileCandidates(file)), true) : void 0;
3175
+ if (initialModules?.size === 0) return [];
3176
+ const source = await read();
3177
+ const prevCompiled = state.cache.get(file);
3178
+ compileFile(file, state.cache, getCompileOptionsForRequest(state, false), source);
3179
+ state.ssrCache.delete(file);
3180
+ const newCompiled = state.cache.get(file);
3181
+ try {
3182
+ const stat = fs.statSync(file);
3183
+ state.precompileMetadata.set(file, {
3184
+ mtimeMs: stat.mtimeMs,
3185
+ size: stat.size
3186
+ });
3187
+ } catch {
3188
+ state.precompileMetadata.delete(file);
3189
+ }
3190
+ if (!hasHmrChanges(prevCompiled, newCompiled)) {
3191
+ state.pendingHmrUpdateTypes.delete(file);
3192
+ state.logger.log(`Re-compiled: ${path.relative(state.root, file)} (no-op)`);
3193
+ return [];
3194
+ }
3195
+ const updateType = detectHmrUpdateType(prevCompiled, newCompiled);
3196
+ state.logger.log(`Re-compiled: ${path.relative(state.root, file)} (${updateType})`);
3197
+ const modules = preferAcceptingClientModules(initialModules ?? await collectModulesByFile(server, getVueModuleFileCandidates(file)), options.requireAcceptingClientModule);
3198
+ const hasDelegated = hasDelegatedStyles(newCompiled);
3199
+ if (isPluginVueCustomElement(state.mergedOptions, file) && updateType === "style-only") {
3200
+ if (modules.size > 0) {
3201
+ state.pendingHmrUpdateTypes.set(file, "full-reload");
3202
+ invalidateModules(server, modules);
3203
+ return [...modules];
3204
+ }
3205
+ state.pendingHmrUpdateTypes.delete(file);
3206
+ return [];
3207
+ }
3208
+ if (hasDelegated && updateType === "style-only") {
3209
+ const affectedModules = /* @__PURE__ */ new Set();
3210
+ for (const block of newCompiled.styles ?? []) {
3211
+ const params = new URLSearchParams();
3212
+ params.set("vue", "");
3213
+ params.set("type", "style");
3214
+ params.set("index", String(block.index));
3215
+ if (block.scoped) params.set("scoped", `data-v-${newCompiled.scopeId}`);
3216
+ params.set("lang", block.lang ?? "css");
3217
+ if (block.module !== false) params.set("module", typeof block.module === "string" ? block.module : "");
3218
+ const styleMods = await collectModulesByFile(server, getStyleModuleFileCandidates(`${file}?${params.toString()}`));
3219
+ for (const mod of styleMods) affectedModules.add(mod);
3220
+ }
3221
+ if (affectedModules.size > 0) return [...affectedModules];
3222
+ if (modules.size > 0) return [...modules];
3223
+ return [];
3224
+ }
3225
+ if (updateType === "style-only" && newCompiled.css && !hasDelegated) {
3226
+ state.pendingHmrUpdateTypes.delete(file);
3227
+ server.ws.send({
3228
+ type: "custom",
3229
+ event: "vize:update",
3230
+ data: {
3231
+ id: newCompiled.scopeId,
3232
+ type: "style-only",
3233
+ css: resolveCssImports(newCompiled.css, file, state.cssAliasRules, true, state.clientViteBase)
3234
+ }
3235
+ });
3236
+ return [];
3237
+ }
3238
+ if (modules.size > 0) {
3239
+ state.pendingHmrUpdateTypes.set(file, updateType);
3240
+ invalidateModules(server, modules);
3241
+ return [...modules];
3242
+ }
3243
+ state.pendingHmrUpdateTypes.delete(file);
3244
+ } catch (e) {
3245
+ state.logger.error(`Re-compilation failed for ${file}:`, e);
3246
+ options.onRecompileError?.(e);
3247
+ }
3248
+ }
3249
+ function handleGenerateBundleHook(state, emitFile, bundle) {
3250
+ if (!state.extractCss || state.collectedCss.size === 0) return;
3251
+ let allCss = "";
3252
+ for (const css of state.collectedCss.values()) allCss += allCss ? `\n\n${css}` : css;
3253
+ if (allCss.trim()) {
3254
+ const cssFileName = state.componentsCssFileName || VIZE_COMPONENTS_CSS_FILE;
3255
+ emitFile({
3256
+ type: "asset",
3257
+ fileName: cssFileName,
3258
+ source: allCss
3259
+ });
3260
+ attachComponentsCssToEntryChunks(bundle, cssFileName);
3261
+ state.logger.log(`Extracted CSS to ${cssFileName} (${state.collectedCss.size} components)`);
3262
+ }
3263
+ }
3264
+ function resolveComponentsCssFileName(assetsDir) {
3265
+ const normalizedAssetsDir = (assetsDir || "assets").replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
3266
+ if (!normalizedAssetsDir || normalizedAssetsDir === ".") return VIZE_COMPONENTS_CSS_BASENAME;
3267
+ return `${normalizedAssetsDir}/${VIZE_COMPONENTS_CSS_BASENAME}`;
3268
+ }
3269
+ function attachComponentsCssToEntryChunks(bundle, cssFileName) {
3270
+ for (const item of Object.values(bundle)) {
3271
+ if (item.type !== "chunk" || !item.isEntry && !item.isDynamicEntry) continue;
3272
+ item.viteMetadata ??= {};
3273
+ item.viteMetadata.importedCss ??= /* @__PURE__ */ new Set();
3274
+ item.viteMetadata.importedCss.add(cssFileName);
3275
+ }
3276
+ }
3277
+ //#endregion
3278
+ //#region src/plugin/hot-update-environment.ts
3279
+ async function handleHotUpdateEnvironmentHook(state, environment, options) {
3280
+ if (environment.name !== "client" && environment.name !== "browser") return options.modules;
3281
+ const server = {
3282
+ moduleGraph: environment.moduleGraph,
3283
+ ws: { send: environment.hot.send.bind(environment.hot) }
3284
+ };
3285
+ let recompileFailed = false;
3286
+ const modules = await handleHotUpdateHook(state, {
3287
+ ...options,
3288
+ server
3289
+ }, {
3290
+ ensureAcceptingClientModule: (vueFile) => environment.moduleGraph.ensureEntryFromUrl(toPluginVisibleVirtualId(vueFile), false),
3291
+ requireAcceptingClientModule: true,
3292
+ onRecompileError: () => {
3293
+ recompileFailed = true;
3294
+ }
3295
+ });
3296
+ if (recompileFailed) return;
3297
+ if (modules === void 0 && options.file.endsWith(".vue") && state.filter(options.file)) return [];
3298
+ return modules;
3299
+ }
3300
+ //#endregion
3301
+ //#region src/plugin/compat.ts
3302
+ /**
3303
+ * The `vite:vue` shim a host framework probes for a Vue plugin.
3304
+ *
3305
+ * `api.include` / `api.exclude` report the patterns behind `state.filter`, and
3306
+ * assigning them rewrites the plugin's own options — the only window where that
3307
+ * is meaningful is before `configResolved` builds the filter, so a later write
3308
+ * throws rather than silently doing nothing (#3227). Upstream guards the same
3309
+ * way, keyed on its `options` hook instead.
3310
+ */
3311
+ function createVueCompatPlugin(state, options) {
3312
+ let compilerSfc = null;
3313
+ const templateOptions = { compilerOptions: {
3314
+ directiveTransforms: {},
3315
+ nodeTransforms: []
3316
+ } };
3317
+ const loadCompilerSfc = () => {
3318
+ if (!compilerSfc) try {
3319
+ compilerSfc = createRequire(import.meta.url)("@vue/compiler-sfc");
3320
+ } catch {
3321
+ compilerSfc = { parse: () => ({
3322
+ descriptor: {},
3323
+ errors: []
3324
+ }) };
3325
+ }
3326
+ return compilerSfc;
3327
+ };
3328
+ const configured = () => state.initialized ? state.mergedOptions : options;
3329
+ const assertUnresolved = (name) => {
3330
+ if (state.initialized) throw new Error(`${name} cannot be updated after the filter is resolved`);
3331
+ };
3332
+ return {
3333
+ name: "vite:vue",
3334
+ api: {
3335
+ get options() {
3336
+ return {
3337
+ compiler: loadCompilerSfc(),
3338
+ isProduction: state.isProduction ?? false,
3339
+ root: state.root ?? process.cwd(),
3340
+ template: templateOptions
3341
+ };
3342
+ },
3343
+ get include() {
3344
+ return configured().include ?? DEFAULT_INCLUDE_PATTERN;
3345
+ },
3346
+ set include(value) {
3347
+ assertUnresolved("include");
3348
+ options.include = value;
3349
+ },
3350
+ get exclude() {
3351
+ return configured().exclude ?? DEFAULT_EXCLUDE_PATTERN;
3352
+ },
3353
+ set exclude(value) {
3354
+ assertUnresolved("exclude");
3355
+ options.exclude = value;
3356
+ },
3357
+ version: PLUGIN_VUE_COMPAT_VERSION
3358
+ }
3359
+ };
3360
+ }
3361
+ function normalizeVirtualStyleId(id) {
3362
+ const withoutPrefix = id.startsWith("\0") ? id.slice(1) : id;
3363
+ if (!withoutPrefix.includes("?vue")) return id;
3364
+ return withoutPrefix.replace(/\.module\.\w+$/, "").replace(/\.\w+$/, "");
3365
+ }
3366
+ /**
3367
+ * String pre-gate for {@link transformScopedPreprocessorCss} (#3427).
3368
+ *
3369
+ * The post-transform plugin's `transform` hook sees every module in the graph,
3370
+ * and without this every one of them crossed the NAPI boundary to be told it is
3371
+ * not a style query. The native `isVueStyleQuery` is
3372
+ * `query.contains("vue&type=style") || query.contains("vue=&type=style")`, both
3373
+ * of which contain `type=style`; the query is a substring of the id, and
3374
+ * `normalizeVirtualStyleId` only ever deletes characters, so a normalized id
3375
+ * that classifies as a style query implies `type=style` in the raw id.
3376
+ */
3377
+ function mayBeVueStyleQuery(id) {
3378
+ return id.includes("type=style");
3379
+ }
3380
+ function transformScopedPreprocessorCss(code, id) {
3381
+ if (!mayBeVueStyleQuery(id)) return null;
3382
+ const request = classifyVitePluginRequest(normalizeVirtualStyleId(id));
3383
+ if (!request.isVueStyleQuery || !request.styleScoped || !request.styleLang || request.styleLang === "css") return null;
3384
+ return scopeCssForPipeline(code, request.styleScoped);
3385
+ }
3386
+ function createStylePostTransformPlugin() {
3387
+ return {
3388
+ name: "vize:style-post-transform",
3389
+ transform(code, id) {
3390
+ const scoped = transformScopedPreprocessorCss(code, id);
3391
+ return scoped === null ? null : {
3392
+ code: scoped,
3393
+ map: null
3394
+ };
3395
+ }
3396
+ };
3397
+ }
3398
+ function stripQuery(id) {
3399
+ const queryStart = id.search(/[?#]/);
3400
+ return queryStart === -1 ? id : id.slice(0, queryStart);
3401
+ }
3402
+ function isSfcLikeSource(code) {
3403
+ return /^<(?:template|script|style)(?:\s|>|\/)/.test(code.trimStart());
3404
+ }
3405
+ function shouldPostTransformSfcLikeModule(state, id) {
3406
+ const filename = stripQuery(id);
3407
+ if (filename.endsWith(".vue") || filename.endsWith(".vue.ts") || filename.endsWith(".vue.tsx") || filename.includes("node_modules")) return false;
3408
+ if (filename.endsWith(".setup.ts")) return true;
3409
+ if (state.filter(filename) || state.filter(id)) return true;
3410
+ return /\.(?:md|markdown)$/i.test(filename);
3411
+ }
3412
+ function createPostTransformPlugin(state) {
3413
+ return {
3414
+ name: "vize:post-transform",
3415
+ enforce: "post",
3416
+ async transform(code, id, transformOptions) {
3417
+ if (shouldPostTransformSfcLikeModule(state, id) && isSfcLikeSource(code)) {
3418
+ state.logger.log(`post-transform: compiling virtual SFC content from ${id}`);
3419
+ try {
3420
+ const isSsr = !!transformOptions?.ssr;
3421
+ const extractCss = shouldExtractCssForRequest(state, isSsr);
3422
+ const compiled = compileFile(id, getEnvironmentCache(state, isSsr), getCompileOptionsForRequest(state, isSsr), code);
3423
+ syncCollectedCssForFile({
3424
+ ...state,
3425
+ extractCss
3426
+ }, id, compiled);
3427
+ const result = await transformVirtualTypeScript(generateOutput(compiled, {
3428
+ isProduction: state.isProduction,
3429
+ isDev: state.server !== null,
3430
+ ssr: isSsr,
3431
+ extractCss,
3432
+ filePath: id
3433
+ }), id);
3434
+ const defines = transformOptions?.ssr ? state.serverViteDefine : state.clientViteDefine;
3435
+ let transformed = result.code;
3436
+ if (Object.keys(defines).length > 0) transformed = applyDefineReplacements(transformed, defines);
3437
+ return {
3438
+ code: transformed,
3439
+ map: null
3440
+ };
3441
+ } catch (e) {
3442
+ state.logger.error(`Virtual SFC compilation failed for ${id}:`, e);
3443
+ }
3444
+ }
3445
+ return null;
3446
+ }
3447
+ };
3448
+ }
3449
+ //#endregion
3450
+ //#region src/plugin/unocss.ts
3451
+ const bridgePatched$1 = Symbol("vize.unocssBridgePatched");
3452
+ const VIZE_SSR_PREFIX$1 = "\0vize-ssr:";
3453
+ const plainSsrPrefix$1 = VIZE_SSR_PREFIX$1.slice(1);
3454
+ function stripBridgePrefix$1(id) {
3455
+ if (id.startsWith(VIZE_SSR_PREFIX$1)) return id.slice(10);
3456
+ if (id.startsWith(plainSsrPrefix$1)) return id.slice(plainSsrPrefix$1.length);
3457
+ if (id.startsWith("\0")) return id.slice(1);
3458
+ return id;
3459
+ }
3460
+ function isUnoCssBridgeModuleId(id) {
3461
+ return /\.vue\.tsx?(?:\?|$)/.test(stripBridgePrefix$1(id));
3462
+ }
3463
+ function normalizeUnoCssBridgeModuleId(id) {
3464
+ return stripBridgePrefix$1(id).replace(/\.tsx?(?=\?|$)/, "");
3465
+ }
3466
+ function appendOriginalVueSourceForUnoCss(code, normalizedId) {
3467
+ const sourcePath = normalizedId.split("?")[0];
3468
+ if (!sourcePath) return code;
3469
+ try {
3470
+ if (fs.statSync(sourcePath).size > 2097152) return code;
3471
+ } catch {
3472
+ return code;
3473
+ }
3474
+ try {
3475
+ return `${code}\n${fs.readFileSync(sourcePath, "utf-8")}`;
3476
+ } catch {
3477
+ return code;
3478
+ }
3479
+ }
3480
+ function patchUnoCssBridge(plugins) {
3481
+ for (const plugin of plugins) {
3482
+ if (!plugin.name?.startsWith("unocss:") || typeof plugin.transform !== "function" || plugin[bridgePatched$1]) continue;
3483
+ const originalTransform = plugin.transform;
3484
+ const isExtractionOnly = plugin.name.startsWith("unocss:global");
3485
+ plugin.transform = function(code, id, ...args) {
3486
+ if (!isUnoCssBridgeModuleId(id)) return originalTransform.call(this, code, id, ...args);
3487
+ const normalizedId = normalizeUnoCssBridgeModuleId(id);
3488
+ let effectiveCode = code;
3489
+ if (isExtractionOnly) effectiveCode = appendOriginalVueSourceForUnoCss(code, normalizedId);
3490
+ return originalTransform.call(this, effectiveCode, normalizedId, ...args);
3491
+ };
3492
+ plugin[bridgePatched$1] = true;
3493
+ }
3494
+ }
3495
+ //#endregion
3496
+ //#region src/plugin/quasar.ts
3497
+ const bridgePatched = Symbol("vize.quasarBridgePatched");
3498
+ const VIZE_SSR_PREFIX = "\0vize-ssr:";
3499
+ const LEGACY_VIZE_PREFIX = "\0vize:";
3500
+ const plainSsrPrefix = VIZE_SSR_PREFIX.slice(1);
3501
+ const plainLegacyPrefix = LEGACY_VIZE_PREFIX.slice(1);
3502
+ function stripBridgePrefix(id) {
3503
+ if (id.startsWith(VIZE_SSR_PREFIX)) return id.slice(10);
3504
+ if (id.startsWith(LEGACY_VIZE_PREFIX)) return id.slice(6);
3505
+ if (id.startsWith(plainSsrPrefix)) return id.slice(plainSsrPrefix.length);
3506
+ if (id.startsWith(plainLegacyPrefix)) return id.slice(plainLegacyPrefix.length);
3507
+ if (id.startsWith("\0")) return id.slice(1);
3508
+ return id;
3509
+ }
3510
+ function isQuasarBridgeModuleId(id) {
3511
+ return /\.vue\.tsx?(?:[?#]|$)/.test(stripBridgePrefix(id));
3512
+ }
3513
+ function normalizeQuasarBridgeModuleId(id) {
3514
+ return stripBridgePrefix(id).replace(/\.vue\.tsx?(?=[?#]|$)/, ".vue");
3515
+ }
3516
+ function patchQuasarBridge(plugins) {
3517
+ for (const plugin of plugins) {
3518
+ if (plugin.name !== "vite:quasar:script" || typeof plugin.transform !== "function" || plugin[bridgePatched]) continue;
3519
+ const originalTransform = plugin.transform;
3520
+ plugin.transform = function(code, id, ...args) {
3521
+ if (!isQuasarBridgeModuleId(id)) return originalTransform.call(this, code, id, ...args);
3522
+ return originalTransform.call(this, code, normalizeQuasarBridgeModuleId(id), ...args);
3523
+ };
3524
+ plugin[bridgePatched] = true;
3525
+ }
3526
+ }
3527
+ //#endregion
3528
+ //#region src/plugin/css-modules.ts
3529
+ function patchCssModuleGenerateScopedName(userConfig) {
3530
+ const cssModules = userConfig.css?.modules;
3531
+ if (!cssModules || typeof cssModules.generateScopedName !== "function") return;
3532
+ const origFn = cssModules.generateScopedName;
3533
+ cssModules.generateScopedName = function(name, filename, css) {
3534
+ return origFn.call(this, name, normalizeCssModuleFilename(filename), css);
3535
+ };
3536
+ }
3537
+ function normalizeCssModuleFilename(filename) {
3538
+ const normalized = normalizeViteCssModuleFilename(filename);
3539
+ if (normalized.startsWith("/@fs/")) return normalized.slice(4);
3540
+ return normalized;
3541
+ }
3542
+ //#endregion
3543
+ //#region src/plugin/inspector-lint-plan.ts
3544
+ const VIZE_INSPECTOR_LINT_PLAN_ENDPOINT = "/__vize/inspector/lint-plan";
3545
+ const MAX_REQUEST_URL_BYTES = 8 * 1024;
3546
+ const MAX_FILE_COUNT = 128;
3547
+ const MAX_FILE_BYTES = 4 * 1024;
3548
+ const MAX_RESPONSE_BYTES = 4 * 1024 * 1024;
3549
+ const ALLOWED_QUERY_KEYS = new Set(["file", "fresh"]);
3550
+ function installInspectorLintPlanMiddleware(devServer, state) {
3551
+ const provider = state.mergedOptions.inspector?.lintPlan;
3552
+ if (!provider) return;
3553
+ devServer.middlewares.use((req, res, next) => {
3554
+ if (!isInspectorLintPlanRequest(req.url, state.clientViteBase)) {
3555
+ next();
3556
+ return;
3557
+ }
3558
+ handleInspectorLintPlanRequest(req, res, provider, state.logger, state.clientViteBase);
3559
+ });
3560
+ }
3561
+ function isInspectorLintPlanRequest(reqUrl, base = "/") {
3562
+ if (!reqUrl) return false;
3563
+ try {
3564
+ return new URL(reqUrl, "http://localhost").pathname === resolveInspectorEndpoint(base);
3565
+ } catch {
3566
+ return false;
3567
+ }
3568
+ }
3569
+ function parseInspectorLintPlanRequest(reqUrl, base = "/") {
3570
+ if (!reqUrl || !isInspectorLintPlanRequest(reqUrl, base)) return null;
3571
+ if (Buffer.byteLength(reqUrl) > MAX_REQUEST_URL_BYTES) return {
3572
+ statusCode: 414,
3573
+ error: "request_uri_too_long"
3574
+ };
3575
+ const url = new URL(reqUrl, "http://localhost");
3576
+ for (const key of url.searchParams.keys()) if (!ALLOWED_QUERY_KEYS.has(key)) return {
3577
+ statusCode: 400,
3578
+ error: "invalid_query"
3579
+ };
3580
+ const freshValues = url.searchParams.getAll("fresh");
3581
+ if (freshValues.length > 1 || freshValues[0] !== void 0 && freshValues[0] !== "1") return {
3582
+ statusCode: 400,
3583
+ error: "invalid_fresh"
3584
+ };
3585
+ const rawFiles = url.searchParams.getAll("file");
3586
+ if (rawFiles.length > MAX_FILE_COUNT) return {
3587
+ statusCode: 413,
3588
+ error: "too_many_files"
3589
+ };
3590
+ const files = [];
3591
+ const seen = /* @__PURE__ */ new Set();
3592
+ for (const file of rawFiles) {
3593
+ if (!isSafeInspectorFile(file)) return {
3594
+ statusCode: 400,
3595
+ error: "invalid_file"
3596
+ };
3597
+ if (!seen.has(file)) {
3598
+ seen.add(file);
3599
+ files.push(file);
3600
+ }
3601
+ }
3602
+ return { request: {
3603
+ files,
3604
+ fresh: freshValues[0] === "1"
3605
+ } };
3606
+ }
3607
+ async function handleInspectorLintPlanRequest(req, res, provider, logger, base = "/") {
3608
+ if (req.method !== "GET" && req.method !== "HEAD") {
3609
+ res.setHeader("allow", "GET, HEAD");
3610
+ sendJson$1(res, 405, { error: "method_not_allowed" });
3611
+ return;
3612
+ }
3613
+ const parsed = parseInspectorLintPlanRequest(req.url, base);
3614
+ if (!parsed) {
3615
+ sendJson$1(res, 404, { error: "not_found" });
3616
+ return;
3617
+ }
3618
+ if ("error" in parsed) {
3619
+ sendJson$1(res, parsed.statusCode, { error: parsed.error }, req.method === "HEAD");
3620
+ return;
3621
+ }
3622
+ try {
3623
+ sendJson$1(res, 200, await provider(parsed.request), req.method === "HEAD");
3624
+ } catch (error) {
3625
+ logger.error("Failed to build inspector lint plan:", error);
3626
+ sendJson$1(res, 500, { error: "inspector_lint_plan_failed" }, req.method === "HEAD");
3627
+ }
3628
+ }
3629
+ function resolveInspectorEndpoint(base) {
3630
+ return `${new URL(base, "http://localhost").pathname.replace(/\/+$/, "")}${VIZE_INSPECTOR_LINT_PLAN_ENDPOINT}`;
3631
+ }
3632
+ function isSafeInspectorFile(file) {
3633
+ if (file.length === 0 || Buffer.byteLength(file) > MAX_FILE_BYTES || file.includes("\0") || file.includes("\\") || path.posix.isAbsolute(file)) return false;
3634
+ return !file.split("/").some((segment) => segment === ".." || segment.length === 0);
3635
+ }
3636
+ function sendJson$1(res, statusCode, payload, headOnly = false) {
3637
+ let body = JSON.stringify(payload);
3638
+ if (body === void 0) throw new TypeError("Inspector payload is not JSON serializable");
3639
+ if (Buffer.byteLength(body) > MAX_RESPONSE_BYTES) {
3640
+ statusCode = 413;
3641
+ body = JSON.stringify({ error: "inspector_response_too_large" });
3642
+ }
3643
+ res.statusCode = statusCode;
3644
+ res.setHeader("cache-control", "no-store");
3645
+ res.setHeader("content-type", "application/json; charset=utf-8");
3646
+ res.setHeader("content-length", Buffer.byteLength(body));
3647
+ res.setHeader("x-content-type-options", "nosniff");
3648
+ res.end(headOnly ? void 0 : body);
3649
+ }
3650
+ //#endregion
3651
+ //#region src/plugin/dev-middleware.ts
3652
+ const VIZE_INSPECTOR_GRAPH_ENDPOINT = "/__vize/inspector/graph";
3653
+ const INSPECTOR_SCRIPT_PATTERNS = ["**/*.{js,jsx,ts,tsx}"];
3654
+ const INSPECTOR_EXTRA_IGNORE_PATTERNS = ["**/*.d.ts"];
3655
+ const INSPECTOR_FILE_EXTENSION_RE = /\.(?:vue|[jt]sx?)$/;
3656
+ function installDevMiddleware(devServer, state) {
3657
+ installVirtualAssetMiddleware(devServer, state);
3658
+ installInspectorGraphMiddleware(devServer, state);
3659
+ installInspectorLintPlanMiddleware(devServer, state);
3660
+ }
3661
+ function installVirtualAssetMiddleware(devServer, state) {
3662
+ devServer.middlewares.use((req, _res, next) => {
3663
+ const rewrite = req.url ? normalizeViteDevMiddlewareUrl(req.url) : null;
3664
+ if (rewrite && fs.existsSync(rewrite.fsPath) && fs.statSync(rewrite.fsPath).isFile()) {
3665
+ state.logger.log(`middleware: rewriting ${req.url} -> ${rewrite.cleanedUrl}`);
3666
+ req.url = rewrite.cleanedUrl;
3667
+ }
3668
+ next();
3669
+ });
3670
+ }
3671
+ function installInspectorGraphMiddleware(devServer, state) {
3672
+ devServer.middlewares.use((req, res, next) => {
3673
+ if (!isInspectorGraphRequest(req.url)) {
3674
+ next();
3675
+ return;
3676
+ }
3677
+ handleInspectorGraphRequest(req, res, state);
3678
+ });
3679
+ }
3680
+ async function createInspectorGraphPayload(state) {
3681
+ const files = await collectInspectorSourceFiles(state);
3682
+ return {
3683
+ schema: "vize.inspector.graph",
3684
+ version: 1,
3685
+ root: state.root,
3686
+ fileCount: files.length,
3687
+ graph: buildInspectorGraph(files)
3688
+ };
3689
+ }
3690
+ async function collectInspectorSourceFiles(state) {
3691
+ const paths = await glob(resolveInspectorScanPatterns(state.scanPatterns), {
3692
+ cwd: state.root,
3693
+ absolute: true,
3694
+ followSymbolicLinks: false,
3695
+ ignore: [...state.ignorePatterns, ...INSPECTOR_EXTRA_IGNORE_PATTERNS]
3696
+ });
3697
+ const files = [];
3698
+ for (const filePath of [...new Set(paths)].sort()) {
3699
+ if (!INSPECTOR_FILE_EXTENSION_RE.test(filePath)) continue;
3700
+ const stat = statFile(filePath);
3701
+ if (!stat) continue;
3702
+ if (!stat.isFile() || stat.isSymbolicLink()) continue;
3703
+ if (!isPathInsideRoot(state.root, filePath)) continue;
3704
+ files.push({
3705
+ path: normalizeInspectorPath(state.root, filePath),
3706
+ source: fs.readFileSync(filePath, "utf-8")
3707
+ });
3708
+ }
3709
+ return files;
3710
+ }
3711
+ function isInspectorGraphRequest(reqUrl) {
3712
+ if (!reqUrl) return false;
3713
+ try {
3714
+ return new URL(reqUrl, "http://localhost").pathname === VIZE_INSPECTOR_GRAPH_ENDPOINT;
3715
+ } catch {
3716
+ return false;
3717
+ }
3718
+ }
3719
+ function resolveInspectorScanPatterns(scanPatterns) {
3720
+ return [...scanPatterns && scanPatterns.length > 0 ? scanPatterns : ["**/*.vue"], ...INSPECTOR_SCRIPT_PATTERNS];
3721
+ }
3722
+ function normalizeInspectorPath(root, filePath) {
3723
+ return path.relative(root, filePath).split(path.sep).join("/");
3724
+ }
3725
+ function isPathInsideRoot(root, filePath) {
3726
+ try {
3727
+ const realRoot = fs.realpathSync.native(root);
3728
+ const realFile = fs.realpathSync.native(filePath);
3729
+ const relative = path.relative(realRoot, realFile);
3730
+ return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
3731
+ } catch {
3732
+ return false;
3733
+ }
3734
+ }
3735
+ function statFile(filePath) {
3736
+ try {
3737
+ return fs.lstatSync(filePath);
3738
+ } catch {
3739
+ return null;
3740
+ }
3741
+ }
3742
+ async function handleInspectorGraphRequest(req, res, state) {
3743
+ if (req.method !== "GET" && req.method !== "HEAD") {
3744
+ sendJson(res, 405, { error: "method_not_allowed" });
3745
+ return;
3746
+ }
3747
+ try {
3748
+ sendJson(res, 200, await createInspectorGraphPayload(state), req.method === "HEAD");
3749
+ } catch (error) {
3750
+ state.logger.error("Failed to build inspector graph:", error);
3751
+ sendJson(res, 500, {
3752
+ error: "inspector_graph_failed",
3753
+ message: formatUnknownError(error)
3754
+ });
3755
+ }
3756
+ }
3757
+ function sendJson(res, statusCode, payload, headOnly = false) {
3758
+ const body = JSON.stringify(payload);
3759
+ res.statusCode = statusCode;
3760
+ res.setHeader("content-type", "application/json; charset=utf-8");
3761
+ res.setHeader("content-length", Buffer.byteLength(body));
3762
+ res.end(headOnly ? void 0 : body);
3763
+ }
3764
+ function formatUnknownError(error) {
3765
+ return error instanceof Error ? error.message : String(error);
3766
+ }
3767
+ //#endregion
3768
+ //#region src/plugin/experimentals.ts
3769
+ function isExperimentalEnabled(value) {
3770
+ return value !== void 0 && value !== null && value !== false;
3771
+ }
3772
+ function resolveExperimentalOptions(options, config) {
3773
+ const pick = (...values) => values.find((value) => value !== void 0);
3774
+ const enabled = (...values) => isExperimentalEnabled(pick(...values));
3775
+ return {
3776
+ vapor: enabled(options?.vapor, config?.vapor),
3777
+ jsxVapor: enabled(options?.jsxVapor, config?.jsxVapor),
3778
+ inTagComments: enabled(options?.intagComment, options?.inTagComment, config?.intagComment, config?.inTagComment),
3779
+ patternedTemplate: enabled(options?.pattenedTemplate, options?.patternedTemplate, config?.pattenedTemplate, config?.patternedTemplate),
3780
+ selfComponent: enabled(options?.selfComponent, config?.selfComponent),
3781
+ strictSlotChildren: enabled(options?.strictSlotChildren, config?.strictSlotChildren),
3782
+ serverScript: enabled(options?.serverScript, options?.["server script"], config?.serverScript, config?.["server script"])
3783
+ };
3784
+ }
3785
+ function resolveExperimentalCompilerOptions(options, compilerConfig, config) {
3786
+ const experimentals = resolveExperimentalOptions(options.experimentals, config);
3787
+ return {
3788
+ vapor: options.vapor ?? compilerConfig?.vapor ?? experimentals.vapor,
3789
+ jsxMode: options.jsxMode ?? compilerConfig?.jsxMode ?? (experimentals.jsxVapor ? "vapor" : void 0),
3790
+ jsxCompat: options.jsxCompat ?? compilerConfig?.jsxCompat,
3791
+ experimentalInTagComments: experimentals.inTagComments,
3792
+ experimentalPatternedTemplate: experimentals.patternedTemplate,
3793
+ experimentalSelfComponent: experimentals.selfComponent,
3794
+ experimentalStrictSlotChildren: experimentals.strictSlotChildren,
3795
+ experimentalServerScript: experimentals.serverScript
3796
+ };
3797
+ }
3798
+ //#endregion
3799
+ //#region src/plugin/vue-version.ts
3800
+ function isLegacyVueVersion(version) {
3801
+ return version === "legacy" || version === .11 || version === 1 || version === 2 || version === "2.7";
3802
+ }
3803
+ function isLegacyVueCompatibilityMode(options) {
3804
+ const vueVersion = options.vueVersion ?? options.compatibility?.vueVersion;
3805
+ return (options.compatibility?.hostCompiler ?? isLegacyVueVersion(vueVersion)) && isLegacyVueVersion(vueVersion);
3806
+ }
3807
+ function hasHostVueSfcCompilerPlugin(plugins) {
3808
+ return plugins.some((plugin) => {
3809
+ const name = plugin.name;
3810
+ return name === "vite:vue" || name === "vite:vue2" || name.includes("plugin-vue") || name.includes("vue2");
3811
+ });
3812
+ }
3813
+ function createLegacyVueCompatibilityPlugin(options) {
3814
+ return {
3815
+ name: "vite-plugin-vize:legacy-vue-compat",
3816
+ configResolved(resolvedConfig) {
3817
+ if (!hasHostVueSfcCompilerPlugin(resolvedConfig.plugins)) throw new Error("vite-plugin-vize: legacy Vue host-compiler mode requires a host Vue SFC compiler plugin. Add @vitejs/plugin-vue2 (or your framework's Vue 2 Vite SFC plugin), or set compatibility.hostCompiler=false if this project can use Vize's compiler pipeline.");
3818
+ createLogger(options.debug ?? false).log(`Legacy Vue compatibility mode is active for ${resolvedConfig.root}; Vize will not compile .vue files.`);
3819
+ }
3820
+ };
3821
+ }
3822
+ //#endregion
3823
+ //#region src/plugin/config-lifecycle.ts
3824
+ const compatibilityOwners = /* @__PURE__ */ new Map();
3825
+ const compatibilityRegistrations = /* @__PURE__ */ new WeakMap();
3826
+ function releaseCompatibilityRegistration(resolvedConfig) {
3827
+ const registration = compatibilityRegistrations.get(resolvedConfig);
3828
+ compatibilityRegistrations.delete(resolvedConfig);
3829
+ if (!registration || compatibilityOwners.get(registration.root) !== registration.token) return;
3830
+ compatibilityOwners.delete(registration.root);
3831
+ if (vizeConfigStore.get(registration.root) === registration.config) vizeConfigStore.delete(registration.root);
3832
+ }
3833
+ function unregisterConfig(resolvedConfig) {
3834
+ unregisterResolvedVizeConfig(resolvedConfig);
3835
+ releaseCompatibilityRegistration(resolvedConfig);
3836
+ }
3837
+ async function register(resolvedConfig, root, sharedConfigPromise) {
3838
+ releaseCompatibilityRegistration(resolvedConfig);
3839
+ const token = Symbol(root);
3840
+ compatibilityOwners.set(root, token);
3841
+ vizeConfigStore.delete(root);
3842
+ registerResolvedVizeConfig(resolvedConfig, sharedConfigPromise);
3843
+ let sharedConfig;
3844
+ try {
3845
+ sharedConfig = await sharedConfigPromise;
3846
+ } catch (error) {
3847
+ unregisterResolvedVizeConfig(resolvedConfig);
3848
+ if (compatibilityOwners.get(root) === token) {
3849
+ compatibilityOwners.delete(root);
3850
+ vizeConfigStore.delete(root);
3851
+ }
3852
+ throw error;
3853
+ }
3854
+ if (compatibilityOwners.get(root) !== token) return sharedConfig;
3855
+ if (sharedConfig) {
3856
+ compatibilityRegistrations.set(resolvedConfig, {
3857
+ config: sharedConfig,
3858
+ root,
3859
+ token
3860
+ });
3861
+ vizeConfigStore.set(root, sharedConfig);
3862
+ } else {
3863
+ compatibilityOwners.delete(root);
3864
+ vizeConfigStore.delete(root);
3865
+ }
3866
+ return sharedConfig;
3867
+ }
3868
+ function configureServerCleanup(devServer) {
3869
+ const resolvedConfig = devServer.config;
3870
+ let unregistered = false;
3871
+ const unregister = () => {
3872
+ if (unregistered) return;
3873
+ unregistered = true;
3874
+ devServer.httpServer?.off("close", unregister);
3875
+ devServer.watcher.off("close", unregister);
3876
+ unregisterConfig(resolvedConfig);
3877
+ };
3878
+ devServer.httpServer?.once("close", unregister);
3879
+ devServer.watcher.once("close", unregister);
3880
+ }
3881
+ function unregisterBuild(context) {
3882
+ const resolvedConfig = context.environment?.getTopLevelConfig?.();
3883
+ if (resolvedConfig) unregisterConfig(resolvedConfig);
3884
+ }
3885
+ //#endregion
3886
+ //#region src/plugin/vue-feature-defines.ts
3887
+ function parseDefine(value) {
3888
+ try {
3889
+ return typeof value === "string" ? JSON.parse(value) : value;
3890
+ } catch {
3891
+ return value;
3892
+ }
3893
+ }
3894
+ /**
3895
+ * Resolve Vue runtime defines with plugin-vue's precedence and defaults.
3896
+ *
3897
+ * `__VUE_PROD_DEVTOOLS__` used to be `command === "serve"`, which left no way to
3898
+ * enable devtools for a production build (#3227). It now follows plugin-vue's
3899
+ * OR semantics, and defaults to `false` in dev as upstream does: a development
3900
+ * build enables devtools through Vue's own `__DEV__`, not through this flag.
3901
+ */
3902
+ function resolveVueFeatureDefines(features, define) {
3903
+ return {
3904
+ __VUE_OPTIONS_API__: features?.optionsAPI ?? parseDefine(define?.__VUE_OPTIONS_API__) ?? true,
3905
+ __VUE_PROD_DEVTOOLS__: (features?.prodDevtools || parseDefine(define?.__VUE_PROD_DEVTOOLS__)) ?? false,
3906
+ __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: (features?.prodHydrationMismatchDetails || parseDefine(define?.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__)) ?? false
3907
+ };
3908
+ }
3909
+ //#endregion
3910
+ //#region src/plugin/index-helpers.ts
3911
+ function shouldExtractCssForBuild(state, context) {
3912
+ if (!state.isProduction) return false;
3913
+ const environmentName = context.environment?.name;
3914
+ if (environmentName === "client" || environmentName === "browser") return true;
3915
+ if (environmentName === "ssr" || environmentName === "server") return false;
3916
+ return state.extractCss;
3917
+ }
3918
+ function resolveCompatibilityOptions(options, compilerConfig = {}) {
3919
+ const compatibility = {
3920
+ ...compilerConfig.compatibility,
3921
+ ...options.compatibility
3922
+ };
3923
+ const vueVersion = options.vueVersion ?? compatibility.vueVersion ?? 3;
3924
+ if (compatibility.hostCompiler === void 0 && isLegacyVueVersion(vueVersion)) compatibility.hostCompiler = true;
3925
+ return compatibility;
3926
+ }
3927
+ function aliasSortKey(find) {
3928
+ return typeof find === "string" ? find.length : find.source.length;
3929
+ }
3930
+ //#endregion
3931
+ //#region src/plugin/index.ts
3932
+ function vize(options = {}) {
3933
+ if (isLegacyVueCompatibilityMode(options)) return [createLegacyVueCompatibilityPlugin(options)];
3934
+ const state = {
3935
+ cache: new CompiledModuleCache(),
3936
+ ssrCache: new CompiledModuleCache(),
3937
+ collectedCss: /* @__PURE__ */ new Map(),
3938
+ precompileMetadata: /* @__PURE__ */ new Map(),
3939
+ pendingHmrUpdateTypes: /* @__PURE__ */ new Map(),
3940
+ viteResolveCache: /* @__PURE__ */ new Map(),
3941
+ isProduction: false,
3942
+ viteBuildSourcemap: false,
3943
+ root: "",
3944
+ clientViteBase: "/",
3945
+ serverViteBase: "/",
3946
+ server: null,
3947
+ filter: () => true,
3948
+ scanPatterns: null,
3949
+ precompileBatchSize: 128,
3950
+ ignorePatterns: [],
3951
+ mergedOptions: options,
3952
+ initialized: false,
3953
+ dynamicImportAliasRules: [],
3954
+ cssAliasRules: [],
3955
+ extractCss: false,
3956
+ componentsCssFileName: "assets/vize-components.css",
3957
+ clientViteDefine: {},
3958
+ serverViteDefine: {},
3959
+ logger: createLogger(options.debug ?? false)
3960
+ };
3961
+ return [
3962
+ createVueCompatPlugin(state, options),
3963
+ {
3964
+ name: "vite-plugin-vize",
3965
+ enforce: "pre",
3966
+ config(userConfig) {
3967
+ patchCssModuleGenerateScopedName(userConfig);
3968
+ return {
3969
+ define: resolveVueFeatureDefines(options.features, userConfig.define),
3970
+ optimizeDeps: { exclude: ["virtual:vize-styles"] }
3971
+ };
3972
+ },
3973
+ async configResolved(resolvedConfig) {
3974
+ state.root = options.root ?? resolvedConfig.root;
3975
+ state.isProduction = options.isProduction ?? resolvedConfig.isProduction;
3976
+ state.viteBuildSourcemap = !!resolvedConfig.build?.sourcemap;
3977
+ const isSsrBuild = !!resolvedConfig.build?.ssr;
3978
+ const currentBase = resolvedConfig.command === "serve" ? options.devUrlBase ?? resolvedConfig.base ?? "/" : resolvedConfig.base ?? "/";
3979
+ if (isSsrBuild) state.serverViteBase = currentBase;
3980
+ else state.clientViteBase = currentBase;
3981
+ state.extractCss = state.isProduction && !isSsrBuild;
3982
+ state.componentsCssFileName = resolveComponentsCssFileName(resolvedConfig.build.assetsDir);
3983
+ const isSsr = !!resolvedConfig.build?.ssr;
3984
+ const envDefine = {};
3985
+ if (resolvedConfig.define) for (const [key, value] of Object.entries(resolvedConfig.define)) {
3986
+ if (!shouldApplyDefineInVirtualModule(key)) continue;
3987
+ if (typeof value === "string") envDefine[key] = value;
3988
+ else envDefine[key] = JSON.stringify(value);
3989
+ }
3990
+ if (isSsr) state.serverViteDefine = envDefine;
3991
+ else state.clientViteDefine = envDefine;
3992
+ const configEnv = {
3993
+ mode: resolvedConfig.mode,
3994
+ command: resolvedConfig.command === "build" ? "build" : "serve",
3995
+ isSsrBuild: !!resolvedConfig.build?.ssr
3996
+ };
3997
+ const sharedConfigPromise = resolveSharedConfig(options, state.root, configEnv, state.logger);
3998
+ const sharedConfig = await register(resolvedConfig, state.root, sharedConfigPromise);
3999
+ const viteConfig = sharedConfig?.vite ?? {};
4000
+ const compilerConfig = sharedConfig?.compiler ?? {};
4001
+ const compatibility = resolveCompatibilityOptions(options, compilerConfig);
4002
+ const vueVersion = options.vueVersion ?? compatibility.vueVersion ?? 3;
4003
+ const mode = options.mode ?? compilerConfig.mode ?? (compatibility.scriptSetupInStandalone === true ? "function" : "module");
4004
+ const templateSyntax = options.templateSyntax ?? compilerConfig.templateSyntax ?? "standard";
4005
+ state.mergedOptions = {
4006
+ ...options,
4007
+ ssr: options.ssr ?? compilerConfig.ssr ?? false,
4008
+ sourceMap: options.sourceMap ?? compilerConfig.sourceMap,
4009
+ ...resolveExperimentalCompilerOptions(options, compilerConfig, sharedConfig?.experimentals),
4010
+ customRenderer: options.customRenderer ?? compilerConfig.customRenderer ?? false,
4011
+ customElements: options.customElements ?? compilerConfig.customElements,
4012
+ templateSyntax,
4013
+ compatibility,
4014
+ vueVersion,
4015
+ mode,
4016
+ runtimeModuleName: options.runtimeModuleName ?? compilerConfig.runtimeModuleName ?? "vue",
4017
+ runtimeGlobalName: options.runtimeGlobalName ?? compilerConfig.runtimeGlobalName ?? "Vue",
4018
+ include: options.include ?? viteConfig.include,
4019
+ exclude: options.exclude ?? viteConfig.exclude,
4020
+ scanPatterns: options.scanPatterns ?? viteConfig.scanPatterns,
4021
+ precompileBatchSize: options.precompileBatchSize ?? viteConfig.precompileBatchSize,
4022
+ ignorePatterns: options.ignorePatterns ?? viteConfig.ignorePatterns
4023
+ };
4024
+ state.dynamicImportAliasRules = [];
4025
+ for (const alias of resolvedConfig.resolve.alias) {
4026
+ if (typeof alias.find !== "string" || typeof alias.replacement !== "string") continue;
4027
+ const fromPrefix = alias.find.endsWith("/") ? alias.find : `${alias.find}/`;
4028
+ const replacement = toBrowserImportPrefix(alias.replacement);
4029
+ const toPrefix = replacement.endsWith("/") ? replacement : `${replacement}/`;
4030
+ state.dynamicImportAliasRules.push({
4031
+ fromPrefix,
4032
+ toPrefix
4033
+ });
4034
+ }
4035
+ state.dynamicImportAliasRules.sort((a, b) => b.fromPrefix.length - a.fromPrefix.length);
4036
+ state.cssAliasRules = [];
4037
+ for (const alias of resolvedConfig.resolve.alias) {
4038
+ if (!(typeof alias.find === "string" || alias.find instanceof RegExp) || typeof alias.replacement !== "string") continue;
4039
+ state.cssAliasRules.push({
4040
+ find: alias.find,
4041
+ replacement: alias.replacement
4042
+ });
4043
+ }
4044
+ state.cssAliasRules.sort((a, b) => aliasSortKey(b.find) - aliasSortKey(a.find));
4045
+ if (isLegacyVueCompatibilityMode(state.mergedOptions)) {
4046
+ state.filter = () => false;
4047
+ state.scanPatterns = [];
4048
+ } else {
4049
+ state.filter = createFilter(state.mergedOptions.include, state.mergedOptions.exclude);
4050
+ state.scanPatterns = state.mergedOptions.scanPatterns ?? ["**/*.vue"];
4051
+ }
4052
+ state.precompileBatchSize = normalizePrecompileBatchSize(state.mergedOptions.precompileBatchSize);
4053
+ state.ignorePatterns = state.mergedOptions.ignorePatterns ?? [...DEFAULT_PRECOMPILE_IGNORE_PATTERNS];
4054
+ patchUnoCssBridge(resolvedConfig.plugins);
4055
+ patchQuasarBridge(resolvedConfig.plugins);
4056
+ state.initialized = true;
4057
+ },
4058
+ configureServer(devServer) {
4059
+ state.server = devServer;
4060
+ configureServerCleanup(devServer);
4061
+ installDevMiddleware(devServer, state);
4062
+ },
4063
+ async buildStart() {
4064
+ state.viteResolveCache?.clear();
4065
+ if (!state.scanPatterns || state.scanPatterns.length === 0) return;
4066
+ await compileAll({
4067
+ ...state,
4068
+ extractCss: shouldExtractCssForBuild(state, this)
4069
+ });
4070
+ state.logger.log("Cache keys:", [...state.cache.keys()].slice(0, 3));
4071
+ },
4072
+ resolveId(id, importer, options) {
4073
+ return resolveIdHook(this, state, id, importer, options);
4074
+ },
4075
+ load(id, loadOptions) {
4076
+ return loadHook(state, id, {
4077
+ ...loadOptions,
4078
+ addWatchFile: this.addWatchFile.bind(this)
4079
+ });
4080
+ },
4081
+ async transform(code, id, transformOptions) {
4082
+ return transformHook(state, code, id, transformOptions);
4083
+ },
4084
+ async hotUpdate(options) {
4085
+ return handleHotUpdateEnvironmentHook(state, this.environment, options);
4086
+ },
4087
+ shouldTransformCachedModule({ id }) {
4088
+ return id?.includes(".vue") ? true : void 0;
4089
+ },
4090
+ async handleHotUpdate(ctx) {
4091
+ return handleHotUpdateHook(state, ctx);
4092
+ },
4093
+ generateBundle(_, bundle) {
4094
+ handleGenerateBundleHook({
4095
+ ...state,
4096
+ extractCss: shouldExtractCssForBuild(state, this)
4097
+ }, this.emitFile.bind(this), bundle);
4098
+ },
4099
+ closeBundle() {
4100
+ if (state.server === null) {
4101
+ unregisterBuild(this);
4102
+ clearBuildCaches(state);
4103
+ }
4104
+ }
4105
+ },
4106
+ createStylePostTransformPlugin(),
4107
+ createPostTransformPlugin(state)
4108
+ ];
4109
+ }
4110
+ //#endregion
4111
+ export { rewriteStaticAssetUrls as n, vize as t };