UNPKG

@zburn/core

Version:

Core utilities for the ZBURN ecosystem.

237 lines (206 loc) 8.34 kB
const API_URL = "https://api.cloudflare.com/client/v4"; const IPFS_MAIN_URL = "https://ipfs.io"; const { loadConfig } = require('../../config') const config = loadConfig(); async function deployCloudflare(cid) { try { if (!config.cloudflare.apiToken) { console.log("apiToken missing in .zburnrc.json field 'cloudflare'. Stopping deployment"); return; } await testAuthToken(); await testCidExistance(cid); if (config.cloudflare.dnsLink) await changeDnsLink(cid); if(config.cloudflare.worker && config.cloudflare.worker.kvNameSpace) await updateWorkerKVCID(cid); } catch (err) { console.error(err) return null; } } async function updateWorkerKVCID(cid) { try { console.log(`Attempting to update KV key "${config.cloudflare.worker.kvKey}" with new CID: ${cid} in namespace "${config.cloudflare.worker.kvNameSpace}"...`); const namespaceId = await getKvNamespaceIdByName( config.cloudflare.worker.kvNameSpace, config.cloudflare.accountId, config.cloudflare.apiToken ); if (!namespaceId) { console.error(`Error: Could not find KV Namespace ID for "${config.cloudflare.worker.kvNameSpace}". Please ensure it exists and your token has permissions.`); return false; } const url = `${API_URL}/accounts/${config.cloudflare.accountId}/storage/kv/namespaces/${namespaceId}/values/${config.cloudflare.worker.kvKey}`; const headers = { 'Authorization': `Bearer ${config.cloudflare.apiToken}`, 'Content-Type': 'text/plain' }; const response = await fetch(url, { method: 'PUT', headers: headers, body: cid }); if (response.ok) { console.log(`Successfully updated KV key "${config.cloudflare.worker.kvKey}" in "${config.cloudflare.worker.kvNameSpace}" with CID: ${cid}.`); return true; } else { const errorText = await response.text(); // Get raw error response console.error(`Failed to update KV key. Cloudflare API error (Status: ${response.status}): ${errorText}`); return false; } } catch (err) { console.error("An error occurred during KV CID update:", err); return false; } } async function getKvNamespaceIdByName(namespaceName, accountId, apiToken) { const url = `${API_URL}/accounts/${accountId}/storage/kv/namespaces`; const headers = { 'Authorization': `Bearer ${apiToken}`, 'Content-Type': 'application/json' }; try { const response = await fetch(url, { method: 'GET', headers }); const data = await response.json(); if (data.success && data.result.length > 0) { const foundNamespace = data.result.find(ns => ns.title === namespaceName); if (foundNamespace) { return foundNamespace.id; } } return null; // Namespace not found } catch (err) { console.error(`Error fetching KV Namespace ID for "${namespaceName}":`, err); return null; } } async function getDnslinkRecordId() { const recordName = `${config.cloudflare.dnsLink.subdomain}.${config.cloudflare.dnsLink.domain}`; const url = `${API_URL}/zones/${config.cloudflare.zoneId}/dns_records?type=TXT&name=${recordName}`; const headers = { 'Authorization': `Bearer ${config.cloudflare.apiToken}`, 'Content-Type': 'application/json' }; const response = await fetch(url, { method: 'GET', headers }); const data = await response.json(); if (data.success && data.result.length > 0) { const dnslinkRecord = data.result.find(record => record.name === recordName && record.type === 'TXT'); if (dnslinkRecord) { return dnslinkRecord.id; } } return null; } async function changeDnsLink(cid) { try { const dns_record_id = await getDnslinkRecordId(); if (dns_record_id) updateDnslinkRecord(dns_record_id, cid) else createDnslinkRecord(cid); } catch (err) { console.error("An error occurred during DNS link update:", err); return null; } } async function createDnslinkRecord(cid) { try { console.log(`Attempting to create DNSLink TXT record for ${config.cloudflare.dnsLink.domain}...`); const url = `${API_URL}/zones/${config.cloudflare.zoneId}/dns_records`; const headers = { 'Authorization': `Bearer ${config.cloudflare.apiToken}`, 'Content-Type': 'application/json' }; const recordName = `${config.cloudflare.dnsLink.subdomain}.${config.cloudflare.dnsLink.domain}`; const body = JSON.stringify({ type: "TXT", name: recordName, content: `"dnslink=/ipfs/${cid}"`, ttl: 300, proxied: false }); const response = await fetch(url, { method: 'POST', headers, body }); const data = await response.json(); if (data.success) { console.log("DNSLink TXT record created successfully!"); return data.result.id; } else { console.error("Failed to create DNSLink TXT record:", data.errors); return null; } } catch (err) { console.error("An error occurred during DNSLink record creation:", err); return null; } } async function updateDnslinkRecord(recordId, newCid) { const url = `${API_URL}/zones/${config.cloudflare.zoneId}/dns_records/${recordId}`; const headers = { 'Authorization': `Bearer ${config.cloudflare.apiToken}`, 'Content-Type': 'application/json' }; const body = JSON.stringify({ type: "TXT", name: `${config.cloudflare.dnsLink.subdomain}`, // Construire le nom complet content: `"dnslink=/ipfs/${newCid}"`, ttl: 300, proxied: false }); const response = await fetch(url, { method: 'PUT', headers, body }); const data = await response.json(); if (data.success) { console.log("DNSLink TXT record updated successfully!"); return true; } else { console.error("Failed to update DNSLink TXT record:", data.errors); return false; } } async function testCidExistance(cid) { try { console.log(`Checking CID existence (retrieving content from ${IPFS_MAIN_URL})...`); const url = IPFS_MAIN_URL + '/ipfs/' + cid; const res = await fetch(url, { method: 'GET' }); if (res.ok) { console.log("CID is valid and content is accessible."); return res; } else { const errorText = await res.text(); console.error(`CID invalid or content not found. Unable to retrieve content from ${IPFS_MAIN_URL}. Status: ${res.status}. Response: ${errorText.substring(0, 100)}...`); return null; } } catch (err) { console.error("An error occurred during CID verification:", err); return null; } } async function testAuthToken() { try { console.log("Requesting token verification..."); const url = API_URL + '/zones/'; const res = await fetch(url, { method: 'GET', headers: { 'Authorization': `Bearer ${config.cloudflare.apiToken}`, 'Content-Type': 'application/json' } }); if (res.ok) { console.log("Token is functional."); return res; } else { const errorData = await res.json(); console.error(`Token invalid. Cloudflare API error: ${res.status} - ${errorData.errors?.[0]?.message || 'Unknown error'}`); return null; } } catch (err) { console.error("An error occurred during token verification:", err); return null; } } module.exports = { deployCloudflare };