{"spec_id":"network-directed","library":"echarts","language":"javascript","code":"// anyplot.ai\n// network-directed: Directed Network Graph\n// Library: echarts 6.1.0 | JavaScript 22.23.2\n// Quality: 85/100 | Created: 2026-09-05\n\n//# anyplot-orientation: square\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data: internal module dependency graph (arrow = \"imports\") ------------\nconst CATEGORIES = [\"Core\", \"Service layer\", \"UI layer\", \"Shared utilities\"];\n\nconst moduleDefs = [\n  [\"App Shell\", 0],\n  [\"Router\", 0],\n  [\"Middleware\", 0],\n  [\"Scheduler\", 0],\n  [\"Auth Service\", 1],\n  [\"API Gateway\", 1],\n  [\"Database\", 1],\n  [\"Cache\", 1],\n  [\"UI Components\", 2],\n  [\"State Store\", 2],\n  [\"Logger\", 3],\n  [\"Config\", 3],\n  [\"Validator\", 3],\n  [\"Utils\", 3],\n];\n\n// [source, target, weight] — weight = number of imported symbols.\n// The State Store -> UI Components edge closes a circular dependency with\n// UI Components -> State Store below, the kind of accidental cycle this\n// graph type is meant to surface.\nconst dependencies = [\n  [\"App Shell\", \"Router\", 5],\n  [\"App Shell\", \"Config\", 2],\n  [\"Router\", \"Auth Service\", 6],\n  [\"Router\", \"API Gateway\", 7],\n  [\"Middleware\", \"Logger\", 3],\n  [\"Middleware\", \"Validator\", 4],\n  [\"Scheduler\", \"API Gateway\", 3],\n  [\"Scheduler\", \"Logger\", 2],\n  [\"Auth Service\", \"Database\", 8],\n  [\"Auth Service\", \"Logger\", 3],\n  [\"API Gateway\", \"Database\", 9],\n  [\"API Gateway\", \"Cache\", 6],\n  [\"API Gateway\", \"Validator\", 4],\n  [\"Database\", \"Logger\", 2],\n  [\"Cache\", \"Logger\", 2],\n  [\"UI Components\", \"State Store\", 7],\n  [\"State Store\", \"API Gateway\", 8],\n  [\"State Store\", \"Auth Service\", 5],\n  [\"Validator\", \"Utils\", 3],\n  [\"Config\", \"Logger\", 2],\n  [\"State Store\", \"UI Components\", 2],\n];\n\nconst degree = {};\nmoduleDefs.forEach(([name]) => (degree[name] = 0));\ndependencies.forEach(([source, target]) => {\n  degree[source] += 1;\n  degree[target] += 1;\n});\n\nconst nodes = moduleDefs.map(([name, category]) => ({\n  name,\n  category,\n  symbolSize: 26 + degree[name] * 5,\n  label: { color: t.ink },\n}));\n\n// Heaviest-weight edges (the most-imported-from modules) get a stronger\n// stroke so the busiest dependencies stand out from the general crisscross.\nconst edges = dependencies.map(([source, target, weight]) => ({\n  source,\n  target,\n  lineStyle: { width: 1 + weight / 2.2, opacity: weight >= 8 ? 0.85 : 0.5 },\n}));\n\n// --- Init --------------------------------------------------------------------\nconst chart = echarts.init(document.getElementById(\"container\"));\n\n// --- Option -------------------------------------------------------------------\nchart.setOption({\n  animation: false,\n  color: t.palette,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"network-directed · javascript · echarts · anyplot.ai\",\n    left: \"center\",\n    textStyle: { color: t.ink, fontSize: 22 },\n  },\n  legend: {\n    data: CATEGORIES,\n    bottom: 14,\n    left: \"center\",\n    textStyle: { color: t.inkSoft, fontSize: 16 },\n  },\n  series: [\n    {\n      type: \"graph\",\n      layout: \"circular\",\n      circular: { rotateLabel: true },\n      center: [\"50%\", \"50%\"],\n      radius: 185,\n      categories: CATEGORIES.map((name) => ({ name })),\n      data: nodes,\n      edges,\n      roam: false,\n      edgeSymbol: [\"none\", \"arrow\"],\n      edgeSymbolSize: [0, 14],\n      label: { show: true, position: \"right\", fontSize: 15 },\n      lineStyle: { color: t.inkSoft, curveness: 0.2 },\n      emphasis: { disabled: true },\n    },\n  ],\n});\n"}