@@ -5,6 +5,7 @@ import { parseFeed } from './feed-parser';
55import type { ParsedFeed , FeedItem } from './types' ;
66import {
77 fetchDocumentsForAuthor ,
8+ fetchSingleDocument ,
89 filterByPublication ,
910 digestScope ,
1011 MAX_DOCUMENTS_PER_AUTHOR ,
@@ -786,6 +787,15 @@ export function initDatabase(db: Database): void {
786787 cached_at INTEGER NOT NULL
787788 )
788789 ` ) ;
790+ // Migration: add name + theme + fonts columns, all consumed by the optional
791+ // magazine view of a curated Collection. `name` is the publication title,
792+ // `theme` is the JSON `basicTheme` palette (colors), and `fonts` is the JSON
793+ // `publicationTheme` typography (Google Font family names).
794+ const pubColumns = db . query < { name : string } , [ ] > ( `PRAGMA table_info(publication_cache)` ) . all ( ) ;
795+ const pubColNames = new Set ( pubColumns . map ( ( c ) => c . name ) ) ;
796+ if ( ! pubColNames . has ( 'name' ) ) db . run ( `ALTER TABLE publication_cache ADD COLUMN name TEXT` ) ;
797+ if ( ! pubColNames . has ( 'theme' ) ) db . run ( `ALTER TABLE publication_cache ADD COLUMN theme TEXT` ) ;
798+ if ( ! pubColNames . has ( 'fonts' ) ) db . run ( `ALTER TABLE publication_cache ADD COLUMN fonts TEXT` ) ;
789799
790800 // Per-author resolved standard.site documents. Same freshness/backoff shape as
791801 // `cache`, keyed by the author DID. Documents are stored unfiltered (full
@@ -2164,6 +2174,26 @@ export function createApp(db: Database, config: AppConfig) {
21642174 // Bulk standard.site document endpoint. Symmetric with /feeds, but keyed by
21652175 // author DID instead of feed URL. Returns each requested author's documents
21662176 // (scoped to a publication and trimmed to what the client hasn't seen yet).
2177+ // On-demand fetch of a single standard.site document by at:// URI. Serves
2178+ // pieces opened from a Collection edition whose authors the reader doesn't
2179+ // subscribe to (so they're in no cached author list). Resolved fresh.
2180+ app . get ( '/document' , async ( c ) => {
2181+ if ( proxySecret && c . req . header ( 'X-Proxy-Secret' ) !== proxySecret ) {
2182+ return c . json ( { error : 'Unauthorized' } , 401 ) ;
2183+ }
2184+
2185+ const uri = c . req . query ( 'uri' ) ;
2186+ if ( ! uri || ! uri . startsWith ( 'at://' ) ) {
2187+ return c . json ( { error : 'Missing or invalid uri' } , 400 ) ;
2188+ }
2189+
2190+ const document = await fetchSingleDocument ( db , uri ) ;
2191+ if ( ! document ) {
2192+ return c . json ( { error : 'Document not found' } , 404 ) ;
2193+ }
2194+ return c . json ( { document } ) ;
2195+ } ) ;
2196+
21672197 app . post ( '/documents' , async ( c ) => {
21682198 if ( proxySecret && c . req . header ( 'X-Proxy-Secret' ) !== proxySecret ) {
21692199 return c . json ( { error : 'Unauthorized' } , 401 ) ;
0 commit comments