@ipfsnut/evermark-sdk-core
Version:
Core image handling logic with pure functions and enhanced storage types
184 lines • 5.36 kB
JavaScript
/**
* Pure utility functions for storage operations - no side effects
*/
/**
* Validates if a URL string is properly formatted
*/
export function isValidUrl(url) {
if (!url || typeof url !== 'string')
return false;
try {
const parsed = new URL(url);
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
}
catch {
return false;
}
}
/**
* Enhanced IPFS hash validation with multiple format support
*/
export function isValidIpfsHash(hash) {
if (!hash || typeof hash !== 'string')
return false;
// CIDv0 (base58btc, starts with Qm)
const cidv0Regex = /^Qm[1-9A-HJ-NP-Za-km-z]{44}$/;
// CIDv1 (base32, starts with b)
const cidv1Base32Regex = /^b[a-z2-7]{58}$/;
// CIDv1 (base32upper, starts with B)
const cidv1Base32UpperRegex = /^B[A-Z2-7]{58}$/;
// CIDv1 (base58btc, starts with z)
const cidv1Base58Regex = /^z[1-9A-HJ-NP-Za-km-z]{48,}$/;
// CIDv1 (base16, starts with f or F)
const cidv1Base16Regex = /^[fF][0-9a-fA-F]{50,}$/;
return (cidv0Regex.test(hash) ||
cidv1Base32Regex.test(hash) ||
cidv1Base32UpperRegex.test(hash) ||
cidv1Base58Regex.test(hash) ||
cidv1Base16Regex.test(hash));
}
/**
* Enhanced Supabase URL validation
*/
export function isValidSupabaseUrl(url) {
if (!isValidUrl(url))
return false;
try {
const parsed = new URL(url);
const supabasePatterns = [
/\.supabase\.co/,
/\.supabase\.in/,
/supabase\.storage/,
/storage\.supabase/
];
return supabasePatterns.some(pattern => pattern.test(parsed.hostname));
}
catch {
return false;
}
}
/**
* Extract Supabase project ID from URL
*/
export function extractSupabaseProjectId(url) {
try {
const parsed = new URL(url);
const parts = parsed.hostname.split('.');
if (parts.length >= 3 && parts[1] === 'supabase') {
return parts[0] || null;
}
return null;
}
catch {
return null;
}
}
/**
* Generate storage path from IPFS hash
*/
export function generateStoragePath(ipfsHash, options = {}) {
const { prefix = 'images', includeHash = true, extension } = options;
if (!isValidIpfsHash(ipfsHash)) {
throw new Error(`Invalid IPFS hash: ${ipfsHash}`);
}
const parts = [prefix];
if (includeHash) {
const hashPrefix = ipfsHash.slice(0, 8);
parts.push(hashPrefix);
}
let filename = ipfsHash;
if (extension) {
filename += `.${extension}`;
}
parts.push(filename);
return parts.join('/');
}
/**
* Create default storage configuration
*/
export function createDefaultStorageConfig(supabaseUrl, supabaseKey, bucketName = 'images') {
return {
supabase: {
url: supabaseUrl,
anonKey: supabaseKey,
bucketName
},
ipfs: {
gateway: 'https://gateway.pinata.cloud/ipfs',
fallbackGateways: [
'https://ipfs.io/ipfs',
'https://cloudflare-ipfs.com/ipfs',
'https://gateway.ipfs.io/ipfs'
],
timeout: 10000
},
upload: {
maxFileSize: 10 * 1024 * 1024, // 10MB
allowedFormats: ['jpg', 'jpeg', 'png', 'gif', 'webp'],
generateThumbnails: true,
thumbnailSize: { width: 400, height: 400 }
}
};
}
/**
* Validate storage configuration
*/
export function validateStorageConfig(config) {
const errors = [];
if (!config.supabase) {
errors.push('Supabase configuration is required');
}
else {
if (!config.supabase.url || !isValidUrl(config.supabase.url)) {
errors.push('Valid Supabase URL is required');
}
if (!config.supabase.anonKey || config.supabase.anonKey.length < 10) {
errors.push('Valid Supabase anonymous key is required');
}
if (!config.supabase.bucketName || config.supabase.bucketName.length === 0) {
errors.push('Supabase bucket name is required');
}
}
if (!config.ipfs) {
errors.push('IPFS configuration is required');
}
else {
if (!config.ipfs.gateway || !isValidUrl(config.ipfs.gateway)) {
errors.push('Valid IPFS gateway URL is required');
}
}
return { valid: errors.length === 0, errors };
}
/**
* Extract file extension from URL or filename
*/
export function extractFileExtension(urlOrFilename) {
try {
let pathname;
try {
pathname = new URL(urlOrFilename).pathname;
}
catch {
pathname = urlOrFilename;
}
const parts = pathname.split('.');
if (parts.length > 1) {
return parts[parts.length - 1]?.toLowerCase() || null;
}
return null;
}
catch {
return null;
}
}
/**
* Check if file is an image based on MIME type or extension
*/
export function isImageFile(file) {
if (typeof file === 'string') {
const extension = file.split('.').pop()?.toLowerCase();
return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'].includes(extension || '');
}
return file.type.startsWith('image/');
}
//# sourceMappingURL=storage-utils.js.map