import { promises as fs } from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
interface VegaLiteExample {
name: string;
description: string;
category: string;
spec: Record<string, unknown>;
url: string;
}
interface ExampleResult {
category: string;
examples: VegaLiteExample[];
totalExamples: number;
}
/**
* Get Vega-Lite examples by category
*/
export async function getExample(
category: string,
search?: string
): Promise<ExampleResult> {
const dataPath = path.join(__dirname, "..", "data", "examples.json");
try {
// Try to load examples data
const data = await fs.readFile(dataPath, "utf-8");
const allExamples: VegaLiteExample[] = JSON.parse(data);
// Filter by category
let examples = allExamples.filter(
(ex) => ex.category.toLowerCase() === category.toLowerCase()
);
// Apply search filter if provided
if (search) {
const lowerSearch = search.toLowerCase();
examples = examples.filter(
(ex) =>
ex.name.toLowerCase().includes(lowerSearch) ||
ex.description.toLowerCase().includes(lowerSearch)
);
}
return {
category,
examples,
totalExamples: examples.length,
};
} catch (error) {
// If examples data doesn't exist yet, return fallback examples
if (error instanceof Error && "code" in error && (error as any).code === "ENOENT") {
return getFallbackExamples(category);
}
throw error;
}
}
/**
* Fallback examples for common categories
*/
function getFallbackExamples(category: string): ExampleResult {
const fallbackExamples: Record<string, VegaLiteExample[]> = {
bar: [
{
name: "Simple Bar Chart",
description: "A basic bar chart showing categorical data",
category: "bar",
url: "https://vega.github.io/vega-lite/examples/bar.html",
spec: {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
description: "A simple bar chart with embedded data.",
data: {
values: [
{ a: "A", b: 28 },
{ a: "B", b: 55 },
{ a: "C", b: 43 },
{ a: "D", b: 91 },
{ a: "E", b: 81 },
{ a: "F", b: 53 },
{ a: "G", b: 19 },
{ a: "H", b: 87 },
{ a: "I", b: 52 },
],
},
mark: "bar",
encoding: {
x: { field: "a", type: "nominal", axis: { labelAngle: 0 } },
y: { field: "b", type: "quantitative" },
},
},
},
],
line: [
{
name: "Simple Line Chart",
description: "A basic line chart showing a trend over time",
category: "line",
url: "https://vega.github.io/vega-lite/examples/line.html",
spec: {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
description: "A simple line chart.",
data: {
values: [
{ x: 0, y: 28 },
{ x: 1, y: 55 },
{ x: 2, y: 43 },
{ x: 3, y: 91 },
{ x: 4, y: 81 },
{ x: 5, y: 53 },
],
},
mark: "line",
encoding: {
x: { field: "x", type: "quantitative" },
y: { field: "y", type: "quantitative" },
},
},
},
],
scatter: [
{
name: "Simple Scatter Plot",
description: "A basic scatter plot showing the relationship between two variables",
category: "scatter",
url: "https://vega.github.io/vega-lite/examples/point_2d.html",
spec: {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
description: "A scatterplot showing body mass and flipper lengths of penguins.",
data: {
url: "https://vega.github.io/vega-lite/data/penguins.json",
},
mark: "point",
encoding: {
x: {
field: "Flipper Length (mm)",
type: "quantitative",
scale: { zero: false },
},
y: {
field: "Body Mass (g)",
type: "quantitative",
scale: { zero: false },
},
color: { field: "Species", type: "nominal" },
},
},
},
],
};
const examples = fallbackExamples[category.toLowerCase()] || [];
return {
category,
examples,
totalExamples: examples.length,
};
}