conductor/backend/src/db/projects.ts
2026-07-18 10:23:13 -04:00

105 lines
3.2 KiB
TypeScript

import db from './database';
// ── Types ─────────────────────────────────────────────────────────────────────
export type ProjectRow = {
id: number;
name: string;
description: string;
project_json: string;
created_at: string;
updated_at: string;
};
export type CreateProjectInput = {
name: string;
description?: string;
project_json?: string;
};
export type UpdateProjectInput = {
name?: string;
description?: string;
project_json?: string;
};
// Minimal valid project definition created when none is supplied on POST
const DEFAULT_PROJECT_JSON = JSON.stringify({
schemaVersion: '0.1.0',
project: {
name: '',
pages: [],
actions: [],
variables: {},
settings: {},
},
});
// ── Queries ───────────────────────────────────────────────────────────────────
const stmtList = db.prepare<[], ProjectRow>(`
SELECT id, name, description, project_json, created_at, updated_at
FROM projects
ORDER BY created_at DESC
`);
const stmtGetById = db.prepare<[number], ProjectRow>(`
SELECT id, name, description, project_json, created_at, updated_at
FROM projects
WHERE id = ?
`);
const stmtInsert = db.prepare<[string, string, string], { lastInsertRowid: number }>(`
INSERT INTO projects (name, description, project_json)
VALUES (?, ?, ?)
`);
const stmtUpdate = db.prepare<[string, string, string, number], void>(`
UPDATE projects
SET name = ?, description = ?, project_json = ?,
updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
WHERE id = ?
`);
const stmtDelete = db.prepare<[number], void>(`
DELETE FROM projects WHERE id = ?
`);
// ── Data access functions ─────────────────────────────────────────────────────
export function listProjects(): ProjectRow[] {
return stmtList.all();
}
export function getProjectById(id: number): ProjectRow | undefined {
return stmtGetById.get(id);
}
export function createProject(input: CreateProjectInput): ProjectRow {
const { name, description = '', project_json = DEFAULT_PROJECT_JSON } = input;
// Embed the project name into the default JSON so it is consistent
const json =
project_json === DEFAULT_PROJECT_JSON
? JSON.stringify({ ...JSON.parse(DEFAULT_PROJECT_JSON), project: { ...JSON.parse(DEFAULT_PROJECT_JSON).project, name } })
: project_json;
const result = stmtInsert.run(name, description, json);
return getProjectById(result.lastInsertRowid as number) as ProjectRow;
}
export function updateProject(id: number, input: UpdateProjectInput): ProjectRow | undefined {
const existing = getProjectById(id);
if (!existing) return undefined;
stmtUpdate.run(
input.name ?? existing.name,
input.description ?? existing.description,
input.project_json ?? existing.project_json,
id,
);
return getProjectById(id);
}
export function deleteProject(id: number): boolean {
const result = stmtDelete.run(id);
return result.changes > 0;
}