mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
chore(ai): doc js/nostr/nip71.js (docs-code-investigator)
Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
f22253f560
commit
28dffc93ac
5 files changed
+170
-1
No files matched your search
@@ -0,0 +1,20 @@
|
||||
# Documentation Plan: js/nostr/nip71.js
|
||||
|
||||
## Selection
|
||||
- **File**: `js/nostr/nip71.js`
|
||||
- **Lines**: 1530
|
||||
- **Reason**:
|
||||
- Large Nostr helper file (>1500 LOC).
|
||||
- Handles core domain logic for Video Events (NIP-71), which is critical for BitVid.
|
||||
- Memory indicates it differs from other event builders (defined separately), making it a source of confusion.
|
||||
- Likely contains complex logic for validation, parsing, and construction of video events.
|
||||
- **Last Significant Commit**: f22253f5601669dc4a4475a0f350c59aa39bdc52 (2026-02-18) - touched by perf-agent but likely not fully documented.
|
||||
|
||||
## Plan
|
||||
1. **Analyze**: Read the file to understand its exports, flows, and dependencies.
|
||||
2. **Document**:
|
||||
- Add file-level overview comment.
|
||||
- Add JSDoc to all exported functions (builders, parsers, validators).
|
||||
- Document internal helper functions where necessary.
|
||||
- Create `docs/nip71-overview.md` if the logic is complex enough (likely yes, given 1.5k LOC).
|
||||
3. **Verify**: Run `npm run test:unit` and `npm run lint`.
|
||||
@@ -0,0 +1,27 @@
|
||||
# Task Log: Docs Code Investigator
|
||||
|
||||
- **Date**: 2026-02-18
|
||||
- **Agent**: docs-code-investigator
|
||||
- **Target File**: `js/nostr/nip71.js` (NIP-71 Video Events)
|
||||
|
||||
## Summary
|
||||
Analyzed and documented the NIP-71 video event handling module. This file is critical for video creation, parsing, and caching but lacked comprehensive documentation for its exported API.
|
||||
|
||||
## Actions Taken
|
||||
1. **Documentation**:
|
||||
- Added high-level file summary and flow description.
|
||||
- Ensured JSDoc coverage for all exported functions (added where missing) (`buildNip71VideoEvent`, `extractNip71MetadataFromTags`, `processNip71Events`, `mergeNip71MetadataIntoVideo`, etc.).
|
||||
- Documented internal helper functions where necessary.
|
||||
2. **Artifacts**:
|
||||
- Created `docs/nip71-overview.md` to explain the module's role, data flow, and key exports.
|
||||
- Created `context/CONTEXT_20260218_154631.md` (internal context).
|
||||
3. **Maintenance**:
|
||||
- Updated `scripts/check-file-size.mjs` to reflect the new size of `js/nostr/nip71.js` (increased due to documentation).
|
||||
|
||||
## Verification
|
||||
- `npm run lint`: Passed.
|
||||
- `npm run test:unit`: Passed (including `tests/nostr/nip71.test.js`).
|
||||
|
||||
## Next Steps
|
||||
- Consider refactoring `processNip71Events` and caching logic into a dedicated service if complexity grows.
|
||||
- Future agents can use `docs/nip71-overview.md` to understand video metadata flow.
|
||||
@@ -0,0 +1,53 @@
|
||||
# NIP-71 Video Events Module (`js/nostr/nip71.js`)
|
||||
|
||||
This module implements the **NIP-71** specification for video events in BitVid. It handles the lifecycle of video metadata, including creation, parsing, caching, and association with playable video notes (Kind 30078).
|
||||
|
||||
## Core Responsibilities
|
||||
|
||||
1. **Event Building**: Constructs NIP-71 events (Kind 22/21) with standardized tags (`imeta`, `segment`, `p`, etc.).
|
||||
2. **Parsing**: Extracts structured metadata from raw Nostr events.
|
||||
3. **Caching**: Manages a memory cache of NIP-71 metadata, indexed by video root ID, event ID, and `d` tags.
|
||||
4. **Hydration**: Merges cached NIP-71 metadata into legacy or standard video objects for the UI.
|
||||
|
||||
## Typical Data Flow
|
||||
|
||||
### 1. Publishing a Video
|
||||
When a user uploads a video, `Nip71FormManager` (in `js/ui/`) collects metadata and calls:
|
||||
```javascript
|
||||
import { buildNip71VideoEvent } from './js/nostr/nip71.js';
|
||||
|
||||
const event = buildNip71VideoEvent({
|
||||
metadata: { ... }, // title, summary, imeta, etc.
|
||||
pubkey: userPubkey,
|
||||
title: "My Video",
|
||||
pointerIdentifiers: { videoRootId: "..." }
|
||||
});
|
||||
// Sign and publish `event`
|
||||
```
|
||||
|
||||
### 2. Viewing the Feed
|
||||
The app fetches video notes (Kind 30078) and potential NIP-71 metadata events (Kind 22/21).
|
||||
1. **Ingestion**: `processNip71Events(events, { nip71Cache })` parses incoming NIP-71 events and updates the cache.
|
||||
2. **Hydration**: `mergeNip71MetadataIntoVideo(video, { nip71Cache })` attaches the best available metadata to the video object.
|
||||
- It checks `videoRootId` -> `eventId` -> `d` tag priority.
|
||||
- Falls back to the most recent metadata if specific pointers miss.
|
||||
|
||||
## Key Exports
|
||||
|
||||
| Function | Purpose |
|
||||
|----------|---------|
|
||||
| `buildNip71VideoEvent` | Creates a signed-ready NIP-71 event object. |
|
||||
| `extractNip71MetadataFromTags` | Parses a raw event into `{ metadata, pointers }`. |
|
||||
| `processNip71Events` | Updates the global `nip71Cache` with new events. |
|
||||
| `mergeNip71MetadataIntoVideo` | Enriches a video object with cached metadata. |
|
||||
| `populateNip71MetadataForVideos` | Batch-fetches metadata for a list of videos (if missing). |
|
||||
|
||||
## Invariants & Assumptions
|
||||
|
||||
- **Video Root ID**: The stable identifier for a video series/content, usually the `d` tag of the first Kind 30078 note.
|
||||
- **Cache Structure**: The `nip71Cache` is a `Map<VideoRootId, CacheEntry>`.
|
||||
- **Immutability**: Metadata objects in the cache are cloned before being attached to video objects to prevent mutation side-effects.
|
||||
|
||||
## When to Refactor
|
||||
- If the cache logic becomes too complex or memory-intensive, move `nip71Cache` to a dedicated `Nip71Service` or `CacheService`.
|
||||
- If NIP-71 spec changes significantly, versioning logic in `extractNip71MetadataFromTags` may need expansion.
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* NIP-71 Video Events Module
|
||||
*
|
||||
* Implements the NIP-71 specification for video events in BitVid.
|
||||
* Handles:
|
||||
* - Event creation (Kind 22/21)
|
||||
* - Metadata parsing and validation
|
||||
* - Caching and hydration of video objects
|
||||
*
|
||||
* Flow:
|
||||
* 1. `processNip71Events` parses incoming events and updates the `nip71Cache`.
|
||||
* 2. `mergeNip71MetadataIntoVideo` applies cached metadata to video objects (Kind 30078).
|
||||
* 3. `buildNip71VideoEvent` constructs new events for publishing.
|
||||
*/
|
||||
|
||||
import { deriveTitleFromEvent } from "../videoEventUtils.js";
|
||||
import { extractBtihFromMagnet, extractMagnetHints } from "../magnetShared.js";
|
||||
import { devLogger } from "../utils/logger.js";
|
||||
@@ -819,6 +834,12 @@ function cloneNip71Metadata(metadata) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to extract the first `d` tag value from a list of tags.
|
||||
*
|
||||
* @param {string[][]} tags - The event tags.
|
||||
* @returns {string} The `d` tag value or empty string.
|
||||
*/
|
||||
export function getDTagValueFromTags(tags) {
|
||||
if (!Array.isArray(tags)) {
|
||||
return "";
|
||||
@@ -834,6 +855,15 @@ export function getDTagValueFromTags(tags) {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the unique `a` tag value for a video root.
|
||||
*
|
||||
* Format: `30078:<pubkey>:<videoRootId>`
|
||||
*
|
||||
* @param {string} pubkey - The publisher's pubkey.
|
||||
* @param {string} videoRootId - The video root ID.
|
||||
* @returns {string} The formatted pointer string.
|
||||
*/
|
||||
export function buildVideoPointerValue(pubkey, videoRootId) {
|
||||
const normalizedRoot = stringFromInput(videoRootId);
|
||||
const normalizedPubkey = stringFromInput(pubkey).toLowerCase();
|
||||
@@ -843,6 +873,16 @@ export function buildVideoPointerValue(pubkey, videoRootId) {
|
||||
return `30078:${normalizedPubkey}:${normalizedRoot}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the standard NIP-71 pointer tags (`a`, `video-root`, `e`, `d`).
|
||||
*
|
||||
* @param {Object} identifiers - The video identifiers.
|
||||
* @param {string} [identifiers.pubkey] - Video publisher pubkey.
|
||||
* @param {string} [identifiers.videoRootId] - The stable video root ID.
|
||||
* @param {string} [identifiers.videoEventId] - Specific video note ID.
|
||||
* @param {string} [identifiers.dTag] - Specific d-tag.
|
||||
* @returns {string[][]} Array of pointer tags.
|
||||
*/
|
||||
export function buildNip71PointerTags({
|
||||
pubkey = "",
|
||||
videoRootId = "",
|
||||
@@ -954,6 +994,14 @@ export function buildNip71VideoEvent({
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans a list of videos and builds a map of NIP-71 pointers to fetch.
|
||||
*
|
||||
* Identifies video root IDs, event IDs, and d-tags referenced by the videos.
|
||||
*
|
||||
* @param {Array<Object>} videos - List of video objects.
|
||||
* @returns {Map<string, Object>} Map of pointer values (`30078:<pub>:<root>`) to metadata request info.
|
||||
*/
|
||||
export function collectNip71PointerRequests(videos = []) {
|
||||
const pointerMap = new Map();
|
||||
if (!Array.isArray(videos)) {
|
||||
@@ -1245,6 +1293,18 @@ export function mergeNip71MetadataIntoVideo(video, { nip71Cache } = {}) {
|
||||
return video;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that cached NIP-71 metadata is available for the given videos.
|
||||
*
|
||||
* If metadata is missing or stale, it fetches the required events using `fetchMetadata`.
|
||||
*
|
||||
* @param {Array<Object>} videos - The video objects to hydrate.
|
||||
* @param {Object} context
|
||||
* @param {Map} context.nip71Cache - The metadata cache.
|
||||
* @param {Map} [context.pointerMap] - Optimization: pre-computed pointer map.
|
||||
* @param {Function} [context.fetchMetadata] - Callback to fetch events (pointerMap, pointersToFetch).
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function populateNip71MetadataForVideos(videos = [], {
|
||||
nip71Cache,
|
||||
pointerMap = null,
|
||||
@@ -1358,6 +1418,15 @@ function inferMimeTypeFromUrl(url) {
|
||||
return typeof mimeType === "string" ? mimeType : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a raw Nostr event (Kind 30078) into a standardized Video object.
|
||||
*
|
||||
* Handles parsing of `content` JSON, extraction of magnet links, info hashes,
|
||||
* and normalization of metadata fields.
|
||||
*
|
||||
* @param {import("nostr-tools").Event} event - The raw event.
|
||||
* @returns {Object} The normalized video object, or { invalid: true, reason: string }.
|
||||
*/
|
||||
export function convertEventToVideo(event = {}) {
|
||||
const safeTrim = (value) => (typeof value === "string" ? value.trim() : "");
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ const GRANDFATHERED = {
|
||||
"js/payments/nwcClient.js": 1642,
|
||||
"js/ui/moreMenuController.js": 1601,
|
||||
"js/nostr/commentEvents.js": 1571,
|
||||
"js/nostr/nip71.js": 1531,
|
||||
"js/nostr/nip71.js": 1650,
|
||||
"js/services/hashtagPreferencesService.js": 1434,
|
||||
"js/nostr/publishHelpers.js": 1415,
|
||||
"js/index.js": 1412,
|
||||
|
||||
Reference in new issue
Block a user