Files
bitvid/tests/nip71-mirror-sync.test.mjs
T
thePR0M3TH3ANandClaude Opus 4.8 89d9a62b87 feat(nip71): auto-sync the mirror on edit/delete (event-driven, no nostrService growth)
Closes the dual-event drift the user flagged: an opted-in 34235 mirror now stays
in lockstep with the canonical 30078 automatically — no per-video babysitting.

- js/services/nip71MirrorSync.js: syncNip71MirrorAfterEdit (re-publish if still
  eligible; unshare + clear flag if it became ineligible, e.g. flipped private),
  syncNip71MirrorAfterDelete (remove + clear flag). Plus initNip71MirrorSync()
  which subscribes to nostrService's EXISTING videos:edited/videos:deleted events
  — so the size-capped nostrService is untouched.
- js/services/nip71MirrorFlags.js: pure resolveEditSync/resolveDeleteSync decisions.
- applicationBootstrap: one-line initNip71MirrorSync(app.nostrService) wiring.
- All best-effort: a mirror failure never breaks the core edit/delete.

tests: resolver decisions (lockstep/unshare/none) + delete clears the flag +
event wiring is idempotent. Mutation-verified (eligibility branch load-bearing).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 10:22:27 -04:00

46 lines
1.7 KiB
JavaScript

// Auto-sync glue: keeps an opted-in NIP-71 mirror in lockstep on edit/delete,
// driven by nostrService's existing videos:edited/videos:deleted events (so the
// size-capped nostrService is untouched).
import "./test-helpers/setup-localstorage.mjs";
import assert from "node:assert/strict";
import test from "node:test";
import {
syncNip71MirrorAfterDelete,
initNip71MirrorSync,
} from "../js/services/nip71MirrorSync.js";
import { isMirrorEnabled, setMirrorEnabled } from "../js/services/nip71MirrorFlags.js";
const PK = "a".repeat(64);
test("deleting a SHARED video clears its opt-in flag (mirror torn down)", async () => {
localStorage.clear();
setMirrorEnabled(PK, "root-x", true);
await syncNip71MirrorAfterDelete({ videoRootId: "root-x", video: {}, pubkey: PK });
assert.equal(isMirrorEnabled(PK, "root-x"), false, "flag cleared after delete");
});
test("deleting a NON-shared video is a no-op (and never throws)", async () => {
localStorage.clear();
await syncNip71MirrorAfterDelete({ videoRootId: "root-y", video: {}, pubkey: PK });
assert.equal(isMirrorEnabled(PK, "root-y"), false);
});
test("initNip71MirrorSync subscribes to edit+delete events, idempotently", () => {
const events = {};
const svc = {
on(name, handler) {
(events[name] = events[name] || []).push(handler);
return () => {};
},
};
const off = initNip71MirrorSync(svc);
assert.equal(events["videos:edited"]?.length, 1, "subscribes to videos:edited");
assert.equal(events["videos:deleted"]?.length, 1, "subscribes to videos:deleted");
initNip71MirrorSync(svc); // guard prevents double-registration
assert.equal(events["videos:edited"].length, 1, "no double-register");
off(); // resets the guard for other tests
});