Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slimy-toys-wear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"sqlseal": patch
---

fixing issue with new wa-sqlite on mobile
34 changes: 7 additions & 27 deletions esbuild.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -98,39 +98,16 @@ const workerPlugin = {
}));

build.onLoad({ filter: /.*/, namespace: 'sqlocal-worker-code' }, async () => {
// Create a plugin for the worker that resolves virtual imports
const workerVirtualPlugin = {
name: 'worker-virtual',
setup(build) {
// Handle virtual WASM URL for wa-sqlite
build.onResolve({ filter: /^virtual:wa-sqlite-wasm-url$/ }, args => ({
path: args.path,
namespace: 'wa-sqlite-wasm-url',
}));

build.onLoad({ filter: /.*/, namespace: 'wa-sqlite-wasm-url' }, async () => {
const wasmPath = join(process.cwd(), 'node_modules/wa-sqlite/dist/wa-sqlite-async.wasm');
const wasmContents = readFileSync(wasmPath);
const wasmBase64 = wasmContents.toString('base64');
const wasmDataUrl = `data:application/wasm;base64,${wasmBase64}`;

return {
contents: `export default ${JSON.stringify(wasmDataUrl)};`,
loader: 'js',
};
});
}
};

// Build sqlocal worker code
// WASM binary is NOT embedded in the worker — it's passed from the main thread via Comlink
const result = await esbuild.build({
entryPoints: ['src/modules/database/sqlocal/sqlocalWorkerDatabase.ts'],
bundle: true,
write: false,
format: 'iife',
target: 'es2020',
external: ['fs', 'path', 'obsidian'],
plugins: [wasmPlugin, workerVirtualPlugin, polyfillNode({
plugins: [wasmPlugin, polyfillNode({
})],
minify: process.argv[2] === 'production',
define: {
Expand Down Expand Up @@ -158,10 +135,13 @@ const workerPlugin = {
const wasmPath = join(process.cwd(), 'node_modules/wa-sqlite/dist/wa-sqlite-async.wasm');
const wasmContents = readFileSync(wasmPath);
const wasmBase64 = wasmContents.toString('base64');
const wasmDataUrl = `data:application/wasm;base64,${wasmBase64}`;

return {
contents: `export default ${JSON.stringify(wasmDataUrl)};`,
contents: `
const wasmBase64 = "${wasmBase64}";
const wasmBinary = Uint8Array.from(atob(wasmBase64), c => c.charCodeAt(0));
export default wasmBinary;
`,
loader: 'js',
};
});
Expand Down
3 changes: 2 additions & 1 deletion src/modules/database/sqlocal/databaseProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ export class DatabaseProvider {
constructor(private app: App) { }

get prefix() {
const appId = ((this.app as any).appId ?? '').replace(/[^a-zA-Z0-9_-]/g, '_');
const filename = `sqlseal_1__` +
sanitise(this.app.vault.getName()) + "___" + (this.app as any).appId;
sanitise(this.app.vault.getName()) + "___" + appId;
return filename;
}

Expand Down
4 changes: 3 additions & 1 deletion src/modules/database/sqlocal/sqlocalDatabaseProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as Comlink from 'comlink';
import { SqlocalWorkerDatabase } from "./sqlocalWorkerDatabase";
import { ColumnDefinition } from "../../../utils/types";
import { sanitise } from "../../../utils/sanitiseColumn";
// @ts-ignore
import wasmBinary from 'virtual:wa-sqlite-wasm-url';

/**
* Main-thread proxy for SqlocalWorkerDatabase.
Expand Down Expand Up @@ -49,7 +51,7 @@ export class SqlocalDatabaseProxy {

const instance = await new DatabaseWrap(this.dbName);

await instance.connect();
await instance.connect(wasmBinary);

this.db = instance;
this.isConnected = true;
Expand Down
23 changes: 9 additions & 14 deletions src/modules/database/sqlocal/sqlocalWorkerDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import { IDBBatchAtomicVFS } from 'wa-sqlite/src/examples/IDBBatchAtomicVFS.js';
import { ColumnDefinition } from "../../../utils/types";
import { sanitise } from "../../../utils/sanitiseColumn";

// Get the WASM URL from the virtual module
// @ts-ignore
import wasmUrl from 'virtual:wa-sqlite-wasm-url';

/**
* Retry an async operation with exponential backoff
* @param operation - The async operation to retry
Expand Down Expand Up @@ -70,6 +66,7 @@ export class SqlocalWorkerDatabase {
private isConnected = false;
private vfsRegistered = false;
private isRecreating = false;
private wasmBinary?: Uint8Array;

constructor(private readonly dbName: string) {
}
Expand Down Expand Up @@ -109,16 +106,12 @@ export class SqlocalWorkerDatabase {
return this.sqlite3;
}

if (!this.wasmBinary) {
throw new Error('SqlocalWorkerDatabase: wasmBinary not provided. Call connect() with the WASM binary.');
}

try {
// Initialize the module with bundled WASM
const asyncModule = await SQLiteAsyncESMFactory({
locateFile: (file: string) => {
if (file.endsWith('.wasm')) {
return wasmUrl;
}
return file;
}
});
const asyncModule = await SQLiteAsyncESMFactory({ wasmBinary: this.wasmBinary, locateFile: (file: string) => file });

// Use Factory to get the actual sqlite3 API
this.sqlite3 = SQLite.Factory(asyncModule);
Expand Down Expand Up @@ -148,11 +141,13 @@ export class SqlocalWorkerDatabase {
}
}

async connect() {
async connect(wasmBinary: Uint8Array) {
if (this.isConnected) {
return Promise.resolve();
}

this.wasmBinary = wasmBinary;

try {
// Initialize SQLite
await this.initializeSQLite();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Mock for virtual:wa-sqlite-wasm-url used in tests
// Returns a file:// URL that works with the fetch polyfill in jest.setup.mjs
// Returns the WASM binary as Uint8Array (same as production build)

import { join } from 'path';
import { pathToFileURL } from 'url';
import { readFileSync } from 'fs';

const wasmPath = join(process.cwd(), 'node_modules/wa-sqlite/dist/wa-sqlite-async.wasm');
const wasmUrl = pathToFileURL(wasmPath).href;
const wasmBinary = new Uint8Array(readFileSync(wasmPath));

export default wasmUrl;
export default wasmBinary;
12 changes: 2 additions & 10 deletions src/modules/explorer/database/waSqliteMemoryDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import SQLiteAsyncESMFactory from 'wa-sqlite/dist/wa-sqlite-async.mjs';
import * as SQLite from 'wa-sqlite';
import { MemoryAsyncVFS } from 'wa-sqlite/src/examples/MemoryAsyncVFS.js';
// @ts-ignore - Virtual module from esbuild
import wasmUrl from 'virtual:wa-sqlite-wasm-url';
import wasmBinary from 'virtual:wa-sqlite-wasm-url';

type ParamsObject = Record<string, any>;

Expand Down Expand Up @@ -33,15 +33,7 @@ export class WaSqliteMemoryDatabase {
throw new Error('Invalid SQLite database file format');
}

// Initialize wa-sqlite
const asyncModule = await SQLiteAsyncESMFactory({
locateFile: (file: string) => {
if (file.endsWith('.wasm')) {
return wasmUrl;
}
return file;
}
});
const asyncModule = await SQLiteAsyncESMFactory({ wasmBinary, locateFile: (file: string) => file });

this.sqlite3 = SQLite.Factory(asyncModule);

Expand Down
Loading