A personal website powered by Astro and ATProto
1import type { GeneratedLexiconUnion, GeneratedLexiconTypeMap } from '../generated/lexicon-types';
2
3// Type-safe component registry
4export interface ComponentRegistryEntry<T = any> {
5 component: string;
6 props?: T;
7}
8
9export type ComponentRegistry = {
10 [K in keyof GeneratedLexiconTypeMap]?: ComponentRegistryEntry;
11} & {
12 [key: string]: ComponentRegistryEntry; // Fallback for unknown types
13};
14
15// Default registry - add your components here
16export const registry: ComponentRegistry = {
17 'ComWhtwndBlogEntry': {
18 component: 'WhitewindBlogPost',
19 props: {}
20 },
21 'AStatusUpdate': {
22 component: 'StatusUpdate',
23 props: {}
24 },
25 // Bluesky posts (not in generated types, but used by components)
26 'app.bsky.feed.post': {
27 component: 'BlueskyPost',
28 props: {}
29 },
30
31};
32
33// Type-safe component lookup
34export function getComponentInfo<T extends keyof GeneratedLexiconTypeMap>(
35 $type: T
36): ComponentRegistryEntry | null {
37 return registry[$type] || null;
38}
39
40// Helper to register a new component
41export function registerComponent<T extends keyof GeneratedLexiconTypeMap>(
42 $type: T,
43 component: string,
44 props?: any
45): void {
46 registry[$type] = { component, props };
47}
48
49// Auto-assignment for unknown types (fallback)
50export function autoAssignComponent($type: string): ComponentRegistryEntry {
51 // Convert NSID to component name
52 const parts = $type.split('.');
53 const componentName = parts[parts.length - 1]
54 .split('-')
55 .map(part => part.charAt(0).toUpperCase() + part.slice(1))
56 .join('');
57
58 return {
59 component: componentName,
60 props: {}
61 };
62}