mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
fix(nuxt): improve error logging in import protections (#28753)
This commit is contained in:
parent
d2ef3145f6
commit
77e36ee274
@ -75,6 +75,7 @@
|
|||||||
"compatx": "^0.1.8",
|
"compatx": "^0.1.8",
|
||||||
"consola": "^3.2.3",
|
"consola": "^3.2.3",
|
||||||
"cookie-es": "^1.2.2",
|
"cookie-es": "^1.2.2",
|
||||||
|
"impound": "^0.1.0",
|
||||||
"defu": "^6.1.4",
|
"defu": "^6.1.4",
|
||||||
"destr": "^2.0.3",
|
"destr": "^2.0.3",
|
||||||
"devalue": "^5.0.0",
|
"devalue": "^5.0.0",
|
||||||
|
@ -11,12 +11,13 @@ import escapeRE from 'escape-string-regexp'
|
|||||||
import { defu } from 'defu'
|
import { defu } from 'defu'
|
||||||
import { dynamicEventHandler } from 'h3'
|
import { dynamicEventHandler } from 'h3'
|
||||||
import { isWindows } from 'std-env'
|
import { isWindows } from 'std-env'
|
||||||
|
import { ImpoundPlugin } from 'impound'
|
||||||
import type { Nuxt, NuxtOptions } from 'nuxt/schema'
|
import type { Nuxt, NuxtOptions } from 'nuxt/schema'
|
||||||
import { version as nuxtVersion } from '../../package.json'
|
import { version as nuxtVersion } from '../../package.json'
|
||||||
import { distDir } from '../dirs'
|
import { distDir } from '../dirs'
|
||||||
import { toArray } from '../utils'
|
import { toArray } from '../utils'
|
||||||
import { template as defaultSpaLoadingTemplate } from '../../../ui-templates/dist/templates/spa-loading-icon'
|
import { template as defaultSpaLoadingTemplate } from '../../../ui-templates/dist/templates/spa-loading-icon'
|
||||||
import { ImportProtectionPlugin, nuxtImportProtections } from './plugins/import-protection'
|
import { nuxtImportProtections } from './plugins/import-protection'
|
||||||
|
|
||||||
const logLevelMapReverse = {
|
const logLevelMapReverse = {
|
||||||
silent: 0,
|
silent: 0,
|
||||||
@ -358,9 +359,8 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
nitroConfig.rollupConfig!.plugins = await nitroConfig.rollupConfig!.plugins || []
|
nitroConfig.rollupConfig!.plugins = await nitroConfig.rollupConfig!.plugins || []
|
||||||
nitroConfig.rollupConfig!.plugins = toArray(nitroConfig.rollupConfig!.plugins)
|
nitroConfig.rollupConfig!.plugins = toArray(nitroConfig.rollupConfig!.plugins)
|
||||||
nitroConfig.rollupConfig!.plugins!.push(
|
nitroConfig.rollupConfig!.plugins!.push(
|
||||||
ImportProtectionPlugin.rollup({
|
ImpoundPlugin.rollup({
|
||||||
rootDir: nuxt.options.rootDir,
|
cwd: nuxt.options.rootDir,
|
||||||
modulesDir: nuxt.options.modulesDir,
|
|
||||||
patterns: nuxtImportProtections(nuxt, { isNitro: true }),
|
patterns: nuxtImportProtections(nuxt, { isNitro: true }),
|
||||||
exclude: [/core[\\/]runtime[\\/]nitro[\\/]renderer/],
|
exclude: [/core[\\/]runtime[\\/]nitro[\\/]renderer/],
|
||||||
}),
|
}),
|
||||||
|
@ -15,13 +15,14 @@ import { colorize } from 'consola/utils'
|
|||||||
import { updateConfig } from 'c12/update'
|
import { updateConfig } from 'c12/update'
|
||||||
import { formatDate, resolveCompatibilityDatesFromEnv } from 'compatx'
|
import { formatDate, resolveCompatibilityDatesFromEnv } from 'compatx'
|
||||||
import type { DateString } from 'compatx'
|
import type { DateString } from 'compatx'
|
||||||
|
|
||||||
import escapeRE from 'escape-string-regexp'
|
import escapeRE from 'escape-string-regexp'
|
||||||
import { withTrailingSlash, withoutLeadingSlash } from 'ufo'
|
import { withTrailingSlash, withoutLeadingSlash } from 'ufo'
|
||||||
|
import { ImpoundPlugin } from 'impound'
|
||||||
|
import type { ImpoundOptions } from 'impound'
|
||||||
import defu from 'defu'
|
import defu from 'defu'
|
||||||
import { gt, satisfies } from 'semver'
|
import { gt, satisfies } from 'semver'
|
||||||
import { hasTTY, isCI } from 'std-env'
|
import { hasTTY, isCI } from 'std-env'
|
||||||
|
|
||||||
import pagesModule from '../pages/module'
|
import pagesModule from '../pages/module'
|
||||||
import metaModule from '../head/module'
|
import metaModule from '../head/module'
|
||||||
import componentsModule from '../components/module'
|
import componentsModule from '../components/module'
|
||||||
@ -31,7 +32,7 @@ import { distDir, pkgDir } from '../dirs'
|
|||||||
import { version } from '../../package.json'
|
import { version } from '../../package.json'
|
||||||
import { scriptsStubsPreset } from '../imports/presets'
|
import { scriptsStubsPreset } from '../imports/presets'
|
||||||
import { resolveTypePath } from './utils/types'
|
import { resolveTypePath } from './utils/types'
|
||||||
import { ImportProtectionPlugin, nuxtImportProtections } from './plugins/import-protection'
|
import { nuxtImportProtections } from './plugins/import-protection'
|
||||||
import type { UnctxTransformPluginOptions } from './plugins/unctx'
|
import type { UnctxTransformPluginOptions } from './plugins/unctx'
|
||||||
import { UnctxTransformPlugin } from './plugins/unctx'
|
import { UnctxTransformPlugin } from './plugins/unctx'
|
||||||
import type { TreeShakeComposablesPluginOptions } from './plugins/tree-shake'
|
import type { TreeShakeComposablesPluginOptions } from './plugins/tree-shake'
|
||||||
@ -245,15 +246,15 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
addBuildPlugin(RemovePluginMetadataPlugin(nuxt))
|
addBuildPlugin(RemovePluginMetadataPlugin(nuxt))
|
||||||
|
|
||||||
// Add import protection
|
// Add import protection
|
||||||
const config = {
|
const config: ImpoundOptions = {
|
||||||
rootDir: nuxt.options.rootDir,
|
cwd: nuxt.options.rootDir,
|
||||||
// Exclude top-level resolutions by plugins
|
// Exclude top-level resolutions by plugins
|
||||||
exclude: [join(nuxt.options.srcDir, 'index.html')],
|
exclude: [join(nuxt.options.srcDir, 'index.html')],
|
||||||
patterns: nuxtImportProtections(nuxt),
|
patterns: nuxtImportProtections(nuxt),
|
||||||
modulesDir: nuxt.options.modulesDir,
|
|
||||||
}
|
}
|
||||||
addVitePlugin(() => ImportProtectionPlugin.vite(config))
|
addVitePlugin(() => Object.assign(ImpoundPlugin.vite({ ...config, error: false }), { name: 'nuxt:import-protection' }), { client: false })
|
||||||
addWebpackPlugin(() => ImportProtectionPlugin.webpack(config))
|
addVitePlugin(() => Object.assign(ImpoundPlugin.vite({ ...config, error: true }), { name: 'nuxt:import-protection' }), { server: false })
|
||||||
|
addWebpackPlugin(() => ImpoundPlugin.webpack(config))
|
||||||
|
|
||||||
// add resolver for modules used in virtual files
|
// add resolver for modules used in virtual files
|
||||||
addVitePlugin(() => resolveDeepImportsPlugin(nuxt))
|
addVitePlugin(() => resolveDeepImportsPlugin(nuxt))
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
import { createUnplugin } from 'unplugin'
|
import { relative, resolve } from 'pathe'
|
||||||
import { logger } from '@nuxt/kit'
|
|
||||||
import { resolvePath } from 'mlly'
|
|
||||||
import { isAbsolute, join, relative, resolve } from 'pathe'
|
|
||||||
import escapeRE from 'escape-string-regexp'
|
import escapeRE from 'escape-string-regexp'
|
||||||
import type { NuxtOptions } from 'nuxt/schema'
|
import type { NuxtOptions } from 'nuxt/schema'
|
||||||
|
|
||||||
@ -53,41 +50,3 @@ export const nuxtImportProtections = (nuxt: { options: NuxtOptions }, options: {
|
|||||||
|
|
||||||
return patterns
|
return patterns
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ImportProtectionPlugin = createUnplugin(function (options: ImportProtectionOptions) {
|
|
||||||
const cache: Record<string, Map<string | RegExp, boolean>> = {}
|
|
||||||
const importersToExclude = options?.exclude || []
|
|
||||||
const proxy = resolvePath('unenv/runtime/mock/proxy', { url: options.modulesDir })
|
|
||||||
return {
|
|
||||||
name: 'nuxt:import-protection',
|
|
||||||
enforce: 'pre',
|
|
||||||
resolveId (id, importer) {
|
|
||||||
if (!importer) { return }
|
|
||||||
if (id[0] === '.') {
|
|
||||||
id = join(importer, '..', id)
|
|
||||||
}
|
|
||||||
if (isAbsolute(id)) {
|
|
||||||
id = relative(options.rootDir, id)
|
|
||||||
}
|
|
||||||
if (importersToExclude.some(p => typeof p === 'string' ? importer === p : p.test(importer))) { return }
|
|
||||||
|
|
||||||
const invalidImports = options.patterns.filter(([pattern]) => pattern instanceof RegExp ? pattern.test(id) : pattern === id)
|
|
||||||
let matched = false
|
|
||||||
for (const match of invalidImports) {
|
|
||||||
cache[id] = cache[id] || new Map()
|
|
||||||
const [pattern, warning] = match
|
|
||||||
// Skip if already warned
|
|
||||||
if (cache[id].has(pattern)) { continue }
|
|
||||||
|
|
||||||
const relativeImporter = isAbsolute(importer) ? relative(options.rootDir, importer) : importer
|
|
||||||
logger.error(warning || 'Invalid import', `[importing \`${id}\` from \`${relativeImporter}\`]`)
|
|
||||||
cache[id].set(pattern, true)
|
|
||||||
matched = true
|
|
||||||
}
|
|
||||||
if (matched) {
|
|
||||||
return proxy
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { fileURLToPath } from 'node:url'
|
|
||||||
import { normalize } from 'pathe'
|
import { normalize } from 'pathe'
|
||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
import { ImportProtectionPlugin, nuxtImportProtections } from '../src/core/plugins/import-protection'
|
import { ImpoundPlugin } from 'impound'
|
||||||
|
import { nuxtImportProtections } from '../src/core/plugins/import-protection'
|
||||||
import type { NuxtOptions } from '../schema'
|
import type { NuxtOptions } from '../schema'
|
||||||
|
|
||||||
const testsToTriggerOn = [
|
const testsToTriggerOn = [
|
||||||
@ -39,9 +39,8 @@ describe('import protection', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const transformWithImportProtection = (id: string, importer: string) => {
|
const transformWithImportProtection = (id: string, importer: string) => {
|
||||||
const plugin = ImportProtectionPlugin.rollup({
|
const plugin = ImpoundPlugin.rollup({
|
||||||
rootDir: '/root',
|
cwd: '/root',
|
||||||
modulesDir: [fileURLToPath(new URL('..', import.meta.url))],
|
|
||||||
patterns: nuxtImportProtections({
|
patterns: nuxtImportProtections({
|
||||||
options: {
|
options: {
|
||||||
modules: ['some-nuxt-module'],
|
modules: ['some-nuxt-module'],
|
||||||
@ -51,5 +50,5 @@ const transformWithImportProtection = (id: string, importer: string) => {
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
return (plugin as any).resolveId(id, importer)
|
return (plugin as any).resolveId.call({ error: () => {} }, id, importer)
|
||||||
}
|
}
|
||||||
|
@ -348,6 +348,9 @@ importers:
|
|||||||
ignore:
|
ignore:
|
||||||
specifier: ^5.3.2
|
specifier: ^5.3.2
|
||||||
version: 5.3.2
|
version: 5.3.2
|
||||||
|
impound:
|
||||||
|
specifier: ^0.1.0
|
||||||
|
version: 0.1.0(rollup@4.21.1)
|
||||||
jiti:
|
jiti:
|
||||||
specifier: 2.0.0-beta.3
|
specifier: 2.0.0-beta.3
|
||||||
version: 2.0.0-beta.3
|
version: 2.0.0-beta.3
|
||||||
@ -4661,6 +4664,9 @@ packages:
|
|||||||
importx@0.4.3:
|
importx@0.4.3:
|
||||||
resolution: {integrity: sha512-x6E6OxmWq/SUaj7wDeDeSjyHP+rMUbEaqJ5fw0uEtC/FTX9ocxNMFJ+ONnpJIsRpFz3ya6qJAK4orwSKqw0BSQ==}
|
resolution: {integrity: sha512-x6E6OxmWq/SUaj7wDeDeSjyHP+rMUbEaqJ5fw0uEtC/FTX9ocxNMFJ+ONnpJIsRpFz3ya6qJAK4orwSKqw0BSQ==}
|
||||||
|
|
||||||
|
impound@0.1.0:
|
||||||
|
resolution: {integrity: sha512-F9nJgOsDc3tysjN74edE0vGPEQrU7DAje6g5nNAL5Jc9Tv4JW3mH7XMGne+EaadTniDXLeUrVR21opkNfWO1zQ==}
|
||||||
|
|
||||||
imurmurhash@0.1.4:
|
imurmurhash@0.1.4:
|
||||||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||||
engines: {node: '>=0.8.19'}
|
engines: {node: '>=0.8.19'}
|
||||||
@ -11803,6 +11809,16 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
impound@0.1.0(rollup@4.21.1):
|
||||||
|
dependencies:
|
||||||
|
'@rollup/pluginutils': 5.1.0(rollup@4.21.1)
|
||||||
|
mlly: 1.7.1
|
||||||
|
pathe: 1.1.2
|
||||||
|
unenv: 1.10.0
|
||||||
|
unplugin: 1.12.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- rollup
|
||||||
|
|
||||||
imurmurhash@0.1.4: {}
|
imurmurhash@0.1.4: {}
|
||||||
|
|
||||||
indent-string@4.0.0: {}
|
indent-string@4.0.0: {}
|
||||||
|
Loading…
Reference in New Issue
Block a user