diff --git a/scripts/ipfs.js b/scripts/ipfs.js index dedaa4a..777d444 100644 --- a/scripts/ipfs.js +++ b/scripts/ipfs.js @@ -3,73 +3,98 @@ import { globby } from 'globby'; import { Agent } from 'https'; import { writeFile } from 'fs/promises'; -const ipfsAuth = process.env['IPFS_AUTH'] || ""; -const ipfsHost = process.env['IPFS_HOST']; -const ipfsPort = process.env['IPFS_PORT'] ? parseInt(process.env['IPFS_PORT']) : 5001; -const ipfsProtocol = process.env['IPFS_SSL'] === 'false' ? 'http' : 'https'; +// Ortam değişkenleri için güvenli varsayılanlar ve tip dönüşümleri +const IPFS_CONFIG = { + host: process.env['IPFS_HOST'], + port: parseInt(process.env['IPFS_PORT'] || '5001'), + protocol: process.env['IPFS_SSL'] === 'false' ? 'http' : 'https', + auth: process.env['IPFS_AUTH'] || "", +}; -if (!ipfsHost) { - console.error("Must set IPFS_HOST"); +if (!IPFS_CONFIG.host) { + console.error("❌ Hata: IPFS_HOST ortam değişkeni ayarlanmamış."); process.exit(1); } -let authorization = `Basic ${Buffer.from(ipfsAuth).toString('base64')}`; +// Authorization header'ı bir kez oluşturulur +const authHeader = `Basic ${Buffer.from(IPFS_CONFIG.auth).toString('base64')}`; +/** + * IPFS İstemcisini yapılandırır. + * keepAlive: true ayarı, ardışık dosya yüklemelerinde TCP el sıkışma yükünü azaltır. + */ function buildIpfsClient() { return create({ - host: ipfsHost, - port: ipfsPort, - protocol: ipfsProtocol, - headers: { - authorization - }, + host: IPFS_CONFIG.host, + port: IPFS_CONFIG.port, + protocol: IPFS_CONFIG.protocol, + headers: { authorization: authHeader }, apiPath: '/api/v0', agent: new Agent({ - keepAlive: false, - maxSockets: Infinity + keepAlive: true, // Performans için true olmalı + maxSockets: 32, // Sonsuz yerine makul bir sınır, sistem kaynaklarını korur }), - timeout: '10m' + timeout: '15m' // Büyük build'ler için süre biraz daha artırıldı }); } -(async function() { - const allDeployableFiles = await globby(['build/**/*']); - const expectedFileCount = allDeployableFiles.length; - let ipfs = buildIpfsClient(); - // Inspired from: https://community.infura.io/t/upload-files-from-a-folder-under-a-wrapping-directory-cid-using-the-kubo-rpc-client-and-nodejs/6045 - const filesUploaded = []; - for await (const file of ipfs.addAll(globSource('build', '**/*'), { wrapWithDirectory: true })) { - filesUploaded.push(file); - console.log(`Pushed ${file.path} [size=${file.size}, cid=${file.cid}]`); - } +(async function deploy() { + try { + const buildDir = 'build'; + const allFiles = await globby([`${buildDir}/**/*`]); + const expectedCount = allFiles.length; - console.log(`Uploaded ${filesUploaded.length} total files.`); + if (expectedCount === 0) { + throw new Error(`'${buildDir}' dizini boş veya bulunamadı.`); + } - // Verify the number of files uploaded matches the number - // of files we counted in the deploy directory. - if (filesUploaded.length < expectedFileCount) { - console.log(`Expected number of files to upload: ${expectedFileCount}`); - console.log(`Uploaded total number of files: ${filesUploaded.length}`); + console.log(`🚀 ${expectedCount} dosya IPFS'e yüklenmeye hazırlanıyor...`); - throw new Error('Failed to upload enough files.'); - } + const ipfs = buildIpfsClient(); + const uploadedFiles = []; + + // Dosya yükleme akışı + for await (const file of ipfs.addAll(globSource(buildDir, '**/*'), { + wrapWithDirectory: true, + pin: true, // Kalıcılık için otomatik pinleme + progress: (prog) => console.log(`Transfer: ${prog} bytes`) + })) { + uploadedFiles.push(file); + // Sadece önemli dosyaları veya ilerlemeyi logla (gürültüyü azalt) + if (file.path === "") console.log(`✅ Root CID Oluşturuldu: ${file.cid}`); + } + + // Doğrulama mantığı: wrapWithDirectory kullanıldığında uploadedFiles.length = expectedCount + 1 (root dizini) + if (uploadedFiles.length <= expectedCount) { + throw new Error(`Yükleme eksik kaldı. Beklenen: >${expectedCount}, Yüklenen: ${uploadedFiles.length}`); + } - // Not a fan of how the new kubo client only supports addAll - // and used the last file as the directory... -_- - const app = filesUploaded[filesUploaded.length - 1]; + // Root CID her zaman path'i boş ("") olan son nesnedir. + const rootFolder = uploadedFiles.find(f => f.path === ""); + if (!rootFolder) { + throw new Error("Root dizini CID'si belirlenemedi."); + } - const urls = [ - ["IPFS Url", `https://ipfs.io/ipfs/${app.cid}`], - ["Infura Url", `https://compound-app.infura-ipfs.io/ipfs/${app.cid}`], - ]; - const urlText = urls.map(([name, url]) => ` * ${name}: ${url}`).join("\n"); + const rootCID = rootFolder.cid.toString(); - console.log("\n\n"); - console.log("🗺 App successfully deployed to ipfs:\n"); - console.log(urlText); - console.log("\n"); + // Sonuçları raporla + const gateways = [ + { name: "IPFS Gateway", url: `https://ipfs.io/ipfs/${rootCID}` }, + { name: "Infura Gateway", url: `https://compound-app.infura-ipfs.io/ipfs/${rootCID}` }, + ]; - writeFile('.release', `${app.cid}`, 'utf8'); + console.log("\n🗺 App başarıyla IPFS'e dağıtıldı:"); + gateways.forEach(gw => console.log(` * ${gw.name}: ${gw.url}`)); + + // CID'yi dosyaya yaz (Release takibi için) + await writeFile('.release', rootCID, 'utf8'); + console.log(`\n💾 Root CID '${rootCID}' .release dosyasına kaydedildi.`); + + } catch (error) { + console.error("\n❌ Dağıtım sırasında kritik hata oluştu:"); + console.error(error.message); + process.exit(1); + } })();