Adding SQLite Database Integration to an Obsidian Plugin

I was able to get SQLite to work by using Libsql. It is a fork of SQLite that is used for some additional use cases.

To do this I need to manage the native node addons myself. So I download the .node binding files into the plugin directory and I use the module-alias package to patch the module path to the plugin’s download path. This is because the electron runtime won’t have these dependencies.

Here’s a snippet of that plugin code:

export default class MyPlugin extends Plugin {
	settings: MyPluginSettings;
	_dbClient: Client | null = null;
	currentFilePath: string = path.join(__dirname, 'main.ts');
	__fsAdapter: FileSystemAdapter;
	__pluginDirectory: string;
	__libsqlModule: any;

	constructor(app: App, manifest: any) {
		super(app, manifest);
		this.__fsAdapter = app.vault.adapter as FileSystemAdapter;
		this.__pluginDirectory = `${this.__fsAdapter.getBasePath()}/${this.manifest.dir}/`;
		const libsqlBinaryName = 'libsql-darwin-arm64.node';

		// Define the expected path for the binary
		const customBinaryPath = path.resolve(`${this.__pluginDirectory}/${libsqlBinaryName}`);

		// Remap the binary resolution, not shown: downloading the right binary module.
		moduleAlias.addAlias('@libsql/darwin-arm64', customBinaryPath);
		this.__libsqlModule = require("@libsql/client");

	}

Once I tell it where to look for the binary I can require the client library dynamically and start using it like this.

...
client= this.__libsqlModule.createClient({
	url: `file:${this.__pluginDirectory}kb.db`
});

This is from a debug button I made to test this out. Don’t judge the promise hell, I was in a hurry :slight_smile: :

			this.getDbClient().then((dbClient) => {
				dbClient?.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)").then(() => {
					dbClient?.execute("SELECT * FROM users").then((result) => {
						if (result.rows.length === 0) {
							return dbClient?.execute("INSERT INTO users (id, name, email) VALUES (1, 'Alice', '[email protected]')");
						}
					}).then(() => {
						return dbClient?.execute("SELECT * FROM users WHERE id = 1");
					}).then((result) => {
						const row = result.rows[0];
						console.log(`Name: ${row.name}, email: ${row.email}`);
					}).catch((error) => {
						console.error('Error executing query:', error);
					});
				});
			});

Not shown is needing to download the right binary for the platform youre on.