your personal website on atproto - mirror forked from flo-bit.dev/blento
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187import { getDetailedProfile, listRecords, resolveHandle, parseUri } from '$lib/atproto';import { CardDefinitionsByType } from '$lib/cards';import type { Item, UserCache, WebsiteData } from '$lib/types';import { compactItems, fixAllCollisions } from '$lib/helper';import { error } from '@sveltejs/kit';import type { Handle } from '@atcute/lexicons';
const CURRENT_CACHE_VERSION = 1;
export async function getCache(handle: string, page: string, cache?: UserCache) { try { const cachedResult = await cache?.get?.(handle);
if (!cachedResult) return; const result = JSON.parse(cachedResult); const update = result.updatedAt; const timePassed = (Date.now() - update) / 1000;
const ONE_DAY = 60 * 60 * 24;
if (!result.version || result.version !== CURRENT_CACHE_VERSION) { console.log('skipping cache because of version mismatch'); return; }
if (timePassed > ONE_DAY) { console.log('skipping cache because of age'); return; }
result.page = 'blento.' + page;
result.publication = (result.publications as Awaited<ReturnType<typeof listRecords>>).find( (v) => parseUri(v.uri).rkey === result.page )?.value;
delete result['publications'];
console.log('using cached result for handle', handle, 'last update', timePassed, 'seconds ago'); return checkData(result); } catch (error) { console.log('getting cached result failed', error); }}
export async function loadData( handle: Handle, cache: UserCache | undefined, forceUpdate: boolean = false, page: string = 'self'): Promise<WebsiteData> { if (!handle) throw error(404);
if (!forceUpdate) { const cachedResult = await getCache(handle, page, cache);
if (cachedResult) return cachedResult; }
if (handle === 'favicon.ico') throw error(404);
console.log('resolving', handle); const did = await resolveHandle({ handle });
const cards = await listRecords({ did, collection: 'app.blento.card' }).catch(() => { console.error('error getting records for collection app.blento.card'); return [] as Awaited<ReturnType<typeof listRecords>>; });
const publications = await listRecords({ did, collection: 'site.standard.publication' }).catch( () => { console.error('error getting records for collection site.standard.publication'); return [] as Awaited<ReturnType<typeof listRecords>>; } );
const profile = await getDetailedProfile({ did });
const cardTypes = new Set(cards.map((v) => v.value.cardType ?? '') as string[]); const cardTypesArray = Array.from(cardTypes);
const additionDataPromises: Record<string, Promise<unknown>> = {};
const loadOptions = { did, handle, cache };
for (const cardType of cardTypesArray) { const cardDef = CardDefinitionsByType[cardType];
if (!cardDef?.loadData) continue;
try { additionDataPromises[cardType] = cardDef.loadData( cards.filter((v) => cardType === v.value.cardType).map((v) => v.value) as Item[], loadOptions ); } catch { console.error('error getting additional data for', cardType); } }
await Promise.all(Object.values(additionDataPromises));
const additionalData: Record<string, unknown> = {}; for (const [key, value] of Object.entries(additionDataPromises)) { try { additionalData[key] = await value; } catch (error) { console.log('error loading', key, error); } }
const result = { page: 'blento.' + page, handle, did, cards: (cards.map((v) => { return { ...v.value }; }) ?? []) as Item[], publications: publications, additionalData, profile, updatedAt: Date.now(), version: CURRENT_CACHE_VERSION };
const stringifiedResult = JSON.stringify(result); await cache?.put?.(handle, stringifiedResult);
const parsedResult = JSON.parse(stringifiedResult); parsedResult.publication = ( parsedResult.publications as Awaited<ReturnType<typeof listRecords>> ).find((v) => parseUri(v.uri).rkey === parsedResult.page)?.value;
delete parsedResult['publications'];
return checkData(parsedResult);}
function migrateFromV0ToV1(data: WebsiteData): WebsiteData { for (const card of data.cards) { if (card.version) continue; card.x *= 2; card.y *= 2; card.h *= 2; card.w *= 2; card.mobileX *= 2; card.mobileY *= 2; card.mobileH *= 2; card.mobileW *= 2; card.version = 1; }
return data;}
function migrateFromV1ToV2(data: WebsiteData): WebsiteData { for (const card of data.cards) { if (!card.version || card.version < 2) { card.page = 'blento.self'; card.version = 2; } } return data;}
function checkData(data: WebsiteData): WebsiteData { data = migrateData(data);
const cards = data.cards.filter((v) => v.page === data.page);
if (cards.length > 0) { fixAllCollisions(cards); fixAllCollisions(cards, true);
compactItems(cards); compactItems(cards, true); }
data.cards = cards;
return data;}
function migrateData(data: WebsiteData): WebsiteData { return migrateFromV1ToV2(migrateFromV0ToV1(data));}