feat(nuxt): allow specifying builder compatibility in modules (#27022)

This commit is contained in:
Horu 2024-05-09 15:28:33 +07:00 committed by GitHub
parent bb23a868ea
commit d66d68cd7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 57 additions and 0 deletions

View File

@ -25,6 +25,12 @@ async function checkNuxtCompatibility(
interface NuxtCompatibility { interface NuxtCompatibility {
nuxt?: string; nuxt?: string;
bridge?: boolean; bridge?: boolean;
builder?: {
// Set `false` if your module is not compatible with a builder
// or a semver-compatible string version constraint
vite?: false | string;
webpack?: false | string;
};
} }
interface NuxtCompatibilityIssue { interface NuxtCompatibilityIssue {

View File

@ -1,4 +1,5 @@
import satisfies from 'semver/functions/satisfies.js' // npm/node-semver#381 import satisfies from 'semver/functions/satisfies.js' // npm/node-semver#381
import { readPackageJSON } from 'pkg-types'
import type { Nuxt, NuxtCompatibility, NuxtCompatibilityIssues } from '@nuxt/schema' import type { Nuxt, NuxtCompatibility, NuxtCompatibilityIssues } from '@nuxt/schema'
import { useNuxt } from './context' import { useNuxt } from './context'
@ -6,6 +7,11 @@ export function normalizeSemanticVersion (version: string) {
return version.replace(/-[0-9]+\.[0-9a-f]+/, '') // Remove edge prefix return version.replace(/-[0-9]+\.[0-9a-f]+/, '') // Remove edge prefix
} }
const builderMap = {
'@nuxt/vite-builder': 'vite',
'@nuxt/webpack-builder': 'webpack',
}
/** /**
* Check version constraints and return incompatibility issues as an array * Check version constraints and return incompatibility issues as an array
*/ */
@ -40,6 +46,28 @@ export async function checkNuxtCompatibility (constraints: NuxtCompatibility, nu
} }
} }
// Builder compatibility check
if (constraints.builder && typeof nuxt.options.builder === 'string') {
const currentBuilder = builderMap[nuxt.options.builder] || nuxt.options.builder
if (currentBuilder in constraints.builder) {
const constraint = constraints.builder[currentBuilder]!
if (constraint === false) {
issues.push({
name: 'builder',
message: `Not compatible with \`${nuxt.options.builder}\`.`,
})
} else {
const builderVersion = await readPackageJSON(nuxt.options.builder, { url: nuxt.options.modulesDir }).then(r => r.version).catch(() => undefined)
if (builderVersion && !satisfies(normalizeSemanticVersion(builderVersion), constraint, { includePrerelease: true })) {
issues.push({
name: 'builder',
message: `Not compatible with \`${builderVersion}\` of \`${currentBuilder}\`. This module requires \`${constraint}\`.`,
})
}
}
}
}
// Allow extending compatibility checks // Allow extending compatibility checks
await nuxt.callHook('kit:compatibility', constraints, issues) await nuxt.callHook('kit:compatibility', constraints, issues)

View File

@ -12,6 +12,29 @@ export interface NuxtCompatibility {
* - `false`: When using Nuxt 2, using bridge module is not supported. * - `false`: When using Nuxt 2, using bridge module is not supported.
*/ */
bridge?: boolean bridge?: boolean
/**
* Mark a builder as incompatible, or require a particular version.
*
* @example
* ```ts
* export default defineNuxtModule({
* meta: {
* name: 'my-module',
* compatibility: {
* builder: {
* // marking as incompatible
* webpack: false,
* // you can require a (semver-compatible) version
* vite: '^5'
* }
* }
* }
* // ...
* })
* ```
*/
builder?: Partial<Record<'vite' | 'webpack' | (string & {}), false | string>>
} }
export interface NuxtCompatibilityIssue { export interface NuxtCompatibilityIssue {