Blossom Servers
Blossom servers store media files by their sha256 hash. Users publish an ordered list of the servers they upload to (kind 10063), with the first server as their default. Apps use it to pick upload targets and to find a user's files when a URL stops working.
Reading a user's servers
user.blossomServers$ loads the user's server list from their outboxes and returns the servers in order as root URLs.
const servers = use$(user.blossomServers$); // URL[] | undefined
const uploadTo = servers?.[0] ?? new URL("https://blossom.example.com");Example: Blossom Server Manager
Subscribing without casts
eventStore.blossomServers() returns the same URL[] for a pubkey or ProfilePointer. It is a shortcut for UserBlossomServersModel and is added by applesauce-common, so import that package before calling it.
eventStore.blossomServers(pubkey).subscribe((servers) => console.log(servers?.map((s) => s.href)));Editing the server list
The blossom actions update the current user's server list and publish it to their outboxes, creating the list if it's missing. AddBlossomServer and RemoveBlossomServer take one server or an array.
await actions.run(AddBlossomServer, "https://cdn.example.com");
await actions.run(RemoveBlossomServer, ["https://old.example.com"]);
await actions.run(SetDefaultBlossomServer, "https://cdn.example.com"); // moves it to the topNewBlossomServers(servers?) creates the list and throws if one already exists.
Building server list events
BlossomServerListFactory from applesauce-common/factories builds the event directly. servers() replaces the whole list in order.
const signed = await BlossomServerListFactory.create().servers([primary, backup]).sign(signer);
const updated = await BlossomServerListFactory.modify(event).addServer(url).setDefaultServer(url).sign(signer);Helpers
Helpers in applesauce-common/helpers handle server URLs:
getBlossomServersFromList(event)returns the ordered servers from a list event or tag arraymergeBlossomServers(...lists)merges servers into one array without duplicates, keeping the first occurrence's ordernormalizeBlossomServer(url)returns a server's root URL, addinghttps://when missingareBlossomServersEqual(a, b)compares two servers by their root URL
const targets = mergeBlossomServers(servers, appDefaults);Best Practices
- Treat the first server as the user's default upload target
- Upload to more than one server so files survive one going down
- Merge the user's servers with app defaults using
mergeBlossomServersinstead of concatenating arrays - Compare servers with
areBlossomServersEqual, since the same server can be written with or without a trailing slash