diff options
| author | Dax Raad <[email protected]> | 2025-05-18 02:43:01 -0400 |
|---|---|---|
| committer | Dax Raad <[email protected]> | 2025-05-26 12:40:17 -0400 |
| commit | d0d67029f4baad7389b5ba072379c2ff44a22dc4 (patch) | |
| tree | cb81e86662c14c20687bf5bac488dda911a9855e /js/src/app | |
| parent | a34d020bc6b252e842f042d935c7a0e6444460cf (diff) | |
| download | opencode-d0d67029f4baad7389b5ba072379c2ff44a22dc4.tar.gz opencode-d0d67029f4baad7389b5ba072379c2ff44a22dc4.zip | |
process
Diffstat (limited to 'js/src/app')
| -rw-r--r-- | js/src/app/config.ts | 52 | ||||
| -rw-r--r-- | js/src/app/index.ts | 34 |
2 files changed, 75 insertions, 11 deletions
diff --git a/js/src/app/config.ts b/js/src/app/config.ts new file mode 100644 index 000000000..84960db61 --- /dev/null +++ b/js/src/app/config.ts @@ -0,0 +1,52 @@ +import path from "node:path"; +import { Log } from "../util/log"; +import { z } from "zod/v4"; + +export namespace Config { + const log = Log.create({ service: "config" }); + + export const Info = z + .object({ + providers: z + .object({ + anthropic: z + .object({ + apiKey: z.string().optional(), + headers: z.record(z.string(), z.string()).optional(), + baseURL: z.string().optional(), + }) + .strict() + .optional(), + }) + .strict() + .optional(), + }) + .strict(); + + export type Info = z.output<typeof Info>; + + export async function load(directory: string) { + let result: Info = {}; + for (const file of ["opencode.jsonc", "opencode.json"]) { + const resolved = path.join(directory, file); + log.info("searching", { path: resolved }); + try { + result = await import(path.join(directory, file)).then((mod) => + Info.parse(mod.default), + ); + log.info("found", { path: resolved }); + break; + } catch (e) { + if (e instanceof z.ZodError) { + for (const issue of e.issues) { + log.info(issue.message); + } + throw e; + } + continue; + } + } + log.info("loaded", result); + return result; + } +} diff --git a/js/src/app/index.ts b/js/src/app/index.ts index 1c063ebd3..7f5a44f30 100644 --- a/js/src/app/index.ts +++ b/js/src/app/index.ts @@ -2,6 +2,7 @@ import fs from "fs/promises"; import { AppPath } from "./path"; import { Log } from "../util/log"; import { Context } from "../util/context"; +import { Config } from "./config"; export namespace App { const log = Log.create({ service: "app" }); @@ -13,29 +14,40 @@ export namespace App { export async function create(input: { directory: string }) { log.info("creating"); + const config = await Config.load(input.directory); + const dataDir = AppPath.data(input.directory); await fs.mkdir(dataDir, { recursive: true }); log.info("created", { path: dataDir }); const services = new Map<any, any>(); - return { + const result = { + get services() { + return services; + }, + get config() { + return config; + }, get root() { return input.directory; }, - service<T extends () => any>(service: any, init: T) { - if (!services.has(service)) { - log.info("registering service", { name: service }); - services.set(service, init()); - } - return services.get(service) as ReturnType<T>; - }, + service<T extends (app: any) => any>(service: any, init: T) {}, }; + + return result; } - export function service<T extends () => any>(key: any, init: T) { - const app = ctx.use(); - return app.service(key, init); + export function state<T extends (app: Info) => any>(key: any, init: T) { + return () => { + const app = ctx.use(); + const services = app.services; + if (!services.has(key)) { + log.info("registering service", { name: key }); + services.set(key, init(app)); + } + return services.get(key) as ReturnType<T>; + }; } export async function use() { |
