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();
|