microsoft/TypeAgent

Public

mirrored fromhttps://github.com/microsoft/TypeAgentAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
baefc8a6037bdbab6d2ac7a1ebfc33cc6ae16cfb

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

ts/tools/scripts/copy-better-sqlite3-node.js

152lines Ā· modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4// Save the Node.js-compatible better-sqlite3 native binary to a safe location.
5//
6// Problem: electron-builder's install-app-deps (in packages/shell postinstall)
7// rebuilds better-sqlite3 for Electron, wiping the entire build/ directory.
8// This runs in the root postinstall BEFORE electron-builder, so we save the
9// correct Node.js binary to prebuild-node/ (outside build/) where
10// electron-builder won't touch it.
11//
12// If the binary in build/Release/ is already for Electron (wrong ABI), we
13// re-download the correct Node.js prebuilt via prebuild-install.
14//
15// Works with pnpm's store layout on Windows, macOS, and Linux.
16
17const fs = require("fs");
18const path = require("path");
19const { execFileSync } = require("child_process");
20
21const expectedABI = process.versions.modules; // e.g. "127" for Node 22
22
23function isNodeCompatible(binaryPath) {
24 try {
25 process.dlopen({ exports: {} }, binaryPath);
26 return true;
27 } catch {
28 return false;
29 }
30}
31
32// Find all better-sqlite3 installations in the pnpm store
33const pnpmDir = path.resolve(__dirname, "..", "..", "node_modules", ".pnpm");
34const entries = fs
35 .readdirSync(pnpmDir)
36 .filter((e) => e.startsWith("better-sqlite3@"));
37
38if (entries.length === 0) {
39 console.error("No better-sqlite3 installations found in", pnpmDir);
40 process.exit(1);
41}
42
43let hasError = false;
44
45for (const entry of entries) {
46 const pkgDir = path.join(pnpmDir, entry, "node_modules", "better-sqlite3");
47 if (!fs.existsSync(path.join(pkgDir, "package.json"))) {
48 continue;
49 }
50
51 console.log(`\nšŸ“¦ Processing ${entry}:`);
52 console.log(" ", pkgDir);
53
54 const dstDir = path.join(pkgDir, "prebuild-node");
55 const dst = path.join(dstDir, "better_sqlite3.node");
56
57 // If prebuild-node/ already has a compatible binary, skip
58 if (fs.existsSync(dst) && isNodeCompatible(dst)) {
59 console.log(
60 "āœ… Already has compatible Node.js binary in prebuild-node/",
61 );
62 continue;
63 }
64
65 const releaseBinary = path.join(
66 pkgDir,
67 "build",
68 "Release",
69 "better_sqlite3.node",
70 );
71
72 // If build/Release/ has a compatible Node.js binary, just copy it
73 if (fs.existsSync(releaseBinary) && isNodeCompatible(releaseBinary)) {
74 fs.mkdirSync(dstDir, { recursive: true });
75 fs.copyFileSync(releaseBinary, dst);
76 console.log("āœ… Copied compatible binary from build/Release/");
77 console.log(" → ", dst);
78 continue;
79 }
80
81 // Binary is missing or wrong ABI (e.g. Electron) — re-download for Node.js
82 console.log(
83 "ā¬‡ļø Downloading Node.js-compatible prebuilt via prebuild-install...",
84 );
85 const tempBuildDir = path.join(pkgDir, "build-node-temp");
86 try {
87 // prebuild-install writes to build/Release/, so use a temp dir
88 // to avoid disturbing any existing Electron binary
89 fs.rmSync(tempBuildDir, { recursive: true, force: true });
90 const origBuild = path.join(pkgDir, "build");
91 const hasBuild = fs.existsSync(origBuild);
92 if (hasBuild) {
93 fs.renameSync(origBuild, tempBuildDir);
94 }
95 try {
96 execFileSync(
97 process.execPath,
98 [
99 require.resolve("prebuild-install/bin", {
100 paths: [pkgDir],
101 }),
102 "--runtime",
103 "node",
104 "--target",
105 process.version,
106 ],
107 {
108 cwd: pkgDir,
109 stdio: "inherit",
110 },
111 );
112
113 const downloaded = path.join(
114 pkgDir,
115 "build",
116 "Release",
117 "better_sqlite3.node",
118 );
119 if (!fs.existsSync(downloaded)) {
120 throw new Error("prebuild-install did not produce a binary");
121 }
122
123 fs.mkdirSync(dstDir, { recursive: true });
124 fs.copyFileSync(downloaded, dst);
125 console.log("āœ… Node.js binary saved to prebuild-node/");
126
127 // Remove the temp build dir created by prebuild-install
128 fs.rmSync(path.join(pkgDir, "build"), {
129 recursive: true,
130 force: true,
131 });
132 } finally {
133 // Restore original build dir (may contain Electron binary)
134 if (hasBuild) {
135 if (!fs.existsSync(origBuild)) {
136 fs.renameSync(tempBuildDir, origBuild);
137 } else {
138 fs.rmSync(tempBuildDir, { recursive: true, force: true });
139 }
140 }
141 }
142 } catch (e) {
143 console.error(`āŒ Failed for ${entry}:`, e.message);
144 fs.rmSync(tempBuildDir, { recursive: true, force: true });
145 hasError = true;
146 continue;
147 }
148}
149
150if (hasError) {
151 process.exit(1);
152}
153