2022-03-11 08:09:11 +00:00
import { addVitePlugin , addWebpackPlugin , defineNuxtModule , addTemplate , resolveAlias , useNuxt , addPluginTemplate , logger } from '@nuxt/kit'
2021-10-20 09:47:18 +00:00
import { isAbsolute , join , relative , resolve , normalize } from 'pathe'
2022-04-26 15:52:39 +00:00
import { createUnimport , Import , scanDirExports , toImports , Unimport } from 'unimport'
2022-08-23 14:22:11 +00:00
import { ImportsOptions , ImportPresetWithDeprecation } from '@nuxt/schema'
import defu from 'defu'
2021-08-24 07:49:03 +00:00
import { TransformPlugin } from './transform'
2022-03-11 08:09:11 +00:00
import { defaultPresets } from './presets'
2021-08-10 00:27:23 +00:00
2022-08-23 14:22:11 +00:00
export default defineNuxtModule < Partial < ImportsOptions > > ( {
2022-01-05 18:09:53 +00:00
meta : {
2022-08-23 14:22:11 +00:00
name : 'imports' ,
configKey : 'imports'
2022-01-05 18:09:53 +00:00
} ,
2021-10-18 13:39:53 +00:00
defaults : {
2022-08-24 08:44:38 +00:00
autoImport : true ,
2022-03-11 08:09:11 +00:00
presets : defaultPresets ,
2021-10-20 09:47:18 +00:00
global : false ,
2022-03-11 08:09:11 +00:00
imports : [ ] ,
2021-12-21 14:28:45 +00:00
dirs : [ ] ,
transform : {
2022-06-10 13:33:16 +00:00
include : [ ] ,
2021-12-21 14:28:45 +00:00
exclude : undefined
}
2021-10-18 13:39:53 +00:00
} ,
async setup ( options , nuxt ) {
2022-08-23 14:22:11 +00:00
// TODO: remove deprecation warning
// @ts-ignore
if ( nuxt . options . autoImports ) {
logger . warn ( '`autoImports` config is deprecated, use `imports` instead.' )
// @ts-ignore
options = defu ( nuxt . options . autoImports , options )
}
2021-10-18 13:39:53 +00:00
// Allow modules extending sources
2022-08-23 14:22:11 +00:00
await nuxt . callHook ( 'imports:sources' , options . presets as ImportPresetWithDeprecation [ ] )
2022-03-11 08:09:11 +00:00
2022-08-12 17:47:58 +00:00
options . presets ? . forEach ( ( i : ImportPresetWithDeprecation | string ) = > {
2022-03-11 08:09:11 +00:00
if ( typeof i !== 'string' && i . names && ! i . imports ) {
i . imports = i . names
2022-08-23 14:22:11 +00:00
logger . warn ( 'imports: presets.names is deprecated, use presets.imports instead' )
2022-03-11 08:09:11 +00:00
}
} )
2021-10-18 13:39:53 +00:00
// Filter disabled sources
2022-03-11 08:09:11 +00:00
// options.sources = options.sources.filter(source => source.disabled !== true)
2021-10-18 13:39:53 +00:00
2021-10-20 09:47:18 +00:00
// Create a context to share state between module internals
2022-03-11 08:09:11 +00:00
const ctx = createUnimport ( {
2022-03-24 13:15:32 +00:00
presets : options.presets ,
2022-06-08 20:09:31 +00:00
imports : options.imports ,
2022-07-21 14:27:23 +00:00
virtualImports : [ '#imports' ] ,
2022-06-08 20:09:31 +00:00
addons : {
2022-08-24 08:44:38 +00:00
vueTemplate : options.autoImport
2022-06-08 20:09:31 +00:00
}
2022-03-11 08:09:11 +00:00
} )
2021-10-20 09:47:18 +00:00
2022-03-16 20:36:30 +00:00
// composables/ dirs from all layers
2022-08-12 17:47:58 +00:00
let composablesDirs : string [ ] = [ ]
2022-03-16 20:36:30 +00:00
for ( const layer of nuxt . options . _layers ) {
2022-03-09 11:03:36 +00:00
composablesDirs . push ( resolve ( layer . config . srcDir , 'composables' ) )
2022-08-23 14:22:11 +00:00
for ( const dir of ( layer . config . imports ? . dirs ? ? [ ] ) ) {
2022-08-12 17:47:58 +00:00
if ( ! dir ) {
continue
}
2022-03-09 11:03:36 +00:00
composablesDirs . push ( resolve ( layer . config . srcDir , dir ) )
}
}
2022-08-23 14:22:11 +00:00
await nuxt . callHook ( 'imports:dirs' , composablesDirs )
2021-10-20 09:47:18 +00:00
composablesDirs = composablesDirs . map ( dir = > normalize ( dir ) )
2021-10-12 12:24:43 +00:00
2021-11-29 11:20:57 +00:00
// Support for importing from '#imports'
addTemplate ( {
filename : 'imports.mjs' ,
2022-08-23 14:22:11 +00:00
getContents : ( ) = > ctx . toExports ( ) + '\nif (process.dev) { console.warn("[nuxt] `#imports` should be transformed with real imports. There seems to be something wrong with the imports plugin.") }'
2021-11-29 11:20:57 +00:00
} )
nuxt . options . alias [ '#imports' ] = join ( nuxt . options . buildDir , 'imports' )
2021-10-20 09:47:18 +00:00
// Transpile and injection
// @ts-ignore temporary disabled due to #746
2021-10-18 13:39:53 +00:00
if ( nuxt . options . dev && options . global ) {
2021-08-10 00:27:23 +00:00
// Add all imports to globalThis in development mode
addPluginTemplate ( {
2022-08-23 14:22:11 +00:00
filename : 'imports.mjs' ,
2021-08-10 00:27:23 +00:00
getContents : ( ) = > {
2022-03-11 08:09:11 +00:00
const imports = ctx . getImports ( )
const importStatement = toImports ( imports )
const globalThisSet = imports . map ( i = > ` globalThis. ${ i . as } = ${ i . as } ; ` ) . join ( '\n' )
return ` ${ importStatement } \ n \ n ${ globalThisSet } \ n \ nexport default () => {}; `
2021-08-10 00:27:23 +00:00
}
} )
} else {
// Transform to inject imports in production mode
2022-09-07 11:32:10 +00:00
addVitePlugin ( TransformPlugin . vite ( { ctx , options , sourcemap : nuxt.options.sourcemap.server || nuxt . options . sourcemap . client } ) )
addWebpackPlugin ( TransformPlugin . webpack ( { ctx , options , sourcemap : nuxt.options.sourcemap.server || nuxt . options . sourcemap . client } ) )
2021-08-10 00:27:23 +00:00
}
2022-08-23 14:22:11 +00:00
const regenerateImports = async ( ) = > {
2022-04-26 15:52:39 +00:00
ctx . clearDynamicImports ( )
2022-03-11 08:09:11 +00:00
await ctx . modifyDynamicImports ( async ( imports ) = > {
2022-04-26 15:52:39 +00:00
// Scan composables/
imports . push ( . . . await scanDirExports ( composablesDirs ) )
// Modules extending
2022-08-23 14:22:11 +00:00
await nuxt . callHook ( 'imports:extend' , imports )
2022-03-11 08:09:11 +00:00
} )
2021-10-05 20:47:19 +00:00
}
2022-02-08 19:09:24 +00:00
2022-08-23 14:22:11 +00:00
await regenerateImports ( )
2022-02-08 19:09:24 +00:00
// Generate types
2022-08-24 08:44:38 +00:00
addDeclarationTemplates ( ctx , options )
2021-08-11 20:28:38 +00:00
2021-10-20 12:53:13 +00:00
// Add generated types to `nuxt.d.ts`
nuxt . hook ( 'prepare:types' , ( { references } ) = > {
2022-08-23 14:22:11 +00:00
references . push ( { path : resolve ( nuxt . options . buildDir , 'types/imports.d.ts' ) } )
2022-02-15 09:50:11 +00:00
references . push ( { path : resolve ( nuxt . options . buildDir , 'imports.d.ts' ) } )
2021-10-20 12:53:13 +00:00
} )
2021-10-20 09:47:18 +00:00
// Watch composables/ directory
nuxt . hook ( 'builder:watch' , async ( _ , path ) = > {
const _resolved = resolve ( nuxt . options . srcDir , path )
if ( composablesDirs . find ( dir = > _resolved . startsWith ( dir ) ) ) {
2022-02-08 19:09:24 +00:00
await nuxt . callHook ( 'builder:generateApp' )
2021-10-20 09:47:18 +00:00
}
2021-08-10 00:27:23 +00:00
} )
2022-03-07 10:39:54 +00:00
nuxt . hook ( 'builder:generateApp' , async ( ) = > {
2022-08-23 14:22:11 +00:00
await regenerateImports ( )
2022-03-07 10:39:54 +00:00
} )
2021-08-10 00:27:23 +00:00
}
} )
2022-08-24 08:44:38 +00:00
function addDeclarationTemplates ( ctx : Unimport , options : Partial < ImportsOptions > ) {
2021-10-20 09:47:18 +00:00
const nuxt = useNuxt ( )
2022-03-08 10:07:40 +00:00
// Remove file extension for benefit of TypeScript
const stripExtension = ( path : string ) = > path . replace ( /\.[a-z]+$/ , '' )
2022-08-12 17:47:58 +00:00
const resolved : Record < string , string > = { }
2022-03-11 08:09:11 +00:00
const r = ( { from } : Import ) = > {
if ( resolved [ from ] ) {
return resolved [ from ]
}
let path = resolveAlias ( from )
2021-10-20 09:47:18 +00:00
if ( isAbsolute ( path ) ) {
2022-02-07 10:20:01 +00:00
path = relative ( join ( nuxt . options . buildDir , 'types' ) , path )
2021-08-10 00:27:23 +00:00
}
2022-03-11 08:09:11 +00:00
2022-03-08 10:07:40 +00:00
path = stripExtension ( path )
2022-03-11 08:09:11 +00:00
resolved [ from ] = path
2021-10-20 09:47:18 +00:00
return path
2021-10-18 13:39:53 +00:00
}
2021-10-20 09:47:18 +00:00
2021-11-29 11:20:57 +00:00
addTemplate ( {
2022-02-15 09:50:11 +00:00
filename : 'imports.d.ts' ,
2022-07-22 07:30:29 +00:00
getContents : ( ) = > ctx . toExports ( nuxt . options . buildDir )
2021-11-29 11:20:57 +00:00
} )
2021-10-20 09:47:18 +00:00
addTemplate ( {
2022-08-23 14:22:11 +00:00
filename : 'types/imports.d.ts' ,
2022-08-24 08:44:38 +00:00
getContents : ( ) = > '// Generated by auto imports\n' + (
options . autoImport
? ctx . generateTypeDeclarations ( { resolvePath : r } )
: '// Implicit auto importing is disabled, you can use explicitly import from `#imports` instead.'
)
2021-10-20 09:47:18 +00:00
} )
2021-08-10 00:27:23 +00:00
}