Skip to content

Commit c5e5888

Browse files
committed
fix: improve migration script coverage
1 parent a1bb167 commit c5e5888

4 files changed

Lines changed: 122 additions & 13 deletions

File tree

src/cli.ts

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as p from '@clack/prompts'
55
import { loadNuxtConfig } from '@nuxt/kit'
66
import { addDependency, detectPackageManager } from 'nypm'
77
import { basename, dirname, join, relative, resolve } from 'pathe'
8+
import { migrateDefaultsComponent, migrateFontsConfig } from './migrations/fonts'
89

910
const __dirname = dirname(fileURLToPath(import.meta.url))
1011

@@ -150,10 +151,12 @@ function globFiles(dir: string, pattern: RegExp, exclude: RegExp[] = []): string
150151
return results
151152
}
152153

153-
// Check if nuxt config has fonts config (deprecated ogImage.fonts)
154+
// Check if nuxt config has deprecated options
154155
async function checkNuxtConfig(rootDir: string): Promise<{
155156
hasDeprecatedFonts: boolean
156157
hasNuxtFonts: boolean
158+
hasDefaultsComponent: boolean
159+
defaultComponentName: string | null
157160
nitroPreset: string | null
158161
}> {
159162
// Check package.json for @nuxt/fonts
@@ -166,9 +169,12 @@ async function checkNuxtConfig(rootDir: string): Promise<{
166169

167170
const config = await loadNuxtConfig({ cwd: rootDir }).catch(() => null)
168171
if (!config)
169-
return { hasDeprecatedFonts: false, hasNuxtFonts: hasNuxtFontsInPkg, nitroPreset: null }
172+
return { hasDeprecatedFonts: false, hasNuxtFonts: hasNuxtFontsInPkg, hasDefaultsComponent: false, defaultComponentName: null, nitroPreset: null }
170173

171-
const hasDeprecatedFonts = !!(config.ogImage as any)?.fonts
174+
const ogImageConfig = config.ogImage as any
175+
const hasDeprecatedFonts = !!ogImageConfig?.fonts
176+
const hasDefaultsComponent = !!ogImageConfig?.defaults?.component
177+
const defaultComponentName = hasDefaultsComponent ? String(ogImageConfig.defaults.component) : null
172178
const modules = config.modules || []
173179
// @ts-expect-error untyped
174180
const hasNuxtFontsInConfig = modules.some((m: string | string[]) =>
@@ -180,6 +186,8 @@ async function checkNuxtConfig(rootDir: string): Promise<{
180186
return {
181187
hasDeprecatedFonts,
182188
hasNuxtFonts: hasNuxtFontsInPkg || hasNuxtFontsInConfig,
189+
hasDefaultsComponent,
190+
defaultComponentName,
183191
nitroPreset,
184192
}
185193
}
@@ -189,6 +197,8 @@ interface MigrationCheck {
189197
needsComponentRename: boolean
190198
needsFontsMigration: boolean
191199
needsNuxtFonts: boolean
200+
needsDefaultsComponentMigration: boolean
201+
defaultComponentName: string | null
192202
componentsToRename: Array<{ from: string, to: string }>
193203
}
194204

@@ -197,6 +207,8 @@ async function checkMigrationNeeded(rootDir: string): Promise<MigrationCheck> {
197207
needsComponentRename: false,
198208
needsFontsMigration: false,
199209
needsNuxtFonts: false,
210+
needsDefaultsComponentMigration: false,
211+
defaultComponentName: null,
200212
componentsToRename: [],
201213
}
202214

@@ -228,10 +240,12 @@ async function checkMigrationNeeded(rootDir: string): Promise<MigrationCheck> {
228240
}
229241
result.needsComponentRename = result.componentsToRename.length > 0
230242

231-
// Check fonts config
243+
// Check config
232244
const configCheck = await checkNuxtConfig(rootDir)
233245
result.needsFontsMigration = configCheck.hasDeprecatedFonts
234246
result.needsNuxtFonts = !configCheck.hasNuxtFonts
247+
result.needsDefaultsComponentMigration = configCheck.hasDefaultsComponent
248+
result.defaultComponentName = configCheck.defaultComponentName
235249

236250
return result
237251
}
@@ -489,11 +503,12 @@ async function runMigrate(args: string[]): Promise<void> {
489503
// Check what needs migration
490504
const migrationCheck = await checkMigrationNeeded(cwd)
491505

492-
// When components all have suffixes and there's no fonts migration needed
506+
// When nothing needs migration
493507
const noComponentWork = !migrationCheck.needsComponentRename
494508
const noFontsWork = !migrationCheck.needsFontsMigration && !migrationCheck.needsNuxtFonts
509+
const noDefaultsWork = !migrationCheck.needsDefaultsComponentMigration
495510

496-
if (noComponentWork && noFontsWork) {
511+
if (noComponentWork && noFontsWork && noDefaultsWork) {
497512
console.log('✓ All OG Image components already have renderer suffixes.')
498513
p.outro('Done')
499514
return
@@ -504,6 +519,9 @@ async function runMigrate(args: string[]): Promise<void> {
504519
if (migrationCheck.needsComponentRename) {
505520
tasks.push(`Rename ${migrationCheck.componentsToRename.length} component(s) to include renderer suffix`)
506521
}
522+
if (migrationCheck.needsDefaultsComponentMigration) {
523+
tasks.push(`Remove deprecated defaults.component: '${migrationCheck.defaultComponentName}'`)
524+
}
507525
if (migrationCheck.needsFontsMigration) {
508526
tasks.push('Migrate ogImage.fonts to @nuxt/fonts config')
509527
}
@@ -615,16 +633,60 @@ async function runMigrate(args: string[]): Promise<void> {
615633
console.log(' No API changes needed')
616634
}
617635

618-
// Handle fonts (only in interactive mode)
619-
if (migrationCheck.needsNuxtFonts && !dryRun && !skipConfirm) {
620-
const addFonts = await p.confirm({
621-
message: '@nuxt/fonts is recommended for custom fonts. Add it?',
622-
initialValue: true,
623-
})
636+
// Migrate defaults.component
637+
if (migrationCheck.needsDefaultsComponentMigration) {
638+
if (dryRun) {
639+
p.log.info(`Would remove defaults.component: '${migrationCheck.defaultComponentName}'`)
640+
}
641+
else {
642+
const result = await migrateDefaultsComponent(cwd).catch((err) => {
643+
p.log.warn(`Failed to migrate defaults.component: ${err.message}`)
644+
return { migrated: false, componentName: null, message: err.message }
645+
})
646+
if (result.migrated) {
647+
p.log.success(`Removed defaults.component: '${result.componentName}'`)
648+
p.log.info(` To use '${result.componentName}' as default, rename it to OgImage/Default.{renderer}.vue`)
649+
}
650+
}
651+
}
624652

625-
if (!p.isCancel(addFonts) && addFonts) {
653+
// Migrate fonts config
654+
if (migrationCheck.needsFontsMigration) {
655+
if (dryRun) {
656+
p.log.info('Would migrate ogImage.fonts to @nuxt/fonts config')
657+
}
658+
else {
659+
const result = await migrateFontsConfig(cwd).catch((err) => {
660+
p.log.warn(`Failed to migrate fonts config: ${err.message}`)
661+
return { migrated: false, message: err.message }
662+
})
663+
if (result.migrated) {
664+
p.log.success(result.message)
665+
}
666+
else {
667+
p.log.warn(`Fonts migration: ${result.message}`)
668+
}
669+
}
670+
}
671+
672+
// Offer @nuxt/fonts installation
673+
if (migrationCheck.needsNuxtFonts && !dryRun) {
674+
if (skipConfirm) {
626675
await installNuxtFonts()
627676
}
677+
else {
678+
const addFonts = await p.confirm({
679+
message: '@nuxt/fonts is recommended for font management. Install it?',
680+
initialValue: true,
681+
})
682+
683+
if (!p.isCancel(addFonts) && addFonts) {
684+
await installNuxtFonts()
685+
}
686+
else {
687+
p.log.info('Skipped @nuxt/fonts installation. Add manually: npx nuxi module add @nuxt/fonts')
688+
}
689+
}
628690
}
629691

630692
if (dryRun) {

src/migrations/fonts.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,46 @@ export async function migrateFontsConfig(rootDir: string): Promise<{ migrated: b
153153
}
154154
}
155155

156+
export async function migrateDefaultsComponent(rootDir: string): Promise<{ migrated: boolean, componentName: string | null, message: string }> {
157+
const configPaths = [
158+
'nuxt.config.ts',
159+
'nuxt.config.js',
160+
'nuxt.config.mjs',
161+
]
162+
163+
let configPath: string | undefined
164+
for (const cp of configPaths) {
165+
const fullPath = join(rootDir, cp)
166+
if (existsSync(fullPath)) {
167+
configPath = fullPath
168+
break
169+
}
170+
}
171+
172+
if (!configPath)
173+
return { migrated: false, componentName: null, message: 'No nuxt.config found' }
174+
175+
const mod = await loadFile(configPath)
176+
const config = mod.exports.default
177+
178+
if (!config?.ogImage?.defaults?.component)
179+
return { migrated: false, componentName: null, message: 'No defaults.component found' }
180+
181+
const componentName = String(config.ogImage.defaults.component)
182+
delete config.ogImage.defaults.component
183+
184+
// Clean up empty defaults
185+
if (config.ogImage.defaults && Object.keys(config.ogImage.defaults).length === 0)
186+
delete config.ogImage.defaults
187+
188+
// Clean up empty ogImage
189+
if (config.ogImage && Object.keys(config.ogImage).length === 0)
190+
delete config.ogImage
191+
192+
await writeFile(mod, configPath)
193+
return { migrated: true, componentName, message: `Removed defaults.component: '${componentName}'` }
194+
}
195+
156196
export async function promptFontsMigration(rootDir: string): Promise<void> {
157197
logger.info('')
158198
logger.info('Detected deprecated ogImage.fonts configuration.')

src/migrations/warnings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const REMOVED_CONFIG: Record<string, string> = {
3939
'chromium-node': 'compatibility.runtime.browser: \'playwright\'',
4040
'componentOptions': 'Removed (<OgImage> component removed, use defineOgImage())',
4141
'defaults.renderer': 'Removed (renderer determined by component filename suffix)',
42+
'defaults.component': 'Removed (rename component to OgImage/Default.{renderer}.vue)',
4243
}
4344

4445
// Deprecated composables

src/onboarding.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,12 @@ export async function onUpgrade(
260260
}
261261
}
262262

263+
// check nested deprecated options
264+
const defaults = ogImageConfig.defaults as Record<string, unknown> | undefined
265+
if (defaults?.component) {
266+
issues.push(`Config \`defaults.component\` is deprecated: Removed — rename component to OgImage/Default.{renderer}.vue`)
267+
}
268+
263269
// offer migration for fonts config
264270
if ('fonts' in ogImageConfig && !nuxt.options._prepare && !isCI) {
265271
await promptFontsMigration(nuxt.options.rootDir)

0 commit comments

Comments
 (0)