import fs from 'fs';
const defaultConfig = {
"domains": ["mempool.space"],
"theme": "default",
"enterprise": "mempool",
"branding": {
"name": "mempool",
"title": "mempool",
"site_id": 5,
},
"meta": {
"title": "mempool - Bitcoin Explorer",
"description": "Explore the full Bitcoin ecosystem with The Mempool Open Source Project®. See the real-time status of your transactions, get network info, and more.",
},
"unfurls": {
"preview": {
"src": "https://mempool.space/resources/previews/mempool-space-preview.jpg",
"type": "image/jpeg",
"width": "2000",
"height": "1000"
}
}
}
function deepMerge(target, source) {
for (const key in source) {
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
target[key] = target[key] || {};
deepMerge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
return target;
}
function addDefaultsToConfig(config) {
return deepMerge(structuredClone(defaultConfig), config);
}
function substitute(indexhtml, config) {
let newhtml = indexhtml;
// substitute title
newhtml = newhtml.replace(/\<\!\-\- TITLE \-\-\>.*\<\!\-\- END TITLE \-\-\>/gis, `
${config.meta.title}`);
// substitute customization script
newhtml = newhtml.replace(/\<\!\-\- CUSTOMIZATION \-\-\>.*\<\!\-\- END CUSTOMIZATION \-\-\>/gis, ``);
// substitute meta tags
newhtml = newhtml.replace(/\<\!\-\- META \-\-\>.*\<\!\-\- END META \-\-\>/gis, `
`);
// substitute favicons
newhtml = newhtml.replace(/\<\!\-\- FAVICONS -->.*\<\!\-\- END FAVICONS \-\-\>/gis, `
`);
return newhtml;
}
async function run() {
const servicesHost = process.argv[2] || 'http://localhost:9000';
const mempoolDir = process.argv[3] || '../';
console.log('fetching list of custom builds');
const customBuilds = await (await fetch(`${servicesHost}/api/v1/services/custom/list`)).json();
// fetch config for each custom build from `$SERVICES/api/v1/services/custom/config/`
const customConfigs = await Promise.all(customBuilds.map(async (build) => {
console.log(`fetching config for ${build} `);
return addDefaultsToConfig(await (await fetch(`${servicesHost}/api/v1/services/custom/config/${build}`)).json());
}));
// for each custom build config:
let i = 0;
for (const config of customConfigs) {
console.log(`generating ${config.enterprise} build (${i + 1}/${customConfigs.length})`);
const browserDir = `${mempoolDir}/frontend/dist/mempool/browser`;
const locales = fs.readdirSync(browserDir)
.filter(file => fs.statSync(`${browserDir}/${file}`).isDirectory())
.filter(file => fs.existsSync(`${browserDir}/${file}/index.html`));
// Process each locale's index.html
for (const locale of locales) {
const indexPath = `${browserDir}/${locale}/index.html`;
const indexContent = fs.readFileSync(indexPath, 'utf-8').toString();
const processedHtml = substitute(indexContent, config);
// Save processed HTML
const outputPath = `${browserDir}/${locale}/index.${config.enterprise}.html`;
fs.writeFileSync(outputPath, processedHtml);
console.log(`updated index.${config.enterprise}.html for locale ${locale}`);
}
console.log(`finished generating ${config.enterprise} build`);
i++;
}
console.log('finished updating custom builds');
}
run();