Skip to content

API Integration and Data Flow

API Architecture Overview

graph TB
    subgraph "Frontend (Next.js)"
        UI[User Interface]
        APIClient[API Client Layer]
        StateMan[State Management]
        Cache[Client Cache]
    end

    subgraph "API Layer"
        NextAuth[NextAuth Endpoints]
        APIRoutes[API Routes]
        Middleware[Auth Middleware]
    end

    subgraph "Backend (NestJS)"
        Controllers[Controllers]
        Services[Services]
        Guards[Auth Guards]
        DTOs[Data Transfer Objects]
    end

    subgraph "Data Layer"
        Database[(PostgreSQL)]
        Redis[Redis Cache]
        External[External APIs]
    end

    UI --> APIClient
    APIClient --> StateMan
    StateMan --> Cache

    APIClient --> NextAuth
    APIClient --> APIRoutes
    APIRoutes --> Middleware

    Middleware --> Controllers
    Controllers --> Guards
    Guards --> Services
    Services --> DTOs

    Services --> Database
    Services --> Redis
    Services --> External

API Request Flow

sequenceDiagram
    participant User
    participant Frontend as Next.js App
    participant Auth as NextAuth
    participant API as API Routes
    participant Backend as NestJS API
    participant DB as PostgreSQL
    participant Cache as Redis

    User->>Frontend: User Action
    Frontend->>Auth: Check Authentication
    Auth-->>Frontend: Return Auth Status

    alt Authenticated
        Frontend->>API: API Request + Token
        API->>Backend: Forward Request
        Backend->>Cache: Check Cache

        alt Cache Hit
            Cache-->>Backend: Return Cached Data
        else Cache Miss
            Backend->>DB: Query Database
            DB-->>Backend: Return Data
            Backend->>Cache: Store in Cache
        end

        Backend-->>API: Response Data
        API-->>Frontend: Return Response
        Frontend-->>User: Update UI
    else Not Authenticated
        Frontend->>Auth: Redirect to Login
        Auth-->>User: Show Login Form
    end

API Endpoints

Authentication

Login

  • Endpoint: /api/auth/[...nextauth]
  • Method: POST
  • Purpose: User authentication and session creation
  • Response: Authentication token and user data

Refresh Token

  • Endpoint: /api/auth/[...nextauth]
  • Method: POST
  • Purpose: Refresh expired authentication tokens
  • Response: New authentication token

Document Management

Upload Document

  • Endpoint: /api/documents
  • Method: POST
  • Purpose: Upload new documents for processing
  • Response: Document ID and processing status

Get Unassigned Documents

  • Endpoint: /api/documents
  • Method: GET
  • Purpose: Retrieve documents not assigned to projects
  • Response: Array of unassigned document objects

Create Project

Get User Projects

Profile Management

Profile Statistics

  • Endpoint: /api/profileStats
  • Method: GET
  • Purpose: Retrieve user activity statistics
  • Response: Usage metrics and document counts

Data Models

Document Object

interface Document {
  DocumentID: string;
  DocumentName: string;
  Status: string;
  DateCreated: Date;
  LastModified: Date;
  ClientName: string | null;
}

Project Object

interface Project {
  ProjectID: string;
  Name: string;
  DateCreated: Date;
  ClientName: string;
}

User Statistics

interface ProfileStats {
  documentsInLast7Days: number;
  documentsInLast30Days: number;
  documentsInLastDay: number;
  totalRequestsInLast7Days: number;
  totalRequestsInLast30Days: number;
  totalRequestsInLastDay: number;
}

Data Flow

Document Processing Flow

  1. Upload Phase
// Upload initiation
const handleUpload = async (file: File) => {
  setIsProcessing(true);
  const response = await uploadDocument(file);
  setPayload(response);
};
  1. Processing Phase
// Document processing
const processDocument = async (payload: any) => {
  const stages = ["Parsing", "Processing", "Populating Editor"];
  for (const stage of stages) {
    setCurrentStage(stage);
    await processStage(stage, payload);
  }
  setIsComplete(true);
};
  1. Editor Population
    // Editor data population
    const populateEditor = async (documentId: string) => {
      const documentData = await fetchDocumentData(documentId);
      setEditorContent(documentData);
    };
    

Project Management Flow

  1. Project Creation
const handleNewProject = async (clientName: string, name: string) => {
  await fetch("/app/api/documents/createNewProject", {
    method: "POST",
    body: JSON.stringify({ userID, clientName, name }),
  });
  fetchProjects();
};
  1. Document Assignment
    const assignDocumentToProject = async (
      documentId: string,
      projectId: string
    ) => {
      await fetch("/app/api/documents/assignDocument", {
        method: "POST",
        body: JSON.stringify({ documentId, projectId }),
      });
      refreshDocuments();
    };
    

Error Handling

API Error Structure

interface APIError {
  code: string;
  message: string;
  details?: any;
}

Error Handling Implementation

const handleAPIRequest = async (endpoint: string, options: RequestInit) => {
  try {
    const response = await fetch(endpoint, options);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return await response.json();
  } catch (error) {
    console.error("API Error:", error);
    handleError(error);
  }
};

State Management

Session Management

const { data: session } = useSession();
const userID = session?.user?.userID;

Document State

const [documents, setDocuments] = useState<Document[]>([]);
const [selectedDocument, setSelectedDocument] = useState<string | null>(null);

Processing State

const [isProcessing, setIsProcessing] = useState<boolean>(false);
const [currentStage, setCurrentStage] = useState<number>(0);
const [isComplete, setIsComplete] = useState<boolean>(false);

WebSocket Integration

Real-time Updates

const socket = new WebSocket(WS_URL);

socket.onmessage = (event) => {
  const data = JSON.parse(event.data);
  handleRealtimeUpdate(data);
};

Connection Management

useEffect(() => {
  const connectWebSocket = () => {
    socket.onopen = () => console.log("WebSocket Connected");
    socket.onclose = () => {
      console.log("WebSocket Disconnected");
      setTimeout(connectWebSocket, 3000);
    };
  };

  connectWebSocket();
  return () => socket.close();
}, []);

Security

Token Management

const fetchWithAuth = async (url: string, options: RequestInit) => {
  const session = await getSession();
  return fetch(url, {
    ...options,
    headers: {
      ...options.headers,
      Authorization: `Bearer ${session?.accessToken}`,
    },
  });
};

Request Validation

const validateRequest = (data: any): boolean => {
  if (!data.userID || !data.documentID) {
    throw new Error("Invalid request parameters");
  }
  return true;
};