@tanstack/start-plugin-core 1.167.35 → 1.168.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.
- package/dist/esm/import-protection/adapterUtils.d.ts +27 -0
- package/dist/esm/import-protection/adapterUtils.js +31 -0
- package/dist/esm/import-protection/adapterUtils.js.map +1 -0
- package/dist/esm/import-protection/analysis.d.ts +36 -0
- package/dist/esm/import-protection/analysis.js +407 -0
- package/dist/esm/import-protection/analysis.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/ast.js +1 -1
- package/dist/esm/import-protection/ast.js.map +1 -0
- package/dist/esm/import-protection/constants.d.ts +11 -0
- package/dist/esm/{import-protection-plugin → import-protection}/constants.js +7 -2
- package/dist/esm/import-protection/constants.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/defaults.js +1 -1
- package/dist/esm/import-protection/defaults.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.js +1 -1
- package/dist/esm/import-protection/extensionlessAbsoluteIdResolver.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/matchers.js +1 -1
- package/dist/esm/import-protection/matchers.js.map +1 -0
- package/dist/esm/{import-protection-plugin/rewriteDeniedImports.d.ts → import-protection/rewrite.d.ts} +0 -4
- package/dist/esm/import-protection/rewrite.js +121 -0
- package/dist/esm/import-protection/rewrite.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.d.ts +32 -3
- package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.js +65 -10
- package/dist/esm/import-protection/sourceLocation.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/trace.d.ts +0 -1
- package/dist/esm/{import-protection-plugin → import-protection}/trace.js +1 -1
- package/dist/esm/import-protection/trace.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/utils.d.ts +18 -1
- package/dist/esm/{import-protection-plugin → import-protection}/utils.js +12 -19
- package/dist/esm/import-protection/utils.js.map +1 -0
- package/dist/esm/import-protection/virtualModules.d.ts +25 -0
- package/dist/esm/{import-protection-plugin → import-protection}/virtualModules.js +5 -117
- package/dist/esm/import-protection/virtualModules.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +3 -1
- package/dist/esm/post-build.d.ts +9 -0
- package/dist/esm/post-build.js +37 -0
- package/dist/esm/post-build.js.map +1 -0
- package/dist/esm/prerender.d.ts +11 -0
- package/dist/esm/prerender.js +159 -0
- package/dist/esm/prerender.js.map +1 -0
- package/dist/esm/rsbuild/dev-server.d.ts +21 -0
- package/dist/esm/rsbuild/dev-server.js +76 -0
- package/dist/esm/rsbuild/dev-server.js.map +1 -0
- package/dist/esm/rsbuild/import-protection.d.ts +10 -0
- package/dist/esm/rsbuild/import-protection.js +775 -0
- package/dist/esm/rsbuild/import-protection.js.map +1 -0
- package/dist/esm/rsbuild/normalized-client-build.d.ts +18 -0
- package/dist/esm/rsbuild/normalized-client-build.js +207 -0
- package/dist/esm/rsbuild/normalized-client-build.js.map +1 -0
- package/dist/esm/rsbuild/planning.d.ts +52 -0
- package/dist/esm/rsbuild/planning.js +108 -0
- package/dist/esm/rsbuild/planning.js.map +1 -0
- package/dist/esm/rsbuild/plugin.d.ts +4 -0
- package/dist/esm/rsbuild/plugin.js +344 -0
- package/dist/esm/rsbuild/plugin.js.map +1 -0
- package/dist/esm/rsbuild/post-build.d.ts +6 -0
- package/dist/esm/rsbuild/post-build.js +57 -0
- package/dist/esm/rsbuild/post-build.js.map +1 -0
- package/dist/esm/rsbuild/schema.d.ts +3372 -0
- package/dist/esm/rsbuild/schema.js +12 -0
- package/dist/esm/rsbuild/schema.js.map +1 -0
- package/dist/esm/rsbuild/start-compiler-host.d.ts +20 -0
- package/dist/esm/rsbuild/start-compiler-host.js +150 -0
- package/dist/esm/rsbuild/start-compiler-host.js.map +1 -0
- package/dist/esm/rsbuild/start-router-plugin.d.ts +18 -0
- package/dist/esm/rsbuild/start-router-plugin.js +63 -0
- package/dist/esm/rsbuild/start-router-plugin.js.map +1 -0
- package/dist/esm/rsbuild/swc-rsc.d.ts +14 -0
- package/dist/esm/rsbuild/swc-rsc.js +93 -0
- package/dist/esm/rsbuild/swc-rsc.js.map +1 -0
- package/dist/esm/rsbuild/types.d.ts +17 -0
- package/dist/esm/rsbuild/types.js +0 -0
- package/dist/esm/rsbuild/virtual-modules.d.ts +53 -0
- package/dist/esm/rsbuild/virtual-modules.js +287 -0
- package/dist/esm/rsbuild/virtual-modules.js.map +1 -0
- package/dist/esm/schema.d.ts +43 -43
- package/dist/esm/start-compiler/compiler.d.ts +1 -1
- package/dist/esm/start-compiler/compiler.js +80 -9
- package/dist/esm/start-compiler/compiler.js.map +1 -1
- package/dist/esm/start-compiler/handleCreateServerFn.js +9 -0
- package/dist/esm/start-compiler/handleCreateServerFn.js.map +1 -1
- package/dist/esm/start-compiler/host.js +5 -1
- package/dist/esm/start-compiler/host.js.map +1 -1
- package/dist/esm/start-compiler/types.d.ts +1 -0
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.js +4 -1
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.js +41 -92
- package/dist/esm/vite/import-protection-plugin/plugin.js.map +1 -0
- package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/types.d.ts +5 -5
- package/dist/esm/vite/import-protection-plugin/virtualModules.d.ts +8 -0
- package/dist/esm/vite/import-protection-plugin/virtualModules.js +49 -0
- package/dist/esm/vite/import-protection-plugin/virtualModules.js.map +1 -0
- package/dist/esm/vite/plugin.js +1 -1
- package/dist/esm/vite/plugin.js.map +1 -1
- package/dist/esm/vite/post-server-build.js +14 -32
- package/dist/esm/vite/post-server-build.js.map +1 -1
- package/dist/esm/vite/prerender.d.ts +2 -2
- package/dist/esm/vite/prerender.js +17 -147
- package/dist/esm/vite/prerender.js.map +1 -1
- package/dist/esm/vite/schema.d.ts +23 -23
- package/dist/esm/vite/start-compiler-plugin/hot-update.d.ts +2 -0
- package/dist/esm/vite/start-compiler-plugin/hot-update.js +16 -0
- package/dist/esm/vite/start-compiler-plugin/hot-update.js.map +1 -0
- package/dist/esm/vite/start-compiler-plugin/module-specifier.js +9 -4
- package/dist/esm/vite/start-compiler-plugin/module-specifier.js.map +1 -1
- package/dist/esm/vite/start-compiler-plugin/plugin.js +86 -13
- package/dist/esm/vite/start-compiler-plugin/plugin.js.map +1 -1
- package/package.json +17 -4
- package/src/import-protection/INTERNALS.md +266 -0
- package/src/import-protection/adapterUtils.ts +94 -0
- package/src/import-protection/analysis.ts +853 -0
- package/src/{import-protection-plugin → import-protection}/constants.ts +7 -0
- package/src/import-protection/rewrite.ts +229 -0
- package/src/{import-protection-plugin → import-protection}/sourceLocation.ts +125 -9
- package/src/{import-protection-plugin → import-protection}/trace.ts +0 -1
- package/src/{import-protection-plugin → import-protection}/utils.ts +35 -20
- package/src/{import-protection-plugin → import-protection}/virtualModules.ts +30 -177
- package/src/index.ts +5 -0
- package/src/post-build.ts +64 -0
- package/src/prerender.ts +292 -0
- package/src/rsbuild/INTERNALS-import-protection.md +169 -0
- package/src/rsbuild/dev-server.ts +129 -0
- package/src/rsbuild/import-protection.ts +1600 -0
- package/src/rsbuild/normalized-client-build.ts +346 -0
- package/src/rsbuild/planning.ts +234 -0
- package/src/rsbuild/plugin.ts +754 -0
- package/src/rsbuild/post-build.ts +96 -0
- package/src/rsbuild/schema.ts +31 -0
- package/src/rsbuild/start-compiler-host.ts +250 -0
- package/src/rsbuild/start-router-plugin.ts +86 -0
- package/src/rsbuild/swc-rsc.ts +166 -0
- package/src/rsbuild/types.ts +20 -0
- package/src/rsbuild/virtual-modules.ts +565 -0
- package/src/start-compiler/compiler.ts +153 -19
- package/src/start-compiler/handleCreateServerFn.ts +18 -0
- package/src/start-compiler/types.ts +1 -0
- package/src/utils.ts +4 -0
- package/src/vite/import-protection-plugin/INTERNALS.md +187 -0
- package/src/{import-protection-plugin → vite/import-protection-plugin}/plugin.ts +73 -158
- package/src/{import-protection-plugin → vite/import-protection-plugin}/types.ts +5 -5
- package/src/vite/import-protection-plugin/virtualModules.ts +122 -0
- package/src/vite/plugin.ts +1 -1
- package/src/vite/post-server-build.ts +14 -57
- package/src/vite/prerender.ts +19 -260
- package/src/vite/start-compiler-plugin/hot-update.ts +24 -0
- package/src/vite/start-compiler-plugin/module-specifier.ts +15 -5
- package/src/vite/start-compiler-plugin/plugin.ts +193 -18
- package/dist/esm/import-protection-plugin/ast.js.map +0 -1
- package/dist/esm/import-protection-plugin/constants.d.ts +0 -6
- package/dist/esm/import-protection-plugin/constants.js.map +0 -1
- package/dist/esm/import-protection-plugin/defaults.js.map +0 -1
- package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js.map +0 -1
- package/dist/esm/import-protection-plugin/matchers.js.map +0 -1
- package/dist/esm/import-protection-plugin/plugin.js.map +0 -1
- package/dist/esm/import-protection-plugin/postCompileUsage.d.ts +0 -13
- package/dist/esm/import-protection-plugin/postCompileUsage.js +0 -63
- package/dist/esm/import-protection-plugin/postCompileUsage.js.map +0 -1
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +0 -205
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +0 -1
- package/dist/esm/import-protection-plugin/sourceLocation.js.map +0 -1
- package/dist/esm/import-protection-plugin/trace.js.map +0 -1
- package/dist/esm/import-protection-plugin/utils.js.map +0 -1
- package/dist/esm/import-protection-plugin/virtualModules.d.ts +0 -78
- package/dist/esm/import-protection-plugin/virtualModules.js.map +0 -1
- package/dist/esm/start-compiler/load-module.d.ts +0 -14
- package/dist/esm/start-compiler/load-module.js +0 -18
- package/dist/esm/start-compiler/load-module.js.map +0 -1
- package/src/import-protection-plugin/INTERNALS.md +0 -700
- package/src/import-protection-plugin/postCompileUsage.ts +0 -100
- package/src/import-protection-plugin/rewriteDeniedImports.ts +0 -379
- package/src/start-compiler/load-module.ts +0 -31
- /package/dist/esm/{import-protection-plugin → import-protection}/ast.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → import-protection}/defaults.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → import-protection}/matchers.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.d.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/ast.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/defaults.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/matchers.ts +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":[],"sources":["../../../src/import-protection-plugin/plugin.ts"],"sourcesContent":["import { normalizePath } from 'vite'\n\nimport { resolveViteId } from '../utils'\nimport { VITE_ENVIRONMENT_NAMES } from '../constants'\nimport { ImportGraph, buildTrace, formatViolation } from './trace'\nimport {\n getDefaultImportProtectionRules,\n getMarkerSpecifiers,\n} from './defaults'\nimport { compileMatchers, matchesAny } from './matchers'\nimport {\n buildResolutionCandidates,\n buildSourceCandidates,\n canonicalizeResolvedId,\n clearNormalizeFilePathCache,\n debugLog,\n dedupePatterns,\n escapeRegExp,\n extractImportSources,\n getOrCreate,\n isInsideDirectory,\n matchesDebugFilter,\n normalizeFilePath,\n relativizePath,\n shouldDeferViolation,\n} from './utils'\nimport {\n collectMockExportNamesBySource,\n collectNamedExports,\n rewriteDeniedImports,\n} from './rewriteDeniedImports'\nimport {\n MOCK_BUILD_PREFIX,\n generateDevSelfDenialModule,\n generateSelfContainedMockModule,\n getResolvedVirtualModuleMatchers,\n loadResolvedVirtualModule,\n makeMockEdgeModuleId,\n mockRuntimeModuleIdFromViolation,\n resolveInternalVirtualModuleId,\n resolvedMarkerVirtualModuleId,\n} from './virtualModules'\nimport { ExtensionlessAbsoluteIdResolver } from './extensionlessAbsoluteIdResolver'\nimport {\n IMPORT_PROTECTION_DEBUG,\n SERVER_FN_LOOKUP_QUERY,\n VITE_BROWSER_VIRTUAL_PREFIX,\n} from './constants'\nimport {\n ImportLocCache,\n addTraceImportLocations,\n buildCodeSnippet,\n buildLineIndex,\n findImportStatementLocationFromTransformed,\n findPostCompileUsageLocation,\n pickOriginalCodeFromSourcesContent,\n} from './sourceLocation'\nimport type { PluginOption, ViteDevServer } from 'vite'\nimport type { CompiledMatcher } from './matchers'\nimport type { Loc, TraceStep, ViolationInfo } from './trace'\nimport type {\n SourceMapLike,\n TransformResult,\n TransformResultProvider,\n} from './sourceLocation'\nimport type { ImportProtectionOptions } from '../schema'\nimport type {\n EnvRules,\n EnvState,\n HandleViolationResult,\n ImportProtectionPluginOptions,\n ModuleGraphNode,\n PendingViolation,\n PluginConfig,\n SharedState,\n ViolationReporter,\n} from './types'\n\nexport type { ImportProtectionPluginOptions } from './types'\n\nexport function importProtectionPlugin(\n opts: ImportProtectionPluginOptions,\n): PluginOption {\n let devServer: ViteDevServer | null = null\n const extensionlessIdResolver = new ExtensionlessAbsoluteIdResolver()\n const resolveExtensionlessAbsoluteId = (id: string) =>\n extensionlessIdResolver.resolve(id)\n\n const importPatternCache = new Map<string, Array<RegExp>>()\n\n function findFirstImportSpecifierIndex(code: string, source: string): number {\n let patterns = importPatternCache.get(source)\n if (!patterns) {\n const escaped = escapeRegExp(source)\n patterns = [\n new RegExp(`\\\\bimport\\\\s+(['\"])${escaped}\\\\1`),\n new RegExp(`\\\\bfrom\\\\s+(['\"])${escaped}\\\\1`),\n new RegExp(`\\\\bimport\\\\s*\\\\(\\\\s*(['\"])${escaped}\\\\1\\\\s*\\\\)`),\n ]\n importPatternCache.set(source, patterns)\n }\n\n let best = -1\n for (const re of patterns) {\n const m = re.exec(code)\n if (!m) continue\n const idx = m.index + m[0].indexOf(source)\n if (idx === -1) continue\n if (best === -1 || idx < best) best = idx\n }\n return best\n }\n\n /**\n * Build an import trace using Vite's per-environment module graph, which\n * is authoritative even on warm starts when the plugin's own ImportGraph\n * may be incomplete (Vite skips resolveId for cached modules).\n */\n function buildTraceFromModuleGraph(\n envName: string,\n env: EnvState,\n targetFile: string,\n ): Array<TraceStep> | null {\n if (!devServer) return null\n const environment = devServer.environments[envName]\n if (!environment) return null\n\n const file = normalizeFilePath(targetFile)\n const start = environment.moduleGraph.getModuleById(file)\n if (!start) return null\n\n // Resolve a module graph node to its normalized file path once and\n // cache the result so BFS + reconstruction don't recompute.\n const nodeIds = new Map<ModuleGraphNode, string>()\n function nodeId(n: ModuleGraphNode): string {\n let cached = nodeIds.get(n)\n if (cached === undefined) {\n cached = n.id\n ? normalizeFilePath(n.id)\n : n.url\n ? normalizeFilePath(n.url)\n : ''\n nodeIds.set(n, cached)\n }\n return cached\n }\n\n const queue: Array<ModuleGraphNode> = [start]\n const visited = new Set<ModuleGraphNode>([start])\n const parent = new Map<ModuleGraphNode, ModuleGraphNode>()\n\n let entryRoot: ModuleGraphNode | null = null\n let fallbackRoot: ModuleGraphNode | null = null\n let qi = 0\n while (qi < queue.length) {\n const node = queue[qi++]!\n const id = nodeId(node)\n\n if (id && env.graph.entries.has(id)) {\n entryRoot = node\n break\n }\n\n const importers = node.importers\n if (importers.size === 0) {\n if (!fallbackRoot) fallbackRoot = node\n continue\n }\n\n for (const imp of importers) {\n if (visited.has(imp)) continue\n visited.add(imp)\n parent.set(imp, node)\n queue.push(imp)\n }\n }\n\n const root = entryRoot ?? fallbackRoot\n\n if (!root) return null\n\n // Reconstruct: root -> ... -> start\n const chain: Array<ModuleGraphNode> = []\n let cur: ModuleGraphNode | undefined = root\n for (let i = 0; i < config.maxTraceDepth + 2 && cur; i++) {\n chain.push(cur)\n if (cur === start) break\n cur = parent.get(cur)\n }\n\n const steps: Array<TraceStep> = []\n for (let i = 0; i < chain.length; i++) {\n const id = nodeId(chain[i]!)\n if (!id) continue\n let specifier: string | undefined\n if (i + 1 < chain.length) {\n const nextId = nodeId(chain[i + 1]!)\n if (nextId) {\n specifier = env.graph.reverseEdges.get(nextId)?.get(id)\n }\n }\n steps.push(specifier ? { file: id, specifier } : { file: id })\n }\n\n return steps.length ? steps : null\n }\n\n const config: PluginConfig = {\n enabled: true,\n root: '',\n command: 'build',\n srcDirectory: '',\n framework: opts.framework,\n effectiveBehavior: 'error',\n mockAccess: 'error',\n logMode: 'once',\n maxTraceDepth: 20,\n compiledRules: {\n client: { specifiers: [], files: [], excludeFiles: [] },\n server: { specifiers: [], files: [], excludeFiles: [] },\n },\n includeMatchers: [],\n excludeMatchers: [],\n ignoreImporterMatchers: [],\n markerSpecifiers: { serverOnly: new Set(), clientOnly: new Set() },\n envTypeMap: new Map(opts.environments.map((e) => [e.name, e.type])),\n onViolation: undefined,\n }\n\n const envStates = new Map<string, EnvState>()\n const shared: SharedState = { fileMarkerKind: new Map() }\n\n /**\n * Build the best available trace for a module and enrich each step with\n * line/column locations. Tries the plugin's own ImportGraph first, then\n * Vite's moduleGraph (authoritative on warm start), keeping whichever is\n * longer. Annotates the last step with the denied specifier + location.\n *\n * Shared by {@link buildViolationInfo} and {@link processPendingViolations}.\n */\n async function rebuildAndAnnotateTrace(\n provider: TransformResultProvider,\n env: EnvState,\n envName: string,\n normalizedImporter: string,\n specifier: string,\n importerLoc: Loc | undefined,\n traceOverride?: Array<TraceStep>,\n ): Promise<Array<TraceStep>> {\n let trace =\n traceOverride ??\n buildTrace(env.graph, normalizedImporter, config.maxTraceDepth)\n\n if (config.command === 'serve') {\n const mgTrace = buildTraceFromModuleGraph(\n envName,\n env,\n normalizedImporter,\n )\n if (mgTrace && mgTrace.length > trace.length) {\n trace = mgTrace\n }\n }\n await addTraceImportLocations(\n provider,\n trace,\n env.importLocCache,\n findFirstImportSpecifierIndex,\n )\n\n if (trace.length > 0) {\n const last = trace[trace.length - 1]!\n if (!last.specifier) last.specifier = specifier\n if (importerLoc && last.line == null) {\n last.line = importerLoc.line\n last.column = importerLoc.column\n }\n }\n\n return trace\n }\n\n /**\n * Build a complete {@link ViolationInfo} with trace, location, and snippet.\n *\n * This is the single path that all violation types go through: specifier,\n * file, and marker.\n */\n async function buildViolationInfo(\n provider: TransformResultProvider,\n env: EnvState,\n envName: string,\n envType: 'client' | 'server',\n importer: string,\n normalizedImporter: string,\n source: string,\n overrides: Omit<\n ViolationInfo,\n | 'env'\n | 'envType'\n | 'behavior'\n | 'specifier'\n | 'importer'\n | 'trace'\n | 'snippet'\n | 'importerLoc'\n >,\n traceOverride?: Array<TraceStep>,\n ): Promise<ViolationInfo> {\n const sourceCandidates = buildSourceCandidates(\n source,\n 'resolved' in overrides && typeof overrides.resolved === 'string'\n ? overrides.resolved\n : undefined,\n config.root,\n )\n\n const loc = await resolveImporterLocation(\n provider,\n env,\n importer,\n sourceCandidates,\n )\n\n const trace = await rebuildAndAnnotateTrace(\n provider,\n env,\n envName,\n normalizedImporter,\n source,\n loc,\n traceOverride,\n )\n\n const snippet = loc ? buildCodeSnippet(provider, importer, loc) : undefined\n\n return {\n env: envName,\n envType,\n behavior: config.effectiveBehavior,\n specifier: source,\n importer: normalizedImporter,\n ...(loc ? { importerLoc: loc } : {}),\n trace,\n snippet,\n ...overrides,\n }\n }\n\n async function resolveImporterLocation(\n provider: TransformResultProvider,\n env: EnvState,\n importer: string,\n sourceCandidates: Iterable<string>,\n ): Promise<Loc | undefined> {\n for (const candidate of sourceCandidates) {\n const loc =\n (await findPostCompileUsageLocation(provider, importer, candidate)) ||\n (await findImportStatementLocationFromTransformed(\n provider,\n importer,\n candidate,\n env.importLocCache,\n findFirstImportSpecifierIndex,\n ))\n if (loc) return loc\n }\n return undefined\n }\n\n /**\n * Check if a resolved import violates marker restrictions (e.g. importing\n * a server-only module in the client env). If so, build and return the\n * {@link ViolationInfo} — the caller is responsible for reporting/deferring.\n *\n * Returns `undefined` when the resolved import has no marker conflict.\n */\n async function buildMarkerViolationFromResolvedImport(\n provider: TransformResultProvider,\n env: EnvState,\n envName: string,\n envType: 'client' | 'server',\n importer: string,\n source: string,\n resolvedId: string,\n relativePath: string,\n traceOverride?: Array<TraceStep>,\n ): Promise<ViolationInfo | undefined> {\n const normalizedResolvedId = normalizeFilePath(resolvedId)\n const markerKind = shared.fileMarkerKind.get(normalizedResolvedId)\n const violates =\n (envType === 'client' && markerKind === 'server') ||\n (envType === 'server' && markerKind === 'client')\n if (!violates) return undefined\n\n const normalizedImporter = normalizeFilePath(importer)\n\n return buildViolationInfo(\n provider,\n env,\n envName,\n envType,\n importer,\n normalizedImporter,\n source,\n {\n type: 'marker',\n resolved: normalizedResolvedId,\n message: buildMarkerViolationMessage(relativePath, markerKind),\n },\n traceOverride,\n )\n }\n\n function buildMarkerViolationMessage(\n relativePath: string,\n markerKind: 'server' | 'client' | undefined,\n ): string {\n return markerKind === 'server'\n ? `Module \"${relativePath}\" is marked server-only but is imported in the client environment`\n : `Module \"${relativePath}\" is marked client-only but is imported in the server environment`\n }\n\n async function buildFileViolationInfo(\n provider: TransformResultProvider,\n env: EnvState,\n envName: string,\n envType: 'client' | 'server',\n importer: string,\n normalizedImporter: string,\n source: string,\n resolvedPath: string,\n pattern: string | RegExp,\n traceOverride?: Array<TraceStep>,\n ): Promise<ViolationInfo> {\n const relativePath = getRelativePath(resolvedPath)\n\n return buildViolationInfo(\n provider,\n env,\n envName,\n envType,\n importer,\n normalizedImporter,\n source,\n {\n type: 'file',\n pattern,\n resolved: resolvedPath,\n message: `Import \"${source}\" (resolved to \"${relativePath}\") is denied in the ${envType} environment`,\n },\n traceOverride,\n )\n }\n\n function getEnvType(envName: string): 'client' | 'server' {\n return config.envTypeMap.get(envName) ?? 'server'\n }\n\n function getRulesForEnvironment(envName: string): EnvRules {\n const type = getEnvType(envName)\n return type === 'client'\n ? config.compiledRules.client\n : config.compiledRules.server\n }\n\n /**\n * Check if a relative path matches any denied file pattern for the given\n * environment, respecting `excludeFiles`. Returns the matching pattern\n * or `undefined` if the file is not denied.\n */\n function checkFileDenial(\n relativePath: string,\n matchers: {\n files: Array<CompiledMatcher>\n excludeFiles: Array<CompiledMatcher>\n },\n ): CompiledMatcher | undefined {\n if (\n matchers.excludeFiles.length > 0 &&\n matchesAny(relativePath, matchers.excludeFiles)\n ) {\n return undefined\n }\n return matchers.files.length > 0\n ? matchesAny(relativePath, matchers.files)\n : undefined\n }\n\n const environmentNames = new Set<string>([\n VITE_ENVIRONMENT_NAMES.client,\n VITE_ENVIRONMENT_NAMES.server,\n ])\n if (opts.providerEnvName !== VITE_ENVIRONMENT_NAMES.server) {\n environmentNames.add(opts.providerEnvName)\n }\n\n /** Get (or lazily create) the per-env state for the given environment name. */\n function getEnv(envName: string): EnvState {\n let envState = envStates.get(envName)\n if (!envState) {\n const transformResultCache = new Map<string, TransformResult>()\n envState = {\n graph: new ImportGraph(),\n mockExportsByImporter: new Map(),\n resolveCache: new Map(),\n resolveCacheByFile: new Map(),\n importLocCache: new ImportLocCache(),\n seenViolations: new Set(),\n transformResultCache,\n transformResultKeysByFile: new Map(),\n transformResultProvider: {\n getTransformResult(id: string) {\n const fullKey = normalizePath(id)\n const exact = transformResultCache.get(fullKey)\n if (exact) return exact\n const strippedKey = normalizeFilePath(id)\n return strippedKey !== fullKey\n ? transformResultCache.get(strippedKey)\n : undefined\n },\n },\n postTransformImports: new Map(),\n serverFnLookupModules: new Set(),\n pendingViolations: new Map(),\n deferredBuildViolations: [],\n }\n envStates.set(envName, envState)\n }\n return envState\n }\n\n /**\n * Search a parsed export-names map for an entry matching any of the\n * specifier candidates. Returns matching names or empty array.\n */\n function findExportsInMap(\n exportMap: Map<string, Array<string>>,\n candidates: Array<string>,\n ): Array<string> {\n for (const candidate of candidates) {\n const hit = exportMap.get(candidate)\n if (hit && hit.length > 0) return hit\n }\n return []\n }\n\n /**\n * Build deduped resolution candidates for a module ID, including the\n * extensionless absolute path when the ID looks like a file path.\n */\n function buildIdCandidates(id: string, extra?: string): Array<string> {\n const set = new Set(buildResolutionCandidates(id))\n if (extra) {\n for (const c of buildResolutionCandidates(extra)) set.add(c)\n set.add(resolveExtensionlessAbsoluteId(extra))\n }\n return Array.from(set)\n }\n\n /**\n * Resolve which named exports the importer needs from a denied specifier,\n * so mock-edge modules can provide explicit ESM named exports.\n *\n * Tries multiple strategies: cached export maps, AST parsing, and\n * resolver-based comparison.\n */\n async function resolveExportsForDeniedSpecifier(\n env: EnvState,\n ctx: ViolationReporter,\n info: ViolationInfo,\n importerIdHint?: string,\n ): Promise<Array<string>> {\n const importerFile = normalizeFilePath(info.importer)\n const specifierCandidates = buildIdCandidates(info.specifier, info.resolved)\n\n // Only parse AST when a violation occurs (this function is only called\n // while handling a violation). Cache per-importer to avoid repeated parses\n // across multiple violations.\n let parsedBySource = env.mockExportsByImporter.get(importerFile)\n if (!parsedBySource) {\n // Try transform-cache result first, then moduleInfo fallback.\n const importerCode =\n env.transformResultProvider.getTransformResult(importerFile)?.code ??\n (importerIdHint && ctx.getModuleInfo\n ? (ctx.getModuleInfo(importerIdHint)?.code ?? undefined)\n : undefined)\n if (typeof importerCode !== 'string' || importerCode.length === 0)\n return []\n\n try {\n parsedBySource = collectMockExportNamesBySource(importerCode)\n\n // Also index by resolved physical IDs so later lookups match.\n await recordMockExportsForImporter(\n env,\n importerFile,\n parsedBySource,\n async (src) => {\n const cacheKey = `${importerFile}:${src}`\n if (env.resolveCache.has(cacheKey)) {\n return env.resolveCache.get(cacheKey) ?? undefined\n }\n if (!ctx.resolve) return undefined\n const resolved = await ctx.resolve(src, info.importer, {\n skipSelf: true,\n })\n if (!resolved || resolved.external) return undefined\n return resolved.id\n },\n )\n\n // Keep the parsed-by-source map for direct lookups.\n parsedBySource =\n env.mockExportsByImporter.get(importerFile) ?? parsedBySource\n } catch {\n return []\n }\n }\n\n // 1. Direct candidate match\n const direct = findExportsInMap(parsedBySource, specifierCandidates)\n if (direct.length > 0) return direct\n\n // 2. Resolve each source key and compare candidates.\n const candidateSet = new Set(specifierCandidates)\n for (const [sourceKey, names] of parsedBySource) {\n if (!names.length) continue\n\n const resolvedId = await resolveSourceKey(\n env,\n ctx,\n importerFile,\n sourceKey,\n info.importer,\n )\n if (!resolvedId) continue\n\n const resolvedCandidates = buildIdCandidates(resolvedId)\n resolvedCandidates.push(resolveExtensionlessAbsoluteId(resolvedId))\n if (resolvedCandidates.some((v) => candidateSet.has(v))) {\n return names\n }\n }\n\n return []\n }\n\n /** Best-effort resolve a source key using the cache or ctx.resolve. */\n async function resolveSourceKey(\n env: EnvState,\n ctx: ViolationReporter,\n importerFile: string,\n sourceKey: string,\n importerId: string,\n ): Promise<string | undefined> {\n const cacheKey = `${importerFile}:${sourceKey}`\n if (env.resolveCache.has(cacheKey)) {\n return env.resolveCache.get(cacheKey) ?? undefined\n }\n if (!ctx.resolve) return undefined\n try {\n const resolved = await ctx.resolve(sourceKey, importerId, {\n skipSelf: true,\n })\n if (!resolved || resolved.external) return undefined\n return resolved.id\n } catch {\n return undefined\n }\n }\n\n async function recordMockExportsForImporter(\n env: EnvState,\n importerId: string,\n namesBySource: Map<string, Array<string>>,\n resolveSource: (source: string) => Promise<string | undefined>,\n ): Promise<void> {\n const importerFile = normalizeFilePath(importerId)\n\n if (namesBySource.size === 0) return\n\n for (const [source, names] of namesBySource) {\n try {\n const resolvedId = await resolveSource(source)\n if (!resolvedId) continue\n\n namesBySource.set(normalizeFilePath(resolvedId), names)\n namesBySource.set(resolveExtensionlessAbsoluteId(resolvedId), names)\n } catch {\n // Best-effort only\n }\n }\n\n const existing = env.mockExportsByImporter.get(importerFile)\n if (!existing) {\n env.mockExportsByImporter.set(importerFile, namesBySource)\n return\n }\n\n for (const [source, names] of namesBySource) {\n const prev = existing.get(source)\n if (!prev) {\n existing.set(source, names)\n continue\n }\n\n const union = new Set([...prev, ...names])\n existing.set(source, Array.from(union).sort())\n }\n }\n\n const shouldCheckImporterCache = new Map<string, boolean>()\n function shouldCheckImporter(importer: string): boolean {\n let result = shouldCheckImporterCache.get(importer)\n if (result !== undefined) return result\n\n const relativePath = relativizePath(importer, config.root)\n\n // Excluded or ignored importers are never checked.\n const excluded =\n (config.excludeMatchers.length > 0 &&\n matchesAny(relativePath, config.excludeMatchers)) ||\n (config.ignoreImporterMatchers.length > 0 &&\n matchesAny(relativePath, config.ignoreImporterMatchers))\n\n if (excluded) {\n result = false\n } else if (config.includeMatchers.length > 0) {\n result = !!matchesAny(relativePath, config.includeMatchers)\n } else if (config.srcDirectory) {\n result = isInsideDirectory(importer, config.srcDirectory)\n } else {\n result = true\n }\n\n shouldCheckImporterCache.set(importer, result)\n return result\n }\n\n function dedupeKey(info: ViolationInfo): string {\n return `${info.type}:${info.importer}:${info.specifier}:${info.resolved ?? ''}`\n }\n\n function hasSeen(env: EnvState, key: string): boolean {\n if (config.logMode === 'always') return false\n if (env.seenViolations.has(key)) return true\n env.seenViolations.add(key)\n return false\n }\n\n function getRelativePath(absolutePath: string): string {\n return relativizePath(normalizePath(absolutePath), config.root)\n }\n\n /** Reset all caches on an EnvState (called from buildStart). */\n function clearEnvState(envState: EnvState): void {\n envState.resolveCache.clear()\n envState.resolveCacheByFile.clear()\n envState.importLocCache.clear()\n envState.seenViolations.clear()\n envState.transformResultCache.clear()\n envState.transformResultKeysByFile.clear()\n envState.postTransformImports.clear()\n envState.serverFnLookupModules.clear()\n envState.pendingViolations.clear()\n envState.deferredBuildViolations.length = 0\n envState.graph.clear()\n envState.mockExportsByImporter.clear()\n }\n\n /** Invalidate all env-level caches that reference a specific file. */\n function invalidateFileFromEnv(envState: EnvState, file: string): void {\n envState.importLocCache.deleteByFile(file)\n\n // Resolve cache (keyed \"importer:source\")\n const resolveKeys = envState.resolveCacheByFile.get(file)\n if (resolveKeys) {\n for (const key of resolveKeys) envState.resolveCache.delete(key)\n envState.resolveCacheByFile.delete(file)\n }\n\n envState.graph.invalidate(file)\n envState.mockExportsByImporter.delete(file)\n envState.serverFnLookupModules.delete(file)\n envState.pendingViolations.delete(file)\n\n // Transform result cache + post-transform imports\n const transformKeys = envState.transformResultKeysByFile.get(file)\n if (transformKeys) {\n for (const key of transformKeys) {\n envState.transformResultCache.delete(key)\n envState.postTransformImports.delete(key)\n }\n envState.transformResultKeysByFile.delete(file)\n } else {\n envState.transformResultCache.delete(file)\n envState.postTransformImports.delete(file)\n }\n }\n\n /** Store a transform result under both the cacheKey and physical file path. */\n function cacheTransformResult(\n envState: EnvState,\n file: string,\n cacheKey: string,\n result: TransformResult,\n ): void {\n envState.transformResultCache.set(cacheKey, result)\n const keySet = getOrCreate(\n envState.transformResultKeysByFile,\n file,\n () => new Set<string>(),\n )\n keySet.add(cacheKey)\n if (cacheKey !== file) {\n envState.transformResultCache.set(file, result)\n keySet.add(file)\n }\n }\n\n /** Register known Start entrypoints as trace roots for all environments. */\n function registerEntries(): void {\n const { resolvedStartConfig } = opts.getConfig()\n for (const envDef of opts.environments) {\n const envState = getEnv(envDef.name)\n if (resolvedStartConfig.routerFilePath) {\n envState.graph.addEntry(\n normalizePath(resolvedStartConfig.routerFilePath),\n )\n }\n if (resolvedStartConfig.startFilePath) {\n envState.graph.addEntry(\n normalizePath(resolvedStartConfig.startFilePath),\n )\n }\n }\n }\n\n /**\n * Get the merged set of post-transform imports for a file, checking all\n * code-split variants. Returns `null` if no post-transform data exists\n * yet (transform hasn't run).\n *\n * Skips `SERVER_FN_LOOKUP` variants because they contain untransformed\n * code — the Start compiler excludes them.\n */\n function getPostTransformImports(\n env: EnvState,\n file: string,\n ): Set<string> | null {\n const keySet = env.transformResultKeysByFile.get(file)\n let merged: Set<string> | null = null\n\n if (keySet) {\n for (const k of keySet) {\n if (k.includes(SERVER_FN_LOOKUP_QUERY)) continue\n const imports = env.postTransformImports.get(k)\n if (imports) {\n if (!merged) merged = new Set(imports)\n else for (const v of imports) merged.add(v)\n }\n }\n }\n\n // Fallback: direct file-path key\n if (!merged) {\n const imports = env.postTransformImports.get(file)\n if (imports) merged = new Set(imports)\n }\n\n return merged\n }\n\n /**\n * Check whether an import edge from `parent` to `target` survived\n * post-transform compilation.\n *\n * Returns:\n * - `'live'` — target appears in a non-lookup variant's post-transform imports\n * - `'dead'` — post-transform data exists but target is absent (compiler stripped it)\n * - `'pending'` — transform ran but import data not yet posted\n * - `'no-data'` — transform never ran (warm-start cached module)\n */\n function checkEdgeLiveness(\n env: EnvState,\n parent: string,\n target: string,\n ): 'live' | 'dead' | 'pending' | 'no-data' {\n const keySet = env.transformResultKeysByFile.get(parent)\n let anyVariantCached = false\n\n if (keySet) {\n for (const k of keySet) {\n if (k.includes(SERVER_FN_LOOKUP_QUERY)) continue\n const imports = env.postTransformImports.get(k)\n if (imports) {\n anyVariantCached = true\n if (imports.has(target)) return 'live'\n }\n }\n }\n\n if (!anyVariantCached) {\n const imports = env.postTransformImports.get(parent)\n if (imports) return imports.has(target) ? 'live' : 'dead'\n const hasTransformResult =\n env.transformResultCache.has(parent) ||\n (keySet ? keySet.size > 0 : false)\n return hasTransformResult ? 'pending' : 'no-data'\n }\n\n return 'dead'\n }\n\n function checkPostTransformReachability(\n env: EnvState,\n file: string,\n ): 'reachable' | 'unreachable' | 'unknown' {\n const visited = new Set<string>()\n const queue: Array<string> = [file]\n let hasUnknownEdge = false\n let qi = 0\n\n while (qi < queue.length) {\n const current = queue[qi++]!\n if (visited.has(current)) continue\n visited.add(current)\n\n if (env.graph.entries.has(current)) {\n return 'reachable'\n }\n\n const importers = env.graph.reverseEdges.get(current)\n if (!importers) continue\n\n for (const [parent] of importers) {\n if (visited.has(parent)) continue\n const liveness = checkEdgeLiveness(env, parent, current)\n if (liveness === 'live' || liveness === 'no-data') {\n // Live edge or warm-start (no transform data) — follow it\n queue.push(parent)\n } else if (liveness === 'pending') {\n hasUnknownEdge = true\n }\n // 'dead' — edge was stripped by compiler, skip\n }\n }\n\n return hasUnknownEdge ? 'unknown' : 'unreachable'\n }\n\n /**\n * Filter pending violations using edge-survival data. Returns the subset\n * of violations whose resolved import survived the Start compiler (or all\n * violations when no post-transform data is available yet).\n *\n * Returns `undefined` when all violations were stripped or when we must wait\n * for post-transform data before proceeding.\n */\n function filterEdgeSurvival(\n env: EnvState,\n file: string,\n violations: Array<PendingViolation>,\n ):\n | { active: Array<PendingViolation>; edgeSurvivalApplied: boolean }\n | 'all-stripped'\n | 'await-transform' {\n const postTransform = getPostTransformImports(env, file)\n\n if (postTransform) {\n const surviving = violations.filter(\n (pv) => !pv.info.resolved || postTransform.has(pv.info.resolved),\n )\n if (surviving.length === 0) return 'all-stripped'\n env.pendingViolations.set(file, surviving)\n return { active: surviving, edgeSurvivalApplied: true }\n }\n\n // Pre-transform violations need edge-survival verification first.\n if (violations.some((pv) => pv.fromPreTransformResolve)) {\n return 'await-transform'\n }\n\n return { active: violations, edgeSurvivalApplied: false }\n }\n\n /**\n * Process pending violations for the given environment. Called from the\n * transform-cache hook after each module transform is cached, because new\n * transform data may allow us to confirm or discard pending violations.\n *\n * @param warnFn - `this.warn` from the transform hook context\n */\n async function processPendingViolations(\n env: EnvState,\n warnFn: (msg: string) => void,\n ): Promise<void> {\n if (env.pendingViolations.size === 0) return\n\n const toDelete: Array<string> = []\n\n for (const [file, violations] of env.pendingViolations) {\n const filtered = filterEdgeSurvival(env, file, violations)\n\n if (filtered === 'all-stripped') {\n toDelete.push(file)\n continue\n }\n if (filtered === 'await-transform') continue\n\n const { active, edgeSurvivalApplied } = filtered\n\n // Wait for entries before running reachability. registerEntries()\n // populates entries at buildStart; resolveId(!importer) may add more.\n const status =\n env.graph.entries.size > 0\n ? checkPostTransformReachability(env, file)\n : 'unknown'\n\n if (status === 'reachable') {\n for (const pv of active) {\n await emitPendingViolation(env, warnFn, pv)\n }\n toDelete.push(file)\n } else if (status === 'unreachable') {\n toDelete.push(file)\n } else if (config.command === 'serve') {\n // 'unknown' reachability — some graph edges lack transform data.\n // When edge-survival was applied, surviving violations are confirmed\n // real. Without it (warm start), emit conservatively.\n let emittedAny = false\n for (const pv of active) {\n if (pv.fromPreTransformResolve) continue\n\n const shouldEmit =\n edgeSurvivalApplied ||\n (pv.info.type === 'file' &&\n !!pv.info.resolved &&\n isInsideDirectory(pv.info.resolved, config.srcDirectory))\n\n if (shouldEmit) {\n emittedAny =\n (await emitPendingViolation(env, warnFn, pv)) || emittedAny\n }\n }\n\n if (emittedAny) {\n toDelete.push(file)\n }\n }\n // 'unknown' — keep pending for next transform-cache invocation.\n }\n\n for (const file of toDelete) {\n env.pendingViolations.delete(file)\n }\n }\n\n async function emitPendingViolation(\n env: EnvState,\n warnFn: (msg: string) => void,\n pv: PendingViolation,\n ): Promise<boolean> {\n if (!pv.info.importerLoc) {\n const sourceCandidates = buildSourceCandidates(\n pv.info.specifier,\n pv.info.resolved,\n config.root,\n )\n const loc = await resolveImporterLocation(\n env.transformResultProvider,\n env,\n pv.info.importer,\n sourceCandidates,\n )\n\n if (loc) {\n pv.info.importerLoc = loc\n pv.info.snippet = buildCodeSnippet(\n env.transformResultProvider,\n pv.info.importer,\n loc,\n )\n }\n }\n\n if (hasSeen(env, dedupeKey(pv.info))) {\n return false\n }\n\n const freshTrace = await rebuildAndAnnotateTrace(\n env.transformResultProvider,\n env,\n pv.info.env,\n pv.info.importer,\n pv.info.specifier,\n pv.info.importerLoc,\n )\n if (freshTrace.length > pv.info.trace.length) {\n pv.info.trace = freshTrace\n }\n\n if (config.onViolation) {\n const result = await config.onViolation(pv.info)\n if (result === false) return false\n }\n\n warnFn(formatViolation(pv.info, config.root))\n return true\n }\n\n /**\n * Record a violation as pending for later confirmation via graph\n * reachability. Called from `resolveId` when `shouldDefer` is true.\n */\n function deferViolation(\n env: EnvState,\n importerFile: string,\n info: ViolationInfo,\n isPreTransformResolve?: boolean,\n ): void {\n getOrCreate(env.pendingViolations, importerFile, () => []).push({\n info,\n fromPreTransformResolve: isPreTransformResolve,\n })\n }\n\n /** Counter for generating unique per-violation mock module IDs in build mode. */\n let buildViolationCounter = 0\n\n async function handleViolation(\n ctx: ViolationReporter,\n env: EnvState,\n info: ViolationInfo,\n importerIdHint?: string,\n violationOpts?: { silent?: boolean },\n ): Promise<HandleViolationResult> {\n if (!violationOpts?.silent) {\n if (config.onViolation) {\n const result = await config.onViolation(info)\n if (result === false) return undefined\n }\n\n if (config.effectiveBehavior === 'error') {\n // Dev+error: throw immediately.\n // Always throw on error — do NOT deduplicate via hasSeen().\n // Rollup may resolve the same specifier multiple times (e.g.\n // commonjs--resolver's nested this.resolve() fires before\n // getResolveStaticDependencyPromises). If we record the key\n // on the first (nested) throw, the second (real) resolve\n // silently returns undefined and the build succeeds — which\n // is the bug this fixes.\n //\n // Build mode never reaches here — all build violations are\n // deferred via shouldDefer and handled silently.\n return ctx.error(formatViolation(info, config.root))\n }\n\n if (!hasSeen(env, dedupeKey(info))) {\n ctx.warn(formatViolation(info, config.root))\n }\n } else if (\n config.effectiveBehavior === 'error' &&\n config.command !== 'build'\n ) {\n return undefined\n }\n\n // File violations: return resolved path — the self-denial transform\n // will replace the file's content with a mock module. This avoids\n // virtual module IDs that could leak across environments via\n // third-party resolver caches.\n if (info.type === 'file') return info.resolved\n\n // Non-file violations (specifier/marker): create mock-edge module.\n // Dev mode uses a runtime diagnostics ID; build mode uses a unique\n // per-violation ID so generateBundle can check tree-shaking survival.\n const exports = await resolveExportsForDeniedSpecifier(\n env,\n ctx,\n info,\n importerIdHint,\n )\n const baseMockId =\n config.command === 'serve'\n ? mockRuntimeModuleIdFromViolation(info, config.mockAccess, config.root)\n : `${MOCK_BUILD_PREFIX}${buildViolationCounter++}`\n return resolveViteId(makeMockEdgeModuleId(exports, baseMockId))\n }\n\n /**\n * Unified violation dispatch: either defers or reports immediately.\n *\n * When `shouldDefer` is true (dev mock + build modes), calls\n * `handleViolation` silently to obtain the mock module ID, then stores\n * the violation for later verification:\n * - Dev mock mode: all violations are deferred to `pendingViolations`\n * for edge-survival and graph-reachability checking via\n * `processPendingViolations`.\n * - Build mode (mock + error): defers to `deferredBuildViolations` for\n * tree-shaking verification in `generateBundle`.\n *\n * Otherwise reports immediately (dev error mode). Pre-transform\n * resolves are silenced in error mode because they fire before the\n * compiler runs and there is no deferred verification path.\n *\n * Returns the mock module ID / resolve result from `handleViolation`.\n */\n async function reportOrDeferViolation(\n ctx: ViolationReporter,\n env: EnvState,\n importerFile: string,\n importerIdHint: string | undefined,\n info: ViolationInfo,\n shouldDefer: boolean,\n isPreTransformResolve: boolean,\n ): Promise<HandleViolationResult> {\n if (shouldDefer) {\n const result = await handleViolation(ctx, env, info, importerIdHint, {\n silent: true,\n })\n\n if (config.command === 'build') {\n // Build mode: store for generateBundle tree-shaking check.\n // The mock-edge module ID is returned as a plain string.\n const mockId = result ?? ''\n env.deferredBuildViolations.push({\n info,\n mockModuleId: mockId,\n // For marker violations, check importer survival instead of mock.\n checkModuleId: info.type === 'marker' ? info.importer : undefined,\n })\n } else {\n // Dev mock: store for graph-reachability check.\n deferViolation(env, importerFile, info, isPreTransformResolve)\n await processPendingViolations(env, ctx.warn.bind(ctx))\n }\n\n return result\n }\n\n // Non-deferred path: dev error mode only.\n // Pre-transform resolves are silenced because they fire before the\n // compiler runs — imports inside `.server()` callbacks haven't been\n // stripped yet and error mode has no deferred verification.\n return handleViolation(ctx, env, info, importerIdHint, {\n silent: isPreTransformResolve,\n })\n }\n\n return [\n {\n name: 'tanstack-start-core:import-protection',\n enforce: 'pre',\n\n applyToEnvironment(env) {\n if (!config.enabled) return false\n // Start's environments are named `client` and `ssr` (not `server`), plus\n // an optional serverFn provider environment (eg `rsc`) when configured.\n return environmentNames.has(env.name)\n },\n\n configResolved(viteConfig) {\n config.root = viteConfig.root\n config.command = viteConfig.command\n\n const { startConfig, resolvedStartConfig } = opts.getConfig()\n config.srcDirectory = resolvedStartConfig.srcDirectory\n\n const userOpts: ImportProtectionOptions | undefined =\n startConfig.importProtection\n\n if (userOpts?.enabled === false) {\n config.enabled = false\n return\n }\n\n config.enabled = true\n\n const behavior = userOpts?.behavior\n if (typeof behavior === 'string') {\n config.effectiveBehavior = behavior\n } else {\n config.effectiveBehavior =\n viteConfig.command === 'serve'\n ? (behavior?.dev ?? 'mock')\n : (behavior?.build ?? 'error')\n }\n\n config.logMode = userOpts?.log ?? 'once'\n config.mockAccess = userOpts?.mockAccess ?? 'error'\n config.maxTraceDepth = userOpts?.maxTraceDepth ?? 20\n if (userOpts?.onViolation) {\n const fn = userOpts.onViolation\n config.onViolation = (info) => fn(info)\n }\n\n const defaults = getDefaultImportProtectionRules()\n // Use user-provided patterns when available, otherwise defaults.\n const pick = <T>(user: Array<T> | undefined, fallback: Array<T>) =>\n user ? [...user] : [...fallback]\n\n // Client specifier denies always include framework defaults even\n // when the user provides a custom list.\n const clientSpecifiers = dedupePatterns([\n ...defaults.client.specifiers,\n ...(userOpts?.client?.specifiers ?? []),\n ])\n\n config.compiledRules.client = {\n specifiers: compileMatchers(clientSpecifiers),\n files: compileMatchers(\n pick(userOpts?.client?.files, defaults.client.files),\n ),\n excludeFiles: compileMatchers(\n pick(userOpts?.client?.excludeFiles, defaults.client.excludeFiles),\n ),\n }\n config.compiledRules.server = {\n specifiers: compileMatchers(\n dedupePatterns(\n pick(userOpts?.server?.specifiers, defaults.server.specifiers),\n ),\n ),\n files: compileMatchers(\n pick(userOpts?.server?.files, defaults.server.files),\n ),\n excludeFiles: compileMatchers(\n pick(userOpts?.server?.excludeFiles, defaults.server.excludeFiles),\n ),\n }\n\n config.includeMatchers = compileMatchers(userOpts?.include ?? [])\n config.excludeMatchers = compileMatchers(userOpts?.exclude ?? [])\n config.ignoreImporterMatchers = compileMatchers(\n userOpts?.ignoreImporters ?? [],\n )\n\n // Marker specifiers\n const markers = getMarkerSpecifiers()\n config.markerSpecifiers = {\n serverOnly: new Set(markers.serverOnly),\n clientOnly: new Set(markers.clientOnly),\n }\n },\n\n configureServer(server) {\n devServer = server\n },\n\n buildStart() {\n if (!config.enabled) return\n // Clear memoization caches that grow unboundedly across builds\n clearNormalizeFilePathCache()\n extensionlessIdResolver.clear()\n importPatternCache.clear()\n shouldCheckImporterCache.clear()\n\n // Clear per-env caches\n for (const envState of envStates.values()) {\n clearEnvState(envState)\n }\n\n // Clear shared state\n shared.fileMarkerKind.clear()\n\n registerEntries()\n },\n\n hotUpdate(ctx) {\n if (!config.enabled) return\n // Invalidate caches for updated files\n for (const mod of ctx.modules) {\n if (mod.id) {\n const id = mod.id\n const importerFile = normalizeFilePath(id)\n\n // Invalidate extensionless-resolution cache entries affected by this file.\n extensionlessIdResolver.invalidateByFile(importerFile)\n shared.fileMarkerKind.delete(importerFile)\n\n // Invalidate per-env caches\n for (const envState of envStates.values()) {\n invalidateFileFromEnv(envState, importerFile)\n }\n }\n }\n },\n\n async resolveId(source, importer, _options) {\n const envName = this.environment.name\n const env = getEnv(envName)\n const envType = getEnvType(envName)\n const provider = env.transformResultProvider\n const isScanResolve = !!(_options as Record<string, unknown>).scan\n\n if (IMPORT_PROTECTION_DEBUG) {\n const importerPath = importer\n ? normalizeFilePath(importer)\n : '(entry)'\n const isEntryResolve = !importer\n const filtered =\n process.env.TSR_IMPORT_PROTECTION_DEBUG_FILTER === 'entry'\n ? isEntryResolve\n : matchesDebugFilter(source, importerPath)\n if (filtered) {\n debugLog('resolveId', {\n env: envName,\n envType,\n source,\n importer: importerPath,\n isEntryResolve,\n command: config.command,\n })\n }\n }\n\n // Internal virtual modules (mock:build:N, mock-edge, mock-runtime, marker)\n const internalVirtualId = resolveInternalVirtualModuleId(source)\n if (internalVirtualId) return internalVirtualId\n\n if (!importer) {\n env.graph.addEntry(source)\n // Flush pending violations now that an additional entry is known\n // and reachability analysis may have new roots.\n await processPendingViolations(env, this.warn.bind(this))\n return undefined\n }\n\n if (source.startsWith('\\0') || source.startsWith('virtual:')) {\n return undefined\n }\n\n const normalizedImporter = normalizeFilePath(importer)\n const isDirectLookup = importer.includes(SERVER_FN_LOOKUP_QUERY)\n\n if (isDirectLookup) {\n env.serverFnLookupModules.add(normalizedImporter)\n }\n\n const isPreTransformResolve =\n isDirectLookup ||\n env.serverFnLookupModules.has(normalizedImporter) ||\n isScanResolve\n\n // Dev mock mode: defer all violations (including pre-transform\n // resolves) until post-transform data is available, then\n // confirm/discard via graph reachability.\n // Build mode (both mock and error): defer violations until\n // generateBundle so tree-shaking can eliminate false positives.\n const isDevMock =\n config.command === 'serve' && config.effectiveBehavior === 'mock'\n const isBuild = config.command === 'build'\n const shouldDefer = shouldDeferViolation({ isBuild, isDevMock })\n\n const resolveAgainstImporter = async (): Promise<string | null> => {\n const primary = await this.resolve(source, importer, {\n skipSelf: true,\n })\n if (primary) {\n return canonicalizeResolvedId(\n primary.id,\n config.root,\n resolveExtensionlessAbsoluteId,\n )\n }\n\n return null\n }\n\n // Check if this is a marker import\n const markerKind = config.markerSpecifiers.serverOnly.has(source)\n ? ('server' as const)\n : config.markerSpecifiers.clientOnly.has(source)\n ? ('client' as const)\n : undefined\n\n if (markerKind) {\n const existing = shared.fileMarkerKind.get(normalizedImporter)\n if (existing && existing !== markerKind) {\n this.error(\n `[import-protection] File \"${getRelativePath(normalizedImporter)}\" has both server-only and client-only markers. This is not allowed.`,\n )\n }\n shared.fileMarkerKind.set(normalizedImporter, markerKind)\n\n const violatesEnv =\n (envType === 'client' && markerKind === 'server') ||\n (envType === 'server' && markerKind === 'client')\n\n if (violatesEnv) {\n const info = await buildViolationInfo(\n provider,\n env,\n envName,\n envType,\n importer,\n normalizedImporter,\n source,\n {\n type: 'marker',\n message: buildMarkerViolationMessage(\n getRelativePath(normalizedImporter),\n markerKind,\n ),\n },\n )\n const markerResult = await reportOrDeferViolation(\n this,\n env,\n normalizedImporter,\n importer,\n info,\n shouldDefer,\n isPreTransformResolve,\n )\n\n // In build mode, if the violation was deferred, return the unique\n // build mock ID instead of the marker module. This lets\n // generateBundle check whether the importer (and thus its marker\n // import) survived tree-shaking. The mock is side-effect-free just\n // like the marker module, and the bare import has no bindings, so\n // replacing it is transparent.\n if (isBuild && markerResult != null) {\n return markerResult\n }\n }\n\n // Retroactive marker violation detection: on cold starts, module\n // A may import module B before B's marker is set (because B hasn't\n // been processed yet). When B's marker is set (here),\n // retroactively check all known importers of B in the graph and\n // create deferred marker violations for them. Without this,\n // cold-start ordering can miss marker violations that warm starts\n // detect (warm starts see markers early from cached transforms).\n //\n // Uses lightweight `deferViolation` to avoid heavy side effects\n // (mock module creation, export resolution). Immediately calls\n // `processPendingViolations` to flush the deferred violations,\n // because the marker resolveId fires during Vite's import\n // analysis (after our transform hook) — there may be no\n // subsequent transform invocation to flush them.\n //\n // Guarded by `violatesEnv` (per-environment) plus a per-env\n // seen-set. The marker is shared across environments but each\n // env's graph has its own edges; this ensures the check runs\n // at most once per (env, module) pair.\n const envRetroKey = `retro-marker:${normalizedImporter}`\n if (violatesEnv && !env.seenViolations.has(envRetroKey)) {\n env.seenViolations.add(envRetroKey)\n let retroDeferred = false\n const importersMap = env.graph.reverseEdges.get(normalizedImporter)\n if (importersMap && importersMap.size > 0) {\n for (const [importerFile, specifier] of importersMap) {\n if (!specifier) continue\n if (!shouldCheckImporter(importerFile)) continue\n const markerInfo = await buildMarkerViolationFromResolvedImport(\n provider,\n env,\n envName,\n envType,\n importerFile,\n specifier,\n normalizedImporter,\n getRelativePath(normalizedImporter),\n )\n if (markerInfo) {\n deferViolation(\n env,\n importerFile,\n markerInfo,\n isPreTransformResolve,\n )\n retroDeferred = true\n }\n }\n }\n if (retroDeferred) {\n await processPendingViolations(env, this.warn.bind(this))\n }\n }\n\n return markerKind === 'server'\n ? resolvedMarkerVirtualModuleId('server')\n : resolvedMarkerVirtualModuleId('client')\n }\n\n // Check if the importer is within our scope\n if (!shouldCheckImporter(normalizedImporter)) {\n return undefined\n }\n\n const matchers = getRulesForEnvironment(envName)\n\n // 1. Specifier-based denial\n const specifierMatch = matchesAny(source, matchers.specifiers)\n if (specifierMatch) {\n if (!isPreTransformResolve) {\n env.graph.addEdge(source, normalizedImporter, source)\n }\n const info = await buildViolationInfo(\n provider,\n env,\n envName,\n envType,\n importer,\n normalizedImporter,\n source,\n {\n type: 'specifier',\n pattern: specifierMatch.pattern,\n message: `Import \"${source}\" is denied in the ${envType} environment`,\n },\n )\n\n // Resolve the specifier so edge-survival can verify whether\n // the import survives the Start compiler transform (e.g.\n // factory-safe pattern strips imports inside .server() callbacks).\n if (shouldDefer && !info.resolved) {\n try {\n const resolvedForInfo = await resolveAgainstImporter()\n if (resolvedForInfo) info.resolved = resolvedForInfo\n } catch {\n // Non-fatal: edge-survival will skip unresolved specifiers\n }\n }\n\n return reportOrDeferViolation(\n this,\n env,\n normalizedImporter,\n importer,\n info,\n shouldDefer,\n isPreTransformResolve,\n )\n }\n\n // 2. Resolve the import (cached)\n const cacheKey = `${normalizedImporter}:${source}`\n let resolved: string | null\n\n if (env.resolveCache.has(cacheKey)) {\n resolved = env.resolveCache.get(cacheKey) ?? null\n } else {\n resolved = await resolveAgainstImporter()\n\n // Only cache successful resolves. Null resolves can be\n // order-dependent across importer variants (e.g. code-split\n // `?tsr-split=...` ids) and may poison later lookups.\n if (resolved !== null) {\n env.resolveCache.set(cacheKey, resolved)\n getOrCreate(\n env.resolveCacheByFile,\n normalizedImporter,\n () => new Set(),\n ).add(cacheKey)\n }\n }\n\n if (resolved) {\n const relativePath = getRelativePath(resolved)\n\n // Propagate pre-transform status transitively\n if (isPreTransformResolve && !isScanResolve) {\n env.serverFnLookupModules.add(resolved)\n }\n\n if (!isPreTransformResolve) {\n env.graph.addEdge(resolved, normalizedImporter, source)\n }\n\n // Skip file-based and marker-based denial for resolved paths that\n // match the per-environment `excludeFiles` patterns. By default\n // this includes `**/node_modules/**` so that third-party packages\n // using `.client.` / `.server.` in their filenames (e.g. react-tweet\n // exports `index.client.js`) are not treated as user-authored\n // environment boundaries. Users can override `excludeFiles` per\n // environment to narrow or widen this exclusion.\n const isExcludedFile =\n matchers.excludeFiles.length > 0 &&\n matchesAny(relativePath, matchers.excludeFiles)\n\n if (!isExcludedFile) {\n const fileMatch =\n matchers.files.length > 0\n ? matchesAny(relativePath, matchers.files)\n : undefined\n\n if (fileMatch) {\n const info = await buildFileViolationInfo(\n provider,\n env,\n envName,\n envType,\n importer,\n normalizedImporter,\n source,\n resolved,\n fileMatch.pattern,\n )\n return reportOrDeferViolation(\n this,\n env,\n normalizedImporter,\n importer,\n info,\n shouldDefer,\n isPreTransformResolve,\n )\n }\n\n const markerInfo = await buildMarkerViolationFromResolvedImport(\n provider,\n env,\n envName,\n envType,\n importer,\n source,\n resolved,\n relativePath,\n )\n if (markerInfo) {\n return reportOrDeferViolation(\n this,\n env,\n normalizedImporter,\n importer,\n markerInfo,\n shouldDefer,\n isPreTransformResolve,\n )\n }\n }\n }\n\n return undefined\n },\n\n load: {\n filter: {\n id: new RegExp(\n getResolvedVirtualModuleMatchers().map(escapeRegExp).join('|'),\n ),\n },\n handler(id) {\n if (IMPORT_PROTECTION_DEBUG) {\n if (matchesDebugFilter(id)) {\n debugLog('load:handler', {\n env: this.environment.name,\n id: normalizePath(id),\n })\n }\n }\n\n return loadResolvedVirtualModule(id)\n },\n },\n\n async generateBundle(_options, bundle) {\n const envName = this.environment.name\n const env = envStates.get(envName)\n if (!env || env.deferredBuildViolations.length === 0) return\n\n const candidateCache = new Map<string, Array<string>>()\n const toModuleIdCandidates = (id: string): Array<string> => {\n let cached = candidateCache.get(id)\n if (cached) return cached\n\n const out = new Set<string>()\n const normalized = normalizeFilePath(id)\n out.add(id)\n out.add(normalized)\n out.add(relativizePath(normalized, config.root))\n\n if (normalized.startsWith(VITE_BROWSER_VIRTUAL_PREFIX)) {\n const internal = `\\0${normalized.slice(VITE_BROWSER_VIRTUAL_PREFIX.length)}`\n out.add(internal)\n out.add(relativizePath(normalizeFilePath(internal), config.root))\n }\n\n if (normalized.startsWith('\\0')) {\n const browser = `${VITE_BROWSER_VIRTUAL_PREFIX}${normalized.slice(1)}`\n out.add(browser)\n out.add(relativizePath(normalizeFilePath(browser), config.root))\n }\n\n cached = Array.from(out)\n candidateCache.set(id, cached)\n return cached\n }\n\n // Collect all module IDs that survived tree-shaking in this bundle.\n const survivingModules = new Set<string>()\n for (const chunk of Object.values(bundle)) {\n if (chunk.type === 'chunk') {\n for (const moduleId of Object.keys(chunk.modules)) {\n for (const candidate of toModuleIdCandidates(moduleId)) {\n survivingModules.add(candidate)\n }\n }\n }\n }\n\n const didModuleSurvive = (moduleId: string): boolean =>\n toModuleIdCandidates(moduleId).some((candidate) =>\n survivingModules.has(candidate),\n )\n\n // Check each deferred violation: if its check module survived\n // in the bundle, the import was NOT tree-shaken — real leak.\n const realViolations: Array<ViolationInfo> = []\n for (const {\n info,\n mockModuleId,\n checkModuleId,\n } of env.deferredBuildViolations) {\n let survived: boolean\n if (checkModuleId != null) {\n // Marker violation: check if the importer survived\n // (marker is about the file's directive, not a binding).\n // Include transform-result keys (e.g. code-split variants)\n // to cover all bundle representations of the importer.\n const importerVariantIds = new Set<string>([info.importer])\n const importerKeys = env.transformResultKeysByFile.get(\n normalizeFilePath(info.importer),\n )\n if (importerKeys) {\n for (const key of importerKeys) {\n importerVariantIds.add(key)\n }\n }\n survived = false\n for (const importerId of importerVariantIds) {\n if (didModuleSurvive(importerId)) {\n survived = true\n break\n }\n }\n } else {\n // File/specifier violation: check if the mock module survived.\n survived = didModuleSurvive(mockModuleId)\n }\n\n if (!survived) continue\n\n if (config.onViolation) {\n const result = await config.onViolation(info)\n if (result === false) continue\n }\n\n realViolations.push(info)\n }\n\n if (realViolations.length === 0) return\n\n if (config.effectiveBehavior === 'error') {\n // Error mode: fail the build on the first real violation.\n this.error(formatViolation(realViolations[0]!, config.root))\n } else {\n // Mock mode: warn for each surviving violation.\n const seen = new Set<string>()\n for (const info of realViolations) {\n const key = dedupeKey(info)\n if (!seen.has(key)) {\n seen.add(key)\n this.warn(formatViolation(info, config.root))\n }\n }\n }\n },\n },\n {\n // Captures transformed code + composed sourcemap for location mapping.\n // Runs after all `enforce: 'pre'` hooks (including the Start compiler).\n // Only files under `srcDirectory` are cached.\n name: 'tanstack-start-core:import-protection-transform-cache',\n\n applyToEnvironment(env) {\n if (!config.enabled) return false\n return environmentNames.has(env.name)\n },\n\n transform: {\n filter: {\n id: {\n include: [/\\.[cm]?[tj]sx?($|\\?)/],\n },\n },\n async handler(code, id) {\n const envName = this.environment.name\n const file = normalizeFilePath(id)\n const envType = getEnvType(envName)\n const matchers = getRulesForEnvironment(envName)\n const isBuild = config.command === 'build'\n\n if (IMPORT_PROTECTION_DEBUG) {\n if (matchesDebugFilter(file)) {\n debugLog('transform-cache', {\n env: envName,\n id: normalizePath(id),\n file,\n })\n }\n }\n\n if (!shouldCheckImporter(file)) {\n return undefined\n }\n\n // Self-denial: if this file is denied in the current environment\n // (e.g. a `.server` file transformed in the client environment),\n // replace its entire content with a mock module.\n //\n // This is the core mechanism for preventing cross-environment\n // cache contamination: resolveId never returns virtual module\n // IDs for file-based violations, so there is nothing for\n // third-party resolver caches (e.g. vite-tsconfig-paths) to\n // leak across environments. Each environment's transform\n // independently decides whether the file is denied.\n //\n // In dev mode, this also solves the cold-start problem where\n // the importer's AST is unavailable for export resolution:\n // the denied file's own source code is always available here,\n // so we parse its exports directly.\n const selfFileMatch = checkFileDenial(getRelativePath(file), matchers)\n if (selfFileMatch) {\n // Parse exports once — shared by build and dev paths.\n // Falls back to empty list on non-standard syntax.\n let exportNames: Array<string> = []\n try {\n exportNames = collectNamedExports(code)\n } catch {\n // Parsing may fail on non-standard syntax\n }\n\n if (isBuild) {\n return generateSelfContainedMockModule(exportNames)\n }\n\n // Dev mode: generate a mock that imports mock-runtime for\n // runtime diagnostics (error/warn on property access).\n const runtimeId = mockRuntimeModuleIdFromViolation(\n {\n type: 'file',\n env: envType,\n envType,\n behavior:\n config.effectiveBehavior === 'error' ? 'error' : 'mock',\n importer: file,\n specifier: relativizePath(file, config.root),\n resolved: file,\n pattern: selfFileMatch.pattern,\n message: `File \"${relativizePath(file, config.root)}\" is denied in the ${envType} environment`,\n trace: [],\n },\n config.mockAccess,\n config.root,\n )\n return generateDevSelfDenialModule(exportNames, runtimeId)\n }\n\n // getCombinedSourcemap() returns the composed sourcemap\n let map: SourceMapLike | undefined\n try {\n map = this.getCombinedSourcemap()\n } catch {\n map = undefined\n }\n\n let originalCode: string | undefined\n if (map?.sourcesContent) {\n originalCode = pickOriginalCodeFromSourcesContent(\n map,\n file,\n config.root,\n )\n }\n\n const lineIndex = buildLineIndex(code)\n const cacheKey = normalizePath(id)\n\n const envState = getEnv(envName)\n const isServerFnLookup = id.includes(SERVER_FN_LOOKUP_QUERY)\n\n // Propagate SERVER_FN_LOOKUP status before import-analysis\n if (isServerFnLookup) {\n envState.serverFnLookupModules.add(file)\n }\n\n const result: TransformResult = {\n code,\n map,\n originalCode,\n lineIndex,\n }\n cacheTransformResult(envState, file, cacheKey, result)\n\n // Build mode: only self-denial (above) and transform caching are\n // needed. All violations are detected and deferred in resolveId;\n // self-denial replaces denied file content; generateBundle checks\n // tree-shaking survival. The import resolution loop below is\n // dev-mode only — it resolves imports for graph reachability,\n // catches violations missed on warm starts (where Vite caches\n // resolveId), and rewrites denied imports to mock modules.\n if (isBuild) return undefined\n\n // Dev mode: resolve imports, populate graph, detect violations,\n // and rewrite denied imports.\n const isDevMock = config.effectiveBehavior === 'mock'\n const importSources = extractImportSources(code)\n const resolvedChildren = new Set<string>()\n const deniedSourceReplacements = new Map<string, string>()\n for (const src of importSources) {\n try {\n const resolved = await this.resolve(src, id, { skipSelf: true })\n if (resolved && !resolved.external) {\n const resolvedPath = canonicalizeResolvedId(\n resolved.id,\n config.root,\n resolveExtensionlessAbsoluteId,\n )\n\n resolvedChildren.add(resolvedPath)\n\n // When the resolved ID is a mock-module (from our\n // resolveId returning a mock-edge ID), postTransformImports\n // would only contain the mock ID. Edge-survival needs the\n // real physical path so pending violations can be matched.\n //\n // For relative specifiers we can compute the physical path\n // directly. For bare/alias specifiers, look up the real\n // resolved path from the pending violations that were\n // already stored by resolveId before this transform ran.\n if (resolved.id.includes('tanstack-start-import-protection:')) {\n let physicalPath: string | undefined\n // Look up real resolved path from pending violations\n const pending = envState.pendingViolations.get(file)\n if (pending) {\n const match = pending.find(\n (pv) => pv.info.specifier === src && pv.info.resolved,\n )\n if (match) physicalPath = match.info.resolved\n }\n if (physicalPath && physicalPath !== resolvedPath) {\n resolvedChildren.add(physicalPath)\n envState.graph.addEdge(physicalPath, file, src)\n }\n }\n\n // Populate import graph edges for warm-start trace accuracy\n envState.graph.addEdge(resolvedPath, file, src)\n\n if (isDevMock) {\n const relativePath = getRelativePath(resolvedPath)\n const fileMatch = checkFileDenial(relativePath, matchers)\n\n if (fileMatch) {\n const info = await buildFileViolationInfo(\n envState.transformResultProvider,\n envState,\n envName,\n envType,\n id,\n file,\n src,\n resolvedPath,\n fileMatch.pattern,\n )\n\n const replacement = await reportOrDeferViolation(\n this,\n envState,\n file,\n id,\n info,\n isDevMock,\n isServerFnLookup,\n )\n\n if (replacement) {\n deniedSourceReplacements.set(\n src,\n replacement.startsWith('\\0')\n ? VITE_BROWSER_VIRTUAL_PREFIX + replacement.slice(1)\n : replacement,\n )\n }\n }\n }\n }\n } catch {\n // Non-fatal\n }\n }\n envState.postTransformImports.set(cacheKey, resolvedChildren)\n if (cacheKey !== file && !isServerFnLookup) {\n envState.postTransformImports.set(file, resolvedChildren)\n }\n\n await processPendingViolations(envState, this.warn.bind(this))\n\n if (deniedSourceReplacements.size > 0) {\n try {\n const rewritten = rewriteDeniedImports(\n code,\n id,\n new Set(deniedSourceReplacements.keys()),\n (source: string) =>\n deniedSourceReplacements.get(source) ?? source,\n )\n\n if (!rewritten) {\n return undefined\n }\n\n const normalizedMap = rewritten.map\n ? {\n ...rewritten.map,\n version: Number(rewritten.map.version),\n sourcesContent:\n rewritten.map.sourcesContent?.map(\n (s: string | null) => s ?? '',\n ) ?? [],\n }\n : {\n version: 3,\n file: id,\n names: [],\n sources: [id],\n sourcesContent: [code],\n mappings: '',\n }\n\n return {\n code: rewritten.code,\n map: normalizedMap,\n }\n } catch {\n // Non-fatal: keep original code when rewrite fails.\n }\n }\n\n return undefined\n },\n },\n },\n ] satisfies Array<PluginOption>\n}\n"],"mappings":"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"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
type UsagePos = {
|
|
2
|
-
line: number;
|
|
3
|
-
column0: number;
|
|
4
|
-
};
|
|
5
|
-
/**
|
|
6
|
-
* Given transformed code, returns the first "meaningful" usage position for an
|
|
7
|
-
* import from `source` that survives compilation.
|
|
8
|
-
*
|
|
9
|
-
* "Preferred" positions (call, new, member-access) take priority over bare
|
|
10
|
-
* identifier references. The returned column is 0-based (Babel loc semantics).
|
|
11
|
-
*/
|
|
12
|
-
export declare function findPostCompileUsagePos(code: string, source: string): UsagePos | undefined;
|
|
13
|
-
export {};
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { parseImportProtectionAst } from "./ast.js";
|
|
2
|
-
import * as t from "@babel/types";
|
|
3
|
-
import babel from "@babel/core";
|
|
4
|
-
//#region src/import-protection-plugin/postCompileUsage.ts
|
|
5
|
-
/**
|
|
6
|
-
* Given transformed code, returns the first "meaningful" usage position for an
|
|
7
|
-
* import from `source` that survives compilation.
|
|
8
|
-
*
|
|
9
|
-
* "Preferred" positions (call, new, member-access) take priority over bare
|
|
10
|
-
* identifier references. The returned column is 0-based (Babel loc semantics).
|
|
11
|
-
*/
|
|
12
|
-
function findPostCompileUsagePos(code, source) {
|
|
13
|
-
return findPostCompileUsagePosFromAst(parseImportProtectionAst(code), source);
|
|
14
|
-
}
|
|
15
|
-
function findPostCompileUsagePosFromAst(ast, source) {
|
|
16
|
-
const imported = /* @__PURE__ */ new Set();
|
|
17
|
-
for (const node of ast.program.body) if (t.isImportDeclaration(node) && node.source.value === source) {
|
|
18
|
-
if (node.importKind === "type") continue;
|
|
19
|
-
for (const s of node.specifiers) {
|
|
20
|
-
if (t.isImportSpecifier(s) && s.importKind === "type") continue;
|
|
21
|
-
imported.add(s.local.name);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
if (imported.size === 0) return void 0;
|
|
25
|
-
let preferred;
|
|
26
|
-
let anyUsage;
|
|
27
|
-
try {
|
|
28
|
-
babel.traverse(ast, {
|
|
29
|
-
ImportDeclaration(path) {
|
|
30
|
-
path.skip();
|
|
31
|
-
},
|
|
32
|
-
Identifier(path) {
|
|
33
|
-
if (preferred && anyUsage) {
|
|
34
|
-
path.stop();
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
const { node, parent, scope } = path;
|
|
38
|
-
if (!imported.has(node.name)) return;
|
|
39
|
-
if (path.isBindingIdentifier()) return;
|
|
40
|
-
if (t.isObjectProperty(parent) && parent.key === node && !parent.computed && !parent.shorthand) return;
|
|
41
|
-
if (t.isObjectMethod(parent) && parent.key === node && !parent.computed) return;
|
|
42
|
-
if (t.isExportSpecifier(parent) && parent.exported === node) return;
|
|
43
|
-
const binding = scope.getBinding(node.name);
|
|
44
|
-
if (binding && binding.kind !== "module") return;
|
|
45
|
-
const loc = node.loc?.start;
|
|
46
|
-
if (!loc) return;
|
|
47
|
-
const pos = {
|
|
48
|
-
line: loc.line,
|
|
49
|
-
column0: loc.column
|
|
50
|
-
};
|
|
51
|
-
if (t.isCallExpression(parent) && parent.callee === node || t.isNewExpression(parent) && parent.callee === node || t.isMemberExpression(parent) && parent.object === node) preferred ||= pos;
|
|
52
|
-
else anyUsage ||= pos;
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
} catch {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
return preferred ?? anyUsage;
|
|
59
|
-
}
|
|
60
|
-
//#endregion
|
|
61
|
-
export { findPostCompileUsagePos };
|
|
62
|
-
|
|
63
|
-
//# sourceMappingURL=postCompileUsage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postCompileUsage.js","names":[],"sources":["../../../src/import-protection-plugin/postCompileUsage.ts"],"sourcesContent":["import babel from '@babel/core'\nimport * as t from '@babel/types'\nimport { parseImportProtectionAst } from './ast'\nimport type { ParsedAst } from './ast'\n\ntype UsagePos = { line: number; column0: number }\n\n/**\n * Given transformed code, returns the first \"meaningful\" usage position for an\n * import from `source` that survives compilation.\n *\n * \"Preferred\" positions (call, new, member-access) take priority over bare\n * identifier references. The returned column is 0-based (Babel loc semantics).\n */\nexport function findPostCompileUsagePos(\n code: string,\n source: string,\n): UsagePos | undefined {\n return findPostCompileUsagePosFromAst(parseImportProtectionAst(code), source)\n}\n\nfunction findPostCompileUsagePosFromAst(\n ast: ParsedAst,\n source: string,\n): UsagePos | undefined {\n // Collect local names bound from this specifier\n const imported = new Set<string>()\n for (const node of ast.program.body) {\n if (t.isImportDeclaration(node) && node.source.value === source) {\n if (node.importKind === 'type') continue\n for (const s of node.specifiers) {\n if (t.isImportSpecifier(s) && s.importKind === 'type') continue\n imported.add(s.local.name)\n }\n }\n }\n if (imported.size === 0) return undefined\n\n let preferred: UsagePos | undefined\n let anyUsage: UsagePos | undefined\n\n // babel.traverse can throw on malformed scopes (e.g. duplicate bindings from\n // import + const re-declaration) because parseAst doesn't attach a hub\n try {\n babel.traverse(ast, {\n ImportDeclaration(path) {\n path.skip()\n },\n\n Identifier(path: babel.NodePath<t.Identifier>) {\n if (preferred && anyUsage) {\n path.stop()\n return\n }\n\n const { node, parent, scope } = path\n if (!imported.has(node.name)) return\n\n // Skip binding positions (declarations, import specifiers, etc.)\n if (path.isBindingIdentifier()) return\n\n // Skip non-shorthand object property keys — they don't reference the import\n if (\n t.isObjectProperty(parent) &&\n parent.key === node &&\n !parent.computed &&\n !parent.shorthand\n )\n return\n if (t.isObjectMethod(parent) && parent.key === node && !parent.computed)\n return\n if (t.isExportSpecifier(parent) && parent.exported === node) return\n\n // Skip if shadowed by a closer binding\n const binding = scope.getBinding(node.name)\n if (binding && binding.kind !== 'module') return\n\n const loc = node.loc?.start\n if (!loc) return\n const pos: UsagePos = { line: loc.line, column0: loc.column }\n\n const isPreferred =\n (t.isCallExpression(parent) && parent.callee === node) ||\n (t.isNewExpression(parent) && parent.callee === node) ||\n (t.isMemberExpression(parent) && parent.object === node)\n\n if (isPreferred) {\n preferred ||= pos\n } else {\n anyUsage ||= pos\n }\n },\n })\n } catch {\n // Scope analysis failed — cannot determine usage positions reliably\n return undefined\n }\n\n return preferred ?? anyUsage\n}\n"],"mappings":";;;;;;;;;;;AAcA,SAAgB,wBACd,MACA,QACsB;AACtB,QAAO,+BAA+B,yBAAyB,KAAK,EAAE,OAAO;;AAG/E,SAAS,+BACP,KACA,QACsB;CAEtB,MAAM,2BAAW,IAAI,KAAa;AAClC,MAAK,MAAM,QAAQ,IAAI,QAAQ,KAC7B,KAAI,EAAE,oBAAoB,KAAK,IAAI,KAAK,OAAO,UAAU,QAAQ;AAC/D,MAAI,KAAK,eAAe,OAAQ;AAChC,OAAK,MAAM,KAAK,KAAK,YAAY;AAC/B,OAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,eAAe,OAAQ;AACvD,YAAS,IAAI,EAAE,MAAM,KAAK;;;AAIhC,KAAI,SAAS,SAAS,EAAG,QAAO,KAAA;CAEhC,IAAI;CACJ,IAAI;AAIJ,KAAI;AACF,QAAM,SAAS,KAAK;GAClB,kBAAkB,MAAM;AACtB,SAAK,MAAM;;GAGb,WAAW,MAAoC;AAC7C,QAAI,aAAa,UAAU;AACzB,UAAK,MAAM;AACX;;IAGF,MAAM,EAAE,MAAM,QAAQ,UAAU;AAChC,QAAI,CAAC,SAAS,IAAI,KAAK,KAAK,CAAE;AAG9B,QAAI,KAAK,qBAAqB,CAAE;AAGhC,QACE,EAAE,iBAAiB,OAAO,IAC1B,OAAO,QAAQ,QACf,CAAC,OAAO,YACR,CAAC,OAAO,UAER;AACF,QAAI,EAAE,eAAe,OAAO,IAAI,OAAO,QAAQ,QAAQ,CAAC,OAAO,SAC7D;AACF,QAAI,EAAE,kBAAkB,OAAO,IAAI,OAAO,aAAa,KAAM;IAG7D,MAAM,UAAU,MAAM,WAAW,KAAK,KAAK;AAC3C,QAAI,WAAW,QAAQ,SAAS,SAAU;IAE1C,MAAM,MAAM,KAAK,KAAK;AACtB,QAAI,CAAC,IAAK;IACV,MAAM,MAAgB;KAAE,MAAM,IAAI;KAAM,SAAS,IAAI;KAAQ;AAO7D,QAJG,EAAE,iBAAiB,OAAO,IAAI,OAAO,WAAW,QAChD,EAAE,gBAAgB,OAAO,IAAI,OAAO,WAAW,QAC/C,EAAE,mBAAmB,OAAO,IAAI,OAAO,WAAW,KAGnD,eAAc;QAEd,cAAa;;GAGlB,CAAC;SACI;AAEN;;AAGF,QAAO,aAAa"}
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import { getOrCreate } from "./utils.js";
|
|
2
|
-
import { MOCK_MODULE_ID } from "./virtualModules.js";
|
|
3
|
-
import { parseImportProtectionAst } from "./ast.js";
|
|
4
|
-
import * as t from "@babel/types";
|
|
5
|
-
import { generateFromAst } from "@tanstack/router-utils";
|
|
6
|
-
//#region src/import-protection-plugin/rewriteDeniedImports.ts
|
|
7
|
-
function isValidExportName(name) {
|
|
8
|
-
if (name === "default" || name.length === 0) return false;
|
|
9
|
-
const first = name.charCodeAt(0);
|
|
10
|
-
if (!(first >= 65 && first <= 90 || first >= 97 && first <= 122 || first === 95 || first === 36)) return false;
|
|
11
|
-
for (let i = 1; i < name.length; i++) {
|
|
12
|
-
const ch = name.charCodeAt(i);
|
|
13
|
-
if (!(ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch >= 48 && ch <= 57 || ch === 95 || ch === 36)) return false;
|
|
14
|
-
}
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
|
-
function collectMockExportNamesBySource(code) {
|
|
18
|
-
return collectMockExportNamesBySourceFromAst(parseImportProtectionAst(code));
|
|
19
|
-
}
|
|
20
|
-
function collectMockExportNamesBySourceFromAst(ast) {
|
|
21
|
-
const namesBySource = /* @__PURE__ */ new Map();
|
|
22
|
-
const memberBindingToSource = /* @__PURE__ */ new Map();
|
|
23
|
-
const add = (source, name) => {
|
|
24
|
-
if (name === "default" || name.length === 0) return;
|
|
25
|
-
getOrCreate(namesBySource, source, () => /* @__PURE__ */ new Set()).add(name);
|
|
26
|
-
};
|
|
27
|
-
for (const node of ast.program.body) {
|
|
28
|
-
if (t.isImportDeclaration(node)) {
|
|
29
|
-
if (node.importKind === "type") continue;
|
|
30
|
-
const source = node.source.value;
|
|
31
|
-
for (const s of node.specifiers) {
|
|
32
|
-
if (t.isImportNamespaceSpecifier(s)) {
|
|
33
|
-
memberBindingToSource.set(s.local.name, source);
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
if (t.isImportDefaultSpecifier(s)) {
|
|
37
|
-
memberBindingToSource.set(s.local.name, source);
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
if (!t.isImportSpecifier(s)) continue;
|
|
41
|
-
if (s.importKind === "type") continue;
|
|
42
|
-
const importedName = t.isIdentifier(s.imported) ? s.imported.name : s.imported.value;
|
|
43
|
-
if (importedName === "default") continue;
|
|
44
|
-
add(source, importedName);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
if (t.isExportNamedDeclaration(node) && node.source?.value) {
|
|
48
|
-
if (node.exportKind === "type") continue;
|
|
49
|
-
const source = node.source.value;
|
|
50
|
-
for (const s of node.specifiers) {
|
|
51
|
-
if (!t.isExportSpecifier(s)) continue;
|
|
52
|
-
if (s.exportKind === "type") continue;
|
|
53
|
-
add(source, s.local.name);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
if (memberBindingToSource.size > 0) {
|
|
58
|
-
const visit = (node) => {
|
|
59
|
-
if (t.isMemberExpression(node)) {
|
|
60
|
-
const object = node.object;
|
|
61
|
-
if (t.isIdentifier(object)) {
|
|
62
|
-
const source = memberBindingToSource.get(object.name);
|
|
63
|
-
if (source) {
|
|
64
|
-
const property = node.property;
|
|
65
|
-
if (!node.computed && t.isIdentifier(property)) add(source, property.name);
|
|
66
|
-
else if (node.computed && t.isStringLiteral(property)) add(source, property.value);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
const keys = t.VISITOR_KEYS[node.type];
|
|
71
|
-
if (!keys) return;
|
|
72
|
-
for (const key of keys) {
|
|
73
|
-
const child = node[key];
|
|
74
|
-
if (Array.isArray(child)) {
|
|
75
|
-
for (const item of child) if (item && typeof item === "object" && "type" in item) visit(item);
|
|
76
|
-
} else if (child && typeof child === "object" && "type" in child) visit(child);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
visit(ast.program);
|
|
80
|
-
}
|
|
81
|
-
const out = /* @__PURE__ */ new Map();
|
|
82
|
-
for (const [source, set] of namesBySource) out.set(source, Array.from(set).sort());
|
|
83
|
-
return out;
|
|
84
|
-
}
|
|
85
|
-
/** Collect all valid named export identifiers from the given code. */
|
|
86
|
-
function collectNamedExports(code) {
|
|
87
|
-
return collectNamedExportsFromAst(parseImportProtectionAst(code));
|
|
88
|
-
}
|
|
89
|
-
function collectIdentifiersFromPattern(pattern, add) {
|
|
90
|
-
if (t.isIdentifier(pattern)) add(pattern.name);
|
|
91
|
-
else if (t.isObjectPattern(pattern)) for (const prop of pattern.properties) if (t.isRestElement(prop)) collectIdentifiersFromPattern(prop.argument, add);
|
|
92
|
-
else collectIdentifiersFromPattern(prop.value, add);
|
|
93
|
-
else if (t.isArrayPattern(pattern)) {
|
|
94
|
-
for (const elem of pattern.elements) if (elem) collectIdentifiersFromPattern(elem, add);
|
|
95
|
-
} else if (t.isAssignmentPattern(pattern)) collectIdentifiersFromPattern(pattern.left, add);
|
|
96
|
-
else if (t.isRestElement(pattern)) collectIdentifiersFromPattern(pattern.argument, add);
|
|
97
|
-
}
|
|
98
|
-
function collectNamedExportsFromAst(ast) {
|
|
99
|
-
const names = /* @__PURE__ */ new Set();
|
|
100
|
-
const add = (name) => {
|
|
101
|
-
if (isValidExportName(name)) names.add(name);
|
|
102
|
-
};
|
|
103
|
-
for (const node of ast.program.body) if (t.isExportNamedDeclaration(node)) {
|
|
104
|
-
if (node.exportKind === "type") continue;
|
|
105
|
-
if (node.declaration) {
|
|
106
|
-
const decl = node.declaration;
|
|
107
|
-
if (t.isFunctionDeclaration(decl) || t.isClassDeclaration(decl)) {
|
|
108
|
-
if (decl.id?.name) add(decl.id.name);
|
|
109
|
-
} else if (t.isVariableDeclaration(decl)) for (const d of decl.declarations) collectIdentifiersFromPattern(d.id, add);
|
|
110
|
-
}
|
|
111
|
-
for (const s of node.specifiers) {
|
|
112
|
-
if (!t.isExportSpecifier(s)) continue;
|
|
113
|
-
if (s.exportKind === "type") continue;
|
|
114
|
-
add(t.isIdentifier(s.exported) ? s.exported.name : s.exported.value);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return Array.from(names).sort();
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Rewrite static imports/re-exports from denied sources using Babel AST transforms.
|
|
121
|
-
*
|
|
122
|
-
* Transforms:
|
|
123
|
-
* import { a as b, c } from 'denied'
|
|
124
|
-
* Into:
|
|
125
|
-
* import __tss_deny_0 from 'tanstack-start-import-protection:mock'
|
|
126
|
-
* const b = __tss_deny_0.a
|
|
127
|
-
* const c = __tss_deny_0.c
|
|
128
|
-
*
|
|
129
|
-
* Also handles:
|
|
130
|
-
* import def from 'denied' -> import def from mock
|
|
131
|
-
* import * as ns from 'denied' -> import ns from mock
|
|
132
|
-
* export { x } from 'denied' -> export const x = mock.x
|
|
133
|
-
* export * from 'denied' -> removed
|
|
134
|
-
* export { x as y } from 'denied' -> export const y = mock.x
|
|
135
|
-
*/
|
|
136
|
-
function rewriteDeniedImports(code, id, deniedSources, getMockModuleId = () => MOCK_MODULE_ID) {
|
|
137
|
-
return rewriteDeniedImportsFromAst(parseImportProtectionAst(code), id, deniedSources, getMockModuleId);
|
|
138
|
-
}
|
|
139
|
-
function rewriteDeniedImportsFromAst(ast, id, deniedSources, getMockModuleId = () => MOCK_MODULE_ID) {
|
|
140
|
-
let modified = false;
|
|
141
|
-
let mockCounter = 0;
|
|
142
|
-
for (let i = ast.program.body.length - 1; i >= 0; i--) {
|
|
143
|
-
const node = ast.program.body[i];
|
|
144
|
-
if (t.isImportDeclaration(node)) {
|
|
145
|
-
if (node.importKind === "type") continue;
|
|
146
|
-
if (!deniedSources.has(node.source.value)) continue;
|
|
147
|
-
const mockVar = `__tss_deny_${mockCounter++}`;
|
|
148
|
-
const replacements = [];
|
|
149
|
-
replacements.push(t.importDeclaration([t.importDefaultSpecifier(t.identifier(mockVar))], t.stringLiteral(getMockModuleId(node.source.value))));
|
|
150
|
-
for (const specifier of node.specifiers) if (t.isImportDefaultSpecifier(specifier) || t.isImportNamespaceSpecifier(specifier)) replacements.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(specifier.local.name), t.identifier(mockVar))]));
|
|
151
|
-
else if (t.isImportSpecifier(specifier)) {
|
|
152
|
-
if (specifier.importKind === "type") continue;
|
|
153
|
-
const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : specifier.imported.value;
|
|
154
|
-
replacements.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(specifier.local.name), t.memberExpression(t.identifier(mockVar), t.identifier(importedName)))]));
|
|
155
|
-
}
|
|
156
|
-
ast.program.body.splice(i, 1, ...replacements);
|
|
157
|
-
modified = true;
|
|
158
|
-
continue;
|
|
159
|
-
}
|
|
160
|
-
if (t.isExportNamedDeclaration(node) && node.source) {
|
|
161
|
-
if (node.exportKind === "type") continue;
|
|
162
|
-
if (!deniedSources.has(node.source.value)) continue;
|
|
163
|
-
const mockVar = `__tss_deny_${mockCounter++}`;
|
|
164
|
-
const replacements = [];
|
|
165
|
-
replacements.push(t.importDeclaration([t.importDefaultSpecifier(t.identifier(mockVar))], t.stringLiteral(getMockModuleId(node.source.value))));
|
|
166
|
-
const exportSpecifiers = [];
|
|
167
|
-
for (const specifier of node.specifiers) if (t.isExportSpecifier(specifier)) {
|
|
168
|
-
if (specifier.exportKind === "type") continue;
|
|
169
|
-
const localName = specifier.local.name;
|
|
170
|
-
const exportedName = t.isIdentifier(specifier.exported) ? specifier.exported.name : specifier.exported.value;
|
|
171
|
-
const internalVar = `__tss_reexport_${localName}`;
|
|
172
|
-
replacements.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(internalVar), t.memberExpression(t.identifier(mockVar), t.identifier(localName)))]));
|
|
173
|
-
exportSpecifiers.push({
|
|
174
|
-
localName: internalVar,
|
|
175
|
-
exportedName
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
if (exportSpecifiers.length > 0) replacements.push(t.exportNamedDeclaration(null, exportSpecifiers.map((s) => t.exportSpecifier(t.identifier(s.localName), t.identifier(s.exportedName)))));
|
|
179
|
-
ast.program.body.splice(i, 1, ...replacements);
|
|
180
|
-
modified = true;
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
if (t.isExportAllDeclaration(node)) {
|
|
184
|
-
if (node.exportKind === "type") continue;
|
|
185
|
-
if (!deniedSources.has(node.source.value)) continue;
|
|
186
|
-
ast.program.body.splice(i, 1);
|
|
187
|
-
modified = true;
|
|
188
|
-
continue;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
if (!modified) return void 0;
|
|
192
|
-
const result = generateFromAst(ast, {
|
|
193
|
-
sourceMaps: true,
|
|
194
|
-
sourceFileName: id,
|
|
195
|
-
filename: id
|
|
196
|
-
});
|
|
197
|
-
return {
|
|
198
|
-
code: result.code,
|
|
199
|
-
...result.map ? { map: result.map } : {}
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
//#endregion
|
|
203
|
-
export { collectMockExportNamesBySource, collectNamedExports, isValidExportName, rewriteDeniedImports };
|
|
204
|
-
|
|
205
|
-
//# sourceMappingURL=rewriteDeniedImports.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rewriteDeniedImports.js","names":[],"sources":["../../../src/import-protection-plugin/rewriteDeniedImports.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport { generateFromAst } from '@tanstack/router-utils'\n\nimport { MOCK_MODULE_ID } from './virtualModules'\nimport { getOrCreate } from './utils'\nimport { parseImportProtectionAst } from './ast'\nimport type { SourceMapLike } from './sourceLocation'\nimport type { ParsedAst } from './ast'\n\nexport function isValidExportName(name: string): boolean {\n if (name === 'default' || name.length === 0) return false\n const first = name.charCodeAt(0)\n // First char: A-Z (65-90), a-z (97-122), _ (95), $ (36)\n if (\n !(\n (first >= 65 && first <= 90) ||\n (first >= 97 && first <= 122) ||\n first === 95 ||\n first === 36\n )\n )\n return false\n for (let i = 1; i < name.length; i++) {\n const ch = name.charCodeAt(i)\n // Subsequent: A-Z, a-z, 0-9 (48-57), _, $\n if (\n !(\n (ch >= 65 && ch <= 90) ||\n (ch >= 97 && ch <= 122) ||\n (ch >= 48 && ch <= 57) ||\n ch === 95 ||\n ch === 36\n )\n )\n return false\n }\n return true\n}\n\nexport function collectMockExportNamesBySource(\n code: string,\n): Map<string, Array<string>> {\n return collectMockExportNamesBySourceFromAst(parseImportProtectionAst(code))\n}\n\nfunction collectMockExportNamesBySourceFromAst(\n ast: ParsedAst,\n): Map<string, Array<string>> {\n const namesBySource = new Map<string, Set<string>>()\n const memberBindingToSource = new Map<string, string>()\n const add = (source: string, name: string) => {\n if (name === 'default' || name.length === 0) return\n getOrCreate(namesBySource, source, () => new Set<string>()).add(name)\n }\n\n for (const node of ast.program.body) {\n if (t.isImportDeclaration(node)) {\n if (node.importKind === 'type') continue\n const source = node.source.value\n for (const s of node.specifiers) {\n if (t.isImportNamespaceSpecifier(s)) {\n memberBindingToSource.set(s.local.name, source)\n continue\n }\n if (t.isImportDefaultSpecifier(s)) {\n memberBindingToSource.set(s.local.name, source)\n continue\n }\n if (!t.isImportSpecifier(s)) continue\n if (s.importKind === 'type') continue\n const importedName = t.isIdentifier(s.imported)\n ? s.imported.name\n : s.imported.value\n // `import { default as x } from 'm'` only requires a default export.\n if (importedName === 'default') continue\n add(source, importedName)\n }\n }\n\n if (t.isExportNamedDeclaration(node) && node.source?.value) {\n if (node.exportKind === 'type') continue\n const source = node.source.value\n for (const s of node.specifiers) {\n if (!t.isExportSpecifier(s)) continue\n if (s.exportKind === 'type') continue\n add(source, s.local.name)\n }\n }\n }\n\n // For namespace/default imports, collect property names used as\n // `binding.foo`/`binding?.foo` so mock-edge modules can expose explicit ESM\n // named exports required by Rolldown/native ESM.\n if (memberBindingToSource.size > 0) {\n const visit = (node: t.Node): void => {\n if (t.isMemberExpression(node)) {\n const object = node.object\n if (t.isIdentifier(object)) {\n const source = memberBindingToSource.get(object.name)\n if (source) {\n const property = node.property\n if (!node.computed && t.isIdentifier(property)) {\n add(source, property.name)\n } else if (node.computed && t.isStringLiteral(property)) {\n add(source, property.value)\n }\n }\n }\n }\n\n const keys = t.VISITOR_KEYS[node.type]\n if (!keys) return\n for (const key of keys) {\n const child = (node as unknown as Record<string, unknown>)[key]\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === 'object' && 'type' in item) {\n visit(item as t.Node)\n }\n }\n } else if (child && typeof child === 'object' && 'type' in child) {\n visit(child as t.Node)\n }\n }\n }\n\n visit(ast.program)\n }\n\n const out = new Map<string, Array<string>>()\n for (const [source, set] of namesBySource) {\n out.set(source, Array.from(set).sort())\n }\n return out\n}\n\n/** Collect all valid named export identifiers from the given code. */\nexport function collectNamedExports(code: string): Array<string> {\n return collectNamedExportsFromAst(parseImportProtectionAst(code))\n}\n\nfunction collectIdentifiersFromPattern(\n pattern: t.LVal,\n add: (name: string) => void,\n): void {\n if (t.isIdentifier(pattern)) {\n add(pattern.name)\n } else if (t.isObjectPattern(pattern)) {\n for (const prop of pattern.properties) {\n if (t.isRestElement(prop)) {\n collectIdentifiersFromPattern(prop.argument as t.LVal, add)\n } else {\n collectIdentifiersFromPattern(prop.value as t.LVal, add)\n }\n }\n } else if (t.isArrayPattern(pattern)) {\n for (const elem of pattern.elements) {\n if (elem) collectIdentifiersFromPattern(elem as t.LVal, add)\n }\n } else if (t.isAssignmentPattern(pattern)) {\n collectIdentifiersFromPattern(pattern.left, add)\n } else if (t.isRestElement(pattern)) {\n collectIdentifiersFromPattern(pattern.argument as t.LVal, add)\n }\n}\n\nfunction collectNamedExportsFromAst(ast: ParsedAst): Array<string> {\n const names = new Set<string>()\n const add = (name: string) => {\n if (isValidExportName(name)) names.add(name)\n }\n\n for (const node of ast.program.body) {\n if (t.isExportNamedDeclaration(node)) {\n if (node.exportKind === 'type') continue\n\n if (node.declaration) {\n const decl = node.declaration\n if (t.isFunctionDeclaration(decl) || t.isClassDeclaration(decl)) {\n if (decl.id?.name) add(decl.id.name)\n } else if (t.isVariableDeclaration(decl)) {\n for (const d of decl.declarations) {\n collectIdentifiersFromPattern(d.id as t.LVal, add)\n }\n }\n }\n\n for (const s of node.specifiers) {\n if (!t.isExportSpecifier(s)) continue\n if (s.exportKind === 'type') continue\n const exportedName = t.isIdentifier(s.exported)\n ? s.exported.name\n : s.exported.value\n add(exportedName)\n }\n }\n }\n\n return Array.from(names).sort()\n}\n\n/**\n * Rewrite static imports/re-exports from denied sources using Babel AST transforms.\n *\n * Transforms:\n * import { a as b, c } from 'denied'\n * Into:\n * import __tss_deny_0 from 'tanstack-start-import-protection:mock'\n * const b = __tss_deny_0.a\n * const c = __tss_deny_0.c\n *\n * Also handles:\n * import def from 'denied' -> import def from mock\n * import * as ns from 'denied' -> import ns from mock\n * export { x } from 'denied' -> export const x = mock.x\n * export * from 'denied' -> removed\n * export { x as y } from 'denied' -> export const y = mock.x\n */\nexport function rewriteDeniedImports(\n code: string,\n id: string,\n deniedSources: Set<string>,\n getMockModuleId: (source: string) => string = () => MOCK_MODULE_ID,\n): { code: string; map?: SourceMapLike } | undefined {\n return rewriteDeniedImportsFromAst(\n parseImportProtectionAst(code),\n id,\n deniedSources,\n getMockModuleId,\n )\n}\n\nfunction rewriteDeniedImportsFromAst(\n ast: ParsedAst,\n id: string,\n deniedSources: Set<string>,\n getMockModuleId: (source: string) => string = () => MOCK_MODULE_ID,\n): { code: string; map?: SourceMapLike } | undefined {\n let modified = false\n let mockCounter = 0\n\n // Walk program body in reverse so splice indices stay valid\n for (let i = ast.program.body.length - 1; i >= 0; i--) {\n const node = ast.program.body[i]!\n\n if (t.isImportDeclaration(node)) {\n if (node.importKind === 'type') continue\n if (!deniedSources.has(node.source.value)) continue\n\n const mockVar = `__tss_deny_${mockCounter++}`\n const replacements: Array<t.Statement> = []\n\n replacements.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(mockVar))],\n t.stringLiteral(getMockModuleId(node.source.value)),\n ),\n )\n\n for (const specifier of node.specifiers) {\n if (\n t.isImportDefaultSpecifier(specifier) ||\n t.isImportNamespaceSpecifier(specifier)\n ) {\n replacements.push(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(specifier.local.name),\n t.identifier(mockVar),\n ),\n ]),\n )\n } else if (t.isImportSpecifier(specifier)) {\n if (specifier.importKind === 'type') continue\n const importedName = t.isIdentifier(specifier.imported)\n ? specifier.imported.name\n : specifier.imported.value\n replacements.push(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(specifier.local.name),\n t.memberExpression(\n t.identifier(mockVar),\n t.identifier(importedName),\n ),\n ),\n ]),\n )\n }\n }\n\n ast.program.body.splice(i, 1, ...replacements)\n modified = true\n continue\n }\n\n if (t.isExportNamedDeclaration(node) && node.source) {\n if (node.exportKind === 'type') continue\n if (!deniedSources.has(node.source.value)) continue\n\n const mockVar = `__tss_deny_${mockCounter++}`\n const replacements: Array<t.Statement> = []\n\n replacements.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(mockVar))],\n t.stringLiteral(getMockModuleId(node.source.value)),\n ),\n )\n const exportSpecifiers: Array<{\n localName: string\n exportedName: string\n }> = []\n for (const specifier of node.specifiers) {\n if (t.isExportSpecifier(specifier)) {\n if (specifier.exportKind === 'type') continue\n const localName = specifier.local.name\n const exportedName = t.isIdentifier(specifier.exported)\n ? specifier.exported.name\n : specifier.exported.value\n\n const internalVar = `__tss_reexport_${localName}`\n replacements.push(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(internalVar),\n t.memberExpression(\n t.identifier(mockVar),\n t.identifier(localName),\n ),\n ),\n ]),\n )\n exportSpecifiers.push({ localName: internalVar, exportedName })\n }\n }\n\n if (exportSpecifiers.length > 0) {\n replacements.push(\n t.exportNamedDeclaration(\n null,\n exportSpecifiers.map((s) =>\n t.exportSpecifier(\n t.identifier(s.localName),\n t.identifier(s.exportedName),\n ),\n ),\n ),\n )\n }\n\n ast.program.body.splice(i, 1, ...replacements)\n modified = true\n continue\n }\n\n if (t.isExportAllDeclaration(node)) {\n if (node.exportKind === 'type') continue\n if (!deniedSources.has(node.source.value)) continue\n\n ast.program.body.splice(i, 1)\n modified = true\n continue\n }\n }\n\n if (!modified) return undefined\n\n const result = generateFromAst(ast, {\n sourceMaps: true,\n sourceFileName: id,\n filename: id,\n })\n\n return {\n code: result.code,\n ...(result.map ? { map: result.map as SourceMapLike } : {}),\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sourceLocation.js","names":[],"sources":["../../../src/import-protection-plugin/sourceLocation.ts"],"sourcesContent":["import { SourceMapConsumer } from 'source-map'\nimport * as path from 'pathe'\n\nimport { findPostCompileUsagePos } from './postCompileUsage'\nimport { getOrCreate, normalizeFilePath } from './utils'\nimport type { Loc } from './trace'\nimport type { RawSourceMap } from 'source-map'\n\n// Source-map type compatible with both Rollup's SourceMap and source-map's\n// RawSourceMap. Structural type avoids version: number vs string mismatch.\n\n/**\n * Minimal source-map shape used throughout the import-protection plugin.\n */\nexport interface SourceMapLike {\n file?: string\n sourceRoot?: string\n version: number | string\n sources: Array<string>\n names: Array<string>\n sourcesContent?: Array<string | null>\n mappings: string\n}\n\n// Transform result provider (replaces ctx.load() which doesn't work in dev)\nexport interface TransformResult {\n code: string\n map: SourceMapLike | undefined\n originalCode: string | undefined\n /** Precomputed line index for `code` (index → line/col). */\n lineIndex?: LineIndex\n}\n\n/**\n * Provides the transformed code and composed sourcemap for a module.\n *\n * Populated from a late-running transform hook. By the time `resolveId`\n * fires for an import, the importer has already been fully transformed.\n */\nexport interface TransformResultProvider {\n getTransformResult: (id: string) => TransformResult | undefined\n}\n\n// Index → line/column conversion\n\nexport type LineIndex = {\n offsets: Array<number>\n}\n\nexport function buildLineIndex(code: string): LineIndex {\n const offsets: Array<number> = [0]\n for (let i = 0; i < code.length; i++) {\n if (code.charCodeAt(i) === 10) {\n offsets.push(i + 1)\n }\n }\n return { offsets }\n}\n\nfunction upperBound(values: Array<number>, x: number): number {\n let lo = 0\n let hi = values.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (values[mid]! <= x) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n\nfunction indexToLineColWithIndex(\n lineIndex: LineIndex,\n idx: number,\n): { line: number; column0: number } {\n const offsets = lineIndex.offsets\n const ub = upperBound(offsets, idx)\n const lineIdx = Math.max(0, ub - 1)\n const line = lineIdx + 1\n\n const lineStart = offsets[lineIdx] ?? 0\n return { line, column0: Math.max(0, idx - lineStart) }\n}\n\n/**\n * Pick the most-likely original source text for `importerFile` from\n * a sourcemap that may contain multiple sources.\n */\nexport function pickOriginalCodeFromSourcesContent(\n map: SourceMapLike | undefined,\n importerFile: string,\n root: string,\n): string | undefined {\n if (!map?.sourcesContent || map.sources.length === 0) {\n return undefined\n }\n\n const file = normalizeFilePath(importerFile)\n const sourceRoot = map.sourceRoot\n const fileSeg = file.split('/').filter(Boolean)\n\n const resolveBase = sourceRoot ? path.resolve(root, sourceRoot) : root\n\n let bestIdx = -1\n let bestScore = -1\n\n for (let i = 0; i < map.sources.length; i++) {\n const content = map.sourcesContent[i]\n if (typeof content !== 'string') continue\n\n const src = map.sources[i] ?? ''\n\n const normalizedSrc = normalizeFilePath(src)\n if (normalizedSrc === file) {\n return content\n }\n\n let resolved: string\n if (!src) {\n resolved = ''\n } else if (path.isAbsolute(src)) {\n resolved = normalizeFilePath(src)\n } else {\n resolved = normalizeFilePath(path.resolve(resolveBase, src))\n }\n if (resolved === file) {\n return content\n }\n\n // Count matching path segments from the end.\n const normalizedSrcSeg = normalizedSrc.split('/').filter(Boolean)\n const resolvedSeg =\n resolved !== normalizedSrc\n ? resolved.split('/').filter(Boolean)\n : normalizedSrcSeg\n const score = Math.max(\n segmentSuffixScore(normalizedSrcSeg, fileSeg),\n segmentSuffixScore(resolvedSeg, fileSeg),\n )\n\n if (score > bestScore) {\n bestScore = score\n bestIdx = i\n }\n }\n\n if (bestIdx !== -1 && bestScore >= 1) {\n return map.sourcesContent[bestIdx] ?? undefined\n }\n\n return map.sourcesContent[0] ?? undefined\n}\n\n/** Count matching path segments from the end of `aSeg` against `bSeg`. */\nfunction segmentSuffixScore(aSeg: Array<string>, bSeg: Array<string>): number {\n let score = 0\n for (\n let i = aSeg.length - 1, j = bSeg.length - 1;\n i >= 0 && j >= 0;\n i--, j--\n ) {\n if (aSeg[i] !== bSeg[j]) break\n score++\n }\n return score\n}\n\nasync function mapGeneratedToOriginal(\n map: SourceMapLike | undefined,\n generated: { line: number; column0: number },\n fallbackFile: string,\n): Promise<Loc> {\n const fallback: Loc = {\n file: fallbackFile,\n line: generated.line,\n column: generated.column0 + 1,\n }\n\n if (!map) {\n return fallback\n }\n\n const consumer = await getSourceMapConsumer(map)\n if (!consumer) return fallback\n\n try {\n const orig = consumer.originalPositionFor({\n line: generated.line,\n column: generated.column0,\n })\n if (orig.line != null && orig.column != null) {\n return {\n file: orig.source ? normalizeFilePath(orig.source) : fallbackFile,\n line: orig.line,\n column: orig.column + 1,\n }\n }\n } catch {\n // Malformed sourcemap\n }\n\n return fallback\n}\n\nconst consumerCache = new WeakMap<object, Promise<SourceMapConsumer | null>>()\n\nfunction toRawSourceMap(map: SourceMapLike): RawSourceMap {\n return {\n ...map,\n file: map.file ?? '',\n version: Number(map.version),\n sourcesContent: map.sourcesContent?.map((s) => s ?? '') ?? [],\n }\n}\n\nasync function getSourceMapConsumer(\n map: SourceMapLike,\n): Promise<SourceMapConsumer | null> {\n const cached = consumerCache.get(map)\n if (cached) return cached\n\n const promise = (async () => {\n try {\n return await new SourceMapConsumer(toRawSourceMap(map))\n } catch {\n return null\n }\n })()\n\n consumerCache.set(map, promise)\n return promise\n}\n\nexport type ImportLocEntry = { file?: string; line: number; column: number }\n\n/**\n * Cache for import statement locations with reverse index for O(1)\n * invalidation by file. Keys: `${importerFile}::${source}`.\n */\nexport class ImportLocCache {\n private cache = new Map<string, ImportLocEntry | null>()\n private reverseIndex = new Map<string, Set<string>>()\n\n has(key: string): boolean {\n return this.cache.has(key)\n }\n\n get(key: string): ImportLocEntry | null | undefined {\n return this.cache.get(key)\n }\n\n set(key: string, value: ImportLocEntry | null): void {\n this.cache.set(key, value)\n const file = key.slice(0, key.indexOf('::'))\n getOrCreate(this.reverseIndex, file, () => new Set()).add(key)\n }\n\n clear(): void {\n this.cache.clear()\n this.reverseIndex.clear()\n }\n\n /** Remove all cache entries where the importer matches `file`. */\n deleteByFile(file: string): void {\n const keys = this.reverseIndex.get(file)\n if (keys) {\n for (const key of keys) {\n this.cache.delete(key)\n }\n this.reverseIndex.delete(file)\n }\n }\n}\n\nexport type FindImportSpecifierIndex = (code: string, source: string) => number\n\n/**\n * Find the location of an import statement in a transformed module\n * by searching the post-transform code and mapping back via sourcemap.\n * Results are cached in `importLocCache`.\n */\nexport async function findImportStatementLocationFromTransformed(\n provider: TransformResultProvider,\n importerId: string,\n source: string,\n importLocCache: ImportLocCache,\n findImportSpecifierIndex: FindImportSpecifierIndex,\n): Promise<Loc | undefined> {\n const importerFile = normalizeFilePath(importerId)\n const cacheKey = `${importerFile}::${source}`\n if (importLocCache.has(cacheKey)) {\n return importLocCache.get(cacheKey) ?? undefined\n }\n\n try {\n const res = provider.getTransformResult(importerId)\n if (!res) {\n importLocCache.set(cacheKey, null)\n return undefined\n }\n\n const { code, map } = res\n\n const lineIndex = res.lineIndex ?? buildLineIndex(code)\n\n const idx = findImportSpecifierIndex(code, source)\n if (idx === -1) {\n importLocCache.set(cacheKey, null)\n return undefined\n }\n\n const generated = indexToLineColWithIndex(lineIndex, idx)\n const loc = await mapGeneratedToOriginal(map, generated, importerFile)\n importLocCache.set(cacheKey, loc)\n return loc\n } catch {\n importLocCache.set(cacheKey, null)\n return undefined\n }\n}\n\n/**\n * Find the first post-compile usage location for a denied import specifier.\n * Best-effort: searches transformed code for non-import uses of imported\n * bindings and maps back to original source via sourcemap.\n */\nexport async function findPostCompileUsageLocation(\n provider: TransformResultProvider,\n importerId: string,\n source: string,\n): Promise<Loc | undefined> {\n try {\n const importerFile = normalizeFilePath(importerId)\n const res = provider.getTransformResult(importerId)\n if (!res) return undefined\n const { code, map } = res\n\n if (!res.lineIndex) {\n res.lineIndex = buildLineIndex(code)\n }\n\n const pos = findPostCompileUsagePos(code, source)\n if (!pos) return undefined\n\n return await mapGeneratedToOriginal(map, pos, importerFile)\n } catch {\n return undefined\n }\n}\n\n/**\n * Annotate each trace hop with the location of the import that created the\n * edge (file:line:col). Skips steps that already have a location.\n */\nexport async function addTraceImportLocations(\n provider: TransformResultProvider,\n trace: Array<{\n file: string\n specifier?: string\n line?: number\n column?: number\n }>,\n importLocCache: ImportLocCache,\n findImportSpecifierIndex: FindImportSpecifierIndex,\n): Promise<void> {\n for (const step of trace) {\n if (!step.specifier) continue\n if (step.line != null && step.column != null) continue\n const loc = await findImportStatementLocationFromTransformed(\n provider,\n step.file,\n step.specifier,\n importLocCache,\n findImportSpecifierIndex,\n )\n if (!loc) continue\n step.line = loc.line\n step.column = loc.column\n }\n}\n\n// Code snippet extraction (vitest-style context around a location)\n\nexport interface CodeSnippet {\n /** Source lines with line numbers, e.g. `[\" 6 | import { getSecret } from './secret.server'\", ...]` */\n lines: Array<string>\n /** The highlighted line (1-indexed original line number) */\n highlightLine: number\n /** Clickable file:line reference */\n location: string\n}\n\n/**\n * Build a vitest-style code snippet showing lines surrounding a location.\n *\n * Prefers `originalCode` from the sourcemap's sourcesContent; falls back\n * to transformed code when unavailable.\n */\nexport function buildCodeSnippet(\n provider: TransformResultProvider,\n moduleId: string,\n loc: Loc,\n contextLines: number = 2,\n): CodeSnippet | undefined {\n try {\n const importerFile = normalizeFilePath(moduleId)\n const res = provider.getTransformResult(moduleId)\n if (!res) return undefined\n\n const sourceCode = res.originalCode ?? res.code\n const targetLine = loc.line // 1-indexed\n const targetCol = loc.column // 1-indexed\n\n if (targetLine < 1) return undefined\n\n const allLines = sourceCode.split('\\n')\n // Strip trailing \\r from \\r\\n line endings\n for (let i = 0; i < allLines.length; i++) {\n const line = allLines[i]!\n if (line.endsWith('\\r')) allLines[i] = line.slice(0, -1)\n }\n\n const wantStart = Math.max(1, targetLine - contextLines)\n const wantEnd = Math.min(allLines.length, targetLine + contextLines)\n\n if (targetLine > allLines.length) return undefined\n\n const lines = allLines.slice(wantStart - 1, wantEnd)\n const gutterWidth = String(wantEnd).length\n\n const sourceFile = loc.file ?? importerFile\n const snippetLines: Array<string> = []\n for (let i = 0; i < lines.length; i++) {\n const ln = wantStart + i\n const lineContent = lines[i]!\n const lineNumStr = String(ln).padStart(gutterWidth, ' ')\n const marker = ln === targetLine ? '>' : ' '\n snippetLines.push(` ${marker} ${lineNumStr} | ${lineContent}`)\n\n if (ln === targetLine && targetCol > 0) {\n const padding = ' '.repeat(targetCol - 1)\n snippetLines.push(` ${' '.repeat(gutterWidth)} | ${padding}^`)\n }\n }\n\n return {\n lines: snippetLines,\n highlightLine: targetLine,\n location: `${sourceFile}:${targetLine}:${targetCol}`,\n }\n } catch {\n return undefined\n }\n}\n"],"mappings":"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"}
|