cloudaxe-opencode/packages/opencode/src/app/app.ts

79 lines
1.8 KiB
TypeScript
Raw Normal View History

2025-05-31 18:41:00 +00:00
import fs from "fs/promises"
import { AppPath } from "./path"
import { Log } from "../util/log"
import { Context } from "../util/context"
2025-05-18 01:31:42 +00:00
export namespace App {
2025-05-31 18:41:00 +00:00
const log = Log.create({ service: "app" })
2025-05-18 01:31:42 +00:00
2025-05-31 18:41:00 +00:00
export type Info = Awaited<ReturnType<typeof create>>
2025-05-18 01:31:42 +00:00
2025-05-31 18:41:00 +00:00
const ctx = Context.create<Info>("app")
2025-05-18 01:31:42 +00:00
2025-05-21 14:30:39 +00:00
async function create(input: { directory: string }) {
2025-05-31 18:41:00 +00:00
const dataDir = AppPath.data(input.directory)
await fs.mkdir(dataDir, { recursive: true })
await Log.file(input.directory)
2025-05-21 14:30:39 +00:00
2025-05-31 18:41:00 +00:00
log.info("created", { path: dataDir })
2025-05-18 01:31:42 +00:00
2025-05-26 18:52:38 +00:00
const services = new Map<
any,
{
2025-05-31 18:41:00 +00:00
state: any
shutdown?: (input: any) => Promise<void>
2025-05-26 18:52:38 +00:00
}
2025-05-31 18:41:00 +00:00
>()
2025-05-18 01:31:42 +00:00
2025-05-18 06:43:01 +00:00
const result = {
get services() {
2025-05-31 18:41:00 +00:00
return services
2025-05-18 06:43:01 +00:00
},
2025-05-18 01:31:42 +00:00
get root() {
2025-05-31 18:41:00 +00:00
return input.directory
2025-05-18 01:31:42 +00:00
},
2025-05-31 18:41:00 +00:00
}
2025-05-18 06:43:01 +00:00
2025-05-31 18:41:00 +00:00
return result
2025-05-18 01:31:42 +00:00
}
2025-05-26 18:52:38 +00:00
export function state<State>(
key: any,
init: (app: Info) => State,
shutdown?: (state: Awaited<State>) => Promise<void>,
) {
2025-05-18 06:43:01 +00:00
return () => {
2025-05-31 18:41:00 +00:00
const app = ctx.use()
const services = app.services
2025-05-18 06:43:01 +00:00
if (!services.has(key)) {
2025-05-31 18:41:00 +00:00
log.info("registering service", { name: key })
2025-05-26 18:52:38 +00:00
services.set(key, {
state: init(app),
shutdown: shutdown,
2025-05-31 18:41:00 +00:00
})
2025-05-18 06:43:01 +00:00
}
2025-05-31 18:41:00 +00:00
return services.get(key)?.state as State
}
2025-05-18 01:31:42 +00:00
}
export async function use() {
2025-05-31 18:41:00 +00:00
return ctx.use()
2025-05-18 01:31:42 +00:00
}
2025-05-21 14:30:39 +00:00
export async function provide<T extends (app: Info) => any>(
input: { directory: string },
cb: T,
) {
2025-05-31 18:41:00 +00:00
const app = await create(input)
2025-05-23 20:20:21 +00:00
return ctx.provide(app, async () => {
2025-05-31 18:41:00 +00:00
const result = await cb(app)
2025-05-26 18:52:38 +00:00
for (const [key, entry] of app.services.entries()) {
2025-05-31 18:41:00 +00:00
log.info("shutdown", { name: key })
await entry.shutdown?.(await entry.state)
2025-05-26 18:52:38 +00:00
}
2025-05-31 18:41:00 +00:00
return result
})
2025-05-21 14:30:39 +00:00
}
2025-05-18 01:31:42 +00:00
}