Files
welshman/docs/app/feeds-and-search.md
T
hodlbod fe5c11b00f
tests / tests (push) Failing after 5m4s
rename client, update docs/skills
2026-06-18 19:31:14 +00:00

78 lines
2.9 KiB
Markdown

# Feeds & Search
## Feeds
`app.use(Feeds)` builds `@welshman/feeds` `FeedController`s wired to this app — its router, web-of-trust graph, signer, and net context are all injected for you, so the controller can resolve scopes (`Self`, `Follows`, `Network`, `Followers`) and WoT ranges to real pubkeys and fetch through the app's repository and pool.
```typescript
import {makeIntersectionFeed, makeScopeFeed, makeKindFeed, Scope} from "@welshman/feeds"
const controller = app.use(Feeds).makeFeedController({
feed: makeIntersectionFeed(
makeScopeFeed(Scope.Follows),
makeKindFeed(1),
),
onEvent: event => {
// render the event
},
})
await controller.load(50) // load a page of 50
```
### `MakeFeedControllerOptions`
```typescript
type MakeFeedControllerOptions = Partial<Omit<FeedControllerOptions, "feed">> & {feed: Feed}
```
You provide the `feed` (and typically `onEvent`); the app injects `router`, `signer`, `context`, and the scope/WoT-range resolvers. The scope resolvers map `@welshman/feeds` `Scope` values to pubkeys via [`Wot`](./wot):
- `Scope.Self` → the current user
- `Scope.Follows``Wot.follows(pubkey)`
- `Scope.Network``Wot.network(pubkey)`
- `Scope.Followers``Wot.followers(pubkey)`
WoT-range feeds resolve to the pubkeys whose trust score falls within a fraction of the maximum score in the graph.
## Search
`app.use(Searches)` provides fuzzy ([Fuse.js](https://fusejs.io)) search over profiles, topics, and relays. Profile search additionally triggers a NIP-50 network search and ranks results by web of trust.
```typescript
import {get} from "svelte/store"
const searches = app.use(Searches)
// Each of these is a Readable<Search<...>> that stays up to date
const profileSearch = get(searches.profileSearch)
const topicSearch = get(searches.topicSearch)
const relaySearch = get(searches.relaySearch)
// A Search exposes both option objects and their values
profileSearch.searchValues("alice") // string[] — pubkeys; also fires a NIP-50 network search
profileSearch.searchOptions("alice") // PublishedProfile[]
profileSearch.getOption(pubkey) // PublishedProfile | undefined
```
Profile results are ranked by blending the Fuse score with the WoT score, so well-trusted matches surface first. An empty search term returns all options.
### Building your own search
The generic `createSearch` helper underlies the built-in searches and is exported for custom indexes:
```typescript
import {createSearch} from "@welshman/app"
const search = createSearch(items, {
getValue: item => item.id, // map an item to its identifier
fuseOptions: {keys: ["name", "about"], threshold: 0.3},
onSearch: term => {/* e.g. trigger a network fetch */},
sortFn: results => results, // optional custom result ordering
})
search.searchOptions("query") // T[]
search.searchValues("query") // V[]
search.getOption(value) // T | undefined
```