@zburn/core
Version:
Core utilities for the ZBURN ecosystem.
237 lines (206 loc) • 8.34 kB
JavaScript
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
};