1
- import { dirname } from 'path'
1
+ import { resolve , dirname } from 'path'
2
+ import { existsSync , realpathSync } from 'fs'
2
3
import Hookable , { configHooksT } from 'hookable'
3
4
import defu from 'defu'
4
5
import jiti from 'jiti'
5
6
import type { NuxtConfig } from '@nuxt/types'
6
7
7
8
declare module '@nuxt/types' {
8
9
interface NuxtConfig {
9
- _level ?: number
10
10
hooks ?: configHooksT
11
11
name ?: string
12
12
extends ?: string
13
13
alias ?: { [ key : string ] : string }
14
14
}
15
15
}
16
16
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 )
23
19
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
+ }
28
27
28
+ function resolveConfig ( config : NuxtConfig , level ) {
29
29
if ( typeof config === 'function' ) {
30
30
throw new TypeError ( 'extending is not possible with nuxt config as a function' )
31
31
}
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
34
38
}
35
39
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
+ }
37
51
38
52
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 )
41
55
}
42
56
43
- // delete tempory _file for error DX
44
- delete config . _file
45
-
46
57
return config
47
58
}
48
59
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 ) )
60
63
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 )
65
68
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
+ }
72
71
72
+ function mergeConfig ( target : NuxtConfig , base : NuxtConfig , level ) : NuxtConfig {
73
73
// Custom merges
74
74
const override : NuxtConfig = { }
75
75
76
76
// Merge hooks
77
77
override . hooks = Hookable . mergeHooks ( base . hooks || { } , target . hooks || { } )
78
78
79
- // Merge components prop
79
+ // Merge components
80
80
if ( base . components || target . components ) {
81
81
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 )
84
84
]
85
85
}
86
86
87
- // Merge with defu
87
+ // Mege with defu
88
88
return { ...defu . arrayFn ( target , base ) , ...override }
89
89
}
90
90
91
- function normalizeComponents ( components : NuxtConfig [ 'components' ] , defaults = { } ) {
91
+ function normalizeComponents ( components : NuxtConfig [ 'components' ] , isBase ?: boolean ) {
92
92
if ( typeof components === 'boolean' || ! components ) {
93
93
components = [ ]
94
94
}
@@ -99,9 +99,12 @@ function normalizeComponents (components: NuxtConfig['components'], defaults = {
99
99
}
100
100
101
101
components = components . map ( dir => ( {
102
- ...defaults ,
103
102
...( typeof dir === 'string' ? { path : dir } : dir )
104
103
} ) )
105
104
105
+ for ( const component of components ) {
106
+ component . level = ( component . level || 0 ) + ( isBase ? 1 : 0 )
107
+ }
108
+
106
109
return components
107
110
}
0 commit comments