58 lines
1.6 KiB
TypeScript
58 lines
1.6 KiB
TypeScript
import type { Config } from "#/lib/config/types.ts";
|
|
import { configSchema } from "#/lib/config/types.zod.ts";
|
|
import { parse } from "jsr:@std/yaml";
|
|
import { debounce } from "jsr:@std/async/debounce";
|
|
|
|
export * from "#/lib/config/types.ts"
|
|
|
|
export class ConfigLoader {
|
|
private currentConfig: Config
|
|
private path: string
|
|
|
|
constructor(firstConfig: Config, path:string) {
|
|
this.path = path
|
|
this.currentConfig = firstConfig
|
|
const run = debounce(async (e: Deno.FsEvent)=>{
|
|
console.log("config file hmr", e);
|
|
const fileText = await Deno.readTextFile(path)
|
|
const parsed = parse(fileText)
|
|
return [await configSchema.parseAsync(parsed), path]
|
|
}, 250)
|
|
const watch = async ()=>{
|
|
const watcher = Deno.watchFs(path)
|
|
for await (const event of watcher) {
|
|
if(event.kind === "remove") {
|
|
return
|
|
}
|
|
run(event)
|
|
}
|
|
}
|
|
watch()
|
|
}
|
|
|
|
static async New(...paths: string[]) {
|
|
const [config, configPath] = await this.firstLoad(paths)
|
|
return new ConfigLoader(config, configPath)
|
|
|
|
}
|
|
config(): Config {
|
|
return this.currentConfig
|
|
}
|
|
static async firstLoad(paths: string[]): Promise<[Config, string]>{
|
|
const errs = []
|
|
for (const path of paths) {
|
|
let fileText:string
|
|
try {
|
|
fileText = await Deno.readTextFile(path)
|
|
} catch (e) {
|
|
errs.push(e)
|
|
console.error(`Failed to load config from ${path}: ${e}`)
|
|
continue
|
|
}
|
|
const parsed = parse(fileText)
|
|
return [await configSchema.parseAsync(parsed), path]
|
|
}
|
|
throw new AggregateError(errs)
|
|
}
|
|
}
|