@nostr-wot/graph 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/storage.ts","../src/graph.ts","../src/crawl.ts","../src/scoring.ts","../src/wot-source.ts","../src/wot-graph.ts"],"names":["_a","DEFAULT_MAX_HOPS"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * IndexedDB storage for the local WoT graph.\n *\n * Ported from the extension (`lib/storage.ts`), generalized from per-account\n * databases to a `namespace` key and wrapped in a class so multiple graphs can\n * coexist. Preserves the two performance-critical techniques:\n *\n * - **Interning**: pubkeys (64-hex) are mapped to small integer ids, so the\n * graph is stored/traversed as numbers instead of strings.\n * - **Delta encoding**: each node's sorted follow-id list is stored as a\n * `Uint32Array` of deltas, which compresses well and keeps memory bounded for\n * the 100k+ nodes a 2-hop crawl can yield.\n *\n * When `indexedDB` is unavailable (Node without a polyfill) the store operates\n * in memory-only mode: crawl/query still work, nothing is persisted.\n */\n\nimport type { GraphMeta, StorageStats } from './types';\n\nconst DB_PREFIX = 'nostr-wot-graph';\nconst DB_VERSION = 1;\nconst STORE_PUBKEYS = 'pubkeys';\nconst STORE_FOLLOWS = 'follows';\nconst STORE_META = 'meta';\n\n// Encode follow ids for storage (sort + delta encode into a Uint32Array).\nexport function encodeFollows(followIds: ArrayLike<number>): ArrayBuffer {\n if (followIds.length === 0) return new ArrayBuffer(0);\n\n const sorted = Array.from(followIds).sort((a, b) => a - b);\n\n const deltas = new Uint32Array(sorted.length);\n deltas[0] = sorted[0];\n for (let i = 1; i < sorted.length; i++) {\n deltas[i] = sorted[i] - sorted[i - 1];\n }\n\n return deltas.buffer;\n}\n\n// Decode follow ids from storage (delta decode back to absolute values).\nexport function decodeFollows(buffer: ArrayBuffer | null | undefined): Uint32Array {\n if (!buffer || buffer.byteLength === 0) return new Uint32Array(0);\n\n const deltas = new Uint32Array(buffer);\n const result = new Uint32Array(deltas.length);\n\n result[0] = deltas[0];\n for (let i = 1; i < deltas.length; i++) {\n result[i] = result[i - 1] + deltas[i];\n }\n\n return result;\n}\n\nfunction hasIndexedDB(): boolean {\n return typeof indexedDB !== 'undefined' && indexedDB !== null;\n}\n\nexport class GraphStorage {\n readonly namespace: string;\n private db: IDBDatabase | null = null;\n private memoryOnly = false;\n private opened = false;\n\n // In-memory caches (source of truth for reads/BFS).\n private pubkeyToId = new Map<string, number>();\n private idToPubkey = new Map<number, string>();\n private nextId = 1;\n private graphCache = new Map<number, Uint32Array>();\n private metaCache = new Map<string, unknown>();\n\n // Pending persistence buffers (drained by flush()).\n private dirtyFollows = new Map<number, number[]>();\n private dirtyPubkeys: Array<{ id: number; pubkey: string }> = [];\n\n constructor(namespace: string) {\n if (!namespace) throw new Error('GraphStorage requires a namespace');\n this.namespace = namespace;\n }\n\n private dbName(): string {\n return `${DB_PREFIX}:${this.namespace}`;\n }\n\n /** Open (or create) the namespace DB and hydrate in-memory caches. */\n async open(): Promise<void> {\n if (this.opened) return;\n\n if (!hasIndexedDB()) {\n this.memoryOnly = true;\n this.opened = true;\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const request = indexedDB.open(this.dbName(), DB_VERSION);\n request.onerror = () => reject(request.error);\n request.onupgradeneeded = (event) => {\n const database = (event.target as IDBOpenDBRequest).result;\n if (!database.objectStoreNames.contains(STORE_PUBKEYS)) {\n const store = database.createObjectStore(STORE_PUBKEYS, { keyPath: 'id' });\n store.createIndex('pubkey', 'pubkey', { unique: true });\n }\n if (!database.objectStoreNames.contains(STORE_FOLLOWS)) {\n database.createObjectStore(STORE_FOLLOWS, { keyPath: 'id' });\n }\n if (!database.objectStoreNames.contains(STORE_META)) {\n database.createObjectStore(STORE_META, { keyPath: 'key' });\n }\n };\n request.onsuccess = () => {\n this.db = request.result;\n resolve();\n };\n });\n\n this.opened = true;\n await this.loadAll();\n }\n\n /** Hydrate the in-memory interning + follow maps + meta from the DB. */\n async loadAll(): Promise<void> {\n this.pubkeyToId.clear();\n this.idToPubkey.clear();\n this.graphCache.clear();\n this.metaCache.clear();\n this.nextId = 1;\n\n if (this.memoryOnly || !this.db) return;\n const db = this.db;\n\n const pubkeys = await this.getAll<{ id: number; pubkey: string }>(db, STORE_PUBKEYS);\n for (const record of pubkeys) {\n this.pubkeyToId.set(record.pubkey, record.id);\n this.idToPubkey.set(record.id, record.pubkey);\n if (record.id >= this.nextId) this.nextId = record.id + 1;\n }\n\n const follows = await this.getAll<{ id: number; follows: ArrayBuffer }>(db, STORE_FOLLOWS);\n for (const record of follows) {\n this.graphCache.set(record.id, decodeFollows(record.follows));\n }\n\n const meta = await this.getAll<{ key: string; value: unknown }>(db, STORE_META);\n for (const record of meta) {\n this.metaCache.set(record.key, record.value);\n }\n }\n\n private getAll<T>(db: IDBDatabase, store: string): Promise<T[]> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(store, 'readonly');\n const request = tx.objectStore(store).getAll();\n request.onsuccess = () => resolve(request.result as T[]);\n request.onerror = () => reject(request.error);\n });\n }\n\n // ── Interning ──\n\n /** Numeric id for a pubkey, or null if never seen. */\n getId(pubkey: string): number | null {\n return this.pubkeyToId.get(pubkey) ?? null;\n }\n\n /** Numeric id for a pubkey, minting and buffering a new one if needed. */\n getOrCreateId(pubkey: string): number {\n const existing = this.pubkeyToId.get(pubkey);\n if (existing !== undefined) return existing;\n\n const id = this.nextId++;\n this.pubkeyToId.set(pubkey, id);\n this.idToPubkey.set(id, pubkey);\n this.dirtyPubkeys.push({ id, pubkey });\n return id;\n }\n\n /** Batch variant of {@link getOrCreateId}. */\n getOrCreateIds(pubkeys: string[]): number[] {\n const ids = new Array<number>(pubkeys.length);\n for (let i = 0; i < pubkeys.length; i++) {\n ids[i] = this.getOrCreateId(pubkeys[i]);\n }\n return ids;\n }\n\n /** Pubkey for a numeric id, or null. */\n getHex(id: number): string | null {\n return this.idToPubkey.get(id) ?? null;\n }\n\n /** Highest assigned id (for typed-array sizing). */\n getMaxId(): number {\n return this.nextId - 1;\n }\n\n // ── Follows ──\n\n /** Store `pubkey`'s follow list. Interns everything and updates the cache. */\n saveFollows(pubkey: string, follows: string[]): void {\n const id = this.getOrCreateId(pubkey);\n const followIds = this.getOrCreateIds(follows);\n this.graphCache.set(id, new Uint32Array(followIds));\n this.dirtyFollows.set(id, followIds);\n }\n\n /** Follow ids for a node id — sync, from the in-memory cache. */\n getFollowIdsSync(id: number): Uint32Array {\n return this.graphCache.get(id) ?? new Uint32Array(0);\n }\n\n /** Follow ids for a pubkey (interned). Empty if unknown. */\n getFollowIds(pubkey: string): Uint32Array {\n const id = this.getId(pubkey);\n if (id === null) return new Uint32Array(0);\n return this.getFollowIdsSync(id);\n }\n\n /** Follow list of `pubkey` as hex strings. */\n getFollows(pubkey: string): string[] {\n const ids = this.getFollowIds(pubkey);\n const out: string[] = [];\n for (let i = 0; i < ids.length; i++) {\n const hex = this.getHex(ids[i]);\n if (hex) out.push(hex);\n }\n return out;\n }\n\n // ── Meta ──\n\n async setMeta(key: string, value: unknown): Promise<void> {\n this.metaCache.set(key, value);\n if (this.memoryOnly || !this.db) return;\n const db = this.db;\n await new Promise<void>((resolve, reject) => {\n const tx = db.transaction(STORE_META, 'readwrite');\n tx.objectStore(STORE_META).put({ key, value });\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n getMeta<T = unknown>(key: string): T | undefined {\n return this.metaCache.get(key) as T | undefined;\n }\n\n /** Read the structured graph meta record. */\n getGraphMeta(): GraphMeta {\n return {\n root: (this.getMeta<string>('root') ?? null) as string | null,\n lastCrawl: (this.getMeta<number>('lastCrawl') ?? null) as number | null,\n maxDepth: (this.getMeta<number>('maxDepth') ?? null) as number | null,\n version: this.getMeta<number>('version') ?? DB_VERSION,\n };\n }\n\n // ── Persistence ──\n\n /** Flush buffered pubkey + follow writes to IndexedDB. No-op in memory mode. */\n async flush(): Promise<void> {\n if (this.memoryOnly || !this.db) {\n this.dirtyPubkeys.length = 0;\n this.dirtyFollows.clear();\n return;\n }\n const db = this.db;\n\n const pubkeys = this.dirtyPubkeys.splice(0, this.dirtyPubkeys.length);\n const follows = Array.from(this.dirtyFollows.entries());\n this.dirtyFollows.clear();\n\n if (pubkeys.length === 0 && follows.length === 0) return;\n\n await new Promise<void>((resolve, reject) => {\n const stores: string[] = [];\n if (pubkeys.length) stores.push(STORE_PUBKEYS);\n if (follows.length) stores.push(STORE_FOLLOWS);\n const tx = db.transaction(stores, 'readwrite');\n\n if (pubkeys.length) {\n const store = tx.objectStore(STORE_PUBKEYS);\n for (const row of pubkeys) store.put(row);\n }\n if (follows.length) {\n const store = tx.objectStore(STORE_FOLLOWS);\n for (const [id, followIds] of follows) {\n store.put({ id, follows: encodeFollows(followIds), updated_at: Date.now() });\n }\n }\n\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n // ── Stats / clear ──\n\n stats(): StorageStats {\n let edges = 0;\n for (const follows of this.graphCache.values()) edges += follows.length;\n return {\n nodes: this.graphCache.size,\n edges,\n uniquePubkeys: this.pubkeyToId.size,\n };\n }\n\n /** Wipe this namespace: memory caches + persisted stores. */\n async clear(): Promise<void> {\n this.pubkeyToId.clear();\n this.idToPubkey.clear();\n this.graphCache.clear();\n this.metaCache.clear();\n this.dirtyFollows.clear();\n this.dirtyPubkeys.length = 0;\n this.nextId = 1;\n\n if (this.memoryOnly || !this.db) return;\n const db = this.db;\n await new Promise<void>((resolve, reject) => {\n const tx = db.transaction([STORE_FOLLOWS, STORE_PUBKEYS, STORE_META], 'readwrite');\n tx.objectStore(STORE_FOLLOWS).clear();\n tx.objectStore(STORE_PUBKEYS).clear();\n tx.objectStore(STORE_META).clear();\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n /** Close the underlying DB connection. */\n close(): void {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n this.opened = false;\n }\n}\n","/**\n * In-memory BFS over the hydrated follow graph.\n *\n * Ported from the extension (`lib/graph.ts`, `LocalGraph`). Given the interned\n * follow map (from {@link GraphStorage}) and a root pubkey, a single BFS pass\n * fills two typed arrays indexed by node id:\n *\n * - `hops` (`Uint8Array`) — distance from root, stored as `hop + 1` so `0`\n * means \"not reached\" (255 max).\n * - `paths` (`Uint32Array`) — count of shortest paths to each node.\n *\n * The cache is keyed by root and invalidated on crawl / root change / clear.\n */\n\nimport type { GraphStorage } from './storage';\nimport type { DistanceInfo } from './types';\n\ninterface BfsCache {\n rootId: number;\n hops: Uint8Array;\n paths: Uint32Array;\n maxId: number;\n}\n\nconst DEFAULT_MAX_HOPS = 6;\n\nexport class LocalGraph {\n private storage: GraphStorage;\n private cache: BfsCache | null = null;\n private cachedRoot: string | null = null;\n\n constructor(storage: GraphStorage) {\n this.storage = storage;\n }\n\n /** Invalidate the precomputed cache (called on crawl / root change / clear). */\n invalidateCache(): void {\n this.cache = null;\n this.cachedRoot = null;\n }\n\n /**\n * Precompute hops and paths from a root pubkey using a single BFS pass.\n * Results stored in typed arrays indexed by node id for O(1) lookup.\n */\n private buildCache(rootPubkey: string, maxHops: number = DEFAULT_MAX_HOPS): void {\n const rootId = this.storage.getId(rootPubkey);\n if (rootId === null) {\n this.cache = null;\n this.cachedRoot = null;\n return;\n }\n\n const maxId = this.storage.getMaxId();\n // Uint8Array: 0 = unreachable, 1-255 = hop distance. Store hop+1 so 0 means \"not reached\".\n const hops = new Uint8Array(maxId + 1);\n const paths = new Uint32Array(maxId + 1);\n\n // Root: distance 0, 1 path\n hops[rootId] = 1; // stored as hop+1\n paths[rootId] = 1;\n\n let frontier: number[] = [rootId];\n let hop = 0;\n\n while (frontier.length > 0 && hop < maxHops) {\n hop++;\n const hopStored = hop + 1;\n const nextFrontier: number[] = [];\n\n for (let f = 0; f < frontier.length; f++) {\n const nodeId = frontier[f];\n const nodePaths = paths[nodeId];\n const followIds = this.storage.getFollowIdsSync(nodeId);\n\n for (let i = 0; i < followIds.length; i++) {\n const fid = followIds[i];\n if (fid > maxId) continue; // safety guard\n\n if (hops[fid] === 0) {\n // First discovery\n hops[fid] = hopStored;\n paths[fid] = nodePaths;\n nextFrontier.push(fid);\n } else if (hops[fid] === hopStored) {\n // Same-level rediscovery -- accumulate paths\n paths[fid] += nodePaths;\n }\n // If hops[fid] < hopStored, it was found at a closer level -- ignore\n }\n }\n\n frontier = nextFrontier;\n }\n\n this.cache = { rootId, hops, paths, maxId };\n this.cachedRoot = rootPubkey;\n }\n\n /** Ensure the cache is built for `root`. */\n private ensureCache(root: string, maxHops: number): void {\n if (this.cachedRoot !== root || !this.cache) {\n this.buildCache(root, maxHops);\n }\n }\n\n /**\n * Distance info from `root` to `pubkey`. Returns `{ hops, paths }`, or `null`\n * when unreached / unknown. Self → `{ hops: 0, paths: 1 }`.\n */\n getDistance(root: string, pubkey: string, maxHops: number = DEFAULT_MAX_HOPS): DistanceInfo | null {\n if (root === pubkey) return { hops: 0, paths: 1 };\n\n this.ensureCache(root, maxHops);\n if (!this.cache || this.cachedRoot !== root) return null;\n\n const toId = this.storage.getId(pubkey);\n if (toId === null || toId > this.cache.maxId) return null;\n\n const h = this.cache.hops[toId];\n if (h === 0) return null; // unreachable\n\n return { hops: h - 1, paths: this.cache.paths[toId] };\n }\n\n /** Follow list of `pubkey` as hex strings. */\n getFollows(pubkey: string): string[] {\n return this.storage.getFollows(pubkey);\n }\n}\n","/**\n * BFS crawler for kind:3 contact lists.\n *\n * Ported from the extension (`lib/sync.ts`, `GraphSync`) but with the raw\n * `WebSocket` transport replaced by `@nostr-wot/relay`'s pool. The pool handles\n * connection/reconnect across relays; this class keeps the proven crawl logic:\n *\n * - BFS by depth: fetch the root's kind:3, enqueue its follows for the next\n * depth, and so on up to `maxDepth`.\n * - Newest-per-author: for each pubkey, take the kind:3 event with the highest\n * `created_at` seen across relays.\n * - Rate limiting: a base delay between dispatches and a max-concurrent cap.\n * - Tolerates unreachable relays; throws `CrawlError` only when zero relays are\n * configured to connect.\n * - Abortable via `signal` or `stop()`; a stopped crawl leaves partial data\n * usable and reports `stoppedEarly: true`.\n */\n\nimport type { GraphStorage } from './storage';\nimport type { CrawlOptions, CrawlResult } from './types';\n\n// Minimal relay-pool surface the crawler needs. `@nostr-wot/relay`'s `RelayPool`\n// (its `subscribe(filter, { onEvent, onEose })`) is structurally assignable.\nexport interface CrawlSubCloser {\n close(): void;\n}\nexport interface CrawlEvent {\n created_at: number;\n tags: string[][];\n [key: string]: unknown;\n}\nexport interface CrawlPool {\n subscribe(\n filter: { kinds?: number[]; authors?: string[]; limit?: number; [key: string]: unknown },\n handlers: {\n onEvent: (e: CrawlEvent) => void;\n onEose?: () => void;\n onStatus?: (s: string) => void;\n },\n ): CrawlSubCloser;\n getConnectedCount?(): number;\n}\n\nexport interface GraphCrawlerOptions {\n pool: CrawlPool;\n storage: GraphStorage;\n relays: string[];\n /** Base delay (ms) between fetch dispatches. Default 50. */\n baseDelayMs?: number;\n /** Max concurrent in-flight fetches. Default 5. */\n maxConcurrent?: number;\n /** Per-pubkey response timeout (ms). Default 10000. */\n requestTimeoutMs?: number;\n}\n\nexport class CrawlError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CrawlError';\n }\n}\n\nconst DEFAULT_MAX_DEPTH = 2;\n\nexport class GraphCrawler {\n private pool: CrawlPool;\n private storage: GraphStorage;\n private relays: string[];\n private baseDelayMs: number;\n private maxConcurrent: number;\n private requestTimeoutMs: number;\n private aborted = false;\n\n constructor(options: GraphCrawlerOptions) {\n this.pool = options.pool;\n this.storage = options.storage;\n this.relays = options.relays;\n this.baseDelayMs = options.baseDelayMs ?? 50;\n this.maxConcurrent = options.maxConcurrent ?? 5;\n this.requestTimeoutMs = options.requestTimeoutMs ?? 10000;\n }\n\n /** Abort an in-flight crawl. */\n stop(): void {\n this.aborted = true;\n }\n\n async crawl(rootPubkey: string, opts: CrawlOptions = {}): Promise<CrawlResult> {\n if (this.relays.length === 0) {\n throw new CrawlError('no relays connected');\n }\n\n const maxDepth = opts.maxDepth ?? DEFAULT_MAX_DEPTH;\n const start = Date.now();\n this.aborted = false;\n\n const signal = opts.signal;\n const onAbort = () => this.stop();\n if (signal) {\n if (signal.aborted) this.aborted = true;\n else signal.addEventListener('abort', onAbort);\n }\n\n const fetched = new Set<string>();\n const failed = new Set<string>();\n const seen = new Set<string>([rootPubkey]);\n let currentLevel: string[] = [rootPubkey];\n let reachedDepth = 0;\n let stoppedEarly = false;\n\n try {\n for (let depth = 0; depth <= maxDepth; depth++) {\n if (currentLevel.length === 0) break;\n if (this.aborted) {\n stoppedEarly = true;\n break;\n }\n\n const nextSet = new Set<string>();\n\n await this.mapLimited(currentLevel, async (pubkey) => {\n if (this.aborted) return;\n const follows = await this.fetchNewest(pubkey);\n if (this.aborted) return;\n\n if (follows === null) {\n failed.add(pubkey);\n } else {\n fetched.add(pubkey);\n reachedDepth = Math.max(reachedDepth, depth);\n this.storage.saveFollows(pubkey, follows);\n if (depth < maxDepth) {\n for (const f of follows) {\n if (!seen.has(f)) {\n seen.add(f);\n nextSet.add(f);\n }\n }\n }\n }\n\n opts.onProgress?.({ depth, fetched: fetched.size, queued: nextSet.size });\n });\n\n if (this.aborted) {\n stoppedEarly = true;\n break;\n }\n\n currentLevel = Array.from(nextSet);\n }\n } finally {\n if (signal) signal.removeEventListener('abort', onAbort);\n await this.storage.flush();\n }\n\n const stats = this.storage.stats();\n return {\n fetched: fetched.size,\n nodes: stats.nodes,\n edges: stats.edges,\n depth: reachedDepth,\n durationMs: Date.now() - start,\n stoppedEarly,\n };\n }\n\n /**\n * Fetch a single pubkey's newest kind:3 follow list across relays.\n * Resolves to the follow pubkeys, or `null` if no event arrived.\n */\n private fetchNewest(pubkey: string): Promise<string[] | null> {\n return new Promise((resolve) => {\n let newestAt = 0;\n let follows: string[] | null = null;\n let settled = false;\n let sub: CrawlSubCloser | null = null;\n\n const finish = () => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n try {\n sub?.close();\n } catch {\n /* ignore */\n }\n resolve(follows);\n };\n\n const timer = setTimeout(finish, this.requestTimeoutMs);\n\n sub = this.pool.subscribe(\n { kinds: [3], authors: [pubkey], limit: 1 },\n {\n onEvent: (ev: CrawlEvent) => {\n if (ev && ev.created_at > newestAt) {\n newestAt = ev.created_at;\n follows = (ev.tags || [])\n .filter((tag) => tag[0] === 'p' && tag[1])\n .map((tag) => tag[1]);\n }\n },\n onEose: finish,\n },\n );\n\n // Guard: a synchronous mock that resolved before assigning `sub` above.\n if (settled) {\n try {\n sub?.close();\n } catch {\n /* ignore */\n }\n }\n });\n }\n\n /**\n * Run `worker` over `items` with a max-concurrency cap and a base delay\n * before each dispatch (preserving the crawler's per-relay rate limiting\n * intent, now applied at the pool boundary).\n */\n private async mapLimited<T>(items: T[], worker: (item: T) => Promise<void>): Promise<void> {\n let index = 0;\n const runNext = async (): Promise<void> => {\n while (index < items.length) {\n if (this.aborted) return;\n const item = items[index++];\n if (this.baseDelayMs > 0) {\n await new Promise((r) => setTimeout(r, this.baseDelayMs));\n }\n if (this.aborted) return;\n await worker(item);\n }\n };\n\n const lanes = Math.min(this.maxConcurrent, Math.max(1, items.length));\n await Promise.all(Array.from({ length: lanes }, () => runNext()));\n }\n}\n","/**\n * Centralized trust score calculation.\n *\n * Formula: score = base + pathBonus (capped at maxPathBonus)\n *\n * Where:\n * - base: base score per hop distance (1 hop = 100%, 2 hops = 50%, etc.)\n * - pathBonus: bonus based on number of shortest paths, capped at maxPathBonus\n *\n * Ported verbatim from the extension (`lib/scoring.ts`).\n */\n\nimport type { ScoringConfig } from './types';\n\nexport const DEFAULT_SCORING: ScoringConfig = {\n distanceWeights: { 1: 1.0, 2: 0.5, 3: 0.25, 4: 0.1 },\n pathBonus: { 2: 0.15, 3: 0.1, 4: 0.05 },\n maxPathBonus: 0.5,\n};\n\n/**\n * Calculate trust score from hops and path count.\n *\n * @param hops - Number of hops (0 = self, 1 = direct follow, etc.)\n * @param paths - Number of shortest paths (null if unknown)\n * @param scoring - Scoring configuration\n * @returns Score between 0 and 1\n */\nexport function calculateScore(\n hops: number | null | undefined,\n paths: number | null,\n scoring: ScoringConfig = DEFAULT_SCORING,\n): number {\n // Self = maximum trust\n if (hops === 0) return 1.0;\n\n // Not connected\n if (hops === null || hops === undefined) return 0;\n\n const { distanceWeights, pathBonus, maxPathBonus } = scoring;\n\n // Get base score for this hop distance (use hop 4 for anything beyond)\n const hopKey = Math.min(hops, 4);\n const base = distanceWeights?.[hopKey] ?? DEFAULT_SCORING.distanceWeights[hopKey] ?? 0.1;\n\n // Calculate path bonus (only for hops > 1 with multiple paths)\n let bonus = 0;\n if (paths !== null && paths > 1 && hops > 1) {\n // Get path bonus for this hop level\n let pathBonusValue: number;\n if (typeof pathBonus === 'object') {\n pathBonusValue = pathBonus[hopKey] ?? DEFAULT_SCORING.pathBonus[hopKey] ?? 0.05;\n } else {\n // Legacy single value\n pathBonusValue = (pathBonus as unknown as number) ?? 0.1;\n }\n // Bonus = pathBonusValue * (paths - 1), capped at maxPathBonus\n bonus = Math.min(pathBonusValue * (paths - 1), maxPathBonus ?? 0.5);\n }\n\n // Final score: base + pathBonus (capped)\n const score = base + bonus;\n\n // Clamp to [0, 1]\n return Math.min(Math.max(score, 0), 1);\n}\n","/**\n * Adapter turning a {@link WotGraph} into the small `WoTLocalSource` shape that\n * `@nostr-wot/wot`'s `WoT` class can consume as a local query source instead of\n * the remote Oracle.\n */\n\nimport type { FilterByWoTOptions, WoTLocalSource } from './types';\n\n/** Minimal surface {@link createWoTSource} needs from a graph. */\nexport interface WoTSourceGraph {\n getDistance(pubkey: string): { hops: number; paths: number } | null;\n isInWoT(pubkey: string, maxHops?: number): boolean;\n filterByWoT(pubkeys: string[], opts?: FilterByWoTOptions): string[];\n}\n\nexport function createWoTSource(graph: WoTSourceGraph): WoTLocalSource {\n return {\n getDistance(target: string): number | null {\n const info = graph.getDistance(target);\n return info ? info.hops : null;\n },\n isInMyWoT(target: string, maxHops?: number): boolean {\n return graph.isInWoT(target, maxHops);\n },\n filterByWoT(pubkeys: string[], opts?: FilterByWoTOptions): string[] {\n return graph.filterByWoT(pubkeys, opts);\n },\n };\n}\n","/**\n * `WotGraph` — the primary public entry point.\n *\n * Ties the four internal layers together: a namespaced {@link GraphStorage},\n * a BFS {@link LocalGraph}, a {@link GraphCrawler}, and the pure scoring\n * function. Consumers create one per origin/app, `load()` to rehydrate any\n * cached graph, `crawl()` to build/refresh it, then run O(1)/O(n) queries.\n */\n\nimport { RelayPool } from '@nostr-wot/relay';\nimport { SimplePool } from 'nostr-tools';\nimport { useWebSocketImplementation } from 'nostr-tools/pool';\n\nimport { GraphStorage } from './storage';\nimport { LocalGraph } from './graph';\nimport { GraphCrawler, CrawlError, type CrawlPool } from './crawl';\nimport { calculateScore, DEFAULT_SCORING } from './scoring';\nimport { createWoTSource } from './wot-source';\nimport type {\n CrawlOptions,\n CrawlResult,\n DistanceInfo,\n FilterByWoTOptions,\n ScoringConfig,\n WebSocketLike,\n WoTLocalSource,\n} from './types';\n\nexport interface WotGraphOptions {\n /** IndexedDB partition key (e.g. the app name). */\n namespace: string;\n /** Relay URLs to crawl. */\n relays: string[];\n /** Optional shared pool; if omitted one is created from `relays`. */\n pool?: CrawlPool;\n /** Scoring overrides merged onto {@link DEFAULT_SCORING}. */\n scoring?: Partial<ScoringConfig>;\n /** WebSocket implementation forwarded to the created pool. */\n websocketImplementation?: WebSocketLike;\n}\n\nexport interface WotGraphStats {\n nodes: number;\n edges: number;\n root: string | null;\n lastCrawl: number | null;\n maxDepth: number | null;\n}\n\nconst DEFAULT_MAX_HOPS = 2;\nconst STORAGE_VERSION = 1;\n\nexport class WotGraph {\n readonly namespace: string;\n private relays: string[];\n private scoring: ScoringConfig;\n private websocketImplementation?: WebSocketLike;\n\n private storage: GraphStorage;\n private graph: LocalGraph;\n\n private pool: CrawlPool | null;\n private ownPool: RelayPool | null = null;\n private crawler: GraphCrawler | null = null;\n\n private root: string | null = null;\n private inFlight: Promise<CrawlResult> | null = null;\n private controller: AbortController | null = null;\n private listeners = new Set<() => void>();\n\n constructor(options: WotGraphOptions) {\n this.namespace = options.namespace;\n this.relays = [...options.relays];\n this.scoring = mergeScoring(options.scoring);\n this.websocketImplementation = options.websocketImplementation;\n this.pool = options.pool ?? null;\n\n this.storage = new GraphStorage(this.namespace);\n this.graph = new LocalGraph(this.storage);\n }\n\n /** Hydrate any cached graph from IndexedDB (fast path). */\n async load(): Promise<void> {\n await this.storage.open();\n this.root = this.storage.getGraphMeta().root;\n this.graph.invalidateCache();\n this.notify();\n }\n\n /**\n * Build/refresh the graph by crawling kind:3 from `rootPubkey`.\n * Concurrent calls return the same in-flight promise (idempotent).\n */\n crawl(rootPubkey: string, opts: CrawlOptions = {}): Promise<CrawlResult> {\n // Synchronous single-flight guard: a second crawl() while one is in flight\n // returns the same promise (idempotent — React strict-mode safe).\n if (this.inFlight) return this.inFlight;\n\n this.controller = new AbortController();\n if (opts.signal) {\n if (opts.signal.aborted) this.controller.abort();\n else opts.signal.addEventListener('abort', () => this.controller?.abort(), { once: true });\n }\n this.root = rootPubkey;\n\n const run = (async (): Promise<CrawlResult> => {\n try {\n await this.storage.open();\n const pool = this.resolvePool();\n this.crawler = new GraphCrawler({ pool, storage: this.storage, relays: this.relays });\n const result = await this.crawler.crawl(rootPubkey, {\n maxDepth: opts.maxDepth,\n onProgress: opts.onProgress,\n signal: this.controller!.signal,\n });\n await this.storage.setMeta('root', rootPubkey);\n await this.storage.setMeta('lastCrawl', Date.now());\n await this.storage.setMeta('maxDepth', opts.maxDepth ?? DEFAULT_MAX_HOPS);\n await this.storage.setMeta('version', STORAGE_VERSION);\n this.graph.invalidateCache();\n this.notify();\n return result;\n } finally {\n this.inFlight = null;\n this.crawler = null;\n this.controller = null;\n }\n })();\n\n this.inFlight = run;\n return run;\n }\n\n /** Distance info from the crawled root, or `null` if unreached/unknown. */\n getDistance(pubkey: string): DistanceInfo | null {\n if (!this.root) return null;\n return this.graph.getDistance(this.root, pubkey);\n }\n\n /** Trust score 0..1 via {@link calculateScore}. */\n getScore(pubkey: string): number {\n const info = this.getDistance(pubkey);\n return calculateScore(info ? info.hops : null, info ? info.paths : null, this.scoring);\n }\n\n /** Whether `pubkey` is within `maxHops` of the root. */\n isInWoT(pubkey: string, maxHops: number = DEFAULT_MAX_HOPS): boolean {\n const info = this.getDistance(pubkey);\n return info !== null && info.hops <= maxHops;\n }\n\n /** Trusted subset of `pubkeys`, sorted by score descending. */\n filterByWoT(pubkeys: string[], opts?: FilterByWoTOptions): string[] {\n const maxHops = opts?.maxHops ?? DEFAULT_MAX_HOPS;\n const scored: Array<{ pubkey: string; score: number }> = [];\n for (const pubkey of pubkeys) {\n const info = this.getDistance(pubkey);\n if (info !== null && info.hops <= maxHops) {\n scored.push({ pubkey, score: calculateScore(info.hops, info.paths, this.scoring) });\n }\n }\n scored.sort((a, b) => b.score - a.score);\n return scored.map((s) => s.pubkey);\n }\n\n /** Follow list of `pubkey` as hex strings. */\n getFollows(pubkey: string): string[] {\n return this.graph.getFollows(pubkey);\n }\n\n /** Aggregate stats + crawl meta. */\n stats(): WotGraphStats {\n const s = this.storage.stats();\n const meta = this.storage.getGraphMeta();\n return {\n nodes: s.nodes,\n edges: s.edges,\n root: meta.root,\n lastCrawl: meta.lastCrawl,\n maxDepth: meta.maxDepth,\n };\n }\n\n /** True if the last crawl is older than `ttlMs` (or never happened). */\n isStale(ttlMs: number): boolean {\n const last = this.storage.getGraphMeta().lastCrawl;\n if (last === null) return true;\n return Date.now() - last > ttlMs;\n }\n\n /** Wipe this namespace. */\n async clear(): Promise<void> {\n await this.storage.clear();\n this.root = null;\n this.graph.invalidateCache();\n this.notify();\n }\n\n /** Abort an in-flight crawl. Partial data stays usable. */\n stop(): void {\n this.controller?.abort();\n this.crawler?.stop();\n }\n\n /** Adapter for `@nostr-wot/wot`'s `WoT` class. */\n asWoTSource(): WoTLocalSource {\n return createWoTSource(this);\n }\n\n /** The root pubkey the graph is currently answering queries from. */\n getRoot(): string | null {\n return this.root;\n }\n\n /** Subscribe to graph changes (crawl / load / clear). Returns an unsubscribe. */\n onChange(cb: () => void): () => void {\n this.listeners.add(cb);\n return () => this.listeners.delete(cb);\n }\n\n /** Release the pool/storage this instance owns. */\n destroy(): void {\n this.storage.close();\n if (this.ownPool) {\n this.ownPool.destroy();\n this.ownPool = null;\n }\n }\n\n private notify(): void {\n for (const cb of this.listeners) cb();\n }\n\n private resolvePool(): CrawlPool {\n if (this.pool) return this.pool;\n if (this.relays.length === 0) throw new CrawlError('no relays connected');\n if (this.websocketImplementation) {\n useWebSocketImplementation(this.websocketImplementation);\n }\n const rp = new RelayPool({ urls: this.relays });\n rp.ensurePool(() => new SimplePool());\n this.ownPool = rp;\n // RelayPool.subscribe(filter, { onEvent, onEose }) is structurally compatible.\n this.pool = rp as unknown as CrawlPool;\n return this.pool;\n }\n}\n\nfunction mergeScoring(overrides?: Partial<ScoringConfig>): ScoringConfig {\n if (!overrides) return { ...DEFAULT_SCORING };\n return {\n distanceWeights: { ...DEFAULT_SCORING.distanceWeights, ...overrides.distanceWeights },\n pathBonus: { ...DEFAULT_SCORING.pathBonus, ...overrides.pathBonus },\n maxPathBonus: overrides.maxPathBonus ?? DEFAULT_SCORING.maxPathBonus,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/storage.ts","../src/graph.ts","../src/crawl.ts","../src/scoring.ts","../src/wot-source.ts","../src/wot-graph.ts"],"names":["_a","_b","DEFAULT_MAX_HOPS"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * IndexedDB storage for the local WoT graph.\n *\n * Ported from the extension (`lib/storage.ts`), generalized from per-account\n * databases to a `namespace` key and wrapped in a class so multiple graphs can\n * coexist. Preserves the two performance-critical techniques:\n *\n * - **Interning**: pubkeys (64-hex) are mapped to small integer ids, so the\n * graph is stored/traversed as numbers instead of strings.\n * - **Compact persistence**: sorted follow ids are delta-varint encoded on disk;\n * hydrated adjacency remains Uint32Array for numeric traversal. Legacy fixed-\n * width delta rows remain readable.\n *\n * When `indexedDB` is unavailable (Node without a polyfill) the store operates\n * in memory-only mode: crawl/query still work, nothing is persisted.\n */\n\nimport type { GraphMeta, StorageStats } from './types';\n\nconst DB_PREFIX = 'nostr-wot-graph';\nconst DB_VERSION = 2;\nconst STORE_PUBKEYS = 'pubkeys';\nconst STORE_FOLLOWS = 'follows';\nconst STORE_META = 'meta';\nconst EMPTY_IDS = new Uint32Array(0);\nexport interface FollowVersion { createdAt: number; id: string }\nexport function newerVersion(candidate: FollowVersion, prior: FollowVersion): boolean {\n return candidate.createdAt > prior.createdAt || candidate.createdAt === prior.createdAt && candidate.id < prior.id;\n}\n\n// Encode follow ids for storage (sort + delta encode into a Uint32Array).\nexport function encodeFollows(followIds: ArrayLike<number>): ArrayBuffer {\n if (followIds.length === 0) return new ArrayBuffer(0);\n\n const sorted = Array.from(followIds).sort((a, b) => a - b);\n\n const deltas = new Uint32Array(sorted.length);\n deltas[0] = sorted[0];\n for (let i = 1; i < sorted.length; i++) {\n deltas[i] = sorted[i] - sorted[i - 1];\n }\n\n return deltas.buffer;\n}\n\n// Decode follow ids from storage (delta decode back to absolute values).\nexport function decodeFollows(buffer: ArrayBuffer | null | undefined): Uint32Array {\n if (!buffer || buffer.byteLength === 0) return new Uint32Array(0);\n\n const deltas = new Uint32Array(buffer);\n const result = new Uint32Array(deltas.length);\n\n result[0] = deltas[0];\n for (let i = 1; i < deltas.length; i++) {\n result[i] = result[i - 1] + deltas[i];\n }\n\n return result;\n}\n\n// Versioned disk rows use unsigned delta varints; the exported fixed-width\n// helpers remain compatible with existing callers and legacy database rows.\nexport function encodeCompactFollows(ids: ArrayLike<number>): ArrayBuffer {\n const sorted = Array.from(new Set(Array.from(ids))).sort((a, b) => a - b);\n const bytes: number[] = [];\n let prior = 0;\n for (const id of sorted) {\n if (!Number.isInteger(id) || id < 0 || id > 0xffffffff) {\n throw new RangeError(\"Follow IDs must be unsigned 32-bit integers\");\n }\n let delta = id - prior;\n prior = id;\n while (delta >= 128) { bytes.push((delta % 128) | 128); delta = Math.floor(delta / 128); }\n bytes.push(delta);\n }\n return Uint8Array.from(bytes).buffer;\n}\n\nexport function decodeCompactFollows(buffer: ArrayBuffer): Uint32Array {\n const values: number[] = [];\n let prior = 0, delta = 0, factor = 1;\n for (const byte of new Uint8Array(buffer)) {\n delta += (byte & 127) * factor;\n if (delta > 0xffffffff || factor > 0x10000000) throw new Error('Invalid follow varint');\n if (byte & 128) factor *= 128;\n else {\n prior += delta;\n if (prior > 0xffffffff) throw new Error('Follow id overflow');\n values.push(prior); delta = 0; factor = 1;\n }\n }\n if (factor !== 1) throw new Error('Truncated follow varint');\n return Uint32Array.from(values);\n}\n\nfunction hasIndexedDB(): boolean {\n return typeof indexedDB !== 'undefined' && indexedDB !== null;\n}\n\nexport class GraphStorage {\n readonly namespace: string;\n private db: IDBDatabase | null = null;\n private memoryOnly = false;\n private opened = false;\n private opening: Promise<void> | null = null;\n private revision = 0;\n private edges = 0;\n private versions = new Map<number, FollowVersion>();\n private flushing: Promise<void> = Promise.resolve();\n\n // In-memory caches (source of truth for reads/BFS).\n private pubkeyToId = new Map<string, number>();\n private idToPubkey = new Map<number, string>();\n private nextId = 1;\n private graphCache = new Map<number, Uint32Array>();\n private metaCache = new Map<string, unknown>();\n\n // Pending persistence buffers (drained by flush()).\n private dirtyFollows = new Map<number, number[]>();\n private dirtyPubkeys: Array<{ id: number; pubkey: string }> = [];\n\n constructor(namespace: string) {\n if (!namespace) throw new Error('GraphStorage requires a namespace');\n this.namespace = namespace;\n }\n\n private dbName(): string {\n return `${DB_PREFIX}:${this.namespace}`;\n }\n\n /** Open (or create) the namespace DB and hydrate in-memory caches. */\n async open(): Promise<void> {\n if (this.opening) return this.opening;\n if (this.opened) return;\n this.opening = this.openDatabase();\n try { await this.opening; } finally { this.opening = null; }\n }\n\n private async openDatabase(): Promise<void> {\n\n if (!hasIndexedDB()) {\n this.memoryOnly = true;\n this.opened = true;\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const request = indexedDB.open(this.dbName(), DB_VERSION);\n request.onerror = () => reject(request.error);\n request.onupgradeneeded = (event) => {\n const database = (event.target as IDBOpenDBRequest).result;\n if (!database.objectStoreNames.contains(STORE_PUBKEYS)) {\n const store = database.createObjectStore(STORE_PUBKEYS, { keyPath: 'id' });\n store.createIndex('pubkey', 'pubkey', { unique: true });\n }\n if (!database.objectStoreNames.contains(STORE_FOLLOWS)) {\n database.createObjectStore(STORE_FOLLOWS, { keyPath: 'id' });\n }\n if (!database.objectStoreNames.contains(STORE_META)) {\n database.createObjectStore(STORE_META, { keyPath: 'key' });\n }\n };\n request.onsuccess = () => {\n this.db = request.result;\n resolve();\n };\n });\n\n await this.loadAll();\n this.opened = true;\n }\n\n /** Hydrate the in-memory interning + follow maps + meta from the DB. */\n async loadAll(): Promise<void> {\n this.pubkeyToId.clear();\n this.idToPubkey.clear();\n this.graphCache.clear();\n this.metaCache.clear();\n this.nextId = 1;\n this.versions.clear();\n this.edges = 0;\n this.revision++;\n\n if (this.memoryOnly || !this.db) return;\n const db = this.db;\n\n const tx = db.transaction([STORE_PUBKEYS, STORE_FOLLOWS, STORE_META], 'readonly');\n const [pubkeys, follows, meta] = await Promise.all([\n this.getAll<{ id: number; pubkey: string }>(tx, STORE_PUBKEYS),\n this.getAll<{ id: number; follows: ArrayBuffer; encoding?: string; version?: FollowVersion }>(tx, STORE_FOLLOWS),\n this.getAll<{ key: string; value: unknown }>(tx, STORE_META),\n ]);\n for (const record of pubkeys) {\n this.pubkeyToId.set(record.pubkey, record.id);\n this.idToPubkey.set(record.id, record.pubkey);\n if (record.id >= this.nextId) this.nextId = record.id + 1;\n }\n\n for (const record of follows) {\n if (record.encoding && record.encoding !== 'delta-varint-v1') throw new Error('Unknown follow encoding');\n const row = record.encoding === 'delta-varint-v1' ? decodeCompactFollows(record.follows) : Uint32Array.from(new Set(decodeFollows(record.follows)));\n this.graphCache.set(record.id, row);\n this.edges += row.length;\n if (record.version) this.versions.set(record.id, record.version);\n }\n\n for (const record of meta) {\n this.metaCache.set(record.key, record.value);\n }\n }\n\n private getAll<T>(tx: IDBTransaction, store: string): Promise<T[]> {\n return new Promise((resolve, reject) => {\n const request = tx.objectStore(store).getAll();\n request.onsuccess = () => resolve(request.result as T[]);\n request.onerror = () => reject(request.error);\n });\n }\n\n // ── Interning ──\n\n /** Numeric id for a pubkey, or null if never seen. */\n getId(pubkey: string): number | null {\n return this.pubkeyToId.get(pubkey) ?? null;\n }\n\n /** Numeric id for a pubkey, minting and buffering a new one if needed. */\n getOrCreateId(pubkey: string): number {\n const existing = this.pubkeyToId.get(pubkey);\n if (existing !== undefined) return existing;\n\n const id = this.nextId++;\n this.pubkeyToId.set(pubkey, id);\n this.idToPubkey.set(id, pubkey);\n this.dirtyPubkeys.push({ id, pubkey });\n return id;\n }\n\n /** Batch variant of {@link getOrCreateId}. */\n getOrCreateIds(pubkeys: string[]): number[] {\n const ids = new Array<number>(pubkeys.length);\n for (let i = 0; i < pubkeys.length; i++) {\n ids[i] = this.getOrCreateId(pubkeys[i]);\n }\n return ids;\n }\n\n /** Pubkey for a numeric id, or null. */\n getHex(id: number): string | null {\n return this.idToPubkey.get(id) ?? null;\n }\n\n /** Highest assigned id (for typed-array sizing). */\n getMaxId(): number {\n return this.nextId - 1;\n }\n\n // ── Follows ──\n\n /** Store `pubkey`'s follow list. Interns everything and updates the cache. */\n saveFollows(pubkey: string, follows: string[], version?: FollowVersion): boolean {\n const id = this.getOrCreateId(pubkey);\n const priorVersion = this.versions.get(id);\n if (version && priorVersion && !newerVersion(version, priorVersion)) return false;\n const followIds = this.getOrCreateIds([...new Set(follows)]).sort((a, b) => a - b);\n const prior = this.graphCache.get(id);\n const changed = !prior || prior.length !== followIds.length || followIds.some((v, i) => prior[i] !== v);\n if (version) this.versions.set(id, { ...version });\n else this.versions.delete(id);\n if (changed) {\n this.edges += followIds.length - (prior?.length ?? 0);\n this.graphCache.set(id, new Uint32Array(followIds));\n this.revision++;\n }\n if (changed || version || priorVersion) this.dirtyFollows.set(id, followIds);\n return true;\n }\n\n getRevision(): number { return this.revision; }\n getFollowVersion(pubkey: string): FollowVersion | undefined {\n const id = this.getId(pubkey);\n const version = id === null ? undefined : this.versions.get(id);\n return version ? { ...version } : undefined;\n }\n\n /** Follow ids for a node id — sync, from the in-memory cache. */\n getFollowIdsSync(id: number): Uint32Array {\n return this.graphCache.get(id) ?? EMPTY_IDS;\n }\n\n /** Follow ids for a pubkey (interned). Empty if unknown. */\n getFollowIds(pubkey: string): Uint32Array {\n const id = this.getId(pubkey);\n if (id === null) return EMPTY_IDS;\n return this.getFollowIdsSync(id);\n }\n\n /** Follow list of `pubkey` as hex strings. */\n getFollows(pubkey: string): string[] {\n const ids = this.getFollowIds(pubkey);\n const out: string[] = [];\n for (let i = 0; i < ids.length; i++) {\n const hex = this.getHex(ids[i]);\n if (hex) out.push(hex);\n }\n return out;\n }\n\n // ── Meta ──\n\n async setMeta(key: string, value: unknown): Promise<void> {\n await this.setMetaBatch({ [key]: value });\n }\n\n async setMetaBatch(values: Record<string, unknown>): Promise<void> {\n if (this.memoryOnly || !this.db) {\n for (const [key, value] of Object.entries(values)) this.metaCache.set(key, value);\n return;\n }\n const db = this.db;\n await new Promise<void>((resolve, reject) => {\n const tx = db.transaction(STORE_META, 'readwrite');\n for (const [key, value] of Object.entries(values)) tx.objectStore(STORE_META).put({ key, value });\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error ?? new Error(\"Graph transaction failed\"));\n tx.onabort = () => reject(tx.error ?? new Error(\"Metadata write aborted\"));\n });\n for (const [key, value] of Object.entries(values)) this.metaCache.set(key, value);\n }\n\n getMeta<T = unknown>(key: string): T | undefined {\n return this.metaCache.get(key) as T | undefined;\n }\n\n /** Read the structured graph meta record. */\n getGraphMeta(): GraphMeta {\n return {\n root: (this.getMeta<string>('root') ?? null) as string | null,\n lastCrawl: (this.getMeta<number>('lastCrawl') ?? null) as number | null,\n maxDepth: (this.getMeta<number>('maxDepth') ?? null) as number | null,\n version: this.getMeta<number>('version') ?? DB_VERSION,\n };\n }\n\n // ── Persistence ──\n\n /** Flush buffered pubkey + follow writes to IndexedDB. No-op in memory mode. */\n flush(): Promise<void> {\n const run = this.flushing.then(() => this.flushPending());\n this.flushing = run.catch(() => {});\n return run;\n }\n\n private async flushPending(): Promise<void> {\n if (this.memoryOnly || !this.db) {\n this.dirtyPubkeys.length = 0;\n this.dirtyFollows.clear();\n return;\n }\n const db = this.db;\n\n const pubkeys = this.dirtyPubkeys.slice();\n const follows = Array.from(this.dirtyFollows.entries());\n const versions = new Map(follows.map(([id]) => [id, this.versions.get(id)]));\n\n if (pubkeys.length === 0 && follows.length === 0) return;\n\n await new Promise<void>((resolve, reject) => {\n const stores: string[] = [];\n if (pubkeys.length) stores.push(STORE_PUBKEYS);\n if (follows.length) stores.push(STORE_FOLLOWS);\n const tx = db.transaction(stores, 'readwrite');\n\n if (pubkeys.length) {\n const store = tx.objectStore(STORE_PUBKEYS);\n for (const row of pubkeys) store.put(row);\n }\n if (follows.length) {\n const store = tx.objectStore(STORE_FOLLOWS);\n for (const [id, followIds] of follows) {\n store.put({ id, follows: encodeCompactFollows(followIds), encoding: 'delta-varint-v1', updated_at: Date.now(), version: versions.get(id) });\n }\n }\n\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error ?? new Error(\"Graph transaction failed\"));\n tx.onabort = () => reject(tx.error ?? new Error(\"Graph flush aborted\"));\n });\n this.dirtyPubkeys.splice(0, pubkeys.length);\n for (const [id, row] of follows) {\n if (this.dirtyFollows.get(id) === row) this.dirtyFollows.delete(id);\n }\n }\n\n // ── Stats / clear ──\n\n stats(): StorageStats {\n return {\n nodes: this.graphCache.size,\n edges: this.edges,\n uniquePubkeys: this.pubkeyToId.size,\n };\n }\n\n /** Wipe this namespace: memory caches + persisted stores. */\n async clear(): Promise<void> {\n await this.flushing;\n if (!this.memoryOnly && this.db) {\n const db = this.db;\n await new Promise<void>((resolve, reject) => {\n const tx = db.transaction([STORE_FOLLOWS, STORE_PUBKEYS, STORE_META], 'readwrite');\n tx.objectStore(STORE_FOLLOWS).clear();\n tx.objectStore(STORE_PUBKEYS).clear();\n tx.objectStore(STORE_META).clear();\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error ?? new Error(\"Graph transaction failed\"));\n tx.onabort = () => reject(tx.error ?? new Error(\"Graph clear aborted\"));\n });\n }\n this.pubkeyToId.clear();\n this.idToPubkey.clear();\n this.graphCache.clear();\n this.metaCache.clear();\n this.dirtyFollows.clear();\n this.dirtyPubkeys.length = 0;\n this.nextId = 1;\n this.versions.clear();\n this.edges = 0;\n this.revision++;\n\n }\n\n /** Close the underlying DB connection. */\n close(): void {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n this.opened = false;\n }\n}\n","/**\n * In-memory BFS over the hydrated follow graph.\n *\n * Ported from the extension (`lib/graph.ts`, `LocalGraph`). Given the interned\n * follow map (from {@link GraphStorage}) and a root pubkey, a single BFS pass\n * fills two typed arrays indexed by node id:\n *\n * - `hops` (`Uint32Array`) — distance from root, stored as `hop + 1` so `0`\n * means \"not reached\" using a 32-bit distance.\n * - `paths` (`Float64Array`) — count of shortest paths to each node.\n *\n * The cache is keyed by root and invalidated on crawl / root change / clear.\n */\n\nimport type { GraphStorage } from './storage';\nimport type { DistanceInfo } from './types';\n\ninterface BfsCache {\n rootId: number;\n hops: Uint32Array;\n paths: Float64Array;\n maxId: number;\n maxHops: number;\n revision: number;\n}\n\nconst DEFAULT_MAX_HOPS = 6;\n\nexport class LocalGraph {\n private storage: GraphStorage;\n private cache: BfsCache | null = null;\n private cachedRoot: string | null = null;\n\n constructor(storage: GraphStorage) {\n this.storage = storage;\n }\n\n /** Invalidate the precomputed cache (called on crawl / root change / clear). */\n invalidateCache(): void {\n this.cache = null;\n this.cachedRoot = null;\n }\n\n /**\n * Precompute hops and paths from a root pubkey using a single BFS pass.\n * Results stored in typed arrays indexed by node id for O(1) lookup.\n */\n private buildCache(rootPubkey: string, maxHops: number = DEFAULT_MAX_HOPS): void {\n const rootId = this.storage.getId(rootPubkey);\n if (rootId === null) {\n this.cache = null;\n this.cachedRoot = null;\n return;\n }\n\n const maxId = this.storage.getMaxId();\n // Store hop + 1 so zero means unreachable.\n const hops = new Uint32Array(maxId + 1);\n const paths = new Float64Array(maxId + 1);\n\n // Root: distance 0, 1 path\n hops[rootId] = 1; // stored as hop+1\n paths[rootId] = 1;\n\n const queue = new Uint32Array(maxId + 1);\n queue[0] = rootId;\n let length = 1;\n for (let head = 0; head < length; head++) {\n const nodeId = queue[head];\n const distance = hops[nodeId] - 1;\n if (distance >= maxHops) continue;\n const hopStored = distance + 2;\n const followIds = this.storage.getFollowIdsSync(nodeId);\n for (let i = 0; i < followIds.length; i++) {\n const fid = followIds[i];\n if (fid > maxId) continue;\n if (hops[fid] === 0) {\n hops[fid] = hopStored;\n queue[length++] = fid;\n }\n if (hops[fid] === hopStored) paths[fid] = Math.min(Number.MAX_SAFE_INTEGER, paths[fid] + paths[nodeId]);\n }\n }\n\n this.cache = { rootId, hops, paths, maxId, maxHops, revision: this.storage.getRevision() };\n this.cachedRoot = rootPubkey;\n }\n\n /** Ensure the cache is built for `root`. */\n private ensureCache(root: string, maxHops: number): void {\n if (this.cachedRoot !== root || !this.cache || this.cache.maxHops < maxHops || this.cache.revision !== this.storage.getRevision()) {\n this.buildCache(root, maxHops);\n }\n }\n\n /**\n * Distance info from `root` to `pubkey`. Returns `{ hops, paths }`, or `null`\n * when unreached / unknown. Self → `{ hops: 0, paths: 1 }`.\n */\n getDistance(root: string, pubkey: string, maxHops: number = DEFAULT_MAX_HOPS): DistanceInfo | null {\n if (!Number.isSafeInteger(maxHops) || maxHops < 0) throw new RangeError(\"maxHops must be a non-negative safe integer\");\n if (root === pubkey) return { hops: 0, paths: 1 };\n\n this.ensureCache(root, maxHops);\n if (!this.cache || this.cachedRoot !== root) return null;\n\n const toId = this.storage.getId(pubkey);\n if (toId === null || toId > this.cache.maxId) return null;\n\n const h = this.cache.hops[toId];\n if (h === 0 || h - 1 > maxHops) return null; // unreachable\n\n return { hops: h - 1, paths: this.cache.paths[toId] };\n }\n\n /** Follow list of `pubkey` as hex strings. */\n getFollows(pubkey: string): string[] {\n return this.storage.getFollows(pubkey);\n }\n}\n","/**\n * BFS crawler for kind:3 contact lists.\n *\n * Ported from the extension (`lib/sync.ts`, `GraphSync`) but with the raw\n * `WebSocket` transport replaced by `@nostr-wot/relay`'s pool. The pool handles\n * connection/reconnect across relays; this class keeps the proven crawl logic:\n *\n * - BFS by depth: fetch the root's kind:3, enqueue its follows for the next\n * depth, and so on up to `maxDepth`.\n * - Newest-per-author: for each pubkey, take the kind:3 event with the highest\n * `created_at` seen across relays.\n * - Rate limiting: a base delay between dispatches and a max-concurrent cap.\n * - Tolerates unreachable relays; throws `CrawlError` only when zero relays are\n * configured to connect.\n * - Abortable via `signal` or `stop()`; a stopped crawl leaves partial data\n * usable and reports `stoppedEarly: true`.\n */\n\nimport { newerVersion, type GraphStorage } from './storage';\nimport type { CrawlOptions, CrawlResult } from './types';\n\n// Minimal relay-pool surface the crawler needs. `@nostr-wot/relay`'s `RelayPool`\n// (its `subscribe(filter, { onEvent, onEose })`) is structurally assignable.\nexport interface CrawlSubCloser {\n close(): void;\n}\nexport interface CrawlEvent {\n created_at: number;\n tags: string[][];\n [key: string]: unknown;\n}\nexport interface CrawlPool {\n subscribe(\n filter: { kinds?: number[]; authors?: string[]; limit?: number; [key: string]: unknown },\n handlers: {\n onEvent: (e: CrawlEvent) => void;\n onEose?: () => void;\n onStatus?: (s: string) => void;\n },\n ): CrawlSubCloser;\n getConnectedCount?(): number;\n}\n\nexport interface GraphCrawlerOptions {\n pool: CrawlPool;\n storage: GraphStorage;\n relays: string[];\n /** Base delay (ms) between fetch dispatches. Default 50. */\n baseDelayMs?: number;\n /** Authors per relay subscription. Default 100. */\n batchSize?: number;\n /** Max concurrent in-flight fetches. Default 5. */\n maxConcurrent?: number;\n /** Per-pubkey response timeout (ms). Default 10000. */\n requestTimeoutMs?: number;\n}\n\nexport class CrawlError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CrawlError';\n }\n}\n\nconst DEFAULT_MAX_DEPTH = 2;\n\nexport class GraphCrawler {\n private pool: CrawlPool;\n private storage: GraphStorage;\n private relays: string[];\n private baseDelayMs: number;\n private maxConcurrent: number;\n private requestTimeoutMs: number;\n private aborted = false;\n private batchSize: number;\n private pending = new Set<() => void>();\n\n constructor(options: GraphCrawlerOptions) {\n this.batchSize = options.batchSize ?? 100;\n for (const [name, value] of Object.entries({ batchSize: this.batchSize, maxConcurrent: options.maxConcurrent ?? 5 })) {\n if (!Number.isSafeInteger(value) || value < 1) throw new RangeError(`${name} must be a positive safe integer`);\n }\n this.pool = options.pool;\n this.storage = options.storage;\n this.relays = options.relays;\n this.baseDelayMs = options.baseDelayMs ?? 50;\n this.maxConcurrent = options.maxConcurrent ?? 5;\n this.requestTimeoutMs = options.requestTimeoutMs ?? 10000;\n }\n\n /** Abort an in-flight crawl. */\n stop(): void {\n this.aborted = true;\n for (const finish of this.pending) finish();\n }\n\n async crawl(rootPubkey: string, opts: CrawlOptions = {}): Promise<CrawlResult> {\n if (this.relays.length === 0) {\n throw new CrawlError('no relays connected');\n }\n\n const maxDepth = opts.maxHops === undefined ? opts.maxDepth ?? DEFAULT_MAX_DEPTH : opts.maxHops - 1;\n const bound = opts.maxHops ?? maxDepth;\n if (!Number.isSafeInteger(bound) || bound < 0) throw new RangeError(\"crawl depth must be a non-negative safe integer\");\n const start = Date.now();\n this.aborted = false;\n\n const signal = opts.signal;\n const onAbort = () => this.stop();\n if (signal) {\n if (signal.aborted) this.aborted = true;\n else signal.addEventListener('abort', onAbort);\n }\n\n const fetched = new Set<string>();\n const failed = new Set<string>();\n const seen = new Set<string>([rootPubkey]);\n let currentLevel: string[] = [rootPubkey];\n let reachedDepth = 0;\n let stoppedEarly = false;\n\n try {\n for (let depth = 0; depth <= maxDepth; depth++) {\n if (currentLevel.length === 0) break;\n if (this.aborted) {\n stoppedEarly = true;\n break;\n }\n\n const nextSet = new Set<string>();\n\n const batches: string[][] = [];\n for (let i = 0; i < currentLevel.length; i += this.batchSize) batches.push(currentLevel.slice(i, i + this.batchSize));\n await this.mapLimited(batches, async (authors) => {\n const events = await this.fetchNewest(authors);\n if (this.aborted) return;\n for (const pubkey of authors) {\n const event = events.get(pubkey);\n if (!event) failed.add(pubkey);\n else {\n fetched.add(pubkey);\n reachedDepth = Math.max(reachedDepth, depth);\n const follows = (event.tags || []).filter(tag => tag[0] === 'p' && typeof tag[1] === 'string' && tag[1]).map(tag => tag[1]);\n this.storage.saveFollows(pubkey, follows, { createdAt: event.created_at, id: String(event.id ?? '') });\n }\n // A missing or older relay response must not erase the cached list.\n if (depth < maxDepth) {\n for (const follow of this.storage.getFollows(pubkey)) {\n if (!seen.has(follow)) { seen.add(follow); nextSet.add(follow); }\n }\n }\n opts.onProgress?.({ depth, fetched: fetched.size, queued: nextSet.size });\n if (this.aborted) break;\n }\n });\n\n if (this.aborted) {\n stoppedEarly = true;\n break;\n }\n\n currentLevel = Array.from(nextSet);\n }\n } finally {\n if (signal) signal.removeEventListener('abort', onAbort);\n await this.storage.flush();\n }\n\n const stats = this.storage.stats();\n return {\n fetched: fetched.size,\n nodes: stats.nodes,\n edges: stats.edges,\n depth: reachedDepth,\n durationMs: Date.now() - start,\n stoppedEarly,\n };\n }\n\n /**\n * Fetch one author batch, retaining the deterministic newest kind:3 per author.\n * No global limit: a prolific author must not displace another author's list.\n */\n private fetchNewest(authors: string[]): Promise<Map<string, CrawlEvent>> {\n return new Promise((resolve, reject) => {\n const newest = new Map<string, CrawlEvent>();\n const allowed = new Set(authors);\n let settled = false;\n let sub: CrawlSubCloser | null = null;\n const finish = () => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n this.pending.delete(finish);\n try { sub?.close(); } catch { /* transport already closed */ }\n resolve(newest);\n };\n const timer = setTimeout(finish, this.requestTimeoutMs);\n this.pending.add(finish);\n try {\n sub = this.pool.subscribe({ kinds: [3], authors }, {\n onEvent: ev => {\n if (settled || !ev || ev.kind !== 3 || typeof ev.pubkey !== 'string' || !allowed.has(ev.pubkey) ||\n !Number.isSafeInteger(ev.created_at) || ev.created_at < 0 || ev.created_at > Date.now() / 1000 + 60) return;\n const prior = newest.get(ev.pubkey);\n if (!prior || newerVersion({ createdAt: ev.created_at, id: String(ev.id ?? '') }, { createdAt: prior.created_at, id: String(prior.id ?? '') })) newest.set(ev.pubkey, ev);\n },\n onEose: finish,\n });\n if (settled) sub.close();\n } catch (error) {\n clearTimeout(timer);\n this.pending.delete(finish);\n settled = true;\n reject(error);\n }\n });\n }\n\n /**\n * Run `worker` over `items` with a max-concurrency cap and a base delay\n * before each dispatch (preserving the crawler's per-relay rate limiting\n * intent, now applied at the pool boundary).\n */\n private async mapLimited<T>(items: T[], worker: (item: T) => Promise<void>): Promise<void> {\n let index = 0;\n const runNext = async (): Promise<void> => {\n while (index < items.length) {\n if (this.aborted) return;\n const item = items[index++];\n if (this.baseDelayMs > 0) {\n await new Promise((r) => setTimeout(r, this.baseDelayMs));\n }\n if (this.aborted) return;\n await worker(item);\n }\n };\n\n const lanes = Math.min(this.maxConcurrent, Math.max(1, items.length));\n const outcomes = await Promise.allSettled(Array.from({ length: lanes }, async () => {\n try { await runNext(); } catch (error) { this.stop(); throw error; }\n }));\n const failure = outcomes.find((outcome): outcome is PromiseRejectedResult => outcome.status === \"rejected\");\n if (failure) throw failure.reason;\n }\n}\n","/**\n * Centralized trust score calculation.\n *\n * Formula: score = base + pathBonus (capped at maxPathBonus)\n *\n * Where:\n * - base: base score per hop distance (1 hop = 100%, 2 hops = 50%, etc.)\n * - pathBonus: bonus based on number of shortest paths, capped at maxPathBonus\n *\n * Ported verbatim from the extension (`lib/scoring.ts`).\n */\n\nimport type { ScoringConfig } from './types';\n\nexport const DEFAULT_SCORING: ScoringConfig = {\n distanceWeights: { 1: 1.0, 2: 0.5, 3: 0.25, 4: 0.1 },\n pathBonus: { 2: 0.15, 3: 0.1, 4: 0.05 },\n maxPathBonus: 0.5,\n};\n\n/**\n * Calculate trust score from hops and path count.\n *\n * @param hops - Number of hops (0 = self, 1 = direct follow, etc.)\n * @param paths - Number of shortest paths (null if unknown)\n * @param scoring - Scoring configuration\n * @returns Score between 0 and 1\n */\nexport function calculateScore(\n hops: number | null | undefined,\n paths: number | null,\n scoring: ScoringConfig = DEFAULT_SCORING,\n): number {\n // Self = maximum trust\n if (hops === 0) return 1.0;\n\n // Not connected\n if (hops === null || hops === undefined) return 0;\n\n const { distanceWeights, pathBonus, maxPathBonus } = scoring;\n\n // Get base score for this hop distance (use hop 4 for anything beyond)\n const hopKey = Math.min(hops, 4);\n const base = distanceWeights?.[hopKey] ?? DEFAULT_SCORING.distanceWeights[hopKey] ?? 0.1;\n\n // Calculate path bonus (only for hops > 1 with multiple paths)\n let bonus = 0;\n if (paths !== null && paths > 1 && hops > 1) {\n // Get path bonus for this hop level\n let pathBonusValue: number;\n if (typeof pathBonus === 'object') {\n pathBonusValue = pathBonus[hopKey] ?? DEFAULT_SCORING.pathBonus[hopKey] ?? 0.05;\n } else {\n // Legacy single value\n pathBonusValue = (pathBonus as unknown as number) ?? 0.1;\n }\n // Bonus = pathBonusValue * (paths - 1), capped at maxPathBonus\n bonus = Math.min(pathBonusValue * (paths - 1), maxPathBonus ?? 0.5);\n }\n\n // Final score: base + pathBonus (capped)\n const score = base + bonus;\n\n // Clamp to [0, 1]\n return Math.min(Math.max(score, 0), 1);\n}\n","/**\n * Adapter turning a {@link WotGraph} into the small `WoTLocalSource` shape that\n * `@nostr-wot/wot`'s `WoT` class can consume as a local query source instead of\n * the remote Oracle.\n */\n\nimport type { FilterByWoTOptions, WoTLocalSource } from './types';\n\n/** Minimal surface {@link createWoTSource} needs from a graph. */\nexport interface WoTSourceGraph {\n getDistance(pubkey: string): { hops: number; paths: number } | null;\n isInWoT(pubkey: string, maxHops?: number): boolean;\n filterByWoT(pubkeys: string[], opts?: FilterByWoTOptions): string[];\n}\n\nexport function createWoTSource(graph: WoTSourceGraph): WoTLocalSource {\n return {\n getDistance(target: string): number | null {\n const info = graph.getDistance(target);\n return info ? info.hops : null;\n },\n isInMyWoT(target: string, maxHops?: number): boolean {\n return graph.isInWoT(target, maxHops);\n },\n filterByWoT(pubkeys: string[], opts?: FilterByWoTOptions): string[] {\n return graph.filterByWoT(pubkeys, opts);\n },\n };\n}\n","/**\n * `WotGraph` — the primary public entry point.\n *\n * Ties the four internal layers together: a namespaced {@link GraphStorage},\n * a BFS {@link LocalGraph}, a {@link GraphCrawler}, and the pure scoring\n * function. Consumers create one per origin/app, `load()` to rehydrate any\n * cached graph, `crawl()` to build/refresh it, then run O(1)/O(n) queries.\n */\n\nimport { RelayPool } from '@nostr-wot/relay';\nimport { SimplePool } from 'nostr-tools';\nimport { useWebSocketImplementation } from 'nostr-tools/pool';\n\nimport { GraphStorage } from './storage';\nimport { LocalGraph } from './graph';\nimport { GraphCrawler, CrawlError, type CrawlPool } from './crawl';\nimport { calculateScore, DEFAULT_SCORING } from './scoring';\nimport { createWoTSource } from './wot-source';\nimport type {\n CrawlOptions,\n CrawlResult,\n DistanceInfo,\n FilterByWoTOptions,\n ScoringConfig,\n WebSocketLike,\n WoTLocalSource,\n} from './types';\n\nexport interface WotGraphOptions {\n /** IndexedDB partition key (e.g. the app name). */\n namespace: string;\n /** Relay URLs to crawl. */\n relays: string[];\n /** Optional shared pool; if omitted one is created from `relays`. */\n pool?: CrawlPool;\n /** Scoring overrides merged onto {@link DEFAULT_SCORING}. */\n scoring?: Partial<ScoringConfig>;\n /** WebSocket implementation forwarded to the created pool. */\n websocketImplementation?: WebSocketLike;\n}\n\nexport interface WotGraphStats {\n nodes: number;\n edges: number;\n root: string | null;\n lastCrawl: number | null;\n maxDepth: number | null;\n}\n\nconst DEFAULT_MAX_HOPS = 2;\nconst STORAGE_VERSION = 2;\n\nexport class WotGraph {\n readonly namespace: string;\n private relays: string[];\n private scoring: ScoringConfig;\n private websocketImplementation?: WebSocketLike;\n\n private storage: GraphStorage;\n private graph: LocalGraph;\n\n private pool: CrawlPool | null;\n private ownPool: RelayPool | null = null;\n private crawler: GraphCrawler | null = null;\n\n private root: string | null = null;\n private inFlight: Promise<CrawlResult> | null = null;\n private controller: AbortController | null = null;\n private listeners = new Set<() => void>();\n\n constructor(options: WotGraphOptions) {\n this.namespace = options.namespace;\n this.relays = [...options.relays];\n this.scoring = mergeScoring(options.scoring);\n this.websocketImplementation = options.websocketImplementation;\n this.pool = options.pool ?? null;\n\n this.storage = new GraphStorage(this.namespace);\n this.graph = new LocalGraph(this.storage);\n }\n\n /** Hydrate any cached graph from IndexedDB (fast path). */\n async load(): Promise<void> {\n await this.storage.open();\n this.root = this.storage.getGraphMeta().root;\n this.graph.invalidateCache();\n this.notify();\n }\n\n /**\n * Build/refresh the graph by crawling kind:3 from `rootPubkey`.\n * Concurrent calls return the same in-flight promise (idempotent).\n */\n crawl(rootPubkey: string, opts: CrawlOptions = {}): Promise<CrawlResult> {\n // Synchronous single-flight guard: a second crawl() while one is in flight\n // returns the same promise (idempotent — React strict-mode safe).\n if (this.inFlight) return this.inFlight;\n\n const controller = new AbortController();\n this.controller = controller;\n const onAbort = () => controller.abort();\n if (opts.signal) {\n if (opts.signal.aborted) controller.abort();\n else opts.signal.addEventListener('abort', onAbort, { once: true });\n }\n this.root = rootPubkey;\n\n const run = (async (): Promise<CrawlResult> => {\n try {\n await this.storage.open();\n const pool = this.resolvePool();\n this.crawler = new GraphCrawler({ pool, storage: this.storage, relays: this.relays });\n const result = await this.crawler.crawl(rootPubkey, {\n maxDepth: opts.maxDepth,\n maxHops: opts.maxHops,\n onProgress: opts.onProgress,\n signal: this.controller!.signal,\n });\n await this.storage.setMetaBatch({\n root: rootPubkey,\n lastCrawl: result.stoppedEarly ? null : Date.now(),\n maxDepth: opts.maxHops === undefined ? opts.maxDepth ?? DEFAULT_MAX_HOPS : Math.max(0, opts.maxHops - 1),\n version: STORAGE_VERSION,\n });\n return result;\n } finally {\n opts.signal?.removeEventListener('abort', onAbort);\n this.graph.invalidateCache();\n this.inFlight = null;\n this.crawler = null;\n this.controller = null;\n this.notify();\n }\n })();\n\n this.inFlight = run;\n return run;\n }\n\n /** Distance info from the crawled root, or `null` if unreached/unknown. */\n getDistance(pubkey: string, maxHops: number = 6): DistanceInfo | null {\n if (!this.root) return null;\n return this.graph.getDistance(this.root, pubkey, maxHops);\n }\n\n /** Batch distances; all lookups share one numeric traversal. */\n getDistances(pubkeys: string[], maxHops: number = 6): Map<string, DistanceInfo | null> {\n return new Map(pubkeys.map(pubkey => [pubkey, this.getDistance(pubkey, maxHops)]));\n }\n\n /** Trust score 0..1 via {@link calculateScore}. */\n getScore(pubkey: string): number {\n const info = this.getDistance(pubkey);\n return calculateScore(info ? info.hops : null, info ? info.paths : null, this.scoring);\n }\n\n /** Whether `pubkey` is within `maxHops` of the root. */\n isInWoT(pubkey: string, maxHops: number = DEFAULT_MAX_HOPS): boolean {\n const info = this.getDistance(pubkey, maxHops);\n return info !== null && info.hops <= maxHops;\n }\n\n /** Trusted subset of `pubkeys`, sorted by score descending. */\n filterByWoT(pubkeys: string[], opts?: FilterByWoTOptions): string[] {\n const maxHops = opts?.maxHops ?? DEFAULT_MAX_HOPS;\n const scored: Array<{ pubkey: string; score: number }> = [];\n for (const pubkey of pubkeys) {\n const info = this.getDistance(pubkey, maxHops);\n if (info !== null && info.hops <= maxHops) {\n scored.push({ pubkey, score: calculateScore(info.hops, info.paths, this.scoring) });\n }\n }\n scored.sort((a, b) => b.score - a.score);\n return scored.map((s) => s.pubkey);\n }\n\n /** Follow list of `pubkey` as hex strings. */\n getFollows(pubkey: string): string[] {\n return this.graph.getFollows(pubkey);\n }\n\n /** Aggregate stats + crawl meta. */\n stats(): WotGraphStats {\n const s = this.storage.stats();\n const meta = this.storage.getGraphMeta();\n return {\n nodes: s.nodes,\n edges: s.edges,\n root: meta.root,\n lastCrawl: meta.lastCrawl,\n maxDepth: meta.maxDepth,\n };\n }\n\n /** True if the last crawl is older than `ttlMs` (or never happened). */\n isStale(ttlMs: number): boolean {\n const last = this.storage.getGraphMeta().lastCrawl;\n if (last === null) return true;\n return Date.now() - last > ttlMs;\n }\n\n /** Wipe this namespace. */\n async clear(): Promise<void> {\n this.stop();\n await this.inFlight?.catch(() => {});\n await this.storage.open();\n await this.storage.clear();\n this.root = null;\n this.graph.invalidateCache();\n this.notify();\n }\n\n /** Abort an in-flight crawl. Partial data stays usable. */\n stop(): void {\n this.controller?.abort();\n this.crawler?.stop();\n }\n\n /** Adapter for `@nostr-wot/wot`'s `WoT` class. */\n asWoTSource(): WoTLocalSource {\n return createWoTSource(this);\n }\n\n /** The root pubkey the graph is currently answering queries from. */\n getRoot(): string | null {\n return this.root;\n }\n\n /** Subscribe to graph changes (crawl / load / clear). Returns an unsubscribe. */\n onChange(cb: () => void): () => void {\n this.listeners.add(cb);\n return () => this.listeners.delete(cb);\n }\n\n /** Release the pool/storage this instance owns. */\n destroy(): void {\n this.stop();\n if (this.inFlight) void this.inFlight.then(() => this.storage.close(), () => this.storage.close());\n else this.storage.close();\n if (this.ownPool) {\n this.ownPool.destroy();\n this.ownPool = null;\n this.pool = null;\n }\n }\n\n private notify(): void {\n for (const cb of this.listeners) cb();\n }\n\n private resolvePool(): CrawlPool {\n if (this.pool) return this.pool;\n if (this.relays.length === 0) throw new CrawlError('no relays connected');\n if (this.websocketImplementation) {\n useWebSocketImplementation(this.websocketImplementation);\n }\n const rp = new RelayPool({ urls: this.relays });\n rp.ensurePool(() => new SimplePool());\n this.ownPool = rp;\n // RelayPool.subscribe(filter, { onEvent, onEose }) is structurally compatible.\n this.pool = rp as unknown as CrawlPool;\n return this.pool;\n }\n}\n\nfunction mergeScoring(overrides?: Partial<ScoringConfig>): ScoringConfig {\n if (!overrides) return { ...DEFAULT_SCORING };\n return {\n distanceWeights: { ...DEFAULT_SCORING.distanceWeights, ...overrides.distanceWeights },\n pathBonus: { ...DEFAULT_SCORING.pathBonus, ...overrides.pathBonus },\n maxPathBonus: overrides.maxPathBonus ?? DEFAULT_SCORING.maxPathBonus,\n };\n}\n"]}