Files
brk/website_next/ask/tools/chart.js
T
2026-07-22 16:50:32 +02:00

67 lines
2.5 KiB
JavaScript

import { colors } from "../../utils/colors.js";
import { units } from "../../chart/units.js";
import { createMetric } from "./metrics/index.js";
/** @typedef {import("../storage.js").ChartArtifact} ChartArtifact */
const VIEWS = new Set(["line", "area", "stacked", "bar", "dots"]);
const SCALES = new Set(["linear", "log"]);
const PALETTE = ["orange", "blue", "green", "violet", "yellow", "red"];
/** @param {unknown} value @param {string} name */
function requiredString(value, name) {
if (typeof value !== "string" || !value.trim()) {
throw new Error(`Chart ${name} is required`);
}
return value.trim();
}
/** @param {Record<string, unknown>} args @returns {ChartArtifact} */
export function createChartArtifact(args) {
const title = requiredString(args.title, "title");
const unit = requiredString(args.unit, "unit");
const view = args.view === undefined ? "line" : requiredString(args.view, "view");
const scale = args.scale === undefined
? "linear"
: requiredString(args.scale, "scale");
if (!Object.hasOwn(units, unit)) throw new Error(`Unknown chart unit: ${unit}`);
if (!VIEWS.has(view)) throw new Error(`Unknown chart view: ${view}`);
if (!SCALES.has(scale)) throw new Error(`Unknown chart scale: ${scale}`);
if (!Array.isArray(args.series) || !args.series.length || args.series.length > 6) {
throw new Error("A chart needs between one and six series");
}
const series = args.series.map((value, index) => {
if (!value || typeof value !== "object") throw new Error("Invalid chart series");
const item = /** @type {Record<string, unknown>} */ (value);
const path = requiredString(item.path, "series path")
.replace(/^brk\.series\./, "")
.replace(/^series\./, "");
const label = requiredString(item.label, "series label");
const color = item.color === undefined
? PALETTE[index]
: requiredString(item.color, "series color");
if (!Object.hasOwn(colors, color)) throw new Error(`Unknown chart color: ${color}`);
createMetric(path);
return {
path,
label,
color: /** @type {ChartArtifact["chart"]["series"][number]["color"]} */ (color),
};
});
return {
type: /** @type {const} */ ("chart"),
id: crypto.randomUUID(),
chart: {
title,
unit: /** @type {ChartArtifact["chart"]["unit"]} */ (unit),
view: /** @type {ChartArtifact["chart"]["view"]} */ (view),
scale: /** @type {ChartArtifact["chart"]["scale"]} */ (scale),
series,
},
};
}