feat: Add IPNS support

This commit is contained in:
2025-07-26 13:57:13 +10:00
parent a7d18d529e
commit 2ba2ef3bef
4 changed files with 121 additions and 23 deletions

View File

@@ -24,26 +24,30 @@ const mimeTypes = {
};
/**
* Fetch content from IPFS by CID and path
* @param {string} cid - IPFS Content Identifier
* @param {string} path - Optional path within the CID
* Fetch content from IPFS by CID and path, or from IPNS
* @param {string} cidOrIpns - IPFS Content Identifier or IPNS hash (prefixed with 'ipns:')
* @param {string} path - Optional path within the CID/IPNS
* @returns {Promise<{data: Buffer, mimeType: string}|null>} - Content and MIME type or null
*/
async function fetchFromIpfs(cid, path = '') {
const contentPath = path ? `${cid}/${path}` : cid;
async function fetchFromIpfs(cidOrIpns, path = '') {
const isIpns = cidOrIpns.startsWith('ipns:');
const hash = isIpns ? cidOrIpns.substring(5) : cidOrIpns;
const contentType = isIpns ? 'ipns' : 'ipfs';
const contentPath = path ? `${hash}/${path}` : hash;
// Check cache first
if (CACHE_ENABLED) {
const cachedContent = cache.get(`ipfs:${contentPath}`);
const cacheKey = `${contentType}:${contentPath}`;
const cachedContent = cache.get(cacheKey);
if (cachedContent) {
console.log(`Cache hit for IPFS content: ${contentPath}`);
console.log(`Cache hit for ${contentType.toUpperCase()} content: ${contentPath}`);
return cachedContent;
}
}
try {
// Use the HTTP gateway directly instead of the IPFS client
const result = await fetchViaGateway(cid, path);
// Use the HTTP gateway directly
const result = await fetchViaGateway(hash, path, contentType);
if (!result) {
return null;
@@ -56,25 +60,29 @@ async function fetchFromIpfs(cid, path = '') {
// Cache the result
if (CACHE_ENABLED) {
cache.set(`ipfs:${contentPath}`, result);
const cacheKey = `${contentType}:${contentPath}`;
// Use shorter TTL for IPNS content since it can change
const ttl = isIpns ? Math.min(CACHE_TTL_SECONDS, 300) : CACHE_TTL_SECONDS;
cache.set(cacheKey, result, ttl);
}
return result;
} catch (error) {
console.error(`Error fetching ${contentPath} from IPFS:`, error);
console.error(`Error fetching ${contentPath} from ${contentType.toUpperCase()}:`, error);
return null;
}
}
/**
* Fetch content via IPFS HTTP gateway
* @param {string} cid - IPFS Content Identifier
* @param {string} path - Path within the CID
* @param {string} hash - IPFS CID or IPNS hash
* @param {string} path - Path within the content
* @param {string} contentType - Either 'ipfs' or 'ipns'
* @returns {Promise<{data: Buffer, mimeType: string}|null>} - Content and MIME type or null
*/
async function fetchViaGateway(cid, path) {
async function fetchViaGateway(hash, path, contentType = 'ipfs') {
try {
const url = new URL(`${IPFS_GATEWAY}/ipfs/${cid}${path ? '/' + path : ''}`);
const url = new URL(`${IPFS_GATEWAY}/${contentType}/${hash}${path ? '/' + path : ''}`);
console.log(`Fetching from IPFS gateway: ${url}`);
const response = await fetch(url);