-

@ hzrd149
2025-02-21 17:54:15
I've been working on the applesauce libraries for a while now but I think this release is the first one I would consider to be stable enough to use
A lot of the core concepts and classes are in place and stable enough where they wont change too much next release
If you want to skip straight to the documentation you can find at [hzrd149.github.io/applesauce](https://hzrd149.github.io/applesauce/) or the typescript docs at [hzrd149.github.io/applesauce/typedoc](https://hzrd149.github.io/applesauce/typedoc)
## Whats new
### Accounts
The `applesauce-accounts` package is an extension of the `applesauce-signers` package and provides classes for building a multi-account system for clients
Its primary features are
- Serialize and deserialize accounts so they can be saved in local storage or IndexededDB
- Account manager for multiple accounts and switching between them
- Account metadata for things like labels, app settings, etc
- Support for NIP-46 Nostr connect accounts
see [documentation](https://hzrd149.github.io/applesauce/accounts/manager.html) for more examples
### Nostr connect signer
The `NostrConnectSigner` class from the `applesauce-signers` package is now in a stable state and has a few new features
- Ability to create `nostrconnect://` URIs and waiting for the remote signer to connect
- SDK agnostic way of subscribing and publishing to relays
For a simple example, here is how to create a signer from a `bunker://` URI
```js
const signer = await NostrConnectSigner.fromBunkerURI(
"bunker://266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5?relay=wss://relay.nsec.app&secret=d9aa70",
{
permissions: NostrConnectSigner.buildSigningPermissions([0, 1, 3, 10002]),
async onSubOpen(filters, relays, onEvent) {
// manually open REQ
},
async onSubClose() {
// close previouse REQ
},
async onPublishEvent(event, relays) {
// Pubilsh an event to relays
},
},
);
```
see [documentation](https://hzrd149.github.io/applesauce/signers/nostr-connect.html) for more examples and other signers
### Event Factory
The `EventFactory` class is probably what I'm most proud of. its a standalone class that can be used to create various types of events from templates ([blueprints](https://hzrd149.github.io/applesauce/typedoc/modules/applesauce_factory.Blueprints.html)) and is really simple to use
For example:
```js
import { EventFactory } from "applesauce-factory";
import { NoteBlueprint } from "applesauce-factory/blueprints";
const factory = new EventFactory({
// optionally pass a NIP-07 signer in to use for encryption / decryption
signer: window.nostr
});
// Create a kind 1 note with a hashtag
let draft = await factory.create(NoteBlueprint, "hello world #grownostr");
// Sign the note so it can be published
let signed = await window.nostr.signEvent(draft);
```
Its included in the `applesauce-factory` package and can be used with any other nostr SDKs or vanilla javascript
It also can be used to modify existing replaceable events
```js
let draft = await factory.modifyTags(
// kind 10002 event
mailboxes,
// add outbox relays
addOutboxRelay("wss://relay.io/"),
addOutboxRelay("wss://nostr.wine/"),
// remove inbox relay
removeInboxRelay("wss://personal.old-relay.com/")
);
```
see [documentation](https://hzrd149.github.io/applesauce/overview/factory.html) for more examples
### Loaders
The `applesauce-loaders` package exports a bunch of loader classes that can be used to load everything from replaceable events (profiles) to timelines and NIP-05 identities
They use [rx-nostr](https://penpenpng.github.io/rx-nostr/) under the hood to subscribe to relays, so for the time being they will not work with other nostr SDKs
I don't expect many other developers or apps to use them since in my experience every nostr client requires a slightly different way or loading events
*They are stable enough to start using but they are not fully tested and they might change slightly in the future*
The following is a short list of the loaders and what they can be used for
- `ReplaceableLoader` loads any replaceable events (0, 3, 1xxxx, 3xxxx)
- `SingleEventLoader` loads single events based on ids
- `TimelineLoader` loads a timeline of events from multiple relays based on filters
- `TagValueLoader` loads events based on a tag name (like "e") and a value, can be used to load replies, zaps, reactions, etc
- `DnsIdentityLoader` loads NIP-05 identities and supports caching
- `UserSetsLoader` loads all lists events for users
see [documentation](https://hzrd149.github.io/applesauce/overview/loaders.html) for more examples
### Real tests
For all new features and a lot of existing ones I'm trying to write tests to ensure I don't leave unexpected bugs for later
I'm not going to pretend its 100% tests coverage or that it will ever get close to that point, but these tests cover some of the core classes and help me prove that my code is doing what it says its supposed to do
At the moment there are about 230 tests covering 45 files. not much but its a start

## Apps built using applesauce
If you want to see some examples of applesauce being used in a nostr client I've been testing a lot of this code in production on the apps I've built in the last few months
- [noStrudel](https://github.com/hzrd149/nostrudel) The main app everything is being built for and tested in
- [nsite-manager](https://github.com/hzrd149/nsite-manager) Still a work-in-progress but supports multiple accounts thanks to the `applesauce-accounts` package
- [blossomservers.com](https://github.com/hzrd149/blossomservers) A simple (and incomplete) nostr client for listing and reviewing public blossom servers
- [libretranslate-dvm](https://github.com/hzrd149/libretranslate-dvm) A libretranslate DVM for nostr:npub1mkvkflncllnvp3adq57klw3wge6k9llqa4r60g42ysp4yyultx6sykjgnu
- [cherry-tree](https://github.com/hzrd149/cherry-tree) A chunked blob uploader / downloader. only uses applesauce for boilerplate
- [nsite-homepage](https://github.com/hzrd149/nsite-homepage) A simple landing page for [nsite.lol](https://nsite.lol)
Thanks to nostr:npub1cesrkrcuelkxyhvupzm48e8hwn4005w0ya5jyvf9kh75mfegqx0q4kt37c for teaching me more about rxjs and consequentially making me re-write a lot of the core observables to be faster