101 lines
3.2 KiB
TypeScript
101 lines
3.2 KiB
TypeScript
import { AuthenticationPage, AuthenticationRules } from "../pages/auth/auth";
|
|
import { NewsData, NewsFeed } from "../pages/feed/news";
|
|
import { NewsItem } from "../pages/feed/news-item";
|
|
|
|
type EndpointURL = "/api" | `http${'s' | ''}://${string}`;
|
|
|
|
interface ErrorDetails {
|
|
code: string,
|
|
message: string,
|
|
}
|
|
|
|
interface APIResponse<T> {
|
|
response ?: T;
|
|
error ?: ErrorDetails;
|
|
}
|
|
|
|
let newsFeed : NewsFeed | null = null;
|
|
let authPage : AuthenticationPage | null = null;
|
|
|
|
class ErrorAPI extends Error {}
|
|
|
|
export class ControllerAPI {
|
|
protected endpoint: EndpointURL;
|
|
constructor(endpoint: EndpointURL = "/api") {
|
|
this.endpoint = endpoint;
|
|
}
|
|
|
|
protected async request<T>(path: string, options: RequestInit = {}): Promise<T> {
|
|
let url : string;
|
|
if (this.endpoint === "/api") {
|
|
url = new URL("/api", window.location.origin).href + path;
|
|
}
|
|
else if (/\/$/i.test(this.endpoint)) {
|
|
url = this.endpoint + path.slice(1);
|
|
}
|
|
else {
|
|
url = this.endpoint + path;
|
|
}
|
|
|
|
const response = await fetch(url, options);
|
|
const result: APIResponse<T> = await response.json();
|
|
if (result.error) throw new ErrorAPI(result.error.message);
|
|
if (result.response === undefined) throw new ErrorAPI("Missing response from API");
|
|
return result.response;
|
|
}
|
|
|
|
protected checkFirstAuth(): boolean {
|
|
// Implement your authentication logic here, e.g., check for a valid token in localStorage
|
|
//const token = localStorage.getItem('authToken');
|
|
//return !!token; // Returns true if token exists and is not empty
|
|
return true;
|
|
}
|
|
|
|
protected throwIfUnauthed(): void {
|
|
// Let's redirect to /auth if not authed
|
|
if (!this.checkFirstAuth()) {
|
|
window.location.href = '/auth';
|
|
}
|
|
}
|
|
|
|
async isAuthenticated(): Promise<boolean> {
|
|
if (!this.checkFirstAuth()) return false;
|
|
|
|
const result = await this.request<boolean>('/isAuthenticated', {
|
|
method: 'GET',
|
|
credentials: 'include' // Include cookies for authentication
|
|
});
|
|
return result;
|
|
}
|
|
|
|
async getNews(returnPage: boolean = false) : Promise<NewsFeed | NewsData[]> {
|
|
this.throwIfUnauthed();
|
|
|
|
const result = await this.request<NewsData[]>('/news', {
|
|
method: 'GET',
|
|
credentials: 'include' // Include cookies for authentication
|
|
});
|
|
if (!returnPage)
|
|
return result;
|
|
if (!newsFeed)
|
|
newsFeed = new NewsFeed(result.map(x => new NewsItem(
|
|
x.id,
|
|
x.title,
|
|
new Date(x.publishedAt),
|
|
x.content,
|
|
x.source
|
|
)));
|
|
return newsFeed;
|
|
}
|
|
|
|
async getAuthRules(returnPage: boolean = false) : Promise<AuthenticationRules | AuthenticationPage> {
|
|
const result = await this.request<AuthenticationRules>('/authenticationRules', {
|
|
method: 'GET',
|
|
credentials: 'include' // Include cookies for authentication
|
|
});
|
|
if (!returnPage) return result;
|
|
if (!authPage)
|
|
authPage = new AuthenticationPage(result);
|
|
return authPage;
|
|
}
|
|
} |