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
3 changes: 3 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
<title>SQLite Wasm Demo</title>
<script type="module" src="script.js"></script>
<script type="module" src="main-thread.js"></script>
<script type="module" src="sqlite-client.js"></script>
</head>
<body>
<h1>SQLite Wasm Demo</h1>
<h2>Main thread</h2>
<div class="main-thread"></div>
<h2>Worker</h2>
<div class="worker"></div>
<h2>Built-in SQLite Client</h2>
<div id="sqlite-client"></div>
</body>
</html>
28 changes: 28 additions & 0 deletions demo/sqlite-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import SqliteClient from '/src/sqlite.client.mjs';

const sqliteClient = new SqliteClient('/db.sqlite3', '/src/sqlite.worker.mjs');

await sqliteClient.init();

await sqliteClient.executeSql('CREATE TABLE IF NOT EXISTS t(a,b)');

for (let i = 20; i <= 25; ++i) {
await sqliteClient.executeSql('INSERT INTO t(a,b) VALUES (?,?)', [i, i * 2]);
}

const rows = await sqliteClient.executeSql(
'SELECT a FROM t ORDER BY a LIMIT 3',
);

console.log(rows);

document.getElementById('sqlite-client').innerHTML =
'<table>' +
'<thead>' +
'<tr>' +
'<th>a</th>' +
'</tr>' +
'</thead>' +
'<tbody>' +
rows.map((row) => '<tr><td> ' + row[0] + '</td></tr>').concat();
'</tbody>' + '</table>';
8 changes: 8 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,8 @@
"prettier": "^2.8.8",
"publint": "^0.1.12",
"shx": "^0.3.4"
},
"dependencies": {
"comlink": "^4.4.1"
}
}
70 changes: 70 additions & 0 deletions src/sqlite-client.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const log = (...args) => console.log(...args);
const error = (...args) => console.error(...args);

export default class SqliteClient {
sqliteWorker;

dbFile = '';
sqliteWorkerPath = '';

constructor(dbFile, sqliteWorkerPath) {
if (typeof dbFile !== 'string') {
return error(
"The 'dbFile' parameter passed to the SqliteClient constructor must be of type 'string'. Instead, you passed: '" +
typeof dbFile +
"'",
);
}

if (typeof sqliteWorkerPath !== 'string') {
return error(
"The 'sqliteWorkerPath' parameter passed to the SqliteClient constructor must be of type 'string'. Instead, you passed: '" +
typeof sqliteWorkerPath +
"'",
);
}

this.dbFile = dbFile;
this.sqliteWorkerPath = sqliteWorkerPath;
}

async init() {
const SqliteWorker = Comlink.wrap(
new Worker(this.sqliteWorkerPath, {
type: 'module',
}),
);

this.sqliteWorker = await new SqliteWorker();

await this.sqliteWorker.init(this.dbFile);
}

async executeSql(sqlStatement, bindParameters = []) {
if (typeof sqlStatement !== 'string') {
return error(
"The 'sqlStatement' parameter passed to the 'executeSql' method of the SqliteClient must be of type 'string'. Instead, you passed: '" +
typeof sqlStatement +
"'",
);
}

if (!Array.isArray(bindParameters)) {
return error(
"The 'bindParameters' parameter passed to the 'executeSql' method of the SqliteClient must be of type 'array'. Instead, you passed: '" +
typeof bindParameters +
"'",
);
}

return new Promise(async (resolve) => {
await this.sqliteWorker.executeSql(
sqlStatement,
bindParameters,
Comlink.proxy((rows) => {
return resolve(rows);
}),
);
});
}
}
38 changes: 38 additions & 0 deletions src/sqlite-worker.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as Comlink from 'https://unpkg.com/comlink/dist/esm/comlink.mjs';
import { default as sqlite3InitModule } from '../index.mjs';

const log = (...args) => console.log(...args);
const error = (...args) => console.error(...args);

class SqliteWorker {
db;
init(dbFile) {
return new Promise((resolve) => {
sqlite3InitModule({
print: log,
printErr: error,
}).then((sqlite3) => {
try {
this.db = new sqlite3.oo1.OpfsDb(dbFile);
} catch (err) {
error(err.name, err.message);
}

return resolve();
});
});
}

executeSql(sqlStatement, bindParameters, callback) {
return callback(
this.db.exec({
sql: sqlStatement,
bind: bindParameters,
returnValue: 'resultRows',
rowMode: 'array',
}),
);
}
}

Comlink.expose(SqliteWorker);