This repository has been archived by the owner on Apr 6, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
module.ts
142 lines (127 loc) · 4.6 KB
/
module.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { addVitePlugin, addWebpackPlugin, defineNuxtModule, addTemplate, resolveAlias, addPluginTemplate, useNuxt } from '@nuxt/kit'
import type { AutoImportsOptions } from '@nuxt/schema'
import { isAbsolute, join, relative, resolve, normalize } from 'pathe'
import { genDynamicImport } from 'knitwork'
import { TransformPlugin } from './transform'
import { Nuxt3AutoImports } from './imports'
import { scanForComposables } from './composables'
import { toExports, toImports } from './utils'
import { AutoImportContext, createAutoImportContext, updateAutoImportContext } from './context'
export default defineNuxtModule<AutoImportsOptions>({
meta: {
name: 'auto-imports',
configKey: 'autoImports'
},
defaults: {
sources: Nuxt3AutoImports,
global: false,
dirs: [],
transform: {
exclude: undefined
}
},
async setup (options, nuxt) {
// Allow modules extending sources
await nuxt.callHook('autoImports:sources', options.sources)
// Filter disabled sources
options.sources = options.sources.filter(source => source.disabled !== true)
// Create a context to share state between module internals
const ctx = createAutoImportContext(options)
// Resolve autoimports from sources
for (const source of options.sources) {
for (const importName of source.names) {
if (typeof importName === 'string') {
ctx.autoImports.push({ name: importName, as: importName, from: source.from })
} else {
ctx.autoImports.push({ name: importName.name, as: importName.as || importName.name, from: source.from })
}
}
}
// composables/ dirs
let composablesDirs = [
join(nuxt.options.srcDir, 'composables'),
...options.dirs
]
await nuxt.callHook('autoImports:dirs', composablesDirs)
composablesDirs = composablesDirs.map(dir => normalize(dir))
// Support for importing from '#imports'
addTemplate({
filename: 'imports.mjs',
getContents: () => toExports(ctx.autoImports)
})
nuxt.options.alias['#imports'] = join(nuxt.options.buildDir, 'imports')
// Transpile and injection
// @ts-ignore temporary disabled due to #746
if (nuxt.options.dev && options.global) {
// Add all imports to globalThis in development mode
addPluginTemplate({
filename: 'auto-imports.mjs',
src: '',
getContents: () => {
const imports = toImports(ctx.autoImports)
const globalThisSet = ctx.autoImports.map(i => `globalThis.${i.as} = ${i.as};`).join('\n')
return `${imports}\n\n${globalThisSet}\n\nexport default () => {};`
}
})
} else {
// Transform to inject imports in production mode
addVitePlugin(TransformPlugin.vite(ctx))
addWebpackPlugin(TransformPlugin.webpack(ctx))
}
const updateAutoImports = async () => {
// Scan composables/
for (const composablesDir of composablesDirs) {
await scanForComposables(composablesDir, ctx.autoImports)
}
// Allow modules extending
await nuxt.callHook('autoImports:extend', ctx.autoImports)
// Update context
updateAutoImportContext(ctx)
// Generate types
generateDts(ctx)
}
await updateAutoImports()
// Add generated types to `nuxt.d.ts`
nuxt.hook('prepare:types', ({ references }) => {
references.push({ path: resolve(nuxt.options.buildDir, 'types/auto-imports.d.ts') })
references.push({ path: resolve(nuxt.options.buildDir, 'types/imports.d.ts') })
})
// Watch composables/ directory
nuxt.hook('builder:watch', async (_, path) => {
const _resolved = resolve(nuxt.options.srcDir, path)
if (composablesDirs.find(dir => _resolved.startsWith(dir))) {
await updateAutoImports()
}
})
}
})
function generateDts (ctx: AutoImportContext) {
const nuxt = useNuxt()
const resolved = {}
const r = (id: string) => {
if (resolved[id]) { return resolved[id] }
let path = resolveAlias(id, nuxt.options.alias)
if (isAbsolute(path)) {
path = relative(join(nuxt.options.buildDir, 'types'), path)
}
// Remove file extension for benefit of TypeScript
path = path.replace(/\.[a-z]+$/, '')
resolved[id] = path
return path
}
addTemplate({
filename: 'types/imports.d.ts',
write: true,
getContents: () => toExports(ctx.autoImports)
})
addTemplate({
filename: 'types/auto-imports.d.ts',
write: true,
getContents: () => `// Generated by auto imports
declare global {
${ctx.autoImports.map(i => ` const ${i.as}: typeof ${genDynamicImport(r(i.from), { wrapper: false })}['${i.name}']`).join('\n')}
}
export {}
`
})
}