import { existsSync, mkdirSync, rmSync } from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' import { Jimp } from 'jimp' import pngToIco from 'png-to-ico' const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..') const INSTALLER_SOURCE = path.join( rootDir, 'assets/logos/farmcontrolinstaller.png' ) const UNINSTALLER_SOURCE = path.join( rootDir, 'assets/logos/farmcontroluninstaller.png' ) const MAC_ICONSET_ENTRIES = [ { name: 'icon_16x16.png', size: 16 }, { name: 'icon_16x16@2x.png', size: 32 }, { name: 'icon_32x32.png', size: 32 }, { name: 'icon_32x32@2x.png', size: 64 }, { name: 'icon_128x128.png', size: 128 }, { name: 'icon_128x128@2x.png', size: 256 }, { name: 'icon_256x256.png', size: 256 }, { name: 'icon_256x256@2x.png', size: 512 }, { name: 'icon_512x512.png', size: 512 }, { name: 'icon_512x512@2x.png', size: 1024 } ] const WIN_ICO_SIZES = [16, 32, 48, 256] async function resizePng(sourceImage, size) { return sourceImage .clone() .resize({ w: size, h: size }) .getBuffer('image/png') } async function writePng(filePath, sourceImage, size) { const png = await resizePng(sourceImage, size) await Bun.write(filePath, png) return png } async function writeWindowsIco(sourceImage, icoPath) { const icoPngs = [] for (const size of WIN_ICO_SIZES) { icoPngs.push(await resizePng(sourceImage, size)) } await Bun.write(icoPath, await pngToIco(icoPngs)) console.log(`prepare-installer-icons: wrote ${icoPath}`) } async function main() { if (!existsSync(INSTALLER_SOURCE)) { console.error( `prepare-installer-icons: source image not found: ${INSTALLER_SOURCE}` ) process.exit(1) } if (!existsSync(UNINSTALLER_SOURCE)) { console.error( `prepare-installer-icons: source image not found: ${UNINSTALLER_SOURCE}` ) process.exit(1) } const installerImage = await Jimp.read(INSTALLER_SOURCE) if (installerImage.width < 256 || installerImage.height < 256) { console.warn( `prepare-installer-icons: installer source is ${installerImage.width}x${installerImage.height}; recommend at least 256x256` ) } const uninstallerImage = await Jimp.read(UNINSTALLER_SOURCE) if (uninstallerImage.width < 256 || uninstallerImage.height < 256) { console.warn( `prepare-installer-icons: uninstaller source is ${uninstallerImage.width}x${uninstallerImage.height}; recommend at least 256x256` ) } const assetsDir = path.join(rootDir, 'assets') mkdirSync(assetsDir, { recursive: true }) const iconsetDir = path.join(assetsDir, 'installer.iconset') rmSync(iconsetDir, { recursive: true, force: true }) mkdirSync(iconsetDir, { recursive: true }) for (const entry of MAC_ICONSET_ENTRIES) { await writePng( path.join(iconsetDir, entry.name), installerImage, entry.size ) } console.log(`prepare-installer-icons: wrote ${iconsetDir}`) await writeWindowsIco(installerImage, path.join(assetsDir, 'installer.ico')) await writeWindowsIco( uninstallerImage, path.join(assetsDir, 'uninstaller.ico') ) } main().catch((error) => { console.error(`prepare-installer-icons: ${error.message}`) process.exit(1) })