im_wower
·
2026-03-22
local-control-plane.ts
1import { readFileSync } from "node:fs";
2import { resolve } from "node:path";
3import { fileURLToPath } from "node:url";
4
5import { D1ControlPlaneRepository, SqliteD1Database } from "../../../packages/db/dist/index.js";
6
7const REPO_ROOT = resolve(fileURLToPath(new URL("../../..", import.meta.url)));
8
9export const DEFAULT_CONTROL_PLANE_DB_FILENAME = "control-plane.sqlite";
10
11export interface ConductorLocalControlPlaneOptions {
12 databasePath?: string | null;
13 schemaPath?: string | null;
14 stateDir?: string | null;
15}
16
17export function resolveConductorRepoRoot(): string {
18 return REPO_ROOT;
19}
20
21export function resolveDefaultConductorStateDir(): string {
22 return resolve(REPO_ROOT, "state");
23}
24
25export function resolveConductorControlPlaneSchemaPath(schemaPath?: string | null): string {
26 return resolve(schemaPath ?? resolve(REPO_ROOT, "ops/sql/schema.sql"));
27}
28
29export function resolveConductorControlPlaneDatabasePath(
30 options: Pick<ConductorLocalControlPlaneOptions, "databasePath" | "stateDir"> = {}
31): string {
32 const explicitDatabasePath = options.databasePath?.trim();
33
34 if (explicitDatabasePath) {
35 return explicitDatabasePath === ":memory:" ? ":memory:" : resolve(explicitDatabasePath);
36 }
37
38 return resolve(options.stateDir ?? resolveDefaultConductorStateDir(), DEFAULT_CONTROL_PLANE_DB_FILENAME);
39}
40
41export class ConductorLocalControlPlane {
42 readonly databasePath: string;
43 readonly repository: D1ControlPlaneRepository;
44 readonly schemaPath: string;
45
46 private readonly database: SqliteD1Database;
47
48 constructor(options: ConductorLocalControlPlaneOptions = {}) {
49 this.databasePath = resolveConductorControlPlaneDatabasePath(options);
50 this.schemaPath = resolveConductorControlPlaneSchemaPath(options.schemaPath);
51 this.database = new SqliteD1Database(this.databasePath, {
52 schemaSql: readFileSync(this.schemaPath, "utf8")
53 });
54 this.repository = new D1ControlPlaneRepository(this.database);
55 }
56
57 async initialize(): Promise<void> {
58 await this.repository.ensureAutomationState();
59 }
60
61 close(): void {
62 this.database.close();
63 }
64}