Models
Models are pre-built methods for subscribing to computed state from the EventStore.
INFO
Models do not fetch any events from relays, they only subscribe to the events that are already in the event store.
Using models
The eventStore.model method can be used to create a model and returns a rxjs observable that can be subscribed to.
import { TimelineModel } from "applesauce-core/models";
// The first argument is the model constructor and the remaining are passed to the model
const observable = eventStore.model(TimelineModel, { kinds: [1] });
// start the query by subscribing to it
observable.subscribe((events) => {
console.log(events);
});
// adding events to the event store will update the timeline query
eventStore.add({kind: 1, content: 'new note', ...})Performance
Models with similar arguments are cached in the event store and reused for performance reasons. This can help with multiple UI components subscribing to the same model.
import { ProfileModel } from "applesauce-core/models";
// Create the first model
const first = eventStore.model(ProfileModel, { pubkey: "pubkey" });
// Create the second model
const second = eventStore.model(ProfileModel, { pubkey: "pubkey" });
// Both will be the same observable
console.log(first === second); // truePrebuilt Models
There are some common prebuilt models that come with applesauce-core
ProfileModelsubscribes to a single pubkey's profile (kind 0)TimelineModelsubscribes to a sorted array of events that match filtersContactsModelsubscribes to a user's contact list (kind 3)MailboxesModelsubscribes to a user's inbox/outbox relays (kind 10002)
There are many more models in applesauce-common/models for common NIPs like replies, reactions, zaps, bookmarks, and more. For example:
RepliesModelsubscribes to all NIP-10 and NIP-22 replies to an eventReactionsModelsubscribes to reactions for an event
See the full list in the API docs and applesauce-common models.
Custom Models
A custom model is simply a function that returns a Model function.
import { Model } from "applesauce-core";
function CustomModel(arg: string): Model<string> {
return (eventStore) =>
new Observable((observer) => {
// observable code here
observer.next("testing");
});
}As an example here is a custom model that will parse a NIP-78 app event that contains JSON
import { map } from "rxjs/operators";
import { Model } from "applesauce-core";
/** A model that gets JSON from a app data event */
function AppSettingsModel<T>(pubkey: string): Model<T> {
return (eventStore) =>
eventStore.replaceable(30078, pubkey, "app-settings").pipe(
map((event) => {
if (!event) return undefined;
return JSON.parse(event.content) as T;
}),
);
}
// Create the model and subscribe to it
const sub = eventStore
.model(AppSettingsModel, "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d")
.subscribe((json) => {
// json will either be undefined or { theme: string }
if (json) console.log("updated data", json);
});
// Add an event to the event store to trigger the model
eventStore.add({
kind: 30078,
content: '{"theme": "dark"}',
// rest of event
});