@@ -683,6 +683,88 @@ function cleanupDeprecatedTsconfigOptions(
683683 }
684684}
685685
686+ // Svelte is intentionally excluded: @sveltejs /vite-plugin-svelte and svelte-check handle
687+ // .svelte file types automatically. No env.d.ts shim is needed or documented officially.
688+ // https://svelte.dev/docs/svelte/typescript
689+ export type Framework = 'vue' | 'astro' ;
690+
691+ const FRAMEWORK_SHIMS : Record < Framework , string > = {
692+ // https://vuejs.org/guide/typescript/overview#volar-takeover-mode
693+ vue : [
694+ "declare module '*.vue' {" ,
695+ " import type { DefineComponent } from 'vue';" ,
696+ ' const component: DefineComponent<{}, {}, unknown>;' ,
697+ ' export default component;' ,
698+ '}' ,
699+ ] . join ( '\n' ) ,
700+ // astro/client is the pre-v4.14 form; v4.14+ prefers `/// <reference path="../.astro/types.d.ts" />`
701+ // but .astro/types.d.ts is generated at build time and may not exist yet after migration.
702+ // astro/client remains valid and is still used in official Astro integrations.
703+ // https://docs.astro.build/en/guides/typescript/#extending-global-types
704+ astro : '/// <reference types="astro/client" />' ,
705+ } ;
706+
707+ export function detectFramework ( projectPath : string ) : Framework | null {
708+ const packageJsonPath = path . join ( projectPath , 'package.json' ) ;
709+ if ( ! fs . existsSync ( packageJsonPath ) ) {
710+ return null ;
711+ }
712+ const pkg = readJsonFile ( packageJsonPath ) as {
713+ dependencies ?: Record < string , string > ;
714+ devDependencies ?: Record < string , string > ;
715+ } ;
716+ const allDeps = { ...pkg . dependencies , ...pkg . devDependencies } ;
717+ for ( const framework of [ 'vue' , 'astro' ] as const ) {
718+ if ( allDeps [ framework ] ) {
719+ return framework ;
720+ }
721+ }
722+ return null ;
723+ }
724+
725+ function getEnvDtsPath ( projectPath : string ) : string {
726+ const srcEnvDts = path . join ( projectPath , 'src' , 'env.d.ts' ) ;
727+ const rootEnvDts = path . join ( projectPath , 'env.d.ts' ) ;
728+ for ( const candidate of [ srcEnvDts , rootEnvDts ] ) {
729+ if ( fs . existsSync ( candidate ) ) {
730+ return candidate ;
731+ }
732+ }
733+ return fs . existsSync ( path . join ( projectPath , 'src' ) ) ? srcEnvDts : rootEnvDts ;
734+ }
735+
736+ export function hasFrameworkShim ( projectPath : string , framework : Framework ) : boolean {
737+ const envDtsPath = getEnvDtsPath ( projectPath ) ;
738+ if ( ! fs . existsSync ( envDtsPath ) ) {
739+ return false ;
740+ }
741+
742+ const content = fs . readFileSync ( envDtsPath , 'utf-8' ) ;
743+ if ( framework === 'astro' ) {
744+ return content . includes ( 'astro/client' ) ;
745+ }
746+ return content . includes ( `'*.${ framework } '` ) || content . includes ( `"*.${ framework } "` ) ;
747+ }
748+
749+ export function addFrameworkShim (
750+ projectPath : string ,
751+ framework : Framework ,
752+ report ?: MigrationReport ,
753+ ) : void {
754+ const envDtsPath = getEnvDtsPath ( projectPath ) ;
755+ const shim = FRAMEWORK_SHIMS [ framework ] ;
756+ if ( fs . existsSync ( envDtsPath ) ) {
757+ const existing = fs . readFileSync ( envDtsPath , 'utf-8' ) ;
758+ fs . writeFileSync ( envDtsPath , `${ existing . trimEnd ( ) } \n\n${ shim } \n` , 'utf-8' ) ;
759+ } else {
760+ fs . mkdirSync ( path . dirname ( envDtsPath ) , { recursive : true } ) ;
761+ fs . writeFileSync ( envDtsPath , `${ shim } \n` , 'utf-8' ) ;
762+ }
763+ if ( report ) {
764+ report . frameworkShimAdded = true ;
765+ }
766+ }
767+
686768/**
687769 * Rewrite standalone project to add vite-plus dependencies
688770 * @param projectPath - The path to the project
0 commit comments