* fix(cli): rebuild better-sqlite3 when binding is missing * fix(cli): support Windows postinstall rebuild shims --------- Co-authored-by: i-trytoohard <193449657+i-trytoohard@users.noreply.github.com>
This commit is contained in:
parent
87c6a3d9f4
commit
d5d0f077ad
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
"@aoagents/ao": patch
|
||||
"@aoagents/ao-core": patch
|
||||
"@aoagents/ao-cli": patch
|
||||
---
|
||||
|
||||
Rebuild missing better-sqlite3 native bindings during ao postinstall and replace noisy activity-events native-binding failures with a one-line diagnostic.
|
||||
|
|
@ -11,19 +11,28 @@
|
|||
* If not (common with nvm/fnm/volta), rebuilds from source via npx node-gyp.
|
||||
* See: https://github.com/ComposioHQ/agent-orchestrator/issues/987
|
||||
*
|
||||
* 3. Clears stale Next.js runtime cache (.next/cache) from @composio/ao-web
|
||||
* 3. Verifies better-sqlite3 has a native binding for this Node ABI.
|
||||
* Node majors can ship new NODE_MODULE_VERSION values before better-sqlite3
|
||||
* publishes matching prebuilds; global installs must rebuild from source.
|
||||
* See: https://github.com/ComposioHQ/agent-orchestrator/issues/1822
|
||||
*
|
||||
* 4. Clears stale Next.js runtime cache (.next/cache) from @composio/ao-web
|
||||
* after a version upgrade, so `ao start` serves fresh dashboard assets.
|
||||
* Writes a version stamp (.next/AO_VERSION) to skip cleanup on subsequent runs.
|
||||
*/
|
||||
|
||||
import { chmodSync, existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { execSync } from "node:child_process";
|
||||
import { execFileSync, execSync } from "node:child_process";
|
||||
import { resolve, dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
function findPackageUp(startDir, ...segments) {
|
||||
function isWindows() {
|
||||
return process.platform === "win32";
|
||||
}
|
||||
|
||||
export function findPackageUp(startDir, ...segments) {
|
||||
let dir = resolve(startDir);
|
||||
while (true) {
|
||||
const candidate = resolve(dir, "node_modules", ...segments);
|
||||
|
|
@ -35,12 +44,12 @@ function findPackageUp(startDir, ...segments) {
|
|||
return null;
|
||||
}
|
||||
|
||||
function resolveNodeModulesPackage(fromDir, ...segments) {
|
||||
export function resolveNodeModulesPackage(fromDir, ...segments) {
|
||||
const packageDir = resolve(fromDir, "node_modules", ...segments);
|
||||
return existsSync(resolve(packageDir, "package.json")) ? packageDir : null;
|
||||
}
|
||||
|
||||
function findWebDir() {
|
||||
export function findWebDir() {
|
||||
const directWebDir = findPackageUp(__dirname, "@aoagents", "ao-web");
|
||||
if (directWebDir) return directWebDir;
|
||||
|
||||
|
|
@ -50,8 +59,112 @@ function findWebDir() {
|
|||
return resolveNodeModulesPackage(cliDir, "@aoagents", "ao-web");
|
||||
}
|
||||
|
||||
// --- 1 & 2. Fix node-pty spawn-helper permissions and verify ABI (non-Windows only) ---
|
||||
if (process.platform !== "win32") {
|
||||
export function findBetterSqlite3Dir() {
|
||||
const directBetterSqlite3Dir = findPackageUp(__dirname, "better-sqlite3");
|
||||
if (directBetterSqlite3Dir) return directBetterSqlite3Dir;
|
||||
|
||||
const cliDir = findPackageUp(__dirname, "@aoagents", "ao-cli");
|
||||
if (!cliDir) return null;
|
||||
|
||||
const coreDir = resolveNodeModulesPackage(cliDir, "@aoagents", "ao-core");
|
||||
if (!coreDir) return null;
|
||||
|
||||
return (
|
||||
resolveNodeModulesPackage(coreDir, "better-sqlite3") ?? findPackageUp(coreDir, "better-sqlite3")
|
||||
);
|
||||
}
|
||||
|
||||
export function betterSqlite3BindingCandidates(
|
||||
packageDir,
|
||||
{
|
||||
platform = process.platform,
|
||||
arch = process.arch,
|
||||
modules = process.versions.modules,
|
||||
nodeVersion = process.versions.node,
|
||||
} = {},
|
||||
) {
|
||||
return [
|
||||
resolve(packageDir, "build", "better_sqlite3.node"),
|
||||
resolve(packageDir, "build", "Debug", "better_sqlite3.node"),
|
||||
resolve(packageDir, "build", "Release", "better_sqlite3.node"),
|
||||
resolve(packageDir, "out", "Debug", "better_sqlite3.node"),
|
||||
resolve(packageDir, "Debug", "better_sqlite3.node"),
|
||||
resolve(packageDir, "out", "Release", "better_sqlite3.node"),
|
||||
resolve(packageDir, "Release", "better_sqlite3.node"),
|
||||
resolve(packageDir, "build", "default", "better_sqlite3.node"),
|
||||
resolve(packageDir, "compiled", nodeVersion, platform, arch, "better_sqlite3.node"),
|
||||
resolve(packageDir, "addon-build", "release", "install-root", "better_sqlite3.node"),
|
||||
resolve(packageDir, "addon-build", "debug", "install-root", "better_sqlite3.node"),
|
||||
resolve(packageDir, "addon-build", "default", "install-root", "better_sqlite3.node"),
|
||||
resolve(
|
||||
packageDir,
|
||||
"lib",
|
||||
"binding",
|
||||
`node-v${modules}-${platform}-${arch}`,
|
||||
"better_sqlite3.node",
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
export function hasBetterSqlite3Binding(packageDir, options = {}) {
|
||||
const fileExists = options.existsSync ?? existsSync;
|
||||
return betterSqlite3BindingCandidates(packageDir, options).some((candidate) =>
|
||||
fileExists(candidate),
|
||||
);
|
||||
}
|
||||
|
||||
export function betterSqlite3RebuildCommand(packageDir, env = process.env) {
|
||||
const packageManager =
|
||||
`${env.npm_config_user_agent ?? ""} ${env.npm_execpath ?? ""}`.toLowerCase();
|
||||
if (packageManager.includes("npm") && !packageManager.includes("pnpm")) {
|
||||
return { command: "npm", args: ["rebuild"], display: `cd ${packageDir} && npm rebuild` };
|
||||
}
|
||||
return {
|
||||
command: "pnpm",
|
||||
args: ["--dir", packageDir, "rebuild"],
|
||||
display: `pnpm --dir ${packageDir} rebuild`,
|
||||
};
|
||||
}
|
||||
|
||||
function checkBetterSqlite3Binding() {
|
||||
const betterSqlite3Dir = findBetterSqlite3Dir();
|
||||
if (!betterSqlite3Dir) {
|
||||
console.warn(
|
||||
"⚠️ better-sqlite3 package not found; skipping activity-events native binding check",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const abi = process.versions.modules;
|
||||
if (hasBetterSqlite3Binding(betterSqlite3Dir)) {
|
||||
console.log(
|
||||
`✓ better-sqlite3 native binding present for Node ${process.version} (ABI v${abi})`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const { command, args, display } = betterSqlite3RebuildCommand(betterSqlite3Dir);
|
||||
try {
|
||||
execFileSync(command, args, {
|
||||
cwd: betterSqlite3Dir,
|
||||
stdio: "ignore",
|
||||
timeout: 120000,
|
||||
shell: isWindows(),
|
||||
windowsHide: true,
|
||||
});
|
||||
console.log(
|
||||
`✓ better-sqlite3 native binding rebuilt for Node ${process.version} (ABI v${abi})`,
|
||||
);
|
||||
} catch {
|
||||
console.warn(
|
||||
`⚠️ better-sqlite3 rebuild failed for Node ${process.version} (ABI v${abi}) — activity events may be unavailable. Manual fix: ${display}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function fixNodePty() {
|
||||
if (isWindows()) return;
|
||||
|
||||
const nodePtyDir = findPackageUp(__dirname, "node-pty");
|
||||
if (nodePtyDir) {
|
||||
const spawnHelper = resolve(
|
||||
|
|
@ -84,7 +197,11 @@ if (process.platform !== "win32") {
|
|||
},
|
||||
);
|
||||
} catch {
|
||||
console.log("⚠️ node-pty prebuilt binary incompatible with Node.js " + process.version + ", rebuilding...");
|
||||
console.log(
|
||||
"⚠️ node-pty prebuilt binary incompatible with Node.js " +
|
||||
process.version +
|
||||
", rebuilding...",
|
||||
);
|
||||
try {
|
||||
execSync("npx --yes node-gyp rebuild", {
|
||||
cwd: nodePtyDir,
|
||||
|
|
@ -100,27 +217,43 @@ if (process.platform !== "win32") {
|
|||
}
|
||||
}
|
||||
|
||||
// --- 3. Clear stale Next.js runtime cache after version upgrade ---
|
||||
try {
|
||||
const webDir = findWebDir();
|
||||
if (webDir) {
|
||||
const pkgPath = resolve(webDir, "package.json");
|
||||
if (existsSync(pkgPath)) {
|
||||
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
||||
const version = pkg.version;
|
||||
const cacheDir = resolve(webDir, ".next", "cache");
|
||||
const stampPath = resolve(webDir, ".next", "AO_VERSION");
|
||||
function clearDashboardCache() {
|
||||
try {
|
||||
const webDir = findWebDir();
|
||||
if (webDir) {
|
||||
const pkgPath = resolve(webDir, "package.json");
|
||||
if (existsSync(pkgPath)) {
|
||||
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
||||
const version = pkg.version;
|
||||
const cacheDir = resolve(webDir, ".next", "cache");
|
||||
const stampPath = resolve(webDir, ".next", "AO_VERSION");
|
||||
|
||||
if (existsSync(cacheDir)) {
|
||||
rmSync(cacheDir, { recursive: true, force: true });
|
||||
console.log("✓ Cleared stale .next/cache");
|
||||
}
|
||||
if (existsSync(resolve(webDir, ".next"))) {
|
||||
writeFileSync(stampPath, version, "utf8");
|
||||
console.log(`✓ Dashboard version stamp set to ${version}`);
|
||||
if (existsSync(cacheDir)) {
|
||||
rmSync(cacheDir, { recursive: true, force: true });
|
||||
console.log("✓ Cleared stale .next/cache");
|
||||
}
|
||||
if (existsSync(resolve(webDir, ".next"))) {
|
||||
writeFileSync(stampPath, version, "utf8");
|
||||
console.log(`✓ Dashboard version stamp set to ${version}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`⚠️ Could not clear dashboard cache (non-critical): ${err.message}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`⚠️ Could not clear dashboard cache (non-critical): ${err.message}`);
|
||||
}
|
||||
|
||||
export function runPostinstall() {
|
||||
// --- 1 & 2. Fix node-pty spawn-helper permissions and verify ABI (non-Windows only) ---
|
||||
fixNodePty();
|
||||
|
||||
// --- 3. Ensure better-sqlite3 has a native binding for this Node ABI ---
|
||||
checkBetterSqlite3Binding();
|
||||
|
||||
// --- 4. Clear stale Next.js runtime cache after version upgrade ---
|
||||
clearDashboardCache();
|
||||
}
|
||||
|
||||
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
||||
runPostinstall();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
betterSqlite3BindingCandidates,
|
||||
betterSqlite3RebuildCommand,
|
||||
hasBetterSqlite3Binding,
|
||||
} from "../../../ao/bin/postinstall.js";
|
||||
|
||||
describe("ao postinstall better-sqlite3 native binding detection", () => {
|
||||
const env = {
|
||||
platform: "darwin",
|
||||
arch: "arm64",
|
||||
modules: "141",
|
||||
nodeVersion: "25.9.0",
|
||||
};
|
||||
|
||||
it("checks the current Node ABI binding path", () => {
|
||||
const packageDir = "virtual-better-sqlite3";
|
||||
const candidates = betterSqlite3BindingCandidates(packageDir, env);
|
||||
|
||||
expect(candidates.some((candidate) => candidate.includes("node-v141-darwin-arm64"))).toBe(true);
|
||||
});
|
||||
|
||||
it("reports the binding present when a mocked candidate exists", () => {
|
||||
const packageDir = "virtual-better-sqlite3";
|
||||
const candidates = betterSqlite3BindingCandidates(packageDir, env);
|
||||
const currentAbiBinding = candidates.find((candidate) =>
|
||||
candidate.includes("node-v141-darwin-arm64"),
|
||||
);
|
||||
if (!currentAbiBinding) {
|
||||
throw new Error("expected current ABI binding candidate");
|
||||
}
|
||||
|
||||
const existingFiles = new Set([currentAbiBinding]);
|
||||
|
||||
expect(
|
||||
hasBetterSqlite3Binding(packageDir, {
|
||||
...env,
|
||||
existsSync: (candidate: string) => existingFiles.has(candidate),
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("reports the binding missing when no mocked candidate exists", () => {
|
||||
expect(
|
||||
hasBetterSqlite3Binding("virtual-better-sqlite3", {
|
||||
...env,
|
||||
existsSync: () => false,
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("uses pnpm to rebuild inside the resolved better-sqlite3 package", () => {
|
||||
expect(
|
||||
betterSqlite3RebuildCommand("virtual-better-sqlite3", {
|
||||
npm_config_user_agent: "pnpm/9.15.4 npm/? node/v25.9.0 darwin arm64",
|
||||
}),
|
||||
).toEqual({
|
||||
command: "pnpm",
|
||||
args: ["--dir", "virtual-better-sqlite3", "rebuild"],
|
||||
display: "pnpm --dir virtual-better-sqlite3 rebuild",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -91,7 +91,7 @@
|
|||
"zod": "^3.24.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"better-sqlite3": "^11.0.0"
|
||||
"better-sqlite3": "^12.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-typescript": "^12.3.0",
|
||||
|
|
@ -99,8 +99,8 @@
|
|||
"@types/node": "^25.2.3",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
"rollup": "^4.60.1",
|
||||
"tsx": "^4.21.0",
|
||||
"tslib": "^2.8.1",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.7.0",
|
||||
"vitest": "^4.0.18"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import {
|
||||
__resetActivityEventsDbWarningForTests,
|
||||
emitActivityEventsDbUnavailableWarning,
|
||||
formatActivityEventsDbUnavailableWarning,
|
||||
} from "../events-db.js";
|
||||
|
||||
describe("activity-events DB unavailable warning", () => {
|
||||
const originalArgv = process.argv;
|
||||
const originalDebug = process.env["AO_DEBUG"];
|
||||
|
||||
beforeEach(() => {
|
||||
__resetActivityEventsDbWarningForTests();
|
||||
vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
delete process.env["AO_DEBUG"];
|
||||
process.argv = ["node", "ao"];
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.argv = originalArgv;
|
||||
if (originalDebug === undefined) {
|
||||
delete process.env["AO_DEBUG"];
|
||||
} else {
|
||||
process.env["AO_DEBUG"] = originalDebug;
|
||||
}
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("formats missing native binding errors without the bindings search path", () => {
|
||||
const message = formatActivityEventsDbUnavailableWarning(
|
||||
new Error(
|
||||
"Could not locate the bindings file. Tried:\n → /tmp/build/Release/better_sqlite3.node",
|
||||
),
|
||||
);
|
||||
|
||||
expect(message).toBe(
|
||||
`[ao] activity-events disabled: better-sqlite3 not compiled for Node ${process.version} (ABI v${process.versions.modules}). Run \`pnpm rebuild better-sqlite3\` or use a supported Node version.`,
|
||||
);
|
||||
expect(message).not.toContain("Tried:");
|
||||
expect(message).not.toContain("/tmp/build/Release");
|
||||
});
|
||||
|
||||
it("prints the runtime warning once per process", () => {
|
||||
process.env["AO_DEBUG"] = "1";
|
||||
const err = new Error(
|
||||
"Could not locate the bindings file. Tried:\n → /tmp/better_sqlite3.node",
|
||||
);
|
||||
|
||||
emitActivityEventsDbUnavailableWarning(err);
|
||||
emitActivityEventsDbUnavailableWarning(err);
|
||||
|
||||
expect(console.warn).toHaveBeenCalledTimes(1);
|
||||
expect(vi.mocked(console.warn).mock.calls[0]?.[0]).toContain(
|
||||
"activity-events disabled: better-sqlite3 not compiled",
|
||||
);
|
||||
});
|
||||
|
||||
it("suppresses non-events invocations unless AO_DEBUG=1", () => {
|
||||
const err = new Error(
|
||||
"Could not locate the bindings file. Tried:\n → /tmp/better_sqlite3.node",
|
||||
);
|
||||
|
||||
process.argv = ["node", "ao", "spawn", "demo"];
|
||||
emitActivityEventsDbUnavailableWarning(err);
|
||||
expect(console.warn).not.toHaveBeenCalled();
|
||||
|
||||
process.argv = ["node", "ao", "events", "stats"];
|
||||
emitActivityEventsDbUnavailableWarning(err);
|
||||
expect(console.warn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
@ -24,6 +24,7 @@ type BetterSqlite3Database = {
|
|||
let _db: BetterSqlite3Database | null = null;
|
||||
let _dbFailed = false;
|
||||
let _ftsEnabled = false;
|
||||
let _dbUnavailableWarningEmitted = false;
|
||||
const PRUNE_BATCH_SIZE = 1000;
|
||||
|
||||
function getEventsDbPath(): string {
|
||||
|
|
@ -90,14 +91,12 @@ function initFts(db: BetterSqlite3Database): void {
|
|||
}
|
||||
|
||||
function pruneOldEvents(db: BetterSqlite3Database, cutoff: number): void {
|
||||
db
|
||||
.prepare(
|
||||
`DELETE FROM activity_events
|
||||
db.prepare(
|
||||
`DELETE FROM activity_events
|
||||
WHERE rowid IN (
|
||||
SELECT rowid FROM activity_events WHERE ts_epoch < ? LIMIT ?
|
||||
)`,
|
||||
)
|
||||
.run(cutoff, PRUNE_BATCH_SIZE);
|
||||
).run(cutoff, PRUNE_BATCH_SIZE);
|
||||
}
|
||||
|
||||
function openDb(): BetterSqlite3Database {
|
||||
|
|
@ -161,6 +160,42 @@ export function closeDb(): void {
|
|||
_ftsEnabled = false;
|
||||
}
|
||||
|
||||
function isAoEventsInvocation(argv = process.argv): boolean {
|
||||
return argv.slice(2).includes("events");
|
||||
}
|
||||
|
||||
function isMissingBetterSqlite3Binding(err: unknown): boolean {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
return (
|
||||
message.includes("Could not locate the bindings file") ||
|
||||
message.includes("better_sqlite3.node") ||
|
||||
message.includes("Cannot find module 'better-sqlite3'")
|
||||
);
|
||||
}
|
||||
|
||||
function firstErrorLine(err: unknown): string {
|
||||
return (err instanceof Error ? err.message : String(err)).split(/\r?\n/, 1)[0] ?? "unknown error";
|
||||
}
|
||||
|
||||
export function formatActivityEventsDbUnavailableWarning(err: unknown): string {
|
||||
if (isMissingBetterSqlite3Binding(err)) {
|
||||
return `[ao] activity-events disabled: better-sqlite3 not compiled for Node ${process.version} (ABI v${process.versions.modules}). Run \`pnpm rebuild better-sqlite3\` or use a supported Node version.`;
|
||||
}
|
||||
return `[ao] activity-events disabled: better-sqlite3 failed to load: ${firstErrorLine(err)}`;
|
||||
}
|
||||
|
||||
export function emitActivityEventsDbUnavailableWarning(err: unknown): void {
|
||||
if (_dbUnavailableWarningEmitted) return;
|
||||
if (process.env["AO_DEBUG"] !== "1" && !isAoEventsInvocation()) return;
|
||||
_dbUnavailableWarningEmitted = true;
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(formatActivityEventsDbUnavailableWarning(err));
|
||||
}
|
||||
|
||||
export function __resetActivityEventsDbWarningForTests(): void {
|
||||
_dbUnavailableWarningEmitted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lazily-initialized DB connection.
|
||||
* Returns null if better-sqlite3 failed to load or init — callers should treat null as no-op.
|
||||
|
|
@ -173,8 +208,7 @@ export function getDb(): BetterSqlite3Database | null {
|
|||
return _db;
|
||||
} catch (err) {
|
||||
_dbFailed = true;
|
||||
// Log once so operators know events are being dropped; subsequent calls return null silently.
|
||||
console.warn("[ao] activity-events DB unavailable — events will be dropped:", err instanceof Error ? err.message : String(err));
|
||||
emitActivityEventsDbUnavailableWarning(err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,8 +163,8 @@ importers:
|
|||
version: 3.25.76
|
||||
optionalDependencies:
|
||||
better-sqlite3:
|
||||
specifier: ^11.0.0
|
||||
version: 11.10.0
|
||||
specifier: ^12.10.0
|
||||
version: 12.10.0
|
||||
devDependencies:
|
||||
'@rollup/plugin-typescript':
|
||||
specifier: ^12.3.0
|
||||
|
|
@ -2352,8 +2352,9 @@ packages:
|
|||
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
better-sqlite3@11.10.0:
|
||||
resolution: {integrity: sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==}
|
||||
better-sqlite3@12.10.0:
|
||||
resolution: {integrity: sha512-CyzaZRQKyHkB2ZInfTTl2nvT33EbDpjkLEbE8/Zck3Ll6O0qqvuGdrJ45HgtH+HykRg88ITY3AdreBGN70aBSQ==}
|
||||
engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x || 26.x}
|
||||
|
||||
bindings@1.5.0:
|
||||
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
|
||||
|
|
@ -5917,7 +5918,7 @@ snapshots:
|
|||
dependencies:
|
||||
is-windows: 1.0.2
|
||||
|
||||
better-sqlite3@11.10.0:
|
||||
better-sqlite3@12.10.0:
|
||||
dependencies:
|
||||
bindings: 1.5.0
|
||||
prebuild-install: 7.1.3
|
||||
|
|
|
|||
Loading…
Reference in New Issue