Decouple Directus from project
This commit is contained in:
+46
-10
@@ -42,7 +42,8 @@ const directusAssetUrlTemplate =
|
||||
process.env.DIRECTUS_ASSET_URL_TEMPLATE && !process.env.DIRECTUS_ASSET_URL_TEMPLATE.includes('example.com')
|
||||
? process.env.DIRECTUS_ASSET_URL_TEMPLATE
|
||||
: undefined;
|
||||
const directusToken = process.env.DIRECTUS_ADMIN_TOKEN;
|
||||
const directusToken = process.env.DIRECTUS_TOKEN ?? process.env.DIRECTUS_ADMIN_TOKEN;
|
||||
const directusDebug = ['1', 'true', 'yes', 'on'].includes((process.env.DIRECTUS_DEBUG ?? '').toLowerCase());
|
||||
const homepageBannerFolder = process.env.DIRECTUS_HOMEPAGE_BANNER_FOLDER ?? 'homepage-banners';
|
||||
const cafePageFolder = process.env.DIRECTUS_CAFE_PAGE_FOLDER ?? 'cafe-page';
|
||||
|
||||
@@ -81,6 +82,15 @@ function directusHeaders(): Record<string, string> | undefined {
|
||||
return { Authorization: `Bearer ${directusToken}` };
|
||||
}
|
||||
|
||||
function directusLog(message: string): void {
|
||||
if (!directusDebug) return;
|
||||
console.warn(`[directus] ${message}`);
|
||||
}
|
||||
|
||||
function directusEndpointLabel(endpoint: URL): string {
|
||||
return `${endpoint.pathname}${endpoint.search}`;
|
||||
}
|
||||
|
||||
async function readCollection<T>(collection: CollectionName): Promise<T[]> {
|
||||
const endpoint = new URL(`/items/${collection}`, directusUrl);
|
||||
endpoint.searchParams.set('limit', '100');
|
||||
@@ -98,27 +108,43 @@ async function readCollection<T>(collection: CollectionName): Promise<T[]> {
|
||||
}
|
||||
|
||||
const payload = (await response.json()) as { data?: T[] };
|
||||
return payload.data ?? [];
|
||||
} catch {
|
||||
const data = payload.data ?? [];
|
||||
directusLog(`collection ${collection}: read ${data.length} item(s)`);
|
||||
return data;
|
||||
} catch (error) {
|
||||
directusLog(`collection ${collection}: using fallback after ${error instanceof Error ? error.message : String(error)}`);
|
||||
return fallbackFor(collection) as T[];
|
||||
}
|
||||
}
|
||||
|
||||
async function readDirectusEndpoint<T>(endpoint: URL): Promise<T[]> {
|
||||
directusLog(`GET ${directusEndpointLabel(endpoint)}`);
|
||||
let response = await fetch(endpoint, {
|
||||
headers: directusHeaders(),
|
||||
});
|
||||
|
||||
if (response.status === 403 && directusToken) {
|
||||
directusLog(`GET ${directusEndpointLabel(endpoint)} returned 403 with token; retrying without token`);
|
||||
response = await fetch(endpoint);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Directus responded with ${response.status}`);
|
||||
let detail = '';
|
||||
try {
|
||||
const payload = (await response.json()) as { errors?: Array<{ message?: string; extensions?: { code?: string; reason?: string } }> };
|
||||
const firstError = payload.errors?.[0];
|
||||
detail = firstError?.extensions?.reason || firstError?.message || '';
|
||||
} catch {
|
||||
detail = '';
|
||||
}
|
||||
|
||||
throw new Error(`Directus responded with ${response.status}${detail ? `: ${detail}` : ''}`);
|
||||
}
|
||||
|
||||
const payload = (await response.json()) as { data?: T[] };
|
||||
return payload.data ?? [];
|
||||
const data = payload.data ?? [];
|
||||
directusLog(`GET ${directusEndpointLabel(endpoint)} returned ${data.length} item(s)`);
|
||||
return data;
|
||||
}
|
||||
|
||||
function extensionFromFilename(filename?: string): string {
|
||||
@@ -177,7 +203,10 @@ async function findFolderByName(name: string): Promise<DirectusFolder | null> {
|
||||
async function getImagesFromFolder(folderName: string, fallbackImages: HomepageBannerImage[]): Promise<HomepageBannerImage[]> {
|
||||
try {
|
||||
const folder = await findFolderByName(folderName);
|
||||
if (!folder) return fallbackImages;
|
||||
if (!folder) {
|
||||
directusLog(`folder "${folderName}": not found; using ${fallbackImages.length} fallback image(s)`);
|
||||
return fallbackImages;
|
||||
}
|
||||
|
||||
const endpoint = new URL('/files', directusUrl);
|
||||
endpoint.searchParams.set('limit', '20');
|
||||
@@ -192,8 +221,15 @@ async function getImagesFromFolder(folderName: string, fallbackImages: HomepageB
|
||||
alt: file.description || file.title || file.filename_download || 'Swansea Airport',
|
||||
}));
|
||||
|
||||
return images.length > 0 ? images : fallbackImages;
|
||||
} catch {
|
||||
if (images.length === 0) {
|
||||
directusLog(`folder "${folderName}": no images found; using ${fallbackImages.length} fallback image(s)`);
|
||||
return fallbackImages;
|
||||
}
|
||||
|
||||
directusLog(`folder "${folderName}": using ${images.length} Directus image(s)`);
|
||||
return images;
|
||||
} catch (error) {
|
||||
directusLog(`folder "${folderName}": using fallback after ${error instanceof Error ? error.message : String(error)}`);
|
||||
return fallbackImages;
|
||||
}
|
||||
}
|
||||
@@ -242,8 +278,8 @@ async function getRecurringEvents(): Promise<EventItem[]> {
|
||||
const endpoint = new URL('/items/event_dates', directusUrl);
|
||||
endpoint.searchParams.set('limit', '100');
|
||||
endpoint.searchParams.set('sort', 'date');
|
||||
endpoint.searchParams.set(
|
||||
'fields',
|
||||
endpoint.searchParams.set(
|
||||
'fields',
|
||||
'id,date,template.id,template.title,template.slug,template.description,template.image.id,template.image.filename_download,template.image.filename_disk,template.logo.id,template.logo.filename_download,template.logo.filename_disk,template.booking_url',
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user