feat(web): scaffold API clients

This commit is contained in:
Collin Barrett 2025-06-25 20:02:43 -05:00
parent 62e8a5a0eb
commit 49b513ac6a
9 changed files with 186 additions and 2 deletions

View file

@ -1 +1,2 @@
export const API_BASE_URL = "https://api.filterlists.com";
export const DEFAULT_REVALIDATE_SECS = 86400;

View file

@ -0,0 +1,53 @@
import { API_BASE_URL, DEFAULT_REVALIDATE_SECS } from "./constants";
export type ViewUrl = {
segmentNumber: number;
primariness: number;
url: string | null;
};
export type FilterListDetails = {
id: number;
name: string;
description: string | null;
licenseId: number;
syntaxIds: number[] | null;
languageIds: number[] | null;
tagIds: number[] | null;
viewUrls: ViewUrl[] | null;
homeUrl: string | null;
onionUrl: string | null;
policyUrl: string | null;
submissionUrl: string | null;
issuesUrl: string | null;
forumUrl: string | null;
chatUrl: string | null;
emailAddress: string | null;
donateUrl: string | null;
maintainerIds: number[] | null;
upstreamFilterListIds: number[] | null;
forkFilterListIds: number[] | null;
includedInFilterListIds: number[] | null;
includesFilterListIds: number[] | null;
dependencyFilterListIds: number[] | null;
dependentFilterListIds: number[] | null;
};
export async function getFilterListDetails(
id: number,
): Promise<FilterListDetails> {
const response = await fetch(`${API_BASE_URL}/lists/${id}`, {
next: { revalidate: DEFAULT_REVALIDATE_SECS },
});
if (!response.ok) {
if (response.status === 404) {
throw new Error(`FilterList with ID ${id} not found`);
}
throw new Error(
`Failed to fetch FilterList details: ${response.statusText}`,
);
}
return await response.json();
}

View file

@ -1,4 +1,4 @@
import { API_BASE_URL } from "./constants";
import { API_BASE_URL, DEFAULT_REVALIDATE_SECS } from "./constants";
export type FilterList = {
id: number;
@ -14,7 +14,7 @@ export type FilterList = {
export async function getFilterLists(): Promise<FilterList[]> {
const response = await fetch(`${API_BASE_URL}/lists`, {
next: { revalidate: 86400 },
next: { revalidate: DEFAULT_REVALIDATE_SECS },
});
if (!response.ok) {

View file

@ -0,0 +1,20 @@
import { API_BASE_URL, DEFAULT_REVALIDATE_SECS } from "./constants";
export type Language = {
id: number;
iso6391: string | null;
name: string | null;
filterListIds: number[] | null;
};
export async function getLanguages(): Promise<Language[]> {
const response = await fetch(`${API_BASE_URL}/languages`, {
next: { revalidate: DEFAULT_REVALIDATE_SECS },
});
if (!response.ok) {
throw new Error(`Failed to fetch languages: ${response.statusText}`);
}
return await response.json();
}

View file

@ -0,0 +1,23 @@
import { API_BASE_URL, DEFAULT_REVALIDATE_SECS } from "./constants";
export type License = {
id: number;
name: string | null;
url: string | null;
permitsModification: boolean;
permitsDistribution: boolean;
permitsCommercialUse: boolean;
filterListIds: number[] | null;
};
export async function getLicenses(): Promise<License[]> {
const response = await fetch(`${API_BASE_URL}/licenses`, {
next: { revalidate: DEFAULT_REVALIDATE_SECS },
});
if (!response.ok) {
throw new Error(`Failed to fetch licenses: ${response.statusText}`);
}
return await response.json();
}

View file

@ -0,0 +1,22 @@
import { API_BASE_URL, DEFAULT_REVALIDATE_SECS } from "./constants";
export type Maintainer = {
id: number;
name: string | null;
url: string | null;
emailAddress: string | null;
twitterHandle: string | null;
filterListIds: number[] | null;
};
export async function getMaintainers(): Promise<Maintainer[]> {
const response = await fetch(`${API_BASE_URL}/maintainers`, {
next: { revalidate: DEFAULT_REVALIDATE_SECS },
});
if (!response.ok) {
throw new Error(`Failed to fetch maintainers: ${response.statusText}`);
}
return await response.json();
}

View file

@ -0,0 +1,23 @@
import { API_BASE_URL, DEFAULT_REVALIDATE_SECS } from "./constants";
export type Software = {
id: number;
name: string | null;
description: string | null;
homeUrl: string | null;
downloadUrl: string | null;
supportsAbpUrlScheme: boolean;
syntaxIds: number[] | null;
};
export async function getSoftware(): Promise<Software[]> {
const response = await fetch(`${API_BASE_URL}/software`, {
next: { revalidate: DEFAULT_REVALIDATE_SECS },
});
if (!response.ok) {
throw new Error(`Failed to fetch software: ${response.statusText}`);
}
return await response.json();
}

View file

@ -0,0 +1,22 @@
import { API_BASE_URL, DEFAULT_REVALIDATE_SECS } from "./constants";
export type Syntax = {
id: number;
name: string | null;
description: string | null;
url: string | null;
filterListIds: number[] | null;
softwareIds: number[] | null;
};
export async function getSyntaxes(): Promise<Syntax[]> {
const response = await fetch(`${API_BASE_URL}/syntaxes`, {
next: { revalidate: DEFAULT_REVALIDATE_SECS },
});
if (!response.ok) {
throw new Error(`Failed to fetch syntaxes: ${response.statusText}`);
}
return await response.json();
}

View file

@ -0,0 +1,20 @@
import { API_BASE_URL, DEFAULT_REVALIDATE_SECS } from "./constants";
export type Tag = {
id: number;
name: string | null;
description: string | null;
filterListIds: number[] | null;
};
export async function getTags(): Promise<Tag[]> {
const response = await fetch(`${API_BASE_URL}/tags`, {
next: { revalidate: DEFAULT_REVALIDATE_SECS },
});
if (!response.ok) {
throw new Error(`Failed to fetch tags: ${response.statusText}`);
}
return await response.json();
}