67 lines
2.3 KiB
TypeScript
67 lines
2.3 KiB
TypeScript
import { query } from '@/lib/db-postgres';
|
|
import type {
|
|
ProjectPhase,
|
|
ProjectPhaseData,
|
|
ProjectPhaseScores,
|
|
ProjectStage,
|
|
} from '@/lib/types/project-artifacts';
|
|
|
|
export const clamp = (value: number) => Math.max(0, Math.min(1, value));
|
|
export const nowIso = () => new Date().toISOString();
|
|
|
|
export function uniqueStrings(values: Array<string | null | undefined>): string[] {
|
|
return Array.from(new Set(values.filter((value): value is string => Boolean(value))));
|
|
}
|
|
|
|
export function toStage(stage?: string | null): ProjectStage {
|
|
const allowed: ProjectStage[] = ['idea', 'prototype', 'mvp_in_progress', 'live_beta', 'live_paid', 'unknown'];
|
|
if (!stage) return 'unknown';
|
|
return allowed.includes(stage as ProjectStage) ? (stage as ProjectStage) : 'unknown';
|
|
}
|
|
|
|
export async function loadPhaseContainers(projectId: string) {
|
|
const rows = await query<{ id: string; data: any }>(`
|
|
SELECT id, data FROM fs_projects WHERE id = $1 LIMIT 1
|
|
`, [projectId]);
|
|
|
|
if (rows.length === 0) throw new Error(`Project ${projectId} not found`);
|
|
|
|
const doc = rows[0].data || {};
|
|
const phaseData = (doc.phaseData ?? {}) as ProjectPhaseData;
|
|
const phaseScores = (doc.phaseScores ?? {}) as ProjectPhaseScores;
|
|
const phaseHistory = Array.isArray(doc.phaseHistory) ? [...doc.phaseHistory] : [];
|
|
return { projectId, doc, phaseData, phaseScores, phaseHistory };
|
|
}
|
|
|
|
interface PersistencePayload {
|
|
phaseData: ProjectPhaseData;
|
|
phaseScores: ProjectPhaseScores;
|
|
phaseHistory: Array<Record<string, unknown>>;
|
|
nextPhase?: ProjectPhase;
|
|
}
|
|
|
|
export async function persistPhaseArtifacts(
|
|
projectId: string,
|
|
builder: (
|
|
phaseData: ProjectPhaseData,
|
|
phaseScores: ProjectPhaseScores,
|
|
phaseHistory: Array<Record<string, unknown>>,
|
|
) => PersistencePayload,
|
|
) {
|
|
const { doc, phaseData, phaseScores, phaseHistory } = await loadPhaseContainers(projectId);
|
|
const payload = builder(phaseData, phaseScores, phaseHistory);
|
|
|
|
const updated = {
|
|
...doc,
|
|
phaseData: payload.phaseData,
|
|
phaseScores: payload.phaseScores,
|
|
phaseHistory: payload.phaseHistory,
|
|
updatedAt: new Date().toISOString(),
|
|
...(payload.nextPhase ? { currentPhase: payload.nextPhase, phaseStatus: 'completed' } : {}),
|
|
};
|
|
|
|
await query(`
|
|
UPDATE fs_projects SET data = $1::jsonb WHERE id = $2
|
|
`, [JSON.stringify(updated), projectId]);
|
|
}
|