AppView in a box as a Vite plugin thing hatk.dev
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

1# BaseContext: Shared Hydration Context 2 3**Goal:** Extract a shared `BaseContext` type from hatk so hydrators work with both feed and XRPC contexts without manual field spreading or `as any` casts. 4 5**Problem:** `HydrateContext` and `XrpcContext` share 90% of their fields (db, lookup, count, getRecords, labels, blobUrl, viewer). Hydrators that need to work with both must manually spread every field and cast. Adding `getRecords` to `XrpcContext` required touching four construction sites. 6 7## Design 8 9### BaseContext 10 11Shared interface in `hydrate.ts`. Provides data access tools any hydrator needs. 12 13```ts 14export interface BaseContext { 15 viewer: { did: string; handle?: string } | null 16 db: { query: (sql: string, params?: unknown[]) => Promise<unknown[]> } 17 getRecords: <R = unknown>(collection: string, uris: string[]) => Promise<Map<string, Row<R>>> 18 lookup: <R = unknown>(collection: string, field: string, values: string[]) => Promise<Map<string, Row<R>>> 19 count: (collection: string, field: string, values: string[]) => Promise<Map<string, number>> 20 labels: (uris: string[]) => Promise<Map<string, unknown[]>> 21 blobUrl: (did: string, ref: unknown, preset?: 'avatar' | 'banner' | 'feed_thumbnail' | 'feed_fullsize') => string | undefined 22} 23``` 24 25`buildBaseContext(viewer)` constructs one. No items parameter — items are always a separate argument. 26 27### XrpcContext extends BaseContext 28 29Adds XRPC-specific fields: params, cursor, limit, search, resolve, exists, packCursor, unpackCursor, isTakendown, filterTakendownDids, db.run. Context construction in xrpc.ts and opengraph.ts reuses `buildBaseContext` and extends. 30 31### Feed hydrate signature 32 33Changes from `(ctx: HydrateContext<T>) => Promise<View[]>` to `(ctx: BaseContext, items: Row<T>[]) => Promise<View[]>`. `HydrateContext` is removed entirely. 34 35### Hydrator reuse 36 37XRPC handlers pass `ctx` directly to hydrators since `XrpcContext extends BaseContext`: 38 39```ts 40// Before 41const galleries = await hydrateGalleries({ 42 items: result.records, viewer: ctx.viewer, db: ctx.db, 43 getRecords: ctx.getRecords, lookup: ctx.lookup, count: ctx.count, 44 labels: ctx.labels, blobUrl: ctx.blobUrl, 45} as any); 46 47// After 48const galleries = await hydrateGalleries(ctx, result.records); 49``` 50 51## Files to change 52 53**hatk framework:** 54- `hydrate.ts` — Add BaseContext, remove HydrateContext, buildBaseContext 55- `xrpc.ts` — XrpcContext extends BaseContext, reuse buildBaseContext 56- `opengraph.ts` — Reuse buildBaseContext 57- `feeds.ts` — Hydrate signature, executeFeed, exports 58- `cli.ts` — Codegen: BaseContext imports/exports, defineFeed overloads 59 60**Template projects:** 61- `server/feeds/_hydrate.ts` — Accept (ctx: BaseContext, items: Row<T>[]) 62- `server/feeds/*.ts` — Pass (ctx, items) to hydrate 63- `server/xrpc/*.ts` — Pass ctx directly to hydrators