Files
leon-ai--leon/scripts/setup/setup-native-node-modules.js
T
2026-07-13 12:44:08 +08:00

96 lines
2.2 KiB
JavaScript

import fs from 'node:fs'
import path from 'node:path'
import execa from 'execa'
import {
CACHE_PATH,
NODE_VERSION,
PNPM_RUNTIME_BIN_PATH
} from '@/constants'
import { RuntimeHelper } from '@/helpers/runtime-helper'
import { createSetupStatus } from './setup-status'
const NODE_MODULES_PATH = path.join(process.cwd(), 'node_modules')
const NATIVE_NODE_MODULE_REBUILD_PACKAGES = [
'better-sqlite3'
]
const STAMP_FILE_PATH = path.join(
CACHE_PATH,
'setup',
'.last-native-node-modules-rebuild'
)
function getPackageManifestPath(packageName) {
return path.join(NODE_MODULES_PATH, packageName, 'package.json')
}
function getInstalledRebuildPackages() {
return NATIVE_NODE_MODULE_REBUILD_PACKAGES.filter((packageName) =>
fs.existsSync(getPackageManifestPath(packageName))
)
}
async function isRebuildCurrent(packageNames) {
if (!fs.existsSync(STAMP_FILE_PATH)) {
return false
}
const stampValue = (await fs.promises.readFile(STAMP_FILE_PATH, 'utf8')).trim()
if (stampValue !== NODE_VERSION) {
return false
}
const stampStat = await fs.promises.stat(STAMP_FILE_PATH)
for (const packageName of packageNames) {
const packageManifestStat = await fs.promises.stat(
getPackageManifestPath(packageName)
)
if (packageManifestStat.mtimeMs > stampStat.mtimeMs) {
return false
}
}
return true
}
/**
* Rebuild native modules that must match Leon's managed Node.js ABI.
*/
export default async function setupNativeNodeModules() {
if (!fs.existsSync(NODE_MODULES_PATH)) {
return
}
const installedPackages = getInstalledRebuildPackages()
if (installedPackages.length === 0) {
return
}
const status = createSetupStatus('Rebuilding native Node.js modules...').start()
if (await isRebuildCurrent(installedPackages)) {
status.succeed('Native Node.js modules: up-to-date')
return
}
await execa(PNPM_RUNTIME_BIN_PATH, [
'rebuild',
...installedPackages
], {
cwd: process.cwd(),
env: RuntimeHelper.getManagedNodeEnvironment()
})
await fs.promises.mkdir(path.dirname(STAMP_FILE_PATH), { recursive: true })
await fs.promises.writeFile(STAMP_FILE_PATH, NODE_VERSION)
status.succeed('Native Node.js modules: ready')
}