feat(Wikidata API): implement endpoints for fetching property labels, properties, and suggestions

This commit is contained in:
ryan 2025-07-03 16:34:26 +03:00
parent c5380c0661
commit d480495715
3 changed files with 169 additions and 0 deletions

View file

@ -0,0 +1,54 @@
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
try {
const { propertyIds } = await request.json();
if (!propertyIds || !Array.isArray(propertyIds)) {
return NextResponse.json({ error: 'propertyIds array is required' }, { status: 400 });
}
const cleanIds = propertyIds.map(id => id.replace('http://www.wikidata.org/prop/', ''));
const propertyIdsStr = cleanIds.join(' wd:');
const sparqlQuery = `
SELECT ?prop ?propLabel WHERE {
VALUES ?prop { wd:${propertyIdsStr} }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
`;
const url = `https://query.wikidata.org/sparql?query=${encodeURIComponent(sparqlQuery)}&format=json`;
const response = await fetch(url, {
headers: {
'Accept': 'application/json',
'User-Agent': 'WikidataApp/1.0 (https://example.com/contact)'
}
});
if (!response.ok) {
throw new Error(`Wikidata SPARQL error: ${response.status}`);
}
const data = await response.json();
const result: Record<string, string> = {};
if (data.results?.bindings) {
for (const binding of data.results.bindings) {
const propUri = binding.prop?.value;
const label = binding.propLabel?.value || '';
if (propUri) {
const propId = propUri.split('/').pop() || '';
result[propId] = label;
}
}
}
return NextResponse.json(result);
} catch (error) {
console.error('Error fetching property labels:', error);
return NextResponse.json({});
}
}

View file

@ -0,0 +1,59 @@
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const wikidataId = searchParams.get('wikidataId');
if (!wikidataId || typeof wikidataId !== 'string') {
return NextResponse.json({ error: 'wikidataId parameter is required' }, { status: 400 });
}
try {
const sparqlQuery = `
SELECT ?prop ?propLabel ?value ?valueLabel WHERE {
wd:${wikidataId} ?prop ?statement.
?statement ?ps ?value.
?property wikibase:claim ?prop.
?property wikibase:statementProperty ?ps.
SERVICE wikibase:label {
bd:serviceParam wikibase:language "en".
?prop rdfs:label ?propLabel.
?value rdfs:label ?valueLabel.
}
}
`;
const url = `https://query.wikidata.org/sparql?query=${encodeURIComponent(sparqlQuery)}&format=json`;
const response = await fetch(url, {
headers: {
'Accept': 'application/json',
'User-Agent': 'WikidataApp/1.0 (https://example.com/contact)'
}
});
if (!response.ok) {
throw new Error(`Wikidata SPARQL error: ${response.status}`);
}
const data = await response.json();
const result: Record<string, string> = {};
if (data.results?.bindings) {
for (const binding of data.results.bindings) {
const propUri = binding.prop?.value;
const value = binding.valueLabel?.value || binding.value?.value || '';
if (propUri) {
const propId = propUri.split('/').pop() || '';
result[propId] = value;
}
}
}
return NextResponse.json(result);
} catch (error) {
console.error('Error fetching Wikidata properties:', error);
return NextResponse.json({});
}
}

View file

@ -0,0 +1,56 @@
import { NextRequest, NextResponse } from 'next/server';
// Define interfaces for Wikidata API response
interface WikidataSearchItem {
id: string;
label?: string;
description?: string;
concepturi?: string;
url?: string;
title?: string;
}
interface WikidataSearchResponse {
search?: WikidataSearchItem[];
searchinfo?: {
search: string;
};
success?: number;
}
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const query = searchParams.get('query');
if (!query || typeof query !== 'string') {
return NextResponse.json({ error: 'Query parameter is required' }, { status: 400 });
}
try {
const wikidataUrl = `https://www.wikidata.org/w/api.php?action=wbsearchentities&search=${encodeURIComponent(query)}&language=en&limit=5&format=json&origin=*`;
const response = await fetch(wikidataUrl, {
headers: {
'User-Agent': 'WikidataApp/1.0 (https://example.com/contact)'
}
});
if (!response.ok) {
throw new Error(`Wikidata API error: ${response.status}`);
}
const data: WikidataSearchResponse = await response.json();
// Transform the response to match our WikidataSuggestion interface
const suggestions = (data.search || []).map((item: WikidataSearchItem) => ({
id: item.id,
label: item.label || '',
description: item.description || ''
}));
return NextResponse.json(suggestions);
} catch (error) {
console.error('Error fetching Wikidata suggestions:', error);
return NextResponse.json({ error: 'Failed to fetch suggestions' }, { status: 500 });
}
}