gradido/dlt-connector/src/bootstrap/initGradidoNode.ts

97 lines
3.9 KiB
TypeScript

import { execSync } from 'node:child_process'
import fs from 'node:fs'
import path from 'node:path'
import AdmZip from 'adm-zip'
import { getLogger } from 'log4js'
import { exportCommunities } from '../client/GradidoNode/communities'
import { GradidoNodeProcess } from '../client/GradidoNode/GradidoNodeProcess'
import { HieroClient } from '../client/hiero/HieroClient'
import { CONFIG } from '../config'
import { GRADIDO_NODE_HOME_FOLDER_NAME, LOG4JS_BASE_CATEGORY } from '../config/const'
import { checkFileExist, checkPathExist } from '../utils/filesystem'
import { isPortOpen } from '../utils/network'
import { AppContextClients } from './appContext'
const logger = getLogger(`${LOG4JS_BASE_CATEGORY}.bootstrap.initGradidoNode`)
export async function initGradidoNode(clients: AppContextClients): Promise<void> {
const url = `http://localhost:${CONFIG.DLT_NODE_SERVER_PORT}`
const isOpen = await isPortOpen(url)
if (isOpen) {
logger.info(`GradidoNode is already running on ${url}`)
return
}
const gradidoNodeHomeFolder = path.join(
CONFIG.DLT_GRADIDO_NODE_SERVER_HOME_FOLDER,
GRADIDO_NODE_HOME_FOLDER_NAME,
)
// check folder, create when missing
checkPathExist(gradidoNodeHomeFolder, true)
await Promise.all([
// write Hedera Address Book
exportHederaAddressbooks(gradidoNodeHomeFolder, clients.hiero),
// check GradidoNode Runtime, download when missing
ensureGradidoNodeRuntimeAvailable(GradidoNodeProcess.getRuntimePathFileName()),
// export communities to GradidoNode Folder
exportCommunities(gradidoNodeHomeFolder, clients.backend),
])
GradidoNodeProcess.getInstance().start()
}
async function exportHederaAddressbooks(
homeFolder: string,
hieroClient: HieroClient,
): Promise<void> {
const networkName = CONFIG.HIERO_HEDERA_NETWORK
const addressBook = await hieroClient.downloadAddressBook()
const addressBookPath = path.join(homeFolder, 'addressbook', `${networkName}.pb`)
checkPathExist(path.dirname(addressBookPath), true)
fs.writeFileSync(addressBookPath, addressBook.toBytes())
}
async function ensureGradidoNodeRuntimeAvailable(runtimeFileName: string): Promise<void> {
const runtimeFolder = path.dirname(runtimeFileName)
const wantedVersion = `v${CONFIG.DLT_GRADIDO_NODE_SERVER_VERSION}`
checkPathExist(runtimeFolder, true)
let versionMatch = false
const isFileExist = checkFileExist(runtimeFileName)
if (isFileExist) {
const foundVersion = await GradidoNodeProcess.checkRuntimeVersion()
if (wantedVersion !== foundVersion) {
logger.info(`GradidoNode version detected: ${foundVersion}, required: ${wantedVersion}`)
} else {
versionMatch = true
}
}
if (!isFileExist || !versionMatch) {
const runtimeArchiveFilename = createGradidoNodeRuntimeArchiveFilename()
const downloadUrl = new URL(
`https://github.com/gradido/gradido_node/releases/download/${wantedVersion}/${runtimeArchiveFilename}`,
)
logger.debug(`download GradidoNode Runtime from ${downloadUrl}`)
const archive = await fetch(downloadUrl)
if (!archive.ok) {
throw new Error(`Failed to download GradidoNode Runtime: ${archive.statusText}`)
}
const compressedBuffer = await archive.arrayBuffer()
if (process.platform === 'win32') {
const zip = new AdmZip(Buffer.from(compressedBuffer))
zip.extractAllTo(runtimeFolder, true)
} else {
const archivePath = path.join(runtimeFolder, runtimeArchiveFilename)
logger.debug(`GradidoNode Runtime Archive: ${archivePath}`)
fs.writeFileSync(archivePath, Buffer.from(compressedBuffer))
execSync(`tar -xzf ${archivePath}`, { cwd: runtimeFolder })
}
}
}
function createGradidoNodeRuntimeArchiveFilename(): string {
const version = CONFIG.DLT_GRADIDO_NODE_SERVER_VERSION
const platform: string = process.platform
const fileEnding = platform === 'win32' ? 'zip' : 'tar.gz'
return `gradido_node-v${version}-${platform}-${process.arch}.${fileEnding}`
}