Initial Commit
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import { AsyncLocalStorage } from "node:async_hooks";
|
||||
import type { ComposeSpecification } from "../schema/docker.d";
|
||||
import { getProject, throwWhen } from "./shared";
|
||||
import { readCompose, resolveComposeFile } from "./yaml";
|
||||
|
||||
type AppContext = {
|
||||
project: string;
|
||||
cwd: string;
|
||||
path(): Promise<string | undefined>;
|
||||
compose(): Promise<ComposeSpecification>;
|
||||
};
|
||||
|
||||
const appContext = new AsyncLocalStorage<AppContext>();
|
||||
|
||||
export function provideContext<T>(fn: () => T): T {
|
||||
const cwd = process.cwd();
|
||||
const path = createCachedGetter("composeFile", () => resolveComposeFile(cwd));
|
||||
return appContext.run(
|
||||
{
|
||||
project: getProject(),
|
||||
cwd,
|
||||
path,
|
||||
compose: createCachedGetter("compose", () =>
|
||||
path()
|
||||
.then(throwWhen((path): path is undefined => path === undefined))
|
||||
.then(readCompose),
|
||||
),
|
||||
},
|
||||
fn,
|
||||
);
|
||||
}
|
||||
|
||||
export function ctx() {
|
||||
const store = appContext.getStore();
|
||||
if (!store) throw new Error("Not in context!");
|
||||
return store;
|
||||
}
|
||||
|
||||
const cache: Record<string, unknown> = {};
|
||||
export function createCachedGetter<T>(
|
||||
key: string,
|
||||
fn: () => Promise<T>,
|
||||
): () => Promise<T> {
|
||||
return async () => {
|
||||
if (key in cache) return cache[key] as T;
|
||||
const result = await fn();
|
||||
cache[key] = result;
|
||||
return result;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user