1
0
mirror of https://github.com/kamranahmedse/developer-roadmap.git synced 2025-08-21 16:41:24 +02:00
Files
developer-roadmap/scripts/editor-roadmap-dirs.ts
2025-05-21 01:39:39 +01:00

105 lines
3.0 KiB
TypeScript

import type { Node } from '@roadmapsh/editor';
import matter from 'gray-matter';
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import type { RoadmapFrontmatter } from '../src/lib/roadmap';
import { slugify } from '../src/lib/slugger';
// ERROR: `__dirname` is not defined in ES module scope
// https://iamwebwiz.medium.com/how-to-fix-dirname-is-not-defined-in-es-module-scope-34d94a86694d
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Usage: tsx ./scripts/editor-roadmap-dirs.ts <roadmapId>
// Directory containing the roadmaps
const ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');
const roadmapId = process.argv[2];
const allowedRoadmapIds = await fs.readdir(ROADMAP_CONTENT_DIR);
if (!roadmapId) {
console.error('Roadmap Id is required');
process.exit(1);
}
if (!allowedRoadmapIds.includes(roadmapId)) {
console.error(`Invalid roadmap key ${roadmapId}`);
console.error(`Allowed keys are ${allowedRoadmapIds.join(', ')}`);
process.exit(1);
}
const roadmapFrontmatterDir = path.join(
ROADMAP_CONTENT_DIR,
roadmapId,
`${roadmapId}.md`,
);
const roadmapFrontmatterRaw = await fs.readFile(roadmapFrontmatterDir, 'utf-8');
const { data } = matter(roadmapFrontmatterRaw);
const roadmapFrontmatter = data as RoadmapFrontmatter;
if (!roadmapFrontmatter) {
console.error('Invalid roadmap frontmatter');
process.exit(1);
}
if (roadmapFrontmatter.renderer !== 'editor') {
console.error('Only Editor Rendered Roadmaps are allowed');
process.exit(1);
}
export async function fetchRoadmapJson(roadmapId: string) {
const response = await fetch(
`https://roadmap.sh/api/v1-official-roadmap/${roadmapId}`,
);
if (!response.ok) {
throw new Error(`Failed to fetch roadmap json: ${response.statusText}`);
}
const data = await response.json();
if (data.error) {
throw new Error(`Failed to fetch roadmap json: ${data.error}`);
}
return data;
}
const roadmapContent = await fetchRoadmapJson(roadmapId);
if (!roadmapContent) {
console.error(`Failed to fetch roadmap json: ${roadmapId}`);
process.exit(1);
}
let { nodes } = roadmapContent as {
nodes: Node[];
};
nodes = nodes.filter(
(node) =>
node?.type && ['topic', 'subtopic'].includes(node.type) && node.data?.label,
);
const roadmapContentDir = path.join(ROADMAP_CONTENT_DIR, roadmapId, 'content');
const stats = await fs.stat(roadmapContentDir).catch(() => null);
if (!stats || !stats.isDirectory()) {
await fs.mkdir(roadmapContentDir, { recursive: true });
}
const roadmapContentFiles = await fs.readdir(roadmapContentDir, {
recursive: true,
});
nodes.forEach(async (node, index) => {
const nodeDirPattern = `${slugify(node.data.label as string)}@${node.id}.md`;
if (roadmapContentFiles.includes(nodeDirPattern)) {
console.log(`Skipping ${nodeDirPattern}`);
return;
}
await fs.writeFile(
path.join(roadmapContentDir, nodeDirPattern),
`# ${node.data.label}`,
);
});