From 4a0881e5d9dc0d4298bde437a4f451d520848536 Mon Sep 17 00:00:00 2001 From: Carlos Menezes Date: Sat, 18 Nov 2023 09:42:37 +0000 Subject: [PATCH] Add agnostic build and dev scripts for Tauri --- scripts/build.js | 9 +++++ scripts/common.js | 77 +++++++++++++++++++++++++++++++++++++++ scripts/dev.js | 9 +++++ src-tauri/tauri.conf.json | 4 +- 4 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 scripts/build.js create mode 100644 scripts/common.js create mode 100644 scripts/dev.js diff --git a/scripts/build.js b/scripts/build.js new file mode 100644 index 00000000..d4bbec99 --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,9 @@ +import { + executeWithPackageManager, + getPackageManagerExecutable, +} from "./common.js"; + +(async () => { + const packageManager = await getPackageManagerExecutable(); + await executeWithPackageManager(packageManager, "build"); +})(); diff --git a/scripts/common.js b/scripts/common.js new file mode 100644 index 00000000..937f046e --- /dev/null +++ b/scripts/common.js @@ -0,0 +1,77 @@ +import { exec as _exec, spawn, spawnSync } from "child_process"; +import { promisify } from "node:util"; +const exec = promisify(_exec); + +/** + * @type {Record<'npm' | 'yarn', { args?: string[] }>}} + * @constant + */ +const PACKAGE_MANAGERS_OPTIONS = { + npm: { + args: ["run"], + }, + yarn: {}, +}; + +/** + * + * @param {keyof typeof PACKAGE_MANAGERS_OPTIONS} executable + * @returns {Promise} + */ +const hasPackageManager = async (executable) => { + try { + await exec(`${executable} --version`, { stdio: "ignore" }); + return true; + } catch { + return false; + } +}; + +/** + * + * @returns {Promise} + */ +export const getPackageManagerExecutable = async () => { + const results = await Promise.allSettled( + Object.keys(PACKAGE_MANAGERS_OPTIONS).map((exec) => + hasPackageManager(exec).then((isInstalled) => isInstalled && exec) + ) + ); + + const packageManager = results.find( + ({ status, value }) => status === "fulfilled" && value + ); + + if (!packageManager) { + console.error( + `No package manager found. Supported: ${Object.keys( + PACKAGE_MANAGERS_OPTIONS + ).join(", ")}` + ); + process.exit(1); + } + + return packageManager.value; +}; + +/** + * + * @param {keyof typeof PACKAGE_MANAGERS_OPTIONS} packageManager + * @param {'build' | 'dev'} command + */ +export const executeWithPackageManager = async (packageManager, command) => { + const commandToRun = [ + packageManager, + ...(PACKAGE_MANAGERS_OPTIONS[packageManager].args ?? []), + command, + ].join(" "); + const executable = spawn(commandToRun, { + shell: true, + cwd: process.cwd(), + timeout: 10000, + }); + + executable.stdout.on("data", (data) => console.log(data.toString())); + executable.stderr.on("data", (data) => console.error(data.toString())); + executable.on("exit", (code) => process.exit(code)); +}; diff --git a/scripts/dev.js b/scripts/dev.js new file mode 100644 index 00000000..6826c9ca --- /dev/null +++ b/scripts/dev.js @@ -0,0 +1,9 @@ +import { + executeWithPackageManager, + getPackageManagerExecutable, +} from "./common.js"; + +(async () => { + const packageManager = await getPackageManagerExecutable(); + await executeWithPackageManager(packageManager, "dev"); +})(); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index d8ffaa62..d8d2f6bc 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "build": { - "beforeDevCommand": "yarn dev", - "beforeBuildCommand": "yarn build", + "beforeDevCommand": "node ./scripts/dev.js", + "beforeBuildCommand": "node ./scripts/build.js", "devPath": "http://localhost:1420", "distDir": "../dist", "withGlobalTauri": false