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.
Collections and Loaders
The collection
utility creates stores that handle caching, loading, and indexing of Nostr data. It provides a consistent pattern for managing entities that need to be fetched from the network and cached locally.
const {
indexStore, // Map of all items by key
deriveItem, // Get reactive item by key
loadItem // Trigger network load
} = collection({
name: "storeName", // For persistence
store: writable([]), // Base store
getKey: item => item.id // How to index items
load: async (key) => { // Network loader
// Load logic here
}
})
Deriving Events
The best way to create collections is by deriving their contents from the app repository
using deriveEvents
from @welshman/store
. For more control, use deriveEventsMapped
.
import {deriveEventsMapped} from "@welshman/store"
export const notes = deriveEvents<TrustedEvent>(repository, {filters: [{kinds: [NOTE]}]})
A collection could then be created by passing the notes
store to collection
.
Available Collections
Several common collections are built-in and ready for use:
// Profiles
profiles → profilesByPubkey → deriveProfile → loadProfile
// Lists
follows → followsByPubkey → deriveFollows → loadFollows
mutes → mutesByPubkey → deriveMutes → loadMutes
pins → pinsByPubkey → derivePins → loadPins
// Relays
relays → relaysByUrl → deriveRelay → loadRelay
relaySelections → relaySelectionsByPubkey → deriveRelaySelections → loadRelaySelections
inboxRelaySelections → inboxRelaySelectionsByPubkey → deriveInboxRelaySelections → loadInboxRelaySelections
// Identity
handles → handlesByNip05 → deriveHandle → loadHandle
zappers → zappersByLnurl → deriveZapper → loadZapper
Example - 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, userFollows, userMutes, userPins } from '@welshman/app'
userProfile.subscribe(profile => {
// Current user's profile data
})
userFollows.subscribe(follows => {
// Current user's follow list
})
Repository Integration
All events from subscriptions are automatically:
- Saved to the repository
- Tracked to their source relay
- Checked against deletion status
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()