Files
abode/src/meta/pack/natives.ts
T
2026-06-29 23:07:14 +00:00

66 lines
1.7 KiB
TypeScript

import { readdir, stat } from "node:fs/promises";
import { join, dirname } from "node:path";
import { createRequire } from "node:module";
async function find(path: string, name: string): Promise<string | null> {
for (const file of await readdir(path, { withFileTypes: true })) {
if (file.isDirectory()) {
const found = await find(join(file.parentPath, file.name), name);
if (found) return found;
} else if (file.isFile()) {
if (file.name === name) return join(file.parentPath, file.name);
}
}
return null;
}
async function isFile(path: string): Promise<boolean> {
try {
const st = await stat(path);
return st.isFile();
} catch {
return false;
}
}
async function getPackageJsonDir(path: string): Promise<string | null> {
if (await isFile(join(path, "package.json"))) return path;
const next = dirname(path);
if (next === path) return null;
return getPackageJsonDir(next);
}
export async function findNative(
module: string,
native: string
): Promise<string> {
const path = await getPackageJsonDir(
createRequire(import.meta.url).resolve(module)
);
if (!path) throw new Error(`Cannot find module directory for ${module}`);
const file = await find(path, native);
if (!file)
throw new Error(
`Cannot find native ${native} of package ${module} in ${path}`
);
return file;
}
export async function tryFindNative(
module: string,
native: string
): Promise<string | null> {
try {
return await findNative(module, native);
} catch (e) {
console.warn(e);
return null;
}
}
export async function findNatives(): Promise<typeof natives> {
return {
sqlite: await tryFindNative("better-sqlite3", "better_sqlite3.node"),
};
}