mono/packages/commons/src/profile.ts
2025-02-07 23:42:16 +01:00

93 lines
3.2 KiB
TypeScript

import * as path from 'path'
import { REGEX_VAR } from "@polymech/core/constants"
import { sync as read } from '@polymech/fs/read'
import { sync as exists } from '@polymech/fs/exists'
import { isString } from '@polymech/core/types'
import { resolve, substitute, template } from './variables.js'
interface EnvVariables {
[key: string]: string
}
interface EnvConfig {
includes: string[]
variables: EnvVariables
}
export interface IProfile {
includes: string[]
variables: EnvVariables
env?: {
[key: string]: EnvConfig
}
}
const _resolve = (config: Record<string, string>): Record<string, unknown> => {
for (const key in config) {
if (isString(config[key])) {
config[key] = template(config[key], config)
}
}
return config
}
export const resolveConfig = (config: Record<string, string>): Record<string, unknown> => _resolve(config)
export const parse = (profilePath: string, profile: IProfile, options: { env: string } = { env: 'default' }, rel?: string) => {
profilePath = path.resolve(resolve(profilePath, false, profile.variables))
if (!exists(profilePath as string)) {
return
}
const _profile = read(profilePath as string, 'json') as any || { includes: [], variables: {} } as IProfile
_profile.includes = _profile.includes || []
_profile.variables = _profile.variables || {}
if (options.env && _profile.env && _profile.env[options.env] && _profile.env[options.env].includes) {
profile.includes = [
...profile.includes,
..._profile.includes,
..._profile.env[options.env].includes
]
} else {
profile.includes = [
...profile.includes,
..._profile.includes
]
}
if (options.env && _profile.env && _profile.env[options.env] && _profile.env[options.env].variables) {
profile.variables = {
...profile.variables,
..._profile.variables,
..._profile.env[options.env].variables
}
}
for (const k in _profile.variables) {
if (isString(_profile.variables[k])) {
_profile.variables[k] = substitute(false, _profile.variables[k], profile.variables)
}
}
profile.variables = { ...profile.variables, ..._profile.variables, ..._profile.env[options.env]?.variables || {} }
for (const k in profile.variables) {
if (isString(profile.variables[k])) {
profile.variables[k] = substitute(false, profile.variables[k], profile.variables)
}
}
profile.includes = Array.from(new Set(profile.includes))
profile.includes = [
...profile.includes.map((i) => {
if (!path.isAbsolute(i) && rel && !i.match(REGEX_VAR)) {
return path.resolve(`${rel}/${i}`)
}
let ret = resolve(i, false, profile.variables)
ret = path.resolve(substitute(false, ret, profile.variables))
return ret
})]
profile.includes = profile.includes.filter((include) =>
include !== null &&
include !== '')
profile.includes = Array.from(new Set(profile.includes))
return profile
}