Skip to content

Commit a4ab4f5

Browse files
committedSep 4, 2024··
feat(module): support customizable config.configFile, use relative path to resolve, fix #495
1 parent 148537b commit a4ab4f5

File tree

7 files changed

+1587
-1036
lines changed

7 files changed

+1587
-1036
lines changed
 

‎docs/pnpm-lock.yaml

+413-421
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎packages/module/src/modules/config/addons/globals.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { Nuxt } from '@nuxt/schema'
22
import type { Unimport } from 'unimport'
3-
import type { Linter } from 'eslint'
43
import type { ESLintConfigGenAddon } from '../../../types'
54

65
export function createAddonGlobals(nuxt: Nuxt): ESLintConfigGenAddon {
@@ -21,17 +20,19 @@ export function createAddonGlobals(nuxt: Nuxt): ESLintConfigGenAddon {
2120
const imports = [
2221
...await unimport?.getImports() || [],
2322
...await nitroUnimport?.getImports() || [],
24-
]
23+
].sort()
2524

2625
return {
2726
configs: [
28-
'// Set globals from imports registry',
29-
JSON.stringify(<Linter.Config>{
30-
name: 'nuxt/import-globals',
31-
languageOptions: {
32-
globals: Object.fromEntries(imports.map(i => [i.as || i.name, 'readonly'])),
33-
},
34-
}),
27+
[
28+
'// Set globals from imports registry',
29+
'{',
30+
` name: 'nuxt/import-globals',`,
31+
' languageOptions: {',
32+
` globals: Object.fromEntries(${JSON.stringify(imports.map(i => i.as || i.name))}.map(i => [i, 'readonly'])),`,
33+
` },`,
34+
'}',
35+
].join('\n'),
3536
],
3637
}
3738
},

‎packages/module/src/modules/config/generate.ts

+43-11
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,36 @@
11
import { builtinModules } from 'node:module'
2+
import { dirname, join, resolve } from 'node:path'
23
import { stringifyImports } from 'unimport'
34
import type { Import } from 'unimport'
45
import type { Nuxt } from '@nuxt/schema'
56
import { relative } from 'pathe'
6-
import type { NuxtESLintConfigOptions } from '@nuxt/eslint-config/flat'
77
import { createResolver } from '@nuxt/kit'
88
import type { ESLintConfigGenAddon } from '../../types'
99
import type { ConfigGenOptions, ModuleOptions } from '../../module'
1010
import { getDirs } from './utils'
1111

1212
const r = createResolver(import.meta.url)
1313

14-
export async function generateESLintConfig(options: ModuleOptions, nuxt: Nuxt, addons: ESLintConfigGenAddon[]) {
14+
export async function generateESLintConfig(
15+
options: ModuleOptions,
16+
nuxt: Nuxt,
17+
addons: ESLintConfigGenAddon[],
18+
) {
1519
const importLines: Import[] = []
1620
const configItems: string[] = []
1721

18-
const configDir = nuxt.options.buildDir
19-
2022
const config: ConfigGenOptions = {
2123
standalone: true,
2224
...typeof options.config !== 'boolean' ? options.config || {} : {},
2325
}
2426

27+
let {
28+
configFile = join(nuxt.options.buildDir, 'eslint.config.mjs'),
29+
} = config
30+
31+
configFile = resolve(nuxt.options.rootDir, configFile)
32+
const configDir = dirname(configFile)
33+
2534
importLines.push(
2635
{
2736
from: 'eslint-typegen',
@@ -40,12 +49,13 @@ export async function generateESLintConfig(options: ModuleOptions, nuxt: Nuxt, a
4049
from: '@nuxt/eslint-config/flat',
4150
name: 'resolveOptions',
4251
},
52+
{
53+
from: 'url',
54+
name: 'fileURLToPath',
55+
},
4356
)
4457

45-
const basicOptions: NuxtESLintConfigOptions = {
46-
features: config,
47-
dirs: getDirs(nuxt),
48-
}
58+
const dirs = getDirs(nuxt) || {}
4959

5060
for (const addon of addons) {
5161
const resolved = await addon.getConfigs()
@@ -69,15 +79,32 @@ export async function generateESLintConfig(options: ModuleOptions, nuxt: Nuxt, a
6979
}
7080
}))
7181

72-
return [
82+
const code = [
7383
'// ESLint config generated by Nuxt',
7484
'/// <reference path="./eslint-typegen.d.ts" />',
85+
'/* eslint-disable */',
86+
'// @ts-nocheck',
7587
'',
7688
stringifyImports(imports, false),
7789
'',
90+
'const r = (...args) => fileURLToPath(new URL(...args, import.meta.url))',
91+
'',
7892
'export { defineFlatConfigs }',
7993
'',
80-
`export const options = resolveOptions(${JSON.stringify(basicOptions, null, 2)})`,
94+
`export const options = resolveOptions({`,
95+
` features: ${JSON.stringify(config, null, 2)},`,
96+
` dirs: {`,
97+
...Object
98+
.entries(dirs)
99+
.map(([key, value]) => {
100+
return ` ${key}: [${value.map(v =>
101+
key === 'root'
102+
? `r(${JSON.stringify(relativeWithDot(v))})`
103+
: JSON.stringify(v),
104+
).join(', ')}],`
105+
}),
106+
`}`,
107+
`})`,
81108
'',
82109
`export const configs = createConfigForNuxt(options)`,
83110

@@ -95,9 +122,14 @@ export async function generateESLintConfig(options: ModuleOptions, nuxt: Nuxt, a
95122
' return configs',
96123
' .clone()',
97124
' .append(...customs)',
98-
' .onResolved(configs => typegen(configs, { dtsPath: new URL("./eslint-typegen.d.ts", import.meta.url), augmentFlatConfigUtils: true }))',
125+
' .onResolved(configs => typegen(configs, { dtsPath: r("./eslint-typegen.d.ts"), augmentFlatConfigUtils: true }))',
99126
'}',
100127
'',
101128
'export default withNuxt',
102129
].join('\n')
130+
131+
return {
132+
code,
133+
configFile,
134+
}
103135
}

‎packages/module/src/modules/config/index.ts

+22-14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { dirname } from 'node:path'
2+
import fs from 'node:fs/promises'
13
import { addTemplate } from '@nuxt/kit'
24
import type { Nuxt } from '@nuxt/schema'
35
import type { ESLintConfigGenAddon } from '../../types'
@@ -32,17 +34,18 @@ export async function setupConfigGen(options: ModuleOptions, nuxt: Nuxt) {
3234
declarations.push('/// <reference path="./eslint-typegen.d.ts" />')
3335
})
3436

35-
const template = addTemplate({
36-
filename: 'eslint.config.mjs',
37-
write: true,
38-
async getContents() {
39-
const addons: ESLintConfigGenAddon[] = [
40-
...defaultAddons,
41-
]
42-
await nuxt.callHook('eslint:config:addons', addons)
43-
return generateESLintConfig(options, nuxt, addons)
44-
},
45-
})
37+
let _configFile: string = undefined!
38+
39+
async function writeConfigFile() {
40+
const addons: ESLintConfigGenAddon[] = [
41+
...defaultAddons,
42+
]
43+
await nuxt.callHook('eslint:config:addons', addons)
44+
const { code, configFile } = await generateESLintConfig(options, nuxt, addons)
45+
await fs.mkdir(dirname(configFile), { recursive: true })
46+
await fs.writeFile(configFile, code, 'utf-8')
47+
_configFile = configFile
48+
}
4649

4750
addTemplate({
4851
filename: 'eslint.config.d.mts',
@@ -52,9 +55,14 @@ export async function setupConfigGen(options: ModuleOptions, nuxt: Nuxt) {
5255
},
5356
})
5457

58+
setupDevToolsIntegration(nuxt)
59+
60+
await writeConfigFile()
61+
nuxt.hook('builder:generateApp', () => {
62+
writeConfigFile()
63+
})
64+
5565
if (autoInit) {
56-
await initRootESLintConfig(nuxt, template.dst)
66+
await initRootESLintConfig(nuxt, _configFile)
5767
}
58-
59-
setupDevToolsIntegration(nuxt)
6068
}

‎packages/module/src/types.ts

+7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ declare module '@nuxt/schema' {
1313
}
1414

1515
export interface ConfigGenOptions extends NuxtESLintFeaturesOptions {
16+
/**
17+
* File path to the generated ESLint config
18+
*
19+
* @default '.nuxt/eslint.config.mjs'
20+
*/
21+
configFile?: string
22+
1623
/**
1724
* Create `eslint.config.mjs` file automatically if not exists
1825
*

‎playground/nuxt.config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default defineNuxtConfig({
1414

1515
eslint: {
1616
config: {
17+
// configFile: './eslint.nuxt.config.mjs',
1718
stylistic: true,
1819
},
1920
checker: {

‎pnpm-lock.yaml

+1,091-581
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.