147 lines
3.9 KiB
TypeScript
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
|
|
);
|
|
}
|