feat(dx/desktop): isolate node_modules dependency

This commit is contained in:
Elian Doran 2025-09-02 10:45:42 +03:00
parent 793102f3ad
commit ae74f8ea83
No known key found for this signature in database
6 changed files with 103 additions and 5 deletions

View file

@ -1 +0,0 @@
node-linker = hoisted

View file

@ -32,9 +32,10 @@
"forge": "./electron-forge/forge.config.ts"
},
"scripts": {
"dev": "cross-env NODE_OPTIONS=\"--import tsx\" NODE_ENV=development TRILIUM_ENV=dev TRILIUM_DATA_DIR=data TRILIUM_RESOURCE_DIR=../server/src electron .",
"dev": "tsx scripts/start.mts",
"build": "tsx scripts/build.ts",
"start-prod": "pnpm build && cross-env TRILIUM_DATA_DIR=data TRILIUM_PORT=37841 electron dist"
"start-prod": "pnpm build && cross-env TRILIUM_DATA_DIR=data TRILIUM_PORT=37841 electron dist",
"postinstall": "tsx scripts/rebuild.mts"
},
"license": "AGPL-3.0-only",
"author": {

View file

@ -0,0 +1,57 @@
import { join } from "path";
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync } from "fs";
import { execSync } from "child_process";
import { rebuild } from "@electron/rebuild"
import { isNixOS, resetPath } from "../../../scripts/utils.mjs";
const desktopProjectRoot = join(import.meta.dirname, "..");
const workspaceRoot = join(desktopProjectRoot, "../..");
function copyNativeDependencies() {
const destPath = join(desktopProjectRoot, "node_modules/better-sqlite3");
if (existsSync(destPath)) {
rmSync(destPath, { recursive: true });
}
mkdirSync(destPath);
cpSync(join(workspaceRoot, "node_modules/better-sqlite3"), destPath, { recursive: true, dereference: true });
}
function rebuildNativeDependencies() {
const electronVersion = determineElectronVersion();
if (!electronVersion) {
console.error("Unable to determine Electron version.");
process.exit(1);
}
console.log(`Rebuilding ${desktopProjectRoot} with ${electronVersion}...`);
rebuild({
projectRootPath: desktopProjectRoot,
buildPath: desktopProjectRoot,
// on NixOS the prebuilt native fails with "Error: libstdc++.so.6: cannot open shared object file: No such file or directory" so we need to build from source.
force: isNixOS(),
electronVersion: electronVersion,
buildFromSource: true
});
}
function determineElectronVersion() {
if (isNixOS()) {
console.log("Detected NixOS, reading Electron version from PATH");
resetPath();
try {
return execSync("electron --version", { }).toString("utf-8");
} catch (e) {
console.error("Got error while trying to read the Electron version from shell. Make sure that an Electron version is in the PATH (e.g. `nix-shell -p electron`)");
process.exit(1);
}
} else {
console.log("Using Electron version from package.json");
}
}
copyNativeDependencies();
rebuildNativeDependencies();

View file

@ -0,0 +1,22 @@
import { execSync, spawnSync } from "child_process";
import { isNixOS, resetPath } from "../../../scripts/utils.mjs";
import { join } from "path";
const projectRoot = join(import.meta.dirname, "..");
if (isNixOS()) {
resetPath();
}
execSync("electron ./src/main.ts", {
stdio: "inherit",
cwd: projectRoot,
env: {
...process.env,
NODE_OPTIONS: "--import tsx",
NODE_ENV: "development",
TRILIUM_ENV: "dev",
TRILIUM_DATA_DIR: "data",
TRILIUM_RESOURCE_DIR: "../server/src"
}
});

View file

@ -2,5 +2,4 @@ packages:
- packages/*
- apps/*
shamefullyHoist: true
nodeLinker: isolated
nodeLinker: hoisted

20
scripts/utils.mts Normal file
View file

@ -0,0 +1,20 @@
import { readFileSync } from "fs";
import { platform } from "os";
export function isNixOS() {
if (platform() !== "linux") return false;
const osReleaseFile = readFileSync("/etc/os-release", "utf-8");
return osReleaseFile.includes("ID=nixos");
}
export function resetPath() {
// On Unix-like systems, PATH is usually inherited from login shell
// but npm prepends node_modules/.bin. Let's remove it:
const origPath = process.env.PATH || "";
// npm usually adds something like ".../node_modules/.bin"
process.env.PATH = origPath
.split(":")
.filter(p => !p.includes("node_modules/.bin"))
.join(":");
}