@@ -895,6 +895,23 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
895895 } ) ;
896896 resumeCreateProgress ( ) ;
897897
898+ // Auto-migrate ESLint → Oxlint and Prettier → Oxfmt after install #1 so
899+ // `@oxlint/migrate` can resolve imports from eslint.config.js, but before
900+ // the vite-plus rewrite so the generated .oxlintrc/.oxfmtrc get merged
901+ // into vite.config.ts — matching `vp migrate`. Always non-interactive;
902+ // Vite+ is opinionated about oxlint/oxfmt. Gated on install success so
903+ // VP_SKIP_INSTALL snap tests don't hit ERR_MODULE_NOT_FOUND.
904+ const migrateLintFmtTools = async ( installed : boolean ) => {
905+ if ( ! installed ) {
906+ return ;
907+ }
908+ updateCreateProgress ( 'Migrating lint and format tools' ) ;
909+ pauseCreateProgress ( ) ;
910+ await promptEslintMigration ( fullPath , /* interactive */ false ) ;
911+ await promptPrettierMigration ( fullPath , /* interactive */ false ) ;
912+ resumeCreateProgress ( ) ;
913+ } ;
914+
898915 let installSummary : CommandRunSummary | undefined ;
899916 if ( isMonorepo ) {
900917 if ( ! compactOutput ) {
@@ -960,35 +977,20 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
960977 }
961978
962979 updateWorkspaceConfig ( projectDir , workspaceInfo ) ;
963- // First install: template deps (incl. ESLint plugins) so `@oxlint/migrate`
964- // can resolve imports from eslint.config.js during migration below.
965980 updateCreateProgress ( 'Installing dependencies' ) ;
966981 installSummary = await runViteInstall ( workspaceInfo . rootDir , options . interactive , installArgs , {
967982 silent : compactOutput ,
968983 } ) ;
969- // Auto-migrate ESLint → Oxlint and Prettier → Oxfmt BEFORE the rewrite
970- // step so the generated .oxlintrc.json / .oxfmtrc.json get merged into
971- // vite.config.ts by `rewriteMonorepoProject` below — matching `vp migrate`.
972- // Always non-interactive: Vite+ is opinionated about oxlint/oxfmt, so
973- // freshly scaffolded projects land on the unified toolchain by default.
974- // Gated on install success so VP_SKIP_INSTALL snap tests don't hit
975- // ERR_MODULE_NOT_FOUND when the plugins aren't on disk.
976- if ( installSummary . status === 'installed' ) {
977- updateCreateProgress ( 'Migrating lint and format tools' ) ;
978- pauseCreateProgress ( ) ;
979- await promptEslintMigration ( fullPath , /* interactive */ false ) ;
980- await promptPrettierMigration ( fullPath , /* interactive */ false ) ;
981- resumeCreateProgress ( ) ;
982- }
984+ await migrateLintFmtTools ( installSummary . status === 'installed' ) ;
983985 updateCreateProgress ( 'Integrating into monorepo' ) ;
984986 rewriteMonorepoProject ( fullPath , workspaceInfo . packageManager , undefined , compactOutput ) ;
985987 for ( const framework of detectFramework ( fullPath ) ) {
986988 if ( ! hasFrameworkShim ( fullPath , framework ) ) {
987989 addFrameworkShim ( fullPath , framework ) ;
988990 }
989991 }
990- // Second install: fetch vite-plus (added by rewrite) and prune the
991- // eslint/prettier deps that migration removed from package.json .
992+ // Re- install so the package manager fetches vite-plus (added by the
993+ // rewrite) and prunes the eslint/prettier deps that migration removed.
992994 updateCreateProgress ( 'Installing dependencies' ) ;
993995 installSummary = await runViteInstall ( workspaceInfo . rootDir , options . interactive , installArgs , {
994996 silent : compactOutput ,
@@ -998,26 +1000,11 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
9981000 silent : compactOutput ,
9991001 } ) ;
10001002 } else {
1001- // First install: template deps (incl. ESLint plugins) so `@oxlint/migrate`
1002- // can resolve imports from eslint.config.js during migration below.
10031003 updateCreateProgress ( 'Installing dependencies' ) ;
10041004 installSummary = await runViteInstall ( fullPath , options . interactive , installArgs , {
10051005 silent : compactOutput ,
10061006 } ) ;
1007- // Auto-migrate ESLint → Oxlint and Prettier → Oxfmt BEFORE the rewrite
1008- // step so the generated .oxlintrc.json / .oxfmtrc.json get merged into
1009- // vite.config.ts by `rewriteStandaloneProject` below — matching `vp migrate`.
1010- // Always non-interactive: Vite+ is opinionated about oxlint/oxfmt, so
1011- // freshly scaffolded projects land on the unified toolchain by default.
1012- // Gated on install success so VP_SKIP_INSTALL snap tests don't hit
1013- // ERR_MODULE_NOT_FOUND when the plugins aren't on disk.
1014- if ( installSummary . status === 'installed' ) {
1015- updateCreateProgress ( 'Migrating lint and format tools' ) ;
1016- pauseCreateProgress ( ) ;
1017- await promptEslintMigration ( fullPath , /* interactive */ false ) ;
1018- await promptPrettierMigration ( fullPath , /* interactive */ false ) ;
1019- resumeCreateProgress ( ) ;
1020- }
1007+ await migrateLintFmtTools ( installSummary . status === 'installed' ) ;
10211008 updateCreateProgress ( 'Applying Vite+ project setup' ) ;
10221009 rewriteStandaloneProject ( fullPath , workspaceInfo , undefined , compactOutput ) ;
10231010 for ( const framework of detectFramework ( fullPath ) ) {
@@ -1028,8 +1015,8 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
10281015 if ( shouldSetupHooks ) {
10291016 installGitHooks ( fullPath , compactOutput ) ;
10301017 }
1031- // Second install: fetch vite-plus (added by rewrite) and prune the
1032- // eslint/prettier deps that migration removed from package.json .
1018+ // Re- install so the package manager fetches vite-plus (added by the
1019+ // rewrite) and prunes the eslint/prettier deps that migration removed.
10331020 updateCreateProgress ( 'Installing dependencies' ) ;
10341021 installSummary = await runViteInstall ( fullPath , options . interactive , installArgs , {
10351022 silent : compactOutput ,
0 commit comments