muddle/core/context.ts
2026-10-23 09:12:49 -04:00

87 lines
2 KiB
TypeScript

import type { Headers } from "../contracts/typegen/http/headers.ts";
export class ServerBuildContext {
private readonly values: {
headers: Headers;
locals: Record<string, unknown>;
} = { headers: {}, locals: {} };
header(name: string, value: string): this {
this.values.headers[name.toLowerCase()] = value;
return this;
}
headers(values: Headers): this {
Object.assign(this.values.headers, values);
return this;
}
local(name: string, value: unknown): this {
this.values.locals[name] = value;
return this;
}
build(): Readonly<{ headers: Headers; locals: Record<string, unknown> }> {
return {
headers: { ...this.values.headers },
locals: { ...this.values.locals },
};
}
}
export class TemplateContext {
readonly imports = new Map<
string,
{
render(
props: Record<string, unknown>,
context: {
locals: Record<string, unknown>;
params: Record<string, string>;
},
): Promise<string> | string;
}
>();
import(
name: string,
component: {
render(
props: Record<string, unknown>,
context: {
locals: Record<string, unknown>;
params: Record<string, string>;
},
): Promise<string> | string;
},
): this {
if (!/^[A-Za-z][\w-]*$/.test(name))
throw new Error("Invalid component import name");
this.imports.set(name, component);
return this;
}
private readonly values: {
templates: string[];
inputs: Record<string, unknown>;
contracts: Record<string, string>;
} = { templates: [], inputs: {}, contracts: {} };
template(path: string): this {
this.values.templates.push(path);
return this;
}
input(name: string, value: unknown): this {
this.values.inputs[name] = value;
return this;
}
contract(name: string, type: string): this {
this.values.contracts[name] = type;
return this;
}
build(): Readonly<{
templates: string[];
inputs: Record<string, unknown>;
contracts: Record<string, string>;
}> {
return {
templates: [...this.values.templates],
inputs: { ...this.values.inputs },
contracts: { ...this.values.contracts },
};
}
}