Files
bitvid/js/watchHistoryActorHelpers.js
T
thePR0M3TH3ANandClaude Opus 4.8 37a675392f refactor(watch-history): extract actor helpers from watchHistoryService (4/10)
File-size decomposition (no behavior change). Move getLoggedInActorKey,
getSessionActorKey, and ensureWatchHistoryExtensionPermissions (which depend only
on imported singletons, not module state) into js/watchHistoryActorHelpers.js, and
drop the now-unused getActiveSigner/requestDefaultExtensionPermissions/getApplication
imports from the service.

watchHistoryService.js: 1491 -> 1388 lines (below its original 1395 baseline;
re-recorded to 1386 to lock the reduction).

Build + full unit suite green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-19 11:33:35 -04:00

120 lines
3.6 KiB
JavaScript

// js/watchHistoryActorHelpers.js
//
// Actor-key resolution + extension-permission helpers extracted from
// watchHistoryService.js to keep that module under the file-size budget. These
// depend only on imported singletons (no watchHistoryService module state), so
// they move cleanly. No behavior change.
import {
getActiveSigner,
nostrClient,
requestDefaultExtensionPermissions,
} from "./nostrClientFacade.js";
import { normalizeActorKey } from "./nostr/watchHistory.js";
import { getApplication } from "./applicationContext.js";
import { devLogger, userLogger } from "./utils/logger.js";
export function getLoggedInActorKey() {
const direct = normalizeActorKey(nostrClient?.pubkey);
if (direct) {
return direct;
}
if (typeof window !== "undefined") {
const appCandidate =
getApplication() || null;
if (appCandidate && typeof appCandidate === "object") {
if (typeof appCandidate.normalizeHexPubkey === "function") {
try {
const normalized = appCandidate.normalizeHexPubkey(
appCandidate.pubkey
);
if (normalized) {
return normalizeActorKey(normalized);
}
} catch (error) {
devLogger.warn(
"[watchHistoryService] Failed to normalize app login pubkey:",
error
);
}
}
if (typeof appCandidate.pubkey === "string" && appCandidate.pubkey) {
const fallback = normalizeActorKey(appCandidate.pubkey);
if (fallback) {
return fallback;
}
}
}
}
return "";
}
export function getSessionActorKey() {
const logged = getLoggedInActorKey();
if (logged) {
return "";
}
return normalizeActorKey(nostrClient?.sessionActor?.pubkey);
}
export async function ensureWatchHistoryExtensionPermissions(actorKey, options = {}) {
const normalizedActor = normalizeActorKey(actorKey);
if (!normalizedActor) {
return { ok: true };
}
const loggedActor = normalizeActorKey(nostrClient?.pubkey);
if (!loggedActor || loggedActor !== normalizedActor) {
return { ok: true };
}
const allowPermissionPrompt = options?.allowPermissionPrompt !== false;
// FIX: Always attempt to resolve the signer regardless of allowPermissionPrompt.
// ensureActiveSignerForPubkey does not prompt the user — it only resolves an
// already-injected extension or returns the existing signer.
let signer = getActiveSigner();
if (
!signer && typeof nostrClient?.ensureActiveSignerForPubkey === "function"
) {
signer = await nostrClient.ensureActiveSignerForPubkey(normalizedActor);
}
const canSign = typeof signer?.canSign === "function"
? signer.canSign()
: typeof signer?.signEvent === "function";
// FIX: NIP-07 adapters use type "nip07", not "extension". Both types
// represent browser extension signers that need permission pre-granting.
if (!canSign || (signer?.type !== "extension" && signer?.type !== "nip07")) {
return { ok: true };
}
if (!allowPermissionPrompt) {
return { ok: true };
}
const permissionResult = await requestDefaultExtensionPermissions();
if (permissionResult.ok) {
return { ok: true };
}
const message =
"Approve your NIP-07 extension to sync watch history.";
const error = new Error(message);
error.code = "watch-history-extension-permission-denied";
error.cause = permissionResult.error;
userLogger.warn(
"[watchHistoryService] Extension denied decrypt permission required for watch history.",
{
actor: normalizeActorKey(actorKey) || null,
error: permissionResult.error,
},
);
return { ok: false, error };
}