API opcional do grafo

Esta API processa o vault Obsidian e gera um grafo de conhecimento interativo. É uma parte essencial da arquitetura backend do projeto.

Conceitos Relacionados

Para entender como essa API se integra no pipeline de desenvolvimento:

Serviço

src/app/api/services/VaultService.ts:

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
 
interface GraphNode { id: string; name: string; path: string; }
interface GraphLink { source: string; target: string; }
interface GraphData { nodes: GraphNode[]; links: GraphLink[]; }
 
class VaultService {
  private contentDir = path.join(process.cwd(), 'obsidian-site', 'content');
  private cache: { data: GraphData | null; timestamp: number } = { data: null, timestamp: 0 };
  private CACHE_DURATION = 5 * 60 * 1000;
 
  private normalizeFileName(name: string) {
    return name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
  }
 
  private extractLinks(content: string) {
    const linkRegex = /\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g;
    const links: string[] = [];
    let match;
    while ((match = linkRegex.exec(content)) !== null) links.push(match[1].trim());
    return links;
  }
 
  private readMarkdownFiles(dir: string, baseDir: string = dir): GraphNode[] {
    const nodes: GraphNode[] = [];
    const items = fs.readdirSync(dir);
 
    for (const item of items) {
      const fullPath = path.join(dir, item);
      const stat = fs.statSync(fullPath);
 
      if (stat.isDirectory()) {
        nodes.push(...this.readMarkdownFiles(fullPath, baseDir));
      } else if (item.endsWith('.md')) {
        const relativePath = path.relative(baseDir, fullPath);
        const fileContent = fs.readFileSync(fullPath, 'utf-8');
        const { data } = matter(fileContent);
        const id = relativePath.replace(/\.md$/, '').replace(/\\/g, '/');
        const name = data.title || path.basename(item, '.md');
        nodes.push({ id, name, path: relativePath });
      }
    }
    return nodes;
  }
 
  public getGraphData(): GraphData {
    const now = Date.now();
    if (this.cache.data && now - this.cache.timestamp < this.CACHE_DURATION) return this.cache.data;
 
    const nodes = this.readMarkdownFiles(this.contentDir);
    const links: GraphLink[] = [];
    const nodeMap = new Map(nodes.map(node => [this.normalizeFileName(node.name), node.id]));
 
    for (const node of nodes) {
      const filePath = path.join(this.contentDir, node.path);
      const content = fs.readFileSync(filePath, 'utf-8');
      const linkedNames = this.extractLinks(content);
 
      for (const linkedName of linkedNames) {
        const normalizedTarget = this.normalizeFileName(linkedName);
        const targetId = nodeMap.get(normalizedTarget);
        if (targetId && targetId !== node.id) links.push({ source: node.id, target: targetId });
      }
    }
 
    const graphData = { nodes, links };
    this.cache = { data: graphData, timestamp: now };
    return graphData;
  }
}
 
export const vaultService = new VaultService();

Rota

src/app/api/graph/route.ts:

import { NextResponse } from 'next/server';
import { vaultService } from '../services/VaultService';
 
export async function GET() {
  try {
    const graphData = vaultService.getGraphData();
    return NextResponse.json(graphData);
  } catch (error) {
    console.error('Erro ao gerar grafo:', error);
    return NextResponse.json({ error: 'Erro ao processar vault' }, { status: 500 });
  }
}

Dependência

Instale:

npm install gray-matter

Integração com CI/CD

Esta API é automaticamente processada durante o pipeline de build. Veja como configurar:

Pipeline GitLab

O arquivo pipeline-gitlab mostra como:

  • Executar ./scripts/update-vault.sh para gerar o vault estático
  • Criar artifacts com o grafo processado
  • Publicar no GitLab Pages ou Vercel

Stages Relacionados

Conforme explicado em Stages:

  1. test: Validação de links e estrutura do vault
  2. build: Execução do VaultService para gerar o grafo
  3. deploy: Publicação do grafo processado

Jobs Específicos

Em Jobs - Os Blocos da Pipeline, você pode configurar:

build-vault-graph:
  stage: build
  script:
    - npm run build  # Executa o VaultService
  artifacts:
    paths:
      - .next/cache

Fluxo de Desenvolvimento

graph LR
    A[Obsidian Notes] --> B[VaultService]
    B --> C[Graph Data]
    C --> D[React Component]
    D --> E[Visualização Interativa]

    B --> F[CI/CD Pipeline]
    F --> G[Deploy Automatizado]

Referências

Tags de Busca

#API #Backend #NextJS #GraphData #Obsidian #CI-CD #DevOps #Automation