~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain

photography-focused photo sharing platform

grain.social
1 collaborator
0
2

web: Profiles, galleries, feeds, stories and search read from grain-serve

Merged
Merged chadtmiller.com asked to merge into feature/rust from grain.social/grain:web/reads

What changes

Stacked on web/client (its pull first). The web's reads move to grain-serve's social.grain.* methods, each called as query<typeof <method>.main>(nsid, params, fetch) with the schema npm run lex generates, as knotless's web calls its queries:

  • Profiles and the graph: actor.getProfile, actor.getFavorites, actor.getSuggestedFollows, graph.getFollowers, getFollowing, getKnownFollowers, getBlocks, getMutes.
  • Galleries: gallery.getGallery, gallery.getFavorites, comment.getThread, gallery.getCameras, gallery.getLocations (with pins).
  • Feeds: social.grain.feed.getFeed, which names a feed by URI. $lib/feed asks describeFeeds once, keeps each feed's URI by name, and getFeed(name, params, fetch) asks for a page; Following and For You no longer send actor, grain-serve reading the viewer from the cookie.
  • Stories: story.getAuthors, getStory, getStories, getArchive; marking one watched is story.markViewed.
  • Search: gallery.searchGalleries, actor.searchActors, actor.searchActorsTypeahead (login, search, sharing a private gallery).
  • Sitemap: server.getSitemap, by the route's fetch.
  • Labels: the definitions the web blurs and reports by are a table in $lib/labels, as grain-serve defines them (grain::labels::DEFINITIONS), in its order, since grain-serve gives listLabelDefinitions only to its admins.
  • Types: components import view types from the generated lexicons ($lib/lexicons/social/grain/gallery/defs.ts) rather than the old generated client.

No read sends viewer any more: who asks is the cookie's. The private gallery page's "Sign in again" logs in by POST /oauth/login rather than navigating to the old GET route.

Why

The second slice of moving the web onto grain-serve. Each renamed method takes and answers what the old one did (lexicons/README.md), less viewer; the feeds are the one change of shape, a URI for a name.

How it was checked

npm run check (with lex) and vp test pass locally; test/storyViews.test.ts and test/resolveRouteActor.test.ts now mock $lib/xrpc and check the new method names. The runner's verdict is below. Not tried in a browser against a running grain-serve.

Shortcomings

  • The generated types brand identifiers (DidString, AtUriString, AtIdentifierString) and leave unions open (Unknown$TypedObject), so call sites cast a route's string to its brand, and a gallery's items are read as PhotoView[], as knotless's web casts its own.
  • Called here but not served by grain-serve yet: graph.getBlocks, graph.getMutes, story.getArchive, story.markViewed, server.getSitemap. Until it serves them, the blocks and mutes settings, the story archive and the sitemap answer 501, and watched stories are not kept.
  • Still on the old methods, for the spaces port: private galleries (listPrivateGalleries, getPrivateGallery, getSpaceMembers, getSpaceSupport, listSharedGalleries) and groups and their pools (getGroup, getGroupHost, listGroups, getGroupSubmissions, listPoolGalleries, listPoolFeed, getPoolGallery). The group and groups feeds are on getFeed.
  • Notifications and every write move in the next pull.

🤖 Generated with Claude Code

Approved

This pull moves the web's reads for profiles, the graph, galleries, feeds, stories, search and the sitemap onto grain-serve's social.grain.* methods. It also adds a $lib/feed that resolves feed names to URIs through describeFeeds, and a static label table.

The diff is about 4,300 lines and I did not read all of it. I read web/src/lib/feed.ts and the private gallery's "Sign in again" login path (a POST /oauth/login through $lib/auth). Both look correct. The feed URI cache is shared across requests, and a failed describeFeeds call is retried on the next ask. I found nothing that must change.

All four checks (check, test, rust, harness) were still queued when I looked, so none had a result.

The five methods the pull lists as not yet served (getBlocks, getMutes, getArchive, markViewed, getSitemap) will answer 501. The pull says so, but don't merge it to production until grain-serve serves them. The label table in $lib/labels duplicates grain::labels::DEFINITIONS, so the two can drift apart.

On the label table: it is a copy because grain-serve gives listLabelDefinitions only to its admins, and the web needs the definitions for every viewer to blur by. The copy goes once grain-serve serves the definitions publicly (or the web asks for them by a public method); until then it is kept to grain::labels::DEFINITIONS by hand, as the pull says.

On the five methods answering 501: agreed. This goes into feature/rust, not main; nothing here deploys until grain-serve serves them.

Approved

Since my last review the head moved from 5b94549 to b76c2f8. The only change is a merge of web/client, which adds the commit "Preferences read on the server are not kept across requests". I didn't re-read the merge. I found nothing new that must change.

My earlier review asked for nothing to change. It noted the label table's drift risk and the five methods that answer 501 until grain-serve serves them. You replied that the table is kept in step by hand until grain-serve serves definitions publicly. You also said this goes into feature/rust and nothing deploys until those methods exist. That answers both points.

All four checks (check, test, rust, harness) were still queued on b76c2f8, so none has a result yet. Please wait for them to pass before you merge.

Merged as b76c2f8
Part of a stack of 2
  1. web: Profiles, galleries, feeds, stories and search read from grain-serve Landed as b76c2f8
  2. main