Refreshes .claude/ skill library: fixes stale refs, adds 4 new skills
- Updates CLAUDE.md tech stack to current versions (Compose 1.10.3, Kotlin 2.3.20). - Reframes kotlin-multiplatform iOS as mature; adds secp256k1-kmp 0.23.0 references. - Updates desktop-expert Main.kt references (code grew from ~270 to 1341 lines and NavigationRail moved to ui/deck/SinglePaneLayout.kt); replaces obsolete "hardcoded ctrl = true" anti-pattern note with accurate isMacOS branching. - Removes compose-desktop.md (superseded by desktop-expert/). - Adds nostr-expert references: nip19-bech32, event-factory, crypto-and-encryption, large-cache. Adds kotlin-expert/common-utilities, compose-expert/rich-text-parsing, android-expert/image-loading. - New skills: account-state (Account + LocalCache), relay-client (subscriptions, filter assemblers, preloaders), feed-patterns (FeedFilter + FeedViewModel family), auth-signers (NostrSigner across internal / NIP-46 / NIP-55).
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# EventFactory: Parsing JSON into Typed Events
|
||||
|
||||
`quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt` is the single dispatch point that turns a parsed `(id, pubKey, createdAt, kind, tags, content, sig)` tuple into the correct `Event` subclass.
|
||||
|
||||
## What It Does
|
||||
|
||||
EventFactory is a giant `when` over `kind` that maps integer kind values to concrete event classes. If a kind isn't recognized, it falls back to the generic base `Event` (so unknown kinds still round-trip). Every NIP that defines a new kind registers its class here.
|
||||
|
||||
Typical shape:
|
||||
|
||||
```kotlin
|
||||
object EventFactory {
|
||||
fun create(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
kind: Int,
|
||||
tags: TagArray,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
): Event = when (kind) {
|
||||
MetadataEvent.KIND -> MetadataEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
TextNoteEvent.KIND -> TextNoteEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
ContactListEvent.KIND -> ContactListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
ReactionEvent.KIND -> ReactionEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
// …hundreds more…
|
||||
else -> Event(id, pubKey, createdAt, kind, tags, content, sig)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Callers are normally upstream of this: `Event.fromJson(...)` / `EventMapper.fromJson(...)` / the relay client's message parser. You rarely call EventFactory directly — you consume typed events it produces.
|
||||
|
||||
## Registering a New Event Kind
|
||||
|
||||
Adding a NIP is roughly:
|
||||
|
||||
1. Create the event class under `quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nipXX…/` alongside the NIP package.
|
||||
2. Subclass the right base:
|
||||
- `Event` — regular events (stored forever).
|
||||
- `BaseReplaceableEvent` — kinds `10000-19999`, `0`, `3`.
|
||||
- `BaseAddressableEvent` — kinds `30000-39999` (identified by `kind:pubkey:d-tag`).
|
||||
- Ephemeral events extend `Event` but have kind `20000-29999`.
|
||||
3. Define `companion object { const val KIND = <n> }`.
|
||||
4. If the event has tag builders, define a `TagArrayBuilder<YourEvent>` DSL in a `TagArrayBuilder` extension — see `nostr-expert/references/tag-patterns.md`.
|
||||
5. Add a branch to `EventFactory.create(...)` so JSON parsing produces your typed class.
|
||||
6. If the event is addressable, ensure it exposes a stable `dTag()` and `address()`.
|
||||
7. Add tests under `quartz/src/commonTest/...`.
|
||||
|
||||
## Why a Monolithic when?
|
||||
|
||||
- **Zero overhead**: compiled to a dense lookup. No reflection, no registry map.
|
||||
- **Exhaustive browsing**: every known kind lives at one search location. `grep KIND = 1234 quartz/...` finds everything.
|
||||
- **Obvious migration path**: adding a kind means adding a case; removing a kind is a grep-and-delete.
|
||||
|
||||
The tradeoff is the file is large and every new kind edits the same file — expect merge conflicts in PRs that touch it, and resolve by keeping both branches.
|
||||
|
||||
## Supporting Utilities
|
||||
|
||||
- `EventAssembler.kt` (crypto/) — higher-level helper that takes a signer and a `kind + tags + content` and produces a fully signed event (id + sig populated).
|
||||
- `EventTemplate.kt` (signers/) — unsigned-event holder, useful in signer flows.
|
||||
- `Event.fromJson(...)` / `Event.toJson()` — JSON round-trip using `OptimizedJsonMapper` (Jackson on jvmAndroid).
|
||||
|
||||
## Related References
|
||||
|
||||
- `event-hierarchy.md` — class hierarchy, Kind ranges
|
||||
- `nip-catalog.md` — which kind maps to which NIP
|
||||
- `tag-patterns.md` — `TagArrayBuilder` DSL for writing tags cleanly
|
||||
Reference in New Issue
Block a user