@@ -10,13 +10,13 @@ export interface InputConfig extends Record<string, any> {}
10
10
11
11
export interface ResolvedConfig < T extends InputConfig = InputConfig > {
12
12
config : T
13
- cwd : string
14
- configFile : string
15
- layers : ResolvedConfig < T > [ ]
13
+ cwd ? : string
14
+ configFile ? : string
15
+ layers ? : ResolvedConfig < T > [ ]
16
16
}
17
17
18
- export interface ExtendConfigOptions {
19
- extendKey ? : string
18
+ export interface ResolveConfigOptions {
19
+ cwd : string
20
20
}
21
21
22
22
export interface LoadConfigOptions < T extends InputConfig = InputConfig > {
@@ -33,7 +33,11 @@ export interface LoadConfigOptions<T extends InputConfig=InputConfig> {
33
33
defaults ?: T
34
34
overrides ?: T
35
35
36
- extend ?: false | ExtendConfigOptions
36
+ resolve ?: ( id : string , opts : LoadConfigOptions ) => null | ResolvedConfig | Promise < ResolvedConfig | null >
37
+
38
+ extend ?: false | {
39
+ extendKey ?: string
40
+ }
37
41
}
38
42
39
43
export async function loadConfig < T extends InputConfig = InputConfig > ( opts : LoadConfigOptions < T > ) : Promise < ResolvedConfig < T > > {
@@ -66,7 +70,7 @@ export async function loadConfig<T extends InputConfig=InputConfig> (opts: LoadC
66
70
}
67
71
68
72
// Load config file
69
- const { config, configFile } = await loadConfigFile ( opts . cwd , opts . configFile )
73
+ const { config, configFile } = await resolveConfig ( '.' , opts )
70
74
if ( configFile ) {
71
75
r . configFile = configFile
72
76
}
@@ -90,7 +94,7 @@ export async function loadConfig<T extends InputConfig=InputConfig> (opts: LoadC
90
94
91
95
// Allow extending
92
96
if ( opts . extend ) {
93
- await extendConfig ( r . config , opts . configFile ! , opts . cwd , opts . extend )
97
+ await extendConfig ( r . config , opts )
94
98
r . layers = r . config . _layers
95
99
delete r . config . _layers
96
100
r . config = defu (
@@ -103,57 +107,56 @@ export async function loadConfig<T extends InputConfig=InputConfig> (opts: LoadC
103
107
return r
104
108
}
105
109
106
- const GIT_PREFIXES = [ 'github:' , 'gitlab:' , 'bitbucket:' , 'https://' ]
107
-
108
- async function extendConfig ( config , configFile : string , cwd : string , opts : ExtendConfigOptions ) {
110
+ async function extendConfig ( config , opts : LoadConfigOptions ) {
109
111
config . _layers = config . _layers || [ ]
110
-
111
- const extendSources = ( Array . isArray ( config [ opts . extendKey ] ) ? config [ opts . extendKey ] : [ config [ opts . extendKey ] ] ) . filter ( Boolean )
112
- delete config [ opts . extendKey ]
113
- for ( let extendSource of extendSources ) {
114
- if ( GIT_PREFIXES . some ( prefix => extendSource . startsWith ( prefix ) ) ) {
115
- const url = new URL ( extendSource )
116
- const subPath = url . pathname . split ( '/' ) . slice ( 2 ) . join ( '/' )
117
- const gitRepo = url . protocol + url . pathname . split ( '/' ) . slice ( 0 , 2 ) . join ( '/' )
118
- const tmpdir = resolve ( os . tmpdir ( ) , 'c12/' , gitRepo . replace ( / [ # : @ / \\ ] / g, '_' ) )
119
- await fsp . rm ( tmpdir , { recursive : true } ) . catch ( ( ) => { } )
120
- const gittar = await import ( 'gittar' ) . then ( r => r . default || r )
121
- const tarFile = await gittar . fetch ( gitRepo )
122
- await gittar . extract ( tarFile , tmpdir )
123
- extendSource = resolve ( tmpdir , subPath )
112
+ if ( ! opts . extend ) {
113
+ return
114
+ }
115
+ const key = opts . extend . extendKey
116
+ const extendSources = ( Array . isArray ( config [ key ] ) ? config [ key ] : [ config [ key ] ] ) . filter ( Boolean )
117
+ delete config [ key ]
118
+ for ( const extendSource of extendSources ) {
119
+ const _config = await resolveConfig ( extendSource , opts )
120
+ if ( ! _config . config ) {
121
+ continue
124
122
}
125
-
126
- const isDir = ! extname ( extendSource )
127
- const _cwd = resolve ( cwd , isDir ? extendSource : dirname ( extendSource ) )
128
- const _config = await loadConfigFile ( _cwd , isDir ? configFile : extendSource )
129
- if ( ! _config . config ) { continue }
130
- await extendConfig ( _config . config , configFile , _cwd , opts )
131
- config . _layers . push ( {
132
- config : _config . config ,
133
- cwd : _cwd ,
134
- configFile : _config . configFile
135
- } )
123
+ await extendConfig ( _config . config , { ...opts , cwd : _config . cwd } )
124
+ config . _layers . push ( _config )
136
125
if ( _config . config . _layers ) {
137
126
config . _layers . push ( ..._config . config . _layers )
138
127
delete _config . config . _layers
139
128
}
140
129
}
141
130
}
142
131
132
+ const GIT_PREFIXES = [ 'github:' , 'gitlab:' , 'bitbucket:' , 'https://' ]
133
+
143
134
const jiti = createJiti ( null , { cache : false , interopDefault : true } )
144
135
145
- async function loadConfigFile ( cwd : string , configFile : string | false ) {
146
- const res = {
147
- configFile : null ,
148
- config : null
136
+ async function resolveConfig ( source : string , opts : LoadConfigOptions ) : Promise < ResolvedConfig > {
137
+ if ( opts . resolve ) {
138
+ const res = await opts . resolve ( source , opts )
139
+ if ( res ) {
140
+ return res
141
+ }
149
142
}
150
-
151
- if ( ! configFile ) {
152
- return res
143
+ if ( GIT_PREFIXES . some ( prefix => source . startsWith ( prefix ) ) ) {
144
+ const url = new URL ( source )
145
+ const subPath = url . pathname . split ( '/' ) . slice ( 2 ) . join ( '/' )
146
+ const gitRepo = url . protocol + url . pathname . split ( '/' ) . slice ( 0 , 2 ) . join ( '/' )
147
+ const tmpdir = resolve ( os . tmpdir ( ) , 'c12/' , gitRepo . replace ( / [ # : @ / \\ ] / g, '_' ) )
148
+ await fsp . rm ( tmpdir , { recursive : true } ) . catch ( ( ) => { } )
149
+ const gittar = await import ( 'gittar' ) . then ( r => r . default || r )
150
+ const tarFile = await gittar . fetch ( gitRepo )
151
+ await gittar . extract ( tarFile , tmpdir )
152
+ source = resolve ( tmpdir , subPath )
153
153
}
154
-
154
+ const isDir = ! extname ( source )
155
+ const cwd = resolve ( opts . cwd , isDir ? source : dirname ( source ) )
156
+ if ( isDir ) { source = opts . configFile }
157
+ const res : ResolvedConfig = { config : { } , cwd }
155
158
try {
156
- res . configFile = jiti . resolve ( resolve ( cwd , configFile ) , { paths : [ cwd ] } )
159
+ res . configFile = jiti . resolve ( resolve ( cwd , source ) , { paths : [ cwd ] } )
157
160
res . config = jiti ( res . configFile )
158
161
if ( typeof res . config === 'function' ) {
159
162
res . config = await res . config ( )
@@ -163,6 +166,5 @@ async function loadConfigFile (cwd: string, configFile: string | false) {
163
166
throw err
164
167
}
165
168
}
166
-
167
169
return res
168
170
}
0 commit comments