| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- import fs from "fs/promises";
- import { AppPath } from "./path";
- import { Log } from "../util/log";
- import { Context } from "../util/context";
- export namespace App {
- const log = Log.create({ service: "app" });
- export type Info = Awaited<ReturnType<typeof create>>;
- const ctx = Context.create<Info>("app");
- async function create(input: { directory: string }) {
- const dataDir = AppPath.data(input.directory);
- await fs.mkdir(dataDir, { recursive: true });
- await Log.file(input.directory);
- log.info("created", { path: dataDir });
- const services = new Map<
- any,
- {
- state: any;
- shutdown?: (input: any) => Promise<void>;
- }
- >();
- const result = {
- get services() {
- return services;
- },
- get root() {
- return input.directory;
- },
- };
- return result;
- }
- export function state<State>(
- key: any,
- init: (app: Info) => State,
- shutdown?: (state: Awaited<State>) => Promise<void>,
- ) {
- return () => {
- const app = ctx.use();
- const services = app.services;
- if (!services.has(key)) {
- log.info("registering service", { name: key });
- services.set(key, {
- state: init(app),
- shutdown: shutdown,
- });
- }
- return services.get(key)?.state as State;
- };
- }
- export async function use() {
- return ctx.use();
- }
- export async function provide<T extends (app: Info) => any>(
- input: { directory: string },
- cb: T,
- ) {
- const app = await create(input);
- return ctx.provide(app, async () => {
- const result = await cb(app);
- for (const [key, entry] of app.services.entries()) {
- log.info("shutdown", { name: key });
- await entry.shutdown?.(await entry.state);
- }
- return result;
- });
- }
- }
|