dimensionlab-website/apps/web/src/lib/server/dashboard.ts

147 lines
3.9 KiB
TypeScript

import { dimensionLabDashboardFixture } from "$lib/dashboard-seed/dimensionlab";
import type { DashboardDocument } from "@dimensionlab/dashboard-model";
import {
createDashboardStore,
DashboardPersistenceValidationError,
type DashboardStore,
} from "$lib/server/db/dashboard-store";
import { UnsupportedDashboardModelVersionError } from "$lib/server/db/model-migrations";
export type DashboardRuntimeState =
| DashboardRuntimeEmpty
| DashboardRuntimeInvalid
| DashboardRuntimeLoading
| DashboardRuntimeReady;
export interface DashboardRuntimeReady {
state: "ready";
document: DashboardDocument;
schemaVersion: string;
currentRevisionId: string;
}
export interface DashboardRuntimeEmpty {
state: "empty";
title: string;
subtitle: string;
message: string;
}
export interface DashboardRuntimeLoading {
state: "loading";
title: string;
subtitle: string;
message: string;
}
export interface DashboardRuntimeInvalid {
state: "invalid";
title: string;
subtitle: string;
message: string;
errors: string[];
}
export interface DashboardRuntimeOptions {
refreshSeedDocument?: boolean;
seedIfEmpty?: boolean;
seedDocument?: DashboardDocument;
}
export function loadDashboardRuntime(
store?: DashboardStore,
options: DashboardRuntimeOptions = {},
): DashboardRuntimeState {
const dashboardStore = store || createDashboardStore();
try {
const seedDocument = options.seedDocument || dimensionLabDashboardFixture;
const active = dashboardStore.getActiveDashboard();
if (active) {
if (
options.refreshSeedDocument &&
shouldRefreshSeedDashboard(active, seedDocument)
) {
const refreshed = dashboardStore.commitDashboard(seedDocument, {
actor: "initial-seed",
message: "refresh bundled dashboard document",
});
return readyRuntimeState(refreshed.document, refreshed.id);
}
return readyRuntimeState(active.document, active.currentRevisionId);
}
if (!options.seedIfEmpty) {
return {
state: "empty",
title: "No Dashboard Model",
subtitle: "No active document",
message: "No validated dashboard document is active yet.",
};
}
const seeded = dashboardStore.seedDashboardIfEmpty(
seedDocument,
{
actor: "initial-seed",
message: "load initial dashboard document",
},
);
return readyRuntimeState(seeded.document, seeded.id);
} catch (error) {
if (error instanceof DashboardPersistenceValidationError) {
return invalidRuntimeState(error.failure.errors);
}
if (error instanceof UnsupportedDashboardModelVersionError) {
return invalidRuntimeState([error.message]);
}
throw error;
} finally {
if (!store) dashboardStore.close();
}
}
function readyRuntimeState(
document: DashboardDocument,
currentRevisionId: string,
): DashboardRuntimeReady {
return {
state: "ready",
document,
schemaVersion: document.schemaVersion,
currentRevisionId,
};
}
function invalidRuntimeState(errors: string[]): DashboardRuntimeInvalid {
return {
state: "invalid",
title: "Invalid Dashboard Model",
subtitle: "Validation failed",
message: "The active dashboard document could not be validated.",
errors,
};
}
function shouldRefreshSeedDashboard(
active: { document: DashboardDocument; revision: { actor: string } },
seedDocument: DashboardDocument,
): boolean {
if (active.revision.actor !== "initial-seed") return false;
if (!isBundledDimensionLabSeed(active.document, seedDocument)) return false;
return JSON.stringify(active.document) !== JSON.stringify(seedDocument);
}
function isBundledDimensionLabSeed(
document: DashboardDocument,
seedDocument: DashboardDocument,
): boolean {
return (
document.metadata.title === seedDocument.metadata.title &&
document.metadata.description === seedDocument.metadata.description
);
}