as-app/src/db/openDbExpoSqlite.js
2026-03-07 07:53:08 +01:00

87 lines
2.5 KiB
JavaScript

// Expo SQLite wrapper (require-safe, Metro/Hermes friendly).
//
// Requirements from runtime backend selection:
// - Must NOT crash at module evaluation time when ExpoSQLite native module is missing.
// - Must be safe to load via `require('./openDbExpoSqlite')` under Metro/Hermes.
// - Must export a callable `openDbExpoSqlite()` function via CommonJS exports.
//
// IMPORTANT: Do NOT use top-level `import` from expo-sqlite here.
function describeKeys(x) {
if (!x) return [];
const t = typeof x;
if (t !== "object" && t !== "function") return [];
try {
return Object.keys(x);
} catch {
return [];
}
}
function requireExpoSqlite() {
// Lazily require so missing native module does not crash at module evaluation time.
// eslint-disable-next-line global-require
const mod = require("expo-sqlite");
const candidate = mod?.default ?? mod;
const openDatabaseAsync =
candidate?.openDatabaseAsync ??
mod?.openDatabaseAsync ??
mod?.default?.openDatabaseAsync;
const openDatabase =
candidate?.openDatabase ?? mod?.openDatabase ?? mod?.default?.openDatabase;
return {
mod,
candidate,
openDatabaseAsync,
openDatabase,
};
}
/**
* Open an expo-sqlite database using whichever API exists.
*
* @param {string} dbName
* @returns {Promise<any>} SQLiteDatabase (new API) or legacy Database (sync open)
*/
async function openDbExpoSqlite(dbName) {
const api = requireExpoSqlite();
if (typeof api.openDatabaseAsync === "function") {
return api.openDatabaseAsync(dbName);
}
if (typeof api.openDatabase === "function") {
// Legacy expo-sqlite API (sync open)
return api.openDatabase(dbName);
}
const modKeys = describeKeys(api.mod);
const defaultKeys = describeKeys(api.mod?.default);
const candidateKeys = describeKeys(api.candidate);
const err = new TypeError(
[
"expo-sqlite require() did not expose openDatabaseAsync nor openDatabase.",
`module typeof=${typeof api.mod} keys=[${modKeys.join(", ")}].`,
`default typeof=${typeof api.mod?.default} keys=[${defaultKeys.join(
", ",
)}].`,
`candidate typeof=${typeof api.candidate} keys=[${candidateKeys.join(
", ",
)}].`,
].join(" "),
);
err.expoSqliteModuleKeys = modKeys;
err.expoSqliteDefaultKeys = defaultKeys;
err.expoSqliteCandidateKeys = candidateKeys;
throw err;
}
// Explicit CommonJS export shape (so require() always returns a non-null object).
module.exports = {
__esModule: true,
openDbExpoSqlite,
openDb: openDbExpoSqlite,
default: openDbExpoSqlite,
};