Skip to content

Commit

Permalink
feat(module): support customizable config.configFile, use relative …
Browse files Browse the repository at this point in the history
…path to resolve, fix #495
  • Loading branch information
antfu committed Sep 4, 2024
1 parent 148537b commit a4ab4f5
Show file tree
Hide file tree
Showing 7 changed files with 1,587 additions and 1,036 deletions.
834 changes: 413 additions & 421 deletions docs/pnpm-lock.yaml

Large diffs are not rendered by default.

19 changes: 10 additions & 9 deletions packages/module/src/modules/config/addons/globals.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Nuxt } from '@nuxt/schema'
import type { Unimport } from 'unimport'
import type { Linter } from 'eslint'
import type { ESLintConfigGenAddon } from '../../../types'

export function createAddonGlobals(nuxt: Nuxt): ESLintConfigGenAddon {
Expand All @@ -21,17 +20,19 @@ export function createAddonGlobals(nuxt: Nuxt): ESLintConfigGenAddon {
const imports = [
...await unimport?.getImports() || [],
...await nitroUnimport?.getImports() || [],
]
].sort()

return {
configs: [
'// Set globals from imports registry',
JSON.stringify(<Linter.Config>{
name: 'nuxt/import-globals',
languageOptions: {
globals: Object.fromEntries(imports.map(i => [i.as || i.name, 'readonly'])),
},
}),
[
'// Set globals from imports registry',
'{',
` name: 'nuxt/import-globals',`,
' languageOptions: {',
` globals: Object.fromEntries(${JSON.stringify(imports.map(i => i.as || i.name))}.map(i => [i, 'readonly'])),`,
` },`,
'}',
].join('\n'),
],
}
},
Expand Down
54 changes: 43 additions & 11 deletions packages/module/src/modules/config/generate.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
import { builtinModules } from 'node:module'
import { dirname, join, resolve } from 'node:path'
import { stringifyImports } from 'unimport'
import type { Import } from 'unimport'
import type { Nuxt } from '@nuxt/schema'
import { relative } from 'pathe'
import type { NuxtESLintConfigOptions } from '@nuxt/eslint-config/flat'
import { createResolver } from '@nuxt/kit'
import type { ESLintConfigGenAddon } from '../../types'
import type { ConfigGenOptions, ModuleOptions } from '../../module'
import { getDirs } from './utils'

const r = createResolver(import.meta.url)

export async function generateESLintConfig(options: ModuleOptions, nuxt: Nuxt, addons: ESLintConfigGenAddon[]) {
export async function generateESLintConfig(
options: ModuleOptions,
nuxt: Nuxt,
addons: ESLintConfigGenAddon[],
) {
const importLines: Import[] = []
const configItems: string[] = []

const configDir = nuxt.options.buildDir

const config: ConfigGenOptions = {
standalone: true,
...typeof options.config !== 'boolean' ? options.config || {} : {},
}

let {
configFile = join(nuxt.options.buildDir, 'eslint.config.mjs'),
} = config

configFile = resolve(nuxt.options.rootDir, configFile)
const configDir = dirname(configFile)

importLines.push(
{
from: 'eslint-typegen',
Expand All @@ -40,12 +49,13 @@ export async function generateESLintConfig(options: ModuleOptions, nuxt: Nuxt, a
from: '@nuxt/eslint-config/flat',
name: 'resolveOptions',
},
{
from: 'url',
name: 'fileURLToPath',
},
)

const basicOptions: NuxtESLintConfigOptions = {
features: config,
dirs: getDirs(nuxt),
}
const dirs = getDirs(nuxt) || {}

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

return [
const code = [
'// ESLint config generated by Nuxt',
'/// <reference path="./eslint-typegen.d.ts" />',
'/* eslint-disable */',
'// @ts-nocheck',
'',
stringifyImports(imports, false),
'',
'const r = (...args) => fileURLToPath(new URL(...args, import.meta.url))',
'',
'export { defineFlatConfigs }',
'',
`export const options = resolveOptions(${JSON.stringify(basicOptions, null, 2)})`,
`export const options = resolveOptions({`,
` features: ${JSON.stringify(config, null, 2)},`,
` dirs: {`,
...Object
.entries(dirs)
.map(([key, value]) => {
return ` ${key}: [${value.map(v =>
key === 'root'
? `r(${JSON.stringify(relativeWithDot(v))})`
: JSON.stringify(v),
).join(', ')}],`
}),
`}`,
`})`,
'',
`export const configs = createConfigForNuxt(options)`,

Expand All @@ -95,9 +122,14 @@ export async function generateESLintConfig(options: ModuleOptions, nuxt: Nuxt, a
' return configs',
' .clone()',
' .append(...customs)',
' .onResolved(configs => typegen(configs, { dtsPath: new URL("./eslint-typegen.d.ts", import.meta.url), augmentFlatConfigUtils: true }))',
' .onResolved(configs => typegen(configs, { dtsPath: r("./eslint-typegen.d.ts"), augmentFlatConfigUtils: true }))',
'}',
'',
'export default withNuxt',
].join('\n')

return {
code,
configFile,
}
}
36 changes: 22 additions & 14 deletions packages/module/src/modules/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { dirname } from 'node:path'
import fs from 'node:fs/promises'
import { addTemplate } from '@nuxt/kit'
import type { Nuxt } from '@nuxt/schema'
import type { ESLintConfigGenAddon } from '../../types'
Expand Down Expand Up @@ -32,17 +34,18 @@ export async function setupConfigGen(options: ModuleOptions, nuxt: Nuxt) {
declarations.push('/// <reference path="./eslint-typegen.d.ts" />')
})

const template = addTemplate({
filename: 'eslint.config.mjs',
write: true,
async getContents() {
const addons: ESLintConfigGenAddon[] = [
...defaultAddons,
]
await nuxt.callHook('eslint:config:addons', addons)
return generateESLintConfig(options, nuxt, addons)
},
})
let _configFile: string = undefined!

async function writeConfigFile() {
const addons: ESLintConfigGenAddon[] = [
...defaultAddons,
]
await nuxt.callHook('eslint:config:addons', addons)
const { code, configFile } = await generateESLintConfig(options, nuxt, addons)
await fs.mkdir(dirname(configFile), { recursive: true })
await fs.writeFile(configFile, code, 'utf-8')
_configFile = configFile
}

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

setupDevToolsIntegration(nuxt)

await writeConfigFile()
nuxt.hook('builder:generateApp', () => {
writeConfigFile()
})

if (autoInit) {
await initRootESLintConfig(nuxt, template.dst)
await initRootESLintConfig(nuxt, _configFile)
}

setupDevToolsIntegration(nuxt)
}
7 changes: 7 additions & 0 deletions packages/module/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ declare module '@nuxt/schema' {
}

export interface ConfigGenOptions extends NuxtESLintFeaturesOptions {
/**
* File path to the generated ESLint config
*
* @default '.nuxt/eslint.config.mjs'
*/
configFile?: string

/**
* Create `eslint.config.mjs` file automatically if not exists
*
Expand Down
1 change: 1 addition & 0 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default defineNuxtConfig({

eslint: {
config: {
// configFile: './eslint.nuxt.config.mjs',
stylistic: true,
},
checker: {
Expand Down
Loading

0 comments on commit a4ab4f5

Please sign in to comment.