-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathuse-ipni-check.ts
More file actions
127 lines (116 loc) · 4.28 KB
/
use-ipni-check.ts
File metadata and controls
127 lines (116 loc) · 4.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import { type WaitForIpniProviderResultsOptions, waitForIpniProviderResults } from 'filecoin-pin/core/utils'
import { CID } from 'multiformats/cid'
import { useEffect, useRef } from 'react'
// Session-scoped cache to prevent repeated IPNI checks per CID within a page session.
// Value indicates the last known result of the IPNI listing check; "pending" marks an in-flight request.
const ipniSessionResultByCid: Map<string, 'success' | 'failed' | 'pending'> = new Map()
// LocalStorage helpers for success-only persistence across tabs/sessions
const LS_SUCCESS_PREFIX = 'ipni-check-success-v1:'
function getLocalStorageSuccess(cid: string): boolean {
try {
const key = `${LS_SUCCESS_PREFIX}${cid}`
return typeof window !== 'undefined' && window.localStorage.getItem(key) === '1'
} catch {
return false
}
}
function setLocalStorageSuccess(cid: string): void {
try {
const key = `${LS_SUCCESS_PREFIX}${cid}`
if (typeof window !== 'undefined') {
window.localStorage.setItem(key, '1')
}
} catch {
// ignore storage write errors (quota/disabled/private mode)
}
}
interface UseIpniCheckOptions {
cid: string | null
isActive: boolean
onSuccess: () => void
onError?: (error: Error) => void
waitForIpniProviderResultsOptions?: WaitForIpniProviderResultsOptions
}
/**
* Hook to check IPNI cache for CID availability.
*
* Note: filecoin-pin now handles IPNI checking, so this hook only provides
* caching functionality. It checks session cache and localStorage cache,
* and calls the appropriate callbacks if cached results are found.
*
* To cache a result, call `cacheIpniResult` with the CID and result.
*/
export const useIpniCheck = ({
cid,
isActive,
onSuccess,
onError,
waitForIpniProviderResultsOptions,
}: UseIpniCheckOptions) => {
// Store callbacks in refs to prevent them from being recreated
const onSuccessRef = useRef(onSuccess)
const onErrorRef = useRef(onError)
// Update refs when callbacks change
useEffect(() => {
onSuccessRef.current = onSuccess
onErrorRef.current = onError
}, [onSuccess, onError])
// Check cache when isActive becomes true
useEffect(() => {
if (isActive && cid) {
let cidInstance: CID
try {
cidInstance = CID.parse(cid)
} catch (err) {
console.error('[IpniCheck] Invalid CID:', err)
onErrorRef.current?.(err instanceof Error ? err : new Error(String(err)))
return
}
// If we've already checked this CID in the current page session, reuse the result and skip checking
const prior = ipniSessionResultByCid.get(cid)
if (prior === 'success') {
console.debug('[IpniCheck] Session cache hit (success) for CID:', cid)
if (!getLocalStorageSuccess(cid)) {
setLocalStorageSuccess(cid)
}
onSuccessRef.current()
return
}
if (prior === 'failed') {
console.debug('[IpniCheck] Session cache hit (failed) for CID:', cid)
return
}
if (prior === 'pending') return
// Check cross-tab/session success cache in localStorage
if (getLocalStorageSuccess(cid)) {
console.debug('[IpniCheck] LocalStorage cache hit (success) for CID:', cid)
ipniSessionResultByCid.set(cid, 'success')
onSuccessRef.current()
return
}
// No cached result found - use waitForIpniProviderResults to check if the CID has a provider result on an ipni indexer
ipniSessionResultByCid.set(cid, 'pending')
console.debug('[IpniCheck] No cache found for CID:', cid, '- filecoin-pin will handle checking')
waitForIpniProviderResults(cidInstance, waitForIpniProviderResultsOptions)
.then(() => {
cacheIpniResult(cid, 'success')
onSuccessRef.current?.()
})
.catch((error) => {
console.error('[IpniCheck] IPNI check failed:', error)
cacheIpniResult(cid, 'failed')
onErrorRef.current?.(error)
})
}
}, [isActive, cid, waitForIpniProviderResultsOptions])
}
/**
* Cache an IPNI check result for a CID.
* This should be called when filecoin-pin reports IPNI advertisement results.
*/
export function cacheIpniResult(cid: string, result: 'success' | 'failed'): void {
ipniSessionResultByCid.set(cid, result)
if (result === 'success') {
setLocalStorageSuccess(cid)
}
}