tutanota/buildSrc/buildUtils.js
ivk fba2b284ec [desktop] Use @signalapp/sqlcipher fork for db
Co-authored-by: paw <paw-hub@users.noreply.github.com>
2025-06-04 10:37:52 +02:00

187 lines
4.9 KiB
JavaScript

/**
* This file contains some utilities used from various build scripts in this directory.
*/
import fs from "node:fs/promises"
import path, { dirname } from "node:path"
import { fileURLToPath } from "node:url"
import stream from "node:stream"
const __dirname = dirname(fileURLToPath(import.meta.url))
/** global used by the measure() function to mark the start of measurement **/
var measureStartTime
/**
* Returns tutanota app version (as in package.json).
* @returns {Promise<string>}
*/
export async function getTutanotaAppVersion() {
const packageJson = JSON.parse(await fs.readFile(path.join(__dirname, "..", "package.json"), "utf8"))
return packageJson.version.trim()
}
/**
* Returns the elapsed time between the last and current call of measure().
* @returns {number}
*/
export function measure() {
if (!measureStartTime) {
measureStartTime = Date.now()
}
return (Date.now() - measureStartTime) / 1000
}
/**
* Returns the (absolute) path to the default dist directory/prefix.
* @returns {string}
*/
export function getDefaultDistDirectory() {
return path.resolve("build")
}
/** Throws if result has a value other than 0. **/
export function exitOnFail(result) {
if (result.status !== 0) {
throw new Error("error invoking process" + JSON.stringify(result))
}
}
/**
* Utility for writing to a logging function when a Writable is expected
*/
export class LogWriter extends stream.Writable {
/**
* @param logger {(string) => void}
*/
constructor(logger) {
super({
autoDestroy: true,
write(chunk, encoding, callback) {
logger(chunk.toString().trim())
callback()
},
})
}
}
/**
* Check if a file exists and is a normal file
* @param filePath {string}
* @returns {Promise<boolean>}
*/
export async function fileExists(filePath) {
return fs
.stat(filePath)
.then((stats) => stats.isFile())
.catch(() => false)
}
/**
* There are various possibilities for how a given platform could be identified
* We need to make sure to be consistent at certain points, such as when caching files or processing CLI args
* @param platformName {string}
* @returns {"darwin"|"win32"|"linux"}
*/
export function getCanonicalPlatformName(platformName) {
switch (platformName) {
case "mac":
case "darwin":
return "darwin"
case "win":
case "win32":
return "win32"
case "linux":
return "linux"
default:
throw new Error(`Unknown platform name ${platformName}`)
}
}
/**
* Checks whether the combination of OS & architecture is supported by the build system
* @param platformName {NodeJS.Platform}
* @param architecture {NodeJS.Architecture|"universal"}
* @returns {architecture is "x64"|"arm64"|"universal"}
*/
export function checkArchitectureIsSupported(platformName, architecture) {
switch (architecture) {
case "x64":
return true
case "arm64":
case "universal":
return platformName === "darwin"
default:
return false
}
}
/**
*
* @param platformName {NodeJS.Platform}
* @param architecture {NodeJS.Architecture|"universal"}
* @return {"x64"|"arm64"|"universal"}
*/
export function getValidArchitecture(platformName, architecture) {
if (!checkArchitectureIsSupported(platformName, architecture)) {
throw new Error(`Unsupported architecture: ${platformName} ${architecture}`)
}
return architecture
}
export async function runStep(name, cmd) {
const before = Date.now()
console.log("Build >", name)
await cmd()
console.log("Build >", name, "took", Date.now() - before, "ms")
}
export function writeFile(targetFile, content) {
return fs.mkdir(path.dirname(targetFile), { recursive: true }).then(() => fs.writeFile(targetFile, content, "utf-8"))
}
export function normalizeCopyTarget(target) {
return removeNpmNamespacePrefix(changeHypenToUnderscore(target))
}
export function changeHypenToUnderscore(target) {
// because its name is used as a C identifier
return target.replace("-", "_")
}
export function removeNpmNamespacePrefix(target) {
// linear complexity Array.last(), wth not?
// gets us the moduleName out of @tutao/moduleName
return target.split("/").reduce((p, c) => c, null)
}
/**
* @param arch {NodeJS.Architecture|"universal"}
* @returns {Array<import("./nativeLibraryProvider.js").BuildArch>}
*/
export function resolveArch(arch) {
if (arch === "universal") {
return ["x64", "arm64"]
} else if (arch === "x64" || arch === "arm64") {
return [arch]
} else {
throw new Error(`Unsupported arch: ${arch}`)
}
}
/**
* napi appends abi to the architecture (see https://napi.rs/docs/cli/napi-config)
*
* NOTE: this is not a triple as in "target triple" known to rust, it is a "tuple" with Clib appended to it.
*
* @param platform {NodeJS.Platform}
* @param architecture {NodeJS.Architecture}
*/
export function getTargetTupleWithLibc(platform, architecture) {
if (platform === "linux") {
return `${platform}-${architecture}-gnu`
} else if (platform === "win32") {
return `${platform}-${architecture}-msvc`
} else {
return `${platform}-${architecture}`
}
}