Skip to content

Commit ede481b

Browse files
committed
feat: improve merge logic
1 parent 3b8a945 commit ede481b

File tree

2 files changed

+53
-59
lines changed

2 files changed

+53
-59
lines changed

src/index.ts

Lines changed: 50 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,94 @@
1-
import { dirname } from 'path'
1+
import { resolve, dirname } from 'path'
2+
import { existsSync, realpathSync } from 'fs'
23
import Hookable, { configHooksT } from 'hookable'
34
import defu from 'defu'
45
import jiti from 'jiti'
56
import type { NuxtConfig } from '@nuxt/types'
67

78
declare module '@nuxt/types' {
89
interface NuxtConfig {
9-
_level?: number
1010
hooks?: configHooksT
1111
name?: string
1212
extends?: string
1313
alias?: { [key: string]: string }
1414
}
1515
}
1616

17-
export function resolveConfig (config: string | NuxtConfig, from: string = process.cwd(), level = 0): NuxtConfig {
18-
if (typeof config === 'string') {
19-
const _require = jiti(from)
20-
const nuxtConfigFile = _require.resolve(config)
21-
config = _require(nuxtConfigFile) as NuxtConfig
22-
config._file = nuxtConfigFile
17+
export function nuxtConfig (config: NuxtConfig): NuxtConfig {
18+
config = resolveConfig(config, 0)
2319

24-
if (!config.rootDir) {
25-
config.rootDir = dirname(nuxtConfigFile)
26-
}
27-
}
20+
delete config._file
21+
delete config._dir
22+
delete config.name
23+
delete config.extends
24+
25+
return config
26+
}
2827

28+
function resolveConfig (config: NuxtConfig, level) {
2929
if (typeof config === 'function') {
3030
throw new TypeError('extending is not possible with nuxt config as a function')
3131
}
32-
if (!config.rootDir) {
33-
config.rootDir = from
32+
33+
const dir = config.srcDir || config.rootDir || config._dir
34+
35+
if (dir && config.name) {
36+
config.alias = config.alias || {}
37+
config.alias[config.name] = dir
3438
}
3539

36-
config._level = level
40+
if (dir && config.components === undefined) {
41+
config.components = []
42+
const componentsDir = resolve(dir, 'components')
43+
if (existsSync(componentsDir)) {
44+
config.components.push({ path: componentsDir })
45+
}
46+
const globalComponentsDir = resolve(dir, 'components/global')
47+
if (existsSync(globalComponentsDir)) {
48+
config.components.push({ path: globalComponentsDir, global: true })
49+
}
50+
}
3751

3852
if (config.extends) {
39-
const _resolvedExtends = resolveConfig(config.extends, config.rootDir, level + 1)
40-
config = extendConfig(config, _resolvedExtends)
53+
const base = loadConfig(config.extends, dir)
54+
return mergeConfig(config, resolveConfig(base, level + 1), level)
4155
}
4256

43-
// delete tempory _file for error DX
44-
delete config._file
45-
4657
return config
4758
}
4859

49-
export function extendConfig (target: NuxtConfig, base: NuxtConfig): NuxtConfig {
50-
// Ensure base has required fields
51-
if (!base.name) {
52-
throw new Error('Config is missing the `name` property' + (base._file ? `in ${base._file}` : ''))
53-
}
54-
if (!base.rootDir) {
55-
throw new Error('Config is missing the `rootDir` property')
56-
}
57-
if (!base.srcDir) {
58-
base.srcDir = base.rootDir
59-
}
60+
function loadConfig (configFile: string, from: string): NuxtConfig {
61+
const _require = jiti(from)
62+
configFile = realpathSync(_require.resolve(configFile))
6063

61-
// Ensure there is no name conflict
62-
if (target.alias && target.alias['~' + base.name]) {
63-
throw new Error('Name conflict: ' + base.name)
64-
}
64+
let config = _require(configFile)
65+
config = (config.default || config) as NuxtConfig
66+
config._file = configFile
67+
config._dir = dirname(configFile)
6568

66-
// Assign aliases for base
67-
base.alias = base.alias || {}
68-
base.alias['~' + base.name] = base.srcDir
69-
base.alias['~~' + base.name] = base.rootDir
70-
base.alias['@' + base.name] = base.srcDir
71-
base.alias['@@' + base.name] = base.rootDir
69+
return config
70+
}
7271

72+
function mergeConfig (target: NuxtConfig, base: NuxtConfig, level): NuxtConfig {
7373
// Custom merges
7474
const override: NuxtConfig = {}
7575

7676
// Merge hooks
7777
override.hooks = Hookable.mergeHooks(base.hooks || {}, target.hooks || {})
7878

79-
// Merge components prop
79+
// Merge components
8080
if (base.components || target.components) {
8181
override.components = [
82-
...normalizeComponents(target.components, { level: target._level }),
83-
...normalizeComponents(base.components, { level: base._level })
82+
...normalizeComponents(target.components),
83+
...normalizeComponents(base.components, true)
8484
]
8585
}
8686

87-
// Merge with defu
87+
// Mege with defu
8888
return { ...defu.arrayFn(target, base), ...override }
8989
}
9090

91-
function normalizeComponents (components: NuxtConfig['components'], defaults = {}) {
91+
function normalizeComponents (components: NuxtConfig['components'], isBase?: boolean) {
9292
if (typeof components === 'boolean' || !components) {
9393
components = []
9494
}
@@ -99,9 +99,12 @@ function normalizeComponents (components: NuxtConfig['components'], defaults = {
9999
}
100100

101101
components = components.map(dir => ({
102-
...defaults,
103102
...(typeof dir === 'string' ? { path: dir } : dir)
104103
}))
105104

105+
for (const component of components) {
106+
component.level = (component.level || 0) + (isBase ? 1 : 0)
107+
}
108+
106109
return components
107110
}

test/__snapshots__/index.test.ts.snap

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,10 @@
22

33
exports[`matches snapshot 1`] = `
44
Object {
5-
"_level": 0,
65
"alias": Object {
7-
"@@baseTheme": "{test}/fixture/themes/base",
8-
"@@baseThemeEx": "{test}/fixture/themes/red",
9-
"@baseTheme": "{test}/fixture/themes/base",
10-
"@baseThemeEx": "{test}/fixture/themes/base",
11-
"~baseTheme": "{test}/fixture/themes/base",
12-
"~baseThemeEx": "{test}/fixture/themes/base",
13-
"~~baseTheme": "{test}/fixture/themes/base",
14-
"~~baseThemeEx": "{test}/fixture/themes/red",
6+
"BaseTheme": "{test}/fixture/themes/base",
7+
"MyApp": "{test}/fixture/app",
8+
"RedTheme": "{test}/fixture/themes/red",
159
},
1610
"components": Array [
1711
Object {
@@ -23,14 +17,11 @@ Object {
2317
"path": "{test}/fixture/themes/red/components",
2418
},
2519
Object {
26-
"global": true,
2720
"level": 2,
2821
"path": "{test}/fixture/themes/base/components",
2922
},
3023
],
31-
"extends": "../themes/red/nuxt.config",
3224
"hooks": Object {},
33-
"name": "myApp",
3425
"publicRuntimeConfig": Object {
3526
"color": "red",
3627
},

0 commit comments

Comments
 (0)