mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-29 00:52:01 +00:00
feat(kit, bridge): version constraint utils and checks (#442)
Co-authored-by: Pooya Parsa <pyapar@gmail.com>
This commit is contained in:
parent
eb0332126e
commit
9503d62607
@ -1,5 +1,5 @@
|
||||
import { createRequire } from 'module'
|
||||
import { defineNuxtModule, installModule } from '@nuxt/kit'
|
||||
import { defineNuxtModule, installModule, checkNuxtCompatibilityIssues } from '@nuxt/kit'
|
||||
import { setupNitroBridge } from './nitro'
|
||||
import { setupAppBridge } from './app'
|
||||
import { setupCAPIBridge } from './capi'
|
||||
@ -15,6 +15,7 @@ export default defineNuxtModule({
|
||||
app: {},
|
||||
capi: {},
|
||||
globalImports: true,
|
||||
constraints: true,
|
||||
// TODO: Remove from 2.16
|
||||
postcss8: true,
|
||||
swc: true,
|
||||
@ -50,5 +51,18 @@ export default defineNuxtModule({
|
||||
if (opts.resolve) {
|
||||
setupBetterResolve()
|
||||
}
|
||||
if (opts.constraints) {
|
||||
nuxt.hook('modules:done', (moduleContainer: any) => {
|
||||
for (const [name, m] of Object.entries(moduleContainer.requiredModules || {})) {
|
||||
const requires = (m as any)?.handler?.meta?.requires
|
||||
if (requires) {
|
||||
const issues = checkNuxtCompatibilityIssues(requires, nuxt)
|
||||
if (issues.length) {
|
||||
console.warn(`[bridge] Detected module incompatibility issues for \`${name}\`:\n` + issues.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -15,6 +15,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash.template": "^4",
|
||||
"@types/semver": "^7",
|
||||
"unbuild": "latest"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -30,6 +31,7 @@
|
||||
"pathe": "^0.2.0",
|
||||
"rc9": "^1.2.0",
|
||||
"scule": "^0.2.1",
|
||||
"semver": "^7.3.5",
|
||||
"std-env": "^2.3.1",
|
||||
"ufo": "^0.7.9",
|
||||
"unctx": "^1.0.2",
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { promises as fsp } from 'fs'
|
||||
import defu from 'defu'
|
||||
import { applyDefaults } from 'untyped'
|
||||
import consola from 'consola'
|
||||
import { useNuxt, nuxtCtx } from '../nuxt'
|
||||
import type { Nuxt, NuxtTemplate } from '../types/nuxt'
|
||||
import type { NuxtModule, LegacyNuxtModule, ModuleOptions } from '../types/module'
|
||||
import { compileTemplate, isNuxt2, templateUtils } from './utils'
|
||||
import { checkNuxtCompatibilityIssues, compileTemplate, isNuxt2, templateUtils } from './utils'
|
||||
|
||||
/**
|
||||
* Define a Nuxt module, automatically merging defaults with user provided options, installing
|
||||
@ -34,6 +35,15 @@ export function defineNuxtModule<OptionsT extends ModuleOptions> (input: NuxtMod
|
||||
return
|
||||
}
|
||||
|
||||
// check nuxt version range
|
||||
if (mod.requires) {
|
||||
const issues = checkNuxtCompatibilityIssues(mod.requires, nuxt)
|
||||
if (issues.length) {
|
||||
consola.warn(`Module \`${mod.name}\` is disabled due to incompatibility issues:\n${issues.toString()}`)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve options
|
||||
const configKey = mod.configKey || mod.name
|
||||
const userOptions = defu(inlineOptions, nuxt.options[configKey]) as OptionsT
|
||||
|
@ -5,6 +5,9 @@ import hash from 'hash-sum'
|
||||
import type { WebpackPluginInstance, Configuration as WebpackConfig } from 'webpack'
|
||||
import type { Plugin as VitePlugin, UserConfig as ViteConfig } from 'vite'
|
||||
import { camelCase } from 'scule'
|
||||
import semver from 'semver'
|
||||
import { NuxtCompatibilityConstraints, NuxtCompatibilityIssues } from '../types/module'
|
||||
import { Nuxt } from '../types/nuxt'
|
||||
import { useNuxt } from '../nuxt'
|
||||
import type { NuxtTemplate, NuxtPlugin, NuxtPluginTemplate } from '../types/nuxt'
|
||||
|
||||
@ -255,15 +258,6 @@ export function addVitePlugin (plugin: VitePlugin, options?: ExtendViteConfigOpt
|
||||
}, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current nuxt instance is version 2 legacy
|
||||
*/
|
||||
export function isNuxt2 (nuxt?: any) {
|
||||
nuxt = nuxt || useNuxt()
|
||||
const version = (nuxt?.version || nuxt?.constructor?.version || '').replace(/^v|-.*$/g, '')
|
||||
return version.startsWith('2.')
|
||||
}
|
||||
|
||||
export async function compileTemplate (template: NuxtTemplate, ctx: any) {
|
||||
const data = { ...ctx, ...template.options }
|
||||
if (template.src) {
|
||||
@ -302,3 +296,64 @@ export const templateUtils = {
|
||||
importName,
|
||||
importSources
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current nuxt instance is version 2 legacy
|
||||
*/
|
||||
export function isNuxt2 (nuxt: Nuxt = useNuxt()) {
|
||||
return getNuxtVersion(nuxt).startsWith('2.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current nuxt instance is version 2 legacy
|
||||
*/
|
||||
export function isNuxt3 (nuxt: Nuxt = useNuxt()) {
|
||||
return getNuxtVersion(nuxt).startsWith('3.')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nuxt version
|
||||
*/
|
||||
export function getNuxtVersion (nuxt: Nuxt | any = useNuxt() /* TODO: LegacyNuxt */) {
|
||||
const version = (nuxt?._version || nuxt?.version || nuxt?.constructor?.version || '').replace(/^v/g, '')
|
||||
if (!version) {
|
||||
throw new Error('Cannot determine nuxt version! Is currect instance passed?')
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
/**
|
||||
* Check version constraints and return incompatibility issues as an array
|
||||
*/
|
||||
export function checkNuxtCompatibilityIssues (constraints: NuxtCompatibilityConstraints, nuxt: Nuxt = useNuxt()): NuxtCompatibilityIssues {
|
||||
const issues: NuxtCompatibilityIssues = []
|
||||
if (constraints.nuxt) {
|
||||
const nuxtVersion = getNuxtVersion(nuxt)
|
||||
if (!semver.satisfies(nuxtVersion, constraints.nuxt)) {
|
||||
issues.push({
|
||||
name: 'nuxt',
|
||||
message: `Nuxt version \`${constraints.nuxt}\` is required but currently using \`${nuxtVersion}\``
|
||||
})
|
||||
}
|
||||
}
|
||||
issues.toString = () => issues.map(issue => ` - [${issue.name}] ${issue.message}`).join('\n')
|
||||
return issues
|
||||
}
|
||||
|
||||
/**
|
||||
* Check version constraints and throw a detailed error if has any, otherwise returns true
|
||||
*/
|
||||
export function ensureNuxtCompatibility (constraints: NuxtCompatibilityConstraints, nuxt: Nuxt = useNuxt()): true {
|
||||
const issues = checkNuxtCompatibilityIssues(constraints, nuxt)
|
||||
if (issues.length) {
|
||||
throw new Error('Nuxt compatibility issues found:\n' + issues.toString())
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Check version constraints and return true if passed, otherwise returns false
|
||||
*/
|
||||
export function hasNuxtCompatibility (constraints: NuxtCompatibilityConstraints, nuxt: Nuxt = useNuxt()) {
|
||||
return !checkNuxtCompatibilityIssues(constraints, nuxt).length
|
||||
}
|
||||
|
@ -2,14 +2,43 @@ import type { ModuleContainer } from '../module/container'
|
||||
import { Nuxt } from './nuxt'
|
||||
import { NuxtHooks } from './hooks'
|
||||
|
||||
export interface NuxtCompatibilityConstraints {
|
||||
/**
|
||||
* Required nuxt version. for example, `^2.14.0` or `>=3.0.0-27219851.6e49637`.
|
||||
*/
|
||||
nuxt?: string
|
||||
}
|
||||
|
||||
export interface NuxtCompatibilityIssue {
|
||||
name: string
|
||||
message: string
|
||||
}
|
||||
|
||||
export interface NuxtCompatibilityIssues extends Array<NuxtCompatibilityIssue> {
|
||||
/**
|
||||
* Return formatted error message
|
||||
*/
|
||||
toString(): string
|
||||
}
|
||||
|
||||
export interface ModuleMeta {
|
||||
/** The module name. */
|
||||
/** Module name */
|
||||
name?: string
|
||||
|
||||
/** Module version */
|
||||
version?: string
|
||||
|
||||
/**
|
||||
* The configuration key used within `nuxt.config` for this module's options.
|
||||
* For example, `@nuxtjs/axios` uses `axios`.
|
||||
*/
|
||||
configKey?: string
|
||||
|
||||
/**
|
||||
* Semver constraints for the versions of Nuxt or features this module are supported.
|
||||
*/
|
||||
requires?: NuxtCompatibilityConstraints
|
||||
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,11 @@ import type { NuxtHooks } from './hooks'
|
||||
import type { NuxtOptions } from './config'
|
||||
|
||||
export interface Nuxt {
|
||||
// Private fields
|
||||
_version: string
|
||||
|
||||
/** The resolved Nuxt configuration. */
|
||||
options: NuxtOptions
|
||||
|
||||
hooks: Hookable<NuxtHooks>
|
||||
hook: Nuxt['hooks']['hook']
|
||||
callHook: Nuxt['hooks']['callHook']
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nuxt3",
|
||||
"version": "0.10.0",
|
||||
"version": "3.0.0",
|
||||
"repository": "nuxt/framework",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
@ -6,12 +6,14 @@ import metaModule from '../meta/module'
|
||||
import componentsModule from '../components/module'
|
||||
import globalImportsModule from '../global-imports/module'
|
||||
import { distDir, pkgDir } from '../dirs'
|
||||
import { version } from '../../package.json'
|
||||
import { initNitro } from './nitro'
|
||||
|
||||
export function createNuxt (options: NuxtOptions): Nuxt {
|
||||
const hooks = createHooks<NuxtHooks>()
|
||||
|
||||
const nuxt: Nuxt = {
|
||||
_version: version,
|
||||
options,
|
||||
hooks,
|
||||
callHook: hooks.callHook,
|
||||
|
@ -1494,6 +1494,7 @@ __metadata:
|
||||
resolution: "@nuxt/kit@workspace:packages/kit"
|
||||
dependencies:
|
||||
"@types/lodash.template": ^4
|
||||
"@types/semver": ^7
|
||||
consola: ^2.15.3
|
||||
create-require: ^1.1.1
|
||||
defu: ^5.0.0
|
||||
@ -1506,6 +1507,7 @@ __metadata:
|
||||
pathe: ^0.2.0
|
||||
rc9: ^1.2.0
|
||||
scule: ^0.2.1
|
||||
semver: ^7.3.5
|
||||
std-env: ^2.3.1
|
||||
ufo: ^0.7.9
|
||||
unbuild: latest
|
||||
@ -2408,6 +2410,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/semver@npm:^7":
|
||||
version: 7.3.8
|
||||
resolution: "@types/semver@npm:7.3.8"
|
||||
checksum: bc90f5a9d5430e36f766c08c898e3c28af88830ebc7736baef8ffc74783bad2efb32f29c40d450e85fc341847ee74e2dd97b76cfc7da407e4232ba9ecae4ff9c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/serve-static@npm:^1.13.10":
|
||||
version: 1.13.10
|
||||
resolution: "@types/serve-static@npm:1.13.10"
|
||||
|
Loading…
Reference in New Issue
Block a user