@vanillaspa/sqlite-database 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +19 -13
- package/package.json +4 -2
- package/sqliteWorker.js +31 -25
package/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
|
|
2
|
-
|
|
3
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
|
|
2
|
+
import { addEventListener, dispatchEvent } from '@vanillaspa/event-bus';
|
|
4
3
|
|
|
5
4
|
if (!window.Worker) throw new Error(`Your browser doesn't support web workers.`);
|
|
6
5
|
export const name = "sqlite"; // module name
|
|
@@ -27,7 +26,6 @@ function initializeWorker(name) {
|
|
|
27
26
|
|
|
28
27
|
function enqueue(worker, payload) {
|
|
29
28
|
const { port1, port2 } = new MessageChannel();
|
|
30
|
-
|
|
31
29
|
return new Promise((resolve, reject) => {
|
|
32
30
|
port1.onmessage = ({ data }) => {
|
|
33
31
|
port1.close();
|
|
@@ -39,34 +37,32 @@ function enqueue(worker, payload) {
|
|
|
39
37
|
port1.close();
|
|
40
38
|
reject(new Error('MessageChannel deserialization error'));
|
|
41
39
|
};
|
|
42
|
-
|
|
43
40
|
worker.postMessage(payload, [port2]);
|
|
44
41
|
})
|
|
45
42
|
}
|
|
46
43
|
|
|
47
44
|
// Public API
|
|
48
|
-
export function downloadDB(name = 'default') {
|
|
49
|
-
getWorker(name).postMessage({ action: 'downloadDB' });
|
|
50
|
-
}
|
|
51
|
-
|
|
52
45
|
export function createDB(name = 'default') {
|
|
53
|
-
initializeWorker(name);
|
|
46
|
+
initializeWorker(name);
|
|
54
47
|
return enqueue(getWorker(name), { action: 'createDB', name });
|
|
55
48
|
}
|
|
56
49
|
|
|
57
50
|
export async function deleteAndTerminateDB(name) {
|
|
58
51
|
const worker = getWorker(name);
|
|
59
|
-
|
|
60
52
|
await enqueue(worker, { action: 'closeDB' })
|
|
61
|
-
|
|
62
53
|
const root = await navigator.storage.getDirectory();
|
|
63
54
|
const fileHandle = await root.getFileHandle(`${name}.sqlite3`).catch(() => null);
|
|
64
55
|
if (fileHandle) await fileHandle.remove();
|
|
65
|
-
|
|
66
56
|
worker.terminate();
|
|
67
57
|
workers.delete(name);
|
|
68
58
|
}
|
|
69
59
|
|
|
60
|
+
export function downloadDB(name = 'default') {
|
|
61
|
+
enqueue(getWorker(name), { action: 'downloadDB' }).then(blob => {
|
|
62
|
+
dispatchEvent(new CustomEvent('sqlite:download', { detail: { blob, name } }))
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
70
66
|
export function executeQuery(sql, name = 'default') {
|
|
71
67
|
return enqueue(getWorker(name), { action: "executeQuery", sql });
|
|
72
68
|
}
|
|
@@ -85,7 +81,7 @@ export function uploadDB(fileName, arrayBuffer) {
|
|
|
85
81
|
}
|
|
86
82
|
|
|
87
83
|
export function terminate(name = 'default') {
|
|
88
|
-
|
|
84
|
+
const worker = workers.get(name);
|
|
89
85
|
if (worker) {
|
|
90
86
|
worker.terminate();
|
|
91
87
|
workers.delete(name);
|
|
@@ -95,3 +91,13 @@ export function terminate(name = 'default') {
|
|
|
95
91
|
export function getWorkers() {
|
|
96
92
|
return workers;
|
|
97
93
|
}
|
|
94
|
+
|
|
95
|
+
addEventListener('sqlite:download', (event) => {
|
|
96
|
+
const { blob, name } = event.detail;
|
|
97
|
+
const url = URL.createObjectURL(blob);
|
|
98
|
+
const a = document.createElement('a');
|
|
99
|
+
a.href = url;
|
|
100
|
+
a.download = `${name}.sqlite3`;
|
|
101
|
+
a.click();
|
|
102
|
+
URL.revokeObjectURL(url);
|
|
103
|
+
});
|
package/package.json
CHANGED
|
@@ -5,11 +5,13 @@
|
|
|
5
5
|
},
|
|
6
6
|
"description": "A serverless SQLite database inside your browser.",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@sqlite.org/sqlite-wasm":"^3.51.2-build6"
|
|
8
|
+
"@sqlite.org/sqlite-wasm":"^3.51.2-build6",
|
|
9
|
+
"@vanillaspa/event-bus": "1.1.0"
|
|
9
10
|
},
|
|
10
11
|
"homepage": "https://github.com/vanillaspa/sqlite-database#readme",
|
|
11
12
|
"keywords": [
|
|
12
13
|
"Database",
|
|
14
|
+
"EventBus",
|
|
13
15
|
"JavaScript",
|
|
14
16
|
"OPFS",
|
|
15
17
|
"SPA",
|
|
@@ -28,5 +30,5 @@
|
|
|
28
30
|
"url": "git+https://github.com/vanillaspa/sqlite-database.git"
|
|
29
31
|
},
|
|
30
32
|
"type": "module",
|
|
31
|
-
"version": "1.
|
|
33
|
+
"version": "1.2.0"
|
|
32
34
|
}
|
package/sqliteWorker.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
|
|
2
|
+
import { dispatchEvent } from '@vanillaspa/event-bus';
|
|
2
3
|
|
|
3
4
|
let db = null;
|
|
4
5
|
let sqlite3 = null;
|
|
@@ -10,15 +11,17 @@ async function getInstance() {
|
|
|
10
11
|
return sqlite3;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
function reply(result) {
|
|
14
|
-
postMessage({ type: 'application/json', result });
|
|
14
|
+
function reply(port, result) {
|
|
15
|
+
port.postMessage({ type: 'application/json', result });
|
|
16
|
+
port.close();
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
function replyError(message) {
|
|
18
|
-
postMessage({ type: 'error', message });
|
|
20
|
+
port.postMessage({ type: 'error', message });
|
|
21
|
+
port.close();
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
function handleSQLiteError(sql, e) {
|
|
24
|
+
function handleSQLiteError(port, sql, e) {
|
|
22
25
|
if (e.message.includes('SQLITE_CANTOPEN')) {
|
|
23
26
|
console.info("Info: No SQLite database available. Upload a new database or reload the page.");
|
|
24
27
|
} else if (e.message.includes('SQLITE_CONSTRAINT_UNIQUE')) {
|
|
@@ -26,40 +29,43 @@ function handleSQLiteError(sql, e) {
|
|
|
26
29
|
} else {
|
|
27
30
|
console.error("Error executing SQL_", sql, e.message);
|
|
28
31
|
}
|
|
29
|
-
replyError(e.message);
|
|
32
|
+
replyError(port, e.message);
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
onmessage = async function ({ data }) {
|
|
35
|
+
onmessage = async function ({ data, ports }) {
|
|
33
36
|
const { action } = data;
|
|
37
|
+
const port = ports[0] ?? null;
|
|
38
|
+
|
|
34
39
|
switch (action) {
|
|
35
|
-
case '
|
|
40
|
+
case 'createDB': {
|
|
41
|
+
const { name } = data;
|
|
36
42
|
try {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
const { newDB, message } = await createDatabase(name)
|
|
44
|
+
db = newDB;
|
|
45
|
+
reply(port, message);
|
|
40
46
|
} catch (e) {
|
|
41
|
-
|
|
47
|
+
replyError(port, e.message)
|
|
42
48
|
}
|
|
43
49
|
break;
|
|
44
50
|
}
|
|
45
|
-
case '
|
|
46
|
-
const { name } = data;
|
|
51
|
+
case 'downloadDB': {
|
|
47
52
|
try {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
reply(
|
|
53
|
+
const byteArray = sqlite3.capi.sqlite3_js_db_export(db);
|
|
54
|
+
const blob = new Blob([byteArray.buffer], { type: "application/vnd.sqlite3" });
|
|
55
|
+
reply(port, blob);
|
|
51
56
|
} catch (e) {
|
|
52
|
-
replyError(e.message)
|
|
57
|
+
replyError(port, e.message);
|
|
53
58
|
}
|
|
54
59
|
break;
|
|
55
60
|
}
|
|
61
|
+
|
|
56
62
|
case 'executeQuery': {
|
|
57
63
|
const { sql } = data;
|
|
58
64
|
try {
|
|
59
65
|
const result = db.exec({ sql, returnValue: "resultRows" });
|
|
60
|
-
reply(result);
|
|
66
|
+
reply(port, result);
|
|
61
67
|
} catch (e) {
|
|
62
|
-
handleSQLiteError(sql, e)
|
|
68
|
+
handleSQLiteError(port, sql, e)
|
|
63
69
|
}
|
|
64
70
|
break;
|
|
65
71
|
}
|
|
@@ -75,9 +81,9 @@ onmessage = async function ({ data }) {
|
|
|
75
81
|
const row = stmt.get([]);
|
|
76
82
|
result.push(Object.fromEntries(columns.map((columnName, index) => [columnName, row[index]])));
|
|
77
83
|
}
|
|
78
|
-
reply(result);
|
|
84
|
+
reply(port, result);
|
|
79
85
|
} catch (e) {
|
|
80
|
-
handleSQLiteError(sql, e);
|
|
86
|
+
handleSQLiteError(port, sql, e);
|
|
81
87
|
} finally {
|
|
82
88
|
stmt?.finalize();
|
|
83
89
|
}
|
|
@@ -87,18 +93,18 @@ onmessage = async function ({ data }) {
|
|
|
87
93
|
const { name, arrayBuffer } = data;
|
|
88
94
|
try {
|
|
89
95
|
const message = await uploadDatabase(name, arrayBuffer)
|
|
90
|
-
reply(message);
|
|
96
|
+
reply(port, message);
|
|
91
97
|
} catch (e) {
|
|
92
|
-
replyError(e.message);
|
|
98
|
+
replyError(port, e.message);
|
|
93
99
|
}
|
|
94
100
|
break;
|
|
95
101
|
}
|
|
96
102
|
case 'closeDB': {
|
|
97
103
|
try {
|
|
98
104
|
closeDB();
|
|
99
|
-
reply(null);
|
|
105
|
+
reply(port, null);
|
|
100
106
|
} catch (e) {
|
|
101
|
-
replyError(e.message);
|
|
107
|
+
replyError(port, e.message);
|
|
102
108
|
}
|
|
103
109
|
break;
|
|
104
110
|
}
|