Skip to content

Commit

Permalink
feat: basic extends support (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Jan 31, 2022
1 parent 5a63f9a commit ef199fc
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 6 deletions.
40 changes: 35 additions & 5 deletions src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface LoadConfigOptions<T extends ConfigT=ConfigT> {
name?: string
cwd?: string

configFile?: false | string
configFile?: string

rcFile?: false | string
globalRc?: boolean
Expand Down Expand Up @@ -50,7 +50,7 @@ export async function loadConfig<T extends ConfigT=ConfigT> (opts: LoadConfigOpt
}

// Load config file
const { config, configPath } = await loadConfigFile(opts)
const { config, configPath } = await loadConfigFile(opts.cwd, opts.configFile)
ctx.configPath = configPath

// Load rc files
Expand All @@ -70,24 +70,54 @@ export async function loadConfig<T extends ConfigT=ConfigT> (opts: LoadConfigOpt
opts.defaults
) as T

// Allow extending
await extendConfig(ctx.config, opts.configFile!, opts.cwd)
ctx.config = defu(
ctx.config,
...ctx.config._extends.map(e => e.config)
) as T

// Return resolved context
return ctx
}

async function extendConfig (config, configFile: string, cwd: string) {
console.log('Extending from', cwd)
config._extends = config._extends || []

const extendSources = (Array.isArray(config.extends) ? config.extends : [config.extends]).filter(Boolean)
for (const extendSource of extendSources) {
// TODO: Assuming extendSource is dir
const _cwd = resolve(cwd, extendSource)
const _config = await loadConfigFile(_cwd, configFile)
await extendConfig(_config.config, configFile, _cwd)
delete _config.config._extends
config._extends.push({
config: _config.config,
meta: {
cwd: _cwd,
configPath: _config.configPath
}
})
}

return config
}

const jiti = createJiti(null, { cache: false, interopDefault: true })

async function loadConfigFile (opts: LoadConfigOptions) {
async function loadConfigFile (cwd: string, configFile: string | false) {
const res = {
configPath: null,
config: null
}

if (!opts.configFile) {
if (!configFile) {
return res
}

try {
res.configPath = jiti.resolve(resolve(opts.cwd, opts.configFile), { paths: [opts.cwd] })
res.configPath = jiti.resolve(resolve(cwd, configFile), { paths: [cwd] })
res.config = jiti(res.configPath)
if (typeof res.config === 'function') {
res.config = await res.config()
Expand Down
3 changes: 3 additions & 0 deletions test/fixture/base/foo.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
baseConfig: true
}
1 change: 1 addition & 0 deletions test/fixture/foo.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default {
extends: './base',
configFile: true,
overriden: false
}
15 changes: 14 additions & 1 deletion test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { fileURLToPath } from 'url'
import { resolve } from 'pathe'
import { expect, it, describe } from 'vitest'
import { loadConfig } from '../src'

describe('c12', () => {
it('load fixture config', async () => {
const fixtureDir = fileURLToPath(new URL('./fixture', import.meta.url))
const rFixture = (...segments: string[]) => resolve(fixtureDir, ...segments)

const { config } = await loadConfig({
cwd: fixtureDir,
dotenv: true,
Expand All @@ -21,7 +24,17 @@ describe('c12', () => {
configFile: true,
rcFile: true,
defaultConfig: true,
overriden: true
overriden: true,
baseConfig: true,
_extends: [
{
config: { baseConfig: true },
meta: {
configPath: rFixture('base/foo.config.ts'),
cwd: rFixture('base')
}
}
]
})
})
})

0 comments on commit ef199fc

Please sign in to comment.