mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 07:05:11 +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",
|
||||
"consola": "^3.2.3",
|
||||
"cookie-es": "^1.2.2",
|
||||
"impound": "^0.1.0",
|
||||
"defu": "^6.1.4",
|
||||
"destr": "^2.0.3",
|
||||
"devalue": "^5.0.0",
|
||||
|
@ -11,12 +11,13 @@ import escapeRE from 'escape-string-regexp'
|
||||
import { defu } from 'defu'
|
||||
import { dynamicEventHandler } from 'h3'
|
||||
import { isWindows } from 'std-env'
|
||||
import { ImpoundPlugin } from 'impound'
|
||||
import type { Nuxt, NuxtOptions } from 'nuxt/schema'
|
||||
import { version as nuxtVersion } from '../../package.json'
|
||||
import { distDir } from '../dirs'
|
||||
import { toArray } from '../utils'
|
||||
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 = {
|
||||
silent: 0,
|
||||
@ -358,9 +359,8 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
||||
nitroConfig.rollupConfig!.plugins = await nitroConfig.rollupConfig!.plugins || []
|
||||
nitroConfig.rollupConfig!.plugins = toArray(nitroConfig.rollupConfig!.plugins)
|
||||
nitroConfig.rollupConfig!.plugins!.push(
|
||||
ImportProtectionPlugin.rollup({
|
||||
rootDir: nuxt.options.rootDir,
|
||||
modulesDir: nuxt.options.modulesDir,
|
||||
ImpoundPlugin.rollup({
|
||||
cwd: nuxt.options.rootDir,
|
||||
patterns: nuxtImportProtections(nuxt, { isNitro: true }),
|
||||
exclude: [/core[\\/]runtime[\\/]nitro[\\/]renderer/],
|
||||
}),
|
||||
|
@ -15,13 +15,14 @@ import { colorize } from 'consola/utils'
|
||||
import { updateConfig } from 'c12/update'
|
||||
import { formatDate, resolveCompatibilityDatesFromEnv } from 'compatx'
|
||||
import type { DateString } from 'compatx'
|
||||
|
||||
import escapeRE from 'escape-string-regexp'
|
||||
import { withTrailingSlash, withoutLeadingSlash } from 'ufo'
|
||||
|
||||
import { ImpoundPlugin } from 'impound'
|
||||
import type { ImpoundOptions } from 'impound'
|
||||
import defu from 'defu'
|
||||
import { gt, satisfies } from 'semver'
|
||||
import { hasTTY, isCI } from 'std-env'
|
||||
|
||||
import pagesModule from '../pages/module'
|
||||
import metaModule from '../head/module'
|
||||
import componentsModule from '../components/module'
|
||||
@ -31,7 +32,7 @@ import { distDir, pkgDir } from '../dirs'
|
||||
import { version } from '../../package.json'
|
||||
import { scriptsStubsPreset } from '../imports/presets'
|
||||
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 { UnctxTransformPlugin } from './plugins/unctx'
|
||||
import type { TreeShakeComposablesPluginOptions } from './plugins/tree-shake'
|
||||
@ -245,15 +246,15 @@ async function initNuxt (nuxt: Nuxt) {
|
||||
addBuildPlugin(RemovePluginMetadataPlugin(nuxt))
|
||||
|
||||
// Add import protection
|
||||
const config = {
|
||||
rootDir: nuxt.options.rootDir,
|
||||
const config: ImpoundOptions = {
|
||||
cwd: nuxt.options.rootDir,
|
||||
// Exclude top-level resolutions by plugins
|
||||
exclude: [join(nuxt.options.srcDir, 'index.html')],
|
||||
patterns: nuxtImportProtections(nuxt),
|
||||
modulesDir: nuxt.options.modulesDir,
|
||||
}
|
||||
addVitePlugin(() => ImportProtectionPlugin.vite(config))
|
||||
addWebpackPlugin(() => ImportProtectionPlugin.webpack(config))
|
||||
addVitePlugin(() => Object.assign(ImpoundPlugin.vite({ ...config, error: false }), { name: 'nuxt:import-protection' }), { client: false })
|
||||
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
|
||||
addVitePlugin(() => resolveDeepImportsPlugin(nuxt))
|
||||
|
@ -1,7 +1,4 @@
|
||||
import { createUnplugin } from 'unplugin'
|
||||
import { logger } from '@nuxt/kit'
|
||||
import { resolvePath } from 'mlly'
|
||||
import { isAbsolute, join, relative, resolve } from 'pathe'
|
||||
import { relative, resolve } from 'pathe'
|
||||
import escapeRE from 'escape-string-regexp'
|
||||
import type { NuxtOptions } from 'nuxt/schema'
|
||||
|
||||
@ -53,41 +50,3 @@ export const nuxtImportProtections = (nuxt: { options: NuxtOptions }, options: {
|
||||
|
||||
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 { 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'
|
||||
|
||||
const testsToTriggerOn = [
|
||||
@ -39,9 +39,8 @@ describe('import protection', () => {
|
||||
})
|
||||
|
||||
const transformWithImportProtection = (id: string, importer: string) => {
|
||||
const plugin = ImportProtectionPlugin.rollup({
|
||||
rootDir: '/root',
|
||||
modulesDir: [fileURLToPath(new URL('..', import.meta.url))],
|
||||
const plugin = ImpoundPlugin.rollup({
|
||||
cwd: '/root',
|
||||
patterns: nuxtImportProtections({
|
||||
options: {
|
||||
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:
|
||||
specifier: ^5.3.2
|
||||
version: 5.3.2
|
||||
impound:
|
||||
specifier: ^0.1.0
|
||||
version: 0.1.0(rollup@4.21.1)
|
||||
jiti:
|
||||
specifier: 2.0.0-beta.3
|
||||
version: 2.0.0-beta.3
|
||||
@ -4661,6 +4664,9 @@ packages:
|
||||
importx@0.4.3:
|
||||
resolution: {integrity: sha512-x6E6OxmWq/SUaj7wDeDeSjyHP+rMUbEaqJ5fw0uEtC/FTX9ocxNMFJ+ONnpJIsRpFz3ya6qJAK4orwSKqw0BSQ==}
|
||||
|
||||
impound@0.1.0:
|
||||
resolution: {integrity: sha512-F9nJgOsDc3tysjN74edE0vGPEQrU7DAje6g5nNAL5Jc9Tv4JW3mH7XMGne+EaadTniDXLeUrVR21opkNfWO1zQ==}
|
||||
|
||||
imurmurhash@0.1.4:
|
||||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||
engines: {node: '>=0.8.19'}
|
||||
@ -11803,6 +11809,16 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- 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: {}
|
||||
|
||||
indent-string@4.0.0: {}
|
||||
|
Loading…
Reference in New Issue
Block a user