All files / src/services odata.ts

0% Statements 0/35
0% Branches 0/10
0% Functions 0/3
0% Lines 0/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128                                                                                                                                                                                                                                                               
import fetch from "node-fetch";
 
/**
 * Service for making requests to the official Dutch Parliament OData API
 */
export class ODataService {
  private readonly BASE_URL = "https://gegevensmagazijn.tweedekamer.nl/OData/v4/2.0";
 
  /**
   * Maps old endpoint names to new ones
   * @param endpoint The original endpoint path
   * @returns The mapped endpoint path
   */
  private mapEndpoint(endpoint: string): string {
    // Map of old endpoint names to new ones
    const endpointMapping: Record<string, string> = {
      '/Personen': '/Persoon',
      '/Activiteiten': '/Activiteit',
      '/Zaken': '/Zaak',
      '/Documenten': '/Document',
      '/Vergaderingen': '/Vergadering',
      '/Verslagen': '/Verslag',
      '/Toezeggingen': '/Toezegging'
    };
 
    // Check if the endpoint starts with any of the old names
    for (const [oldPrefix, newPrefix] of Object.entries(endpointMapping)) {
      Iif (endpoint.startsWith(oldPrefix)) {
        return endpoint.replace(oldPrefix, newPrefix);
      }
    }
 
    return endpoint;
  }
 
  /**
   * Fetches a list of all current Members of Parliament
   * @returns Array of MP data
   */
  async getPersons(): Promise<any[]> {
    try {
      const res = await fetch(
        `${this.BASE_URL}/Persoon?$filter=Verwijderd eq false and (Functie eq 'Eerste Kamerlid' or Functie eq 'Tweede Kamerlid')`,
        {
          headers: {
            Accept: "application/json",
            'User-Agent': 'Mozilla/5.0 (compatible; OpenTK-MCP/1.0)'
          },
          // We would add timeout here, but it's not supported in the RequestInit type
        }
      );
 
      Iif (!res.ok) {
        console.error(`OData API error: ${res.status} ${res.statusText}`);
        return [];
      }
 
      const text = await res.text();
 
      try {
        const data = JSON.parse(text) as { value: any[] };
        return data.value || [];
      } catch (error) {
        console.error(`Failed to parse OData API response: ${(error as Error).message}`);
        return [];
      }
    } catch (error) {
      console.error(`Error fetching persons from OData API: ${(error as Error).message}`);
      return [];
    }
  }
 
  /**
   * Fetches a specific Member of Parliament by ID
   * @param id The ID of the MP to fetch
   * @returns MP data or null if not found
   */
  async getPerson(id: number): Promise<any | null> {
    try {
      // Try with the new endpoint first
      try {
        const res = await fetch(
          `${this.BASE_URL}/Persoon(${id})`,
          {
            headers: {
              Accept: "application/json",
              'User-Agent': 'Mozilla/5.0 (compatible; OpenTK-MCP/1.0)'
            }
          }
        );
 
        Iif (!res.ok) {
          throw new Error(`API error: ${res.status} ${res.statusText}`);
        }
 
        const data = await res.json();
        return data || null;
      } catch (error) {
        // If the new endpoint fails, try the old one as fallback
        console.log(`New endpoint failed, trying old endpoint: ${(error as Error).message}`);
 
        const fallbackRes = await fetch(
          `${this.BASE_URL}/Personen(${id})`,
          {
            headers: {
              Accept: "application/json",
              'User-Agent': 'Mozilla/5.0 (compatible; OpenTK-MCP/1.0)'
            }
          }
        );
 
        Iif (!fallbackRes.ok) {
          throw new Error(`API error: ${fallbackRes.status} ${fallbackRes.statusText}`);
        }
 
        const fallbackData = await fallbackRes.json();
        return fallbackData || null;
      }
    } catch (error) {
      console.error(`Error fetching person with ID ${id}: ${(error as Error).message}`);
      return null;
    }
  }
}
 
// Export a singleton instance
export const odataService = new ODataService();