5b8fef5b23
tests / tests (push) Failing after 5m8s
NIP fixes: - RelayMembers (13534): use NIP-43 `member` tags (not `p`) and set the required NIP-70 `-` protected tag. - Profile (kind 0): remove display-name support entirely (getter, setter, display() fallback, and the search weight). - Comment (1111): A/a tags now carry a real address, not the event id. - BlossomServerList (10063): normalize server URLs with normalizeUrl (HTTP), not normalizeRelayUrl (which forced wss://). - HandlerRecommendation (31989): fix inverted removeRecommendation filter; add setSupportedKind()/supportedKind() for the NIP-89 d-tag. - Report (1984): place the report-type string on the e tag (note reports) or p tag (profile reports); always emit the p tag. Docs/skills: - Add @welshman/domain docs (docs/domain/) and the welshman-domain skill. - Prune @welshman/util docs/skill of the moved Profile/List/Handler/Encryptable helpers; register domain in the sidebar, index, and skills README. - Apply accuracy fixes to the @welshman/app docs/skill. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BsMjvv7krpZeHK1Njeneru
82 lines
3.4 KiB
Markdown
82 lines
3.4 KiB
Markdown
# Profile
|
|
|
|
`Profile` / `ProfileBuilder` model NIP-01 kind-0 metadata — the JSON blob that carries a user's name, picture, NIP-05, lightning address, and so on. Like every kind in `@welshman/domain`, it is a thin pair of classes over the [base Reader/Builder machinery](./readers-and-builders): a read-only view plus a chainable producer of an event template.
|
|
|
|
The content of a kind-0 event is a JSON object, so `Profile.parse` decodes it into a `values` record and the getters read fields off that.
|
|
|
|
## Reading
|
|
|
|
```typescript
|
|
import {Profile} from "@welshman/domain"
|
|
|
|
const profile = await Profile.fromEvent(event) // no signer needed — kind 0 is not encrypted
|
|
|
|
profile.name() // string | undefined
|
|
profile.displayName() // values.display_name
|
|
profile.about() // string | undefined
|
|
profile.picture() // string | undefined
|
|
profile.banner() // string | undefined
|
|
profile.website() // string | undefined
|
|
profile.nip05() // string | undefined
|
|
profile.lnurl() // lud16/lud06 → lnurl, via parseLnUrl
|
|
profile.values // the raw decoded JSON object
|
|
```
|
|
|
|
`display(fallback = "")` is the best-effort label you usually want in UI. It prefers `name`, then `display_name` (each truncated to 60 chars via `ellipsize`), and finally falls back to a shortened npub:
|
|
|
|
```typescript
|
|
profile.display() // "alice" · "npub1abc…wxyz" · fallback
|
|
profile.display("anonymous") // fallback used only when there is nothing else
|
|
```
|
|
|
|
## Building
|
|
|
|
Construct empty to author a new profile, or from a reader to edit one. Setters are chainable; finish with `toTemplate()` / `toEvent(signer)`.
|
|
|
|
```typescript
|
|
import {ProfileBuilder} from "@welshman/domain"
|
|
|
|
const template = await new ProfileBuilder()
|
|
.setName("alice")
|
|
.setAbout("hello nostr")
|
|
.setPicture("https://example.com/avatar.png")
|
|
.setNip05("alice@example.com")
|
|
.toTemplate() // EventTemplate {kind: 0, content, tags: []}
|
|
```
|
|
|
|
Editing round-trips through the reader. `buildContent` re-serializes `values` to JSON, so unknown profile fields you never touched are preserved:
|
|
|
|
```typescript
|
|
const signed = await profile.builder()
|
|
.setAbout("updated bio")
|
|
.toEvent(signer) // SignedEvent
|
|
```
|
|
|
|
Available setters: `setName`, `setDisplayName`, `setNip05`, `setAbout`, `setBanner`, `setPicture`, `setWebsite`, plus `update(values)` to merge an arbitrary object into `values`.
|
|
|
|
```typescript
|
|
new ProfileBuilder().update({name: "alice", lud16: "alice@walletofsatoshi.com"})
|
|
```
|
|
|
|
::: warning Asymmetric display name
|
|
`setDisplayName(x)` writes `values.displayName` (camelCase), but `displayName()` reads `values.display_name` (snake_case, the NIP-01 field). They are **not** symmetric — a value you set with `setDisplayName` will not be read back by `displayName()`. Use `update({display_name: x})` if you need the getter to see it.
|
|
:::
|
|
|
|
## Free functions
|
|
|
|
`Profile.ts` also exports two standalone helpers, used internally by the getters above but available on their own:
|
|
|
|
```typescript
|
|
import {parseLnUrl, displayPubkey} from "@welshman/domain"
|
|
|
|
// Resolve an lnurl from a metadata object: checks lud06 then lud16.
|
|
parseLnUrl({lud16: "alice@example.com"}) // string | undefined
|
|
|
|
// A short, human-readable npub: first 8 chars + "…" + last 5.
|
|
displayPubkey(pubkey) // "npub1abc…wxyz"
|
|
```
|
|
|
|
## See also
|
|
|
|
- [Readers & Builders](./readers-and-builders) — the base `EventReader`/`EventBuilder` pattern every kind shares.
|