Making Requests
Welshman extends Nostr's base subscription model with intelligent caching, repository integration, and configurable behaviors.
Key Concepts
- Local Repository: Events are automatically cached and tracked
- Cache Intelligence: Smart decisions about when to use cached data
- Relay Integration: Works with the router for optimal relay selection
- Configurable Behavior: Control caching and timeouts
Request and Load
The base functionality for subscription management is implemented in @welshman/net. Please refer to the documentation for that module for details.
Indexed Collections and Loaders
Create indexed stores with automatic loading using repository derivations and loader utilities:
import {deriveItemsByKey, deriveItems, makeDeriveItem, makeLoadItem, getter} from "@welshman/store"
// Create indexed map from repository
const itemsByKey = deriveItemsByKey({
repository,
filters: [{kinds: [SOME_KIND]}],
eventToItem: event => transformEvent(event),
getKey: item => item.id
})
// Create array view
const items = deriveItems(itemsByKey)
// Create getter for accessing map
const getItemsByKey = getter(itemsByKey)
// Create loader
const loadItem = makeLoadItem(fetchItem, key => getItemsByKey().get(key))
// Create deriver with automatic loading
const deriveItem = makeDeriveItem(itemsByKey, loadItem)Deriving Events
Query events from the repository using deriveEventsById and deriveEvents:
import {deriveEventsById, deriveEvents} from "@welshman/store"
const noteEventsById = deriveEventsById({repository, filters: [{kinds: [NOTE]}]})
export const notes = deriveEvents(noteEventsById)Available Collections
Several common collections are built-in and ready for use:
// Profiles
profiles → profilesByPubkey → deriveProfile → loadProfile
// Lists
followLists → followListsByPubkey → deriveFollowList → loadFollowList
muteLists → muteListsByPubkey → deriveMuteList → loadMuteList
pinLists → pinListsByPubkey → derivePinList → loadPinList
// Relays
relays → relaysByUrl → deriveRelay → loadRelay
relayLists → relayListsByPubkey → deriveRelayList → loadRelayList
messagingRelayLists → messagingRelayListsByPubkey → deriveMessagingRelayList → loadMessagingRelayList
// Identity
handles → handlesByNip05 → deriveHandle → loadHandle
zappers → zappersByLnurl → deriveZapper → loadZapperExample - Loading and Displaying Profiles
import {get} from 'svelte/store'
import {displayProfile} from '@welshman/util'
import {deriveProfile, deriveProfileDisplay} from '@welshman/app'
// Subscribe to profile changes - this will automatically load the profile in the background
const profile = deriveProfile(pubkey)
// Display with fallback
const name = displayProfile(get(profile), 'unknown')
// Better: use built-in deriveProfileDisplay utility
const name = deriveProfileDisplay(pubkey)User-Specific Collections
Several modules provide user-specific derived stores that automatically load data for the currently signed-in user:
import { userProfile, userFollowList, userMuteList, userPinList } from '@welshman/app'
userProfile.subscribe(profile => {
// Current user's profile data
})
userFollowList.subscribe(follows => {
// Current user's follow list
})Repository Integration
Events from subscriptions are automatically tracked to their source relay and saved to the repository, unless they are DVM-kind or ephemeral events (which are discarded). WRAP (kind 1059) events are handled separately and only processed when shouldUnwrap is set to true.
The repository serves as an intelligent cache layer, making subsequent queries for the same data faster.
Feeds
A high-level feed loader utility is also provided, which combines application state with utilities from @welshman/net and @welshman/feeds.
import {NOTE} from '@welshman/util'
import {makeKindFeed} from '@welshman/feeds'
import {createFeedController} from '@welshman/app'
const abortController = new AbortController()
let done = false
const ctrl = createFeedController({
feed: makeKindFeed(NOTE),
useWindowing: true,
signal: abortController.signal,
onEvent: e => {
console.log(e)
},
onExhausted: () => {
done = true
},
})
// Load some notes
ctrl.load(100)
// Cancel any pending requests
abortController.abort()