factor out loadAndMergeConfig()
It's useful for non-device kind of configs too.
This commit is contained in:
parent
7eceea9041
commit
c4e850b86b
2 changed files with 59 additions and 49 deletions
53
src/config/config-loader.ts
Normal file
53
src/config/config-loader.ts
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import _ from 'lodash'
|
||||||
|
import path from 'path'
|
||||||
|
import YAML from 'yaml'
|
||||||
|
|
||||||
|
import { readFile } from '../util/fs'
|
||||||
|
import { parseFilters, SerializedFilters } from './filters'
|
||||||
|
|
||||||
|
function mergeConfigs(base: any, overlay: any) {
|
||||||
|
return _.mergeWith(base, overlay, (a, b) => {
|
||||||
|
if (_.isArray(a)) {
|
||||||
|
return a.concat(b)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadOverlaysRecursive(overlays: any[], rootDir: string, root: any) {
|
||||||
|
if (_.isArray(root.includes)) {
|
||||||
|
for (let relPath of root.includes) {
|
||||||
|
let overlayPath = path.resolve(rootDir, relPath)
|
||||||
|
let overlayDir = path.dirname(overlayPath)
|
||||||
|
|
||||||
|
let overlay = YAML.parse(await readFile(overlayPath))
|
||||||
|
await loadOverlaysRecursive(overlays, overlayDir, overlay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
overlays.push(root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// No dedicated parse function as this requires loading includes and overlaying
|
||||||
|
// them in the correct order
|
||||||
|
export async function loadAndMergeConfig(configPath: string, baseConfig: Readonly<object>) {
|
||||||
|
let base = structuredClone(baseConfig) // deep copy to avoid mutating base
|
||||||
|
|
||||||
|
let rootOverlay = YAML.parse(await readFile(configPath))
|
||||||
|
let rootPath = path.dirname(configPath)
|
||||||
|
let overlays: any[] = []
|
||||||
|
await loadOverlaysRecursive(overlays, rootPath, rootOverlay)
|
||||||
|
|
||||||
|
// Merge from base to final root
|
||||||
|
let merged = overlays.reduce((base, overlay) => mergeConfigs(base, overlay), base)
|
||||||
|
|
||||||
|
if (merged.filters !== undefined) {
|
||||||
|
// Parse filters
|
||||||
|
merged.filters = Object.fromEntries(
|
||||||
|
Object.entries(merged.filters).map(([group, filters]) => [group, parseFilters(filters as SerializedFilters)]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, cast it to the parsed config type
|
||||||
|
delete merged.includes
|
||||||
|
return merged
|
||||||
|
}
|
|
@ -2,12 +2,10 @@
|
||||||
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
||||||
///<reference path="../util/jstypes.d.ts" />
|
///<reference path="../util/jstypes.d.ts" />
|
||||||
|
|
||||||
import _ from 'lodash'
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import YAML from 'yaml'
|
|
||||||
|
|
||||||
import { readFile } from '../util/fs'
|
import { loadAndMergeConfig } from './config-loader'
|
||||||
import { FilterMode, Filters, parseFilters, SerializedFilters } from './filters'
|
import { FilterMode, Filters, SerializedFilters } from './filters'
|
||||||
|
|
||||||
export enum ConfigType {
|
export enum ConfigType {
|
||||||
Device = 'device',
|
Device = 'device',
|
||||||
|
@ -114,53 +112,12 @@ const DEFAULT_CONFIG_BASE = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeConfigs(base: any, overlay: any) {
|
async function loadAndMergeDeviceConfig(configPath: string) {
|
||||||
return _.mergeWith(base, overlay, (a, b) => {
|
return await loadAndMergeConfig(configPath, DEFAULT_CONFIG_BASE)
|
||||||
if (_.isArray(a)) {
|
|
||||||
return a.concat(b)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadOverlaysRecursive(overlays: any[], rootDir: string, root: any) {
|
|
||||||
if (_.isArray(root.includes)) {
|
|
||||||
for (let relPath of root.includes) {
|
|
||||||
let overlayPath = path.resolve(rootDir, relPath)
|
|
||||||
let overlayDir = path.dirname(overlayPath)
|
|
||||||
|
|
||||||
let overlay = YAML.parse(await readFile(overlayPath))
|
|
||||||
await loadOverlaysRecursive(overlays, overlayDir, overlay)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
overlays.push(root)
|
|
||||||
}
|
|
||||||
|
|
||||||
// No dedicated parse function as this requires loading includes and overlaying
|
|
||||||
// them in the correct order
|
|
||||||
async function loadAndMergeConfig(configPath: string) {
|
|
||||||
let base = structuredClone(DEFAULT_CONFIG_BASE) // deep copy to avoid mutating base
|
|
||||||
|
|
||||||
let rootOverlay = YAML.parse(await readFile(configPath))
|
|
||||||
let rootPath = path.dirname(configPath)
|
|
||||||
let overlays: any[] = []
|
|
||||||
await loadOverlaysRecursive(overlays, rootPath, rootOverlay)
|
|
||||||
|
|
||||||
// Merge from base to final root
|
|
||||||
let merged = overlays.reduce((base, overlay) => mergeConfigs(base, overlay), base)
|
|
||||||
|
|
||||||
// Parse filters
|
|
||||||
merged.filters = Object.fromEntries(
|
|
||||||
Object.entries(merged.filters).map(([group, filters]) => [group, parseFilters(filters as SerializedFilters)]),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Finally, cast it to the parsed config type
|
|
||||||
delete merged.includes
|
|
||||||
return merged
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadDeviceConfigs(configPath: string) {
|
export async function loadDeviceConfigs(configPath: string) {
|
||||||
let merged = await loadAndMergeConfig(configPath)
|
let merged = await loadAndMergeDeviceConfig(configPath)
|
||||||
let { type } = merged
|
let { type } = merged
|
||||||
delete merged.type
|
delete merged.type
|
||||||
|
|
||||||
|
@ -173,7 +130,7 @@ export async function loadDeviceConfigs(configPath: string) {
|
||||||
let devices: DeviceConfig[] = []
|
let devices: DeviceConfig[] = []
|
||||||
for (let devicePath of list.devices) {
|
for (let devicePath of list.devices) {
|
||||||
devicePath = path.resolve(path.dirname(configPath), devicePath)
|
devicePath = path.resolve(path.dirname(configPath), devicePath)
|
||||||
devices.push(await loadAndMergeConfig(devicePath))
|
devices.push(await loadAndMergeDeviceConfig(devicePath))
|
||||||
}
|
}
|
||||||
|
|
||||||
return devices
|
return devices
|
||||||
|
|
Loading…
Reference in a new issue