feat: Initial code drop

This commit is contained in:
2025-06-17 18:28:35 +10:00
commit 0e4c5e12a0
13 changed files with 7541 additions and 0 deletions

113
lib/ipfs.js Normal file
View File

@@ -0,0 +1,113 @@
const NodeCache = require('node-cache');
const config = require('../config');
const { IPFS_GATEWAY, CACHE_ENABLED, CACHE_TTL_SECONDS } = config;
// Setup cache
const cache = new NodeCache({
stdTTL: CACHE_TTL_SECONDS,
checkperiod: CACHE_TTL_SECONDS * 0.2,
});
// MIME type mapping helper
const mimeTypes = {
'.html': 'text/html',
'.css': 'text/css',
'.js': 'application/javascript',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.pdf': 'application/pdf',
'.txt': 'text/plain'
};
/**
* Fetch content from IPFS by CID and path
* @param {string} cid - IPFS Content Identifier
* @param {string} path - Optional path within the CID
* @returns {Promise<{data: Buffer, mimeType: string}|null>} - Content and MIME type or null
*/
async function fetchFromIpfs(cid, path = '') {
const contentPath = path ? `${cid}/${path}` : cid;
// Check cache first
if (CACHE_ENABLED) {
const cachedContent = cache.get(`ipfs:${contentPath}`);
if (cachedContent) {
console.log(`Cache hit for IPFS content: ${contentPath}`);
return cachedContent;
}
}
try {
// Use the HTTP gateway directly instead of the IPFS client
const result = await fetchViaGateway(cid, path);
if (!result) {
return null;
}
// Determine MIME type if not set
if (!result.mimeType) {
result.mimeType = getMimeType(path);
}
// Cache the result
if (CACHE_ENABLED) {
cache.set(`ipfs:${contentPath}`, result);
}
return result;
} catch (error) {
console.error(`Error fetching ${contentPath} from IPFS:`, error);
return null;
}
}
/**
* Fetch content via IPFS HTTP gateway
* @param {string} cid - IPFS Content Identifier
* @param {string} path - Path within the CID
* @returns {Promise<{data: Buffer, mimeType: string}|null>} - Content and MIME type or null
*/
async function fetchViaGateway(cid, path) {
try {
const url = new URL(`${IPFS_GATEWAY}/ipfs/${cid}${path ? '/' + path : ''}`);
console.log(`Fetching from IPFS gateway: ${url}`);
const response = await fetch(url);
if (!response.ok) {
console.error(`Gateway returned ${response.status} for ${url}`);
return null;
}
const data = Buffer.from(await response.arrayBuffer());
const mimeType = response.headers.get('content-type');
return { data, mimeType };
} catch (error) {
console.error('Gateway fetch error:', error);
return null;
}
}
/**
* Determine MIME type from file path
* @param {string} path - File path
* @returns {string} - MIME type or default
*/
function getMimeType(path) {
if (!path) return 'application/octet-stream';
const extension = path.split('.').pop();
if (!extension) return 'application/octet-stream';
return mimeTypes['.' + extension] || 'application/octet-stream';
}
module.exports = {
fetchFromIpfs
};