Finish pass on docs
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
# NIP-42
|
||||
|
||||
Utilities for NIP-42 relay authentication, allowing clients to authenticate with relays that require it.
|
||||
|
||||
## Functions
|
||||
|
||||
### makeRelayAuth(url, challenge)
|
||||
|
||||
Creates a CLIENT_AUTH event (kind 22242) for relay authentication as specified in NIP-42.
|
||||
|
||||
**Parameters:**
|
||||
- `url` - The relay URL to authenticate with
|
||||
- `challenge` - The challenge string provided by the relay
|
||||
|
||||
**Returns:** Unsigned event object with relay and challenge tags
|
||||
|
||||
## Example
|
||||
|
||||
```typescript
|
||||
import {makeRelayAuth} from "@welshman/util"
|
||||
|
||||
// Create auth event when relay sends AUTH challenge
|
||||
const authEvent = makeRelayAuth(
|
||||
"wss://relay.example.com",
|
||||
"challenge-string-from-relay"
|
||||
)
|
||||
|
||||
// Sign the event with your signer
|
||||
const signedAuth = await signer.sign(authEvent)
|
||||
```
|
||||
@@ -70,89 +70,3 @@ export declare const displayRelayUrl: (url: string) => string;
|
||||
// Get display name for relay profile
|
||||
export declare const displayRelayProfile: (profile?: RelayProfile, fallback?: string) => string;
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### URL Validation
|
||||
|
||||
```typescript
|
||||
import {
|
||||
isRelayUrl,
|
||||
isOnionUrl,
|
||||
isLocalUrl,
|
||||
isShareableRelayUrl
|
||||
} from '@welshman/util';
|
||||
|
||||
// Valid relay URLs
|
||||
console.log(isRelayUrl('wss://relay.damus.io')); // true
|
||||
console.log(isRelayUrl('relay.damus.io')); // true (auto-adds wss://)
|
||||
console.log(isRelayUrl('ws://localhost:8080')); // true
|
||||
|
||||
// Invalid URLs
|
||||
console.log(isRelayUrl('https://example.com')); // false (not websocket)
|
||||
console.log(isRelayUrl('invalid-url')); // false
|
||||
|
||||
// Special URL types
|
||||
console.log(isOnionUrl('wss://7rqsrjfmyb3n2k72.onion')); // true
|
||||
console.log(isLocalUrl('ws://localhost:8080')); // true
|
||||
console.log(isLocalUrl('wss://relay.local')); // true
|
||||
|
||||
// Safe to share publicly
|
||||
console.log(isShareableRelayUrl('wss://relay.damus.io')); // true
|
||||
console.log(isShareableRelayUrl('ws://localhost:8080')); // false (local)
|
||||
```
|
||||
|
||||
### URL Normalization
|
||||
|
||||
```typescript
|
||||
import { normalizeRelayUrl, displayRelayUrl } from '@welshman/util';
|
||||
|
||||
// Normalize various URL formats
|
||||
console.log(normalizeRelayUrl('relay.damus.io'));
|
||||
// 'wss://relay.damus.io/'
|
||||
|
||||
console.log(normalizeRelayUrl('ws://RELAY.EXAMPLE.COM/path'));
|
||||
// 'ws://relay.example.com/path'
|
||||
|
||||
console.log(normalizeRelayUrl('wss://relay.damus.io/?ref=123'));
|
||||
// 'wss://relay.damus.io/' (strips query params)
|
||||
|
||||
// Format for display
|
||||
console.log(displayRelayUrl('wss://relay.damus.io/'));
|
||||
// 'relay.damus.io'
|
||||
|
||||
console.log(displayRelayUrl('ws://localhost:8080/'));
|
||||
// 'localhost:8080'
|
||||
```
|
||||
|
||||
### Working with Relay Profiles
|
||||
|
||||
```typescript
|
||||
import { displayRelayProfile, RelayProfile } from '@welshman/util';
|
||||
|
||||
const relayProfile: RelayProfile = {
|
||||
url: 'wss://relay.damus.io',
|
||||
name: 'Damus Relay',
|
||||
description: 'A high-performance Nostr relay',
|
||||
software: 'strfry',
|
||||
version: '1.0.0',
|
||||
supported_nips: [1, 2, 4, 9, 11, 12, 15, 16, 20, 22],
|
||||
limitation: {
|
||||
payment_required: false,
|
||||
auth_required: false,
|
||||
min_pow_difficulty: 0
|
||||
}
|
||||
};
|
||||
|
||||
// Get display name
|
||||
const displayName = displayRelayProfile(relayProfile);
|
||||
console.log(displayName); // 'Damus Relay'
|
||||
|
||||
// With fallback for unnamed relays
|
||||
const anonymousRelay: RelayProfile = {
|
||||
url: 'wss://anonymous.relay.com'
|
||||
};
|
||||
|
||||
const name = displayRelayProfile(anonymousRelay, 'Unknown Relay');
|
||||
console.log(name); // 'Unknown Relay'
|
||||
```
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
# Repository
|
||||
|
||||
The Repository module provides a robust in-memory event storage system with indexing, querying, and event replacement capabilities.
|
||||
|
||||
## Core Features
|
||||
|
||||
- Event storage and indexing
|
||||
- Query support with multiple filters
|
||||
- Event replacement and deletion tracking
|
||||
- Event update notifications
|
||||
- Optimized indexes for common queries
|
||||
|
||||
## Class Definition
|
||||
|
||||
```typescript
|
||||
class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
|
||||
// Storage indexes
|
||||
eventsById = new Map<string, E>()
|
||||
eventsByWrap = new Map<string, E>()
|
||||
eventsByAddress = new Map<string, E>()
|
||||
eventsByTag = new Map<string, E[]>()
|
||||
eventsByDay = new Map<number, E[]>()
|
||||
eventsByAuthor = new Map<string, E[]>()
|
||||
eventsByKind = new Map<number, E[]>()
|
||||
deletes = new Map<string, number>()
|
||||
}
|
||||
```
|
||||
|
||||
## Core Methods
|
||||
|
||||
### Event Management
|
||||
```typescript
|
||||
// Store or update event
|
||||
publish(event: E, opts = { shouldNotify: true }): boolean
|
||||
|
||||
// Get event by ID or address
|
||||
getEvent(idOrAddress: string): E | undefined
|
||||
|
||||
// Check if event exists
|
||||
hasEvent(event: E): boolean
|
||||
|
||||
// Remove event
|
||||
removeEvent(idOrAddress: string): void
|
||||
|
||||
// Check deletion status
|
||||
isDeleted(event: E): boolean
|
||||
isDeletedByAddress(event: E): boolean
|
||||
isDeletedById(event: E): boolean
|
||||
```
|
||||
|
||||
### Querying
|
||||
```typescript
|
||||
// Query events with filters
|
||||
query(
|
||||
filters: Filter[],
|
||||
opts = {
|
||||
includeDeleted: false,
|
||||
shouldSort: true
|
||||
}
|
||||
): E[]
|
||||
|
||||
// Dump all events
|
||||
dump(): E[]
|
||||
|
||||
// Load events in bulk
|
||||
load(events: E[], chunkSize = 1000): void
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Repository Operations
|
||||
```typescript
|
||||
// Create repository
|
||||
const repo = new Repository<TrustedEvent>()
|
||||
|
||||
// Add events
|
||||
repo.publish(event)
|
||||
|
||||
// Query events
|
||||
const events = repo.query([
|
||||
{ kinds: [1], limit: 100 }
|
||||
])
|
||||
|
||||
// Check event status
|
||||
if (!repo.isDeleted(event)) {
|
||||
processEvent(event)
|
||||
}
|
||||
```
|
||||
|
||||
### Bulk Operations
|
||||
```typescript
|
||||
// Load multiple events
|
||||
repo.load(events, 500) // Process in chunks of 500
|
||||
|
||||
// Get all events
|
||||
const allEvents = repo.dump()
|
||||
```
|
||||
|
||||
### Query Examples
|
||||
```typescript
|
||||
// Query with multiple filters
|
||||
const events = repo.query([
|
||||
// Recent events from specific authors
|
||||
{
|
||||
kinds: [1],
|
||||
authors: ['pub1', 'pub2'],
|
||||
since: now() - 24 * 60 * 60
|
||||
},
|
||||
// Events with specific tags
|
||||
{
|
||||
'#t': ['bitcoin', 'nostr'],
|
||||
limit: 50
|
||||
}
|
||||
])
|
||||
```
|
||||
Reference in New Issue
Block a user