Skip to content

Commit 6061759

Browse files
committed
Merge branch 'main' into node
2 parents ce9e7fd + beff9fe commit 6061759

File tree

14 files changed

+272
-306
lines changed

14 files changed

+272
-306
lines changed

README.md

Lines changed: 85 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,41 +20,71 @@ npm install @sqlite.org/sqlite-wasm
2020

2121
## Usage
2222

23-
There are two ways to use SQLite Wasm:
24-
[in the main thread](#in-the-main-thread-without-opfs) and
25-
[in a worker](#in-a-worker-with-opfs-if-available). Only the worker version
26-
allows you to use the origin private file system (OPFS) storage back-end.
23+
There are three ways to use SQLite Wasm:
2724

28-
### In the main thread (without OPFS):
25+
- [in the main thread with a wrapped worker](#in-a-wrapped-worker-with-opfs-if-available)
26+
(🏆 preferred option)
27+
- [in a worker](#in-a-worker-with-opfs-if-available)
28+
- [in the main thread](#in-the-main-thread-without-opfs)
29+
30+
Only the worker versions allow you to use the origin private file system (OPFS)
31+
storage back-end.
32+
33+
### In a wrapped worker (with OPFS if available):
34+
35+
> **Warning**
36+
>
37+
> For this to work, you need to set the following headers on your server:
38+
>
39+
> `Cross-Origin-Opener-Policy: same-origin`
40+
>
41+
> `Cross-Origin-Embedder-Policy: require-corp`
2942
3043
```js
31-
import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
44+
import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';
3245

3346
const log = (...args) => console.log(...args);
3447
const error = (...args) => console.error(...args);
3548

36-
const start = function (sqlite3) {
37-
log('Running SQLite3 version', sqlite3.version.libVersion);
38-
const db = new sqlite3.oo1.DB('/mydb.sqlite3', 'ct');
39-
// Your SQLite code here.
40-
};
41-
42-
log('Loading and initializing SQLite3 module...');
43-
sqlite3InitModule({
44-
print: log,
45-
printErr: error,
46-
}).then((sqlite3) => {
49+
(async () => {
4750
try {
51+
log('Loading and initializing SQLite3 module...');
52+
53+
const promiser = await new Promise((resolve) => {
54+
const _promiser = sqlite3Worker1Promiser({
55+
onready: () => {
56+
resolve(_promiser);
57+
},
58+
});
59+
});
60+
4861
log('Done initializing. Running demo...');
49-
start(sqlite3);
62+
63+
let response;
64+
65+
response = await promiser('config-get', {});
66+
log('Running SQLite3 version', response.result.version.libVersion);
67+
68+
response = await promiser('open', {
69+
filename: 'file:mydb.sqlite3?vfs=opfs',
70+
});
71+
const { dbId } = response;
72+
log(
73+
'OPFS is available, created persisted database at',
74+
response.result.filename.replace(/^file:(.*?)\?vfs=opfs$/, '$1'),
75+
);
76+
// Your SQLite code here.
5077
} catch (err) {
78+
if (!(err instanceof Error)) {
79+
err = new Error(err.result.message);
80+
}
5181
error(err.name, err.message);
5282
}
53-
});
83+
})();
5484
```
5585

56-
The `db` object above implements the
57-
[Object Oriented API #1](https://sqlite.org/wasm/doc/trunk/api-oo1.md).
86+
The `promiser` object above implements the
87+
[Worker1 API](https://sqlite.org/wasm/doc/trunk/api-worker1.md#worker1-methods).
5888

5989
### In a worker (with OPFS if available):
6090

@@ -105,6 +135,40 @@ sqlite3InitModule({
105135
});
106136
```
107137

138+
The `db` object above implements the
139+
[Object Oriented API #1](https://sqlite.org/wasm/doc/trunk/api-oo1.md).
140+
141+
### In the main thread (without OPFS):
142+
143+
```js
144+
import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
145+
146+
const log = (...args) => console.log(...args);
147+
const error = (...args) => console.error(...args);
148+
149+
const start = function (sqlite3) {
150+
log('Running SQLite3 version', sqlite3.version.libVersion);
151+
const db = new sqlite3.oo1.DB('/mydb.sqlite3', 'ct');
152+
// Your SQLite code here.
153+
};
154+
155+
log('Loading and initializing SQLite3 module...');
156+
sqlite3InitModule({
157+
print: log,
158+
printErr: error,
159+
}).then((sqlite3) => {
160+
try {
161+
log('Done initializing. Running demo...');
162+
start(sqlite3);
163+
} catch (err) {
164+
error(err.name, err.message);
165+
}
166+
});
167+
```
168+
169+
The `db` object above implements the
170+
[Object Oriented API #1](https://sqlite.org/wasm/doc/trunk/api-oo1.md).
171+
108172
## Usage with vite
109173

110174
If you are using [vite](https://vitejs.dev/), you need to add the following

bin/index.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import fs from 'fs';
22
import fetch from 'node-fetch';
3-
import * as cheerio from 'cheerio';
43
import decompress from 'decompress';
54

65
async function getSqliteWasmDownloadLink() {
76
const response = await fetch('https://sqlite.org/download.html');
87
const html = await response.text();
9-
const $ = cheerio.load(html);
10-
const fileName = $('a[name="wasm"]').closest('tr').next().find('a').text();
11-
const sqliteWasmLink = `https://sqlite.org/${new Date().getFullYear()}/${fileName}`;
8+
const sqliteWasmLink =
9+
'https://sqlite.org/' +
10+
html
11+
.replace(
12+
/^.*?<!-- Download product data for scripts to read(.*?)-->.*?$/gms,
13+
'$1',
14+
)
15+
.split(/\n/)
16+
.filter((row) => /sqlite-wasm/.test(row))[0]
17+
.split(/,/)[2];
1218
console.log(`Found SQLite Wasm download link: ${sqliteWasmLink}`);
1319
return sqliteWasmLink;
1420
}
@@ -19,6 +25,11 @@ async function downloadAndUnzipSqliteWasm(sqliteWasmDownloadLink) {
1925
}
2026
console.log('Downloading and unzipping SQLite Wasm...');
2127
const response = await fetch(sqliteWasmDownloadLink);
28+
if (!response.ok || response.status !== 200) {
29+
throw new Error(
30+
`Unable to download SQLite Wasm from ${sqliteWasmDownloadLink}`,
31+
);
32+
}
2233
const buffer = await response.arrayBuffer();
2334
fs.writeFileSync('sqlite-wasm.zip', Buffer.from(buffer));
2435
const files = await decompress('sqlite-wasm.zip', 'sqlite-wasm', {
@@ -35,9 +46,9 @@ async function downloadAndUnzipSqliteWasm(sqliteWasmDownloadLink) {
3546
}
3647

3748
async function main() {
38-
const sqliteWasmLink = await getSqliteWasmDownloadLink();
39-
await downloadAndUnzipSqliteWasm(sqliteWasmLink);
4049
try {
50+
const sqliteWasmLink = await getSqliteWasmDownloadLink();
51+
await downloadAndUnzipSqliteWasm(sqliteWasmLink);
4152
fs.copyFileSync(
4253
'./node_modules/module-workers-polyfill/module-workers-polyfill.min.js',
4354
'./demo/module-workers-polyfill.min.js',

demo/index.html

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
<meta charset="utf-8" />
55
<title>SQLite Wasm Demo</title>
66
<script type="module" src="script.js"></script>
7+
<script type="module" src="wrapped-worker.js"></script>
78
<script type="module" src="main-thread.js"></script>
89
</head>
910
<body>
1011
<h1>SQLite Wasm Demo</h1>
11-
<h2>Main thread</h2>
12-
<div class="main-thread"></div>
12+
<h2>Wrapped Worker</h2>
13+
<div class="worker-promiser"></div>
1314
<h2>Worker</h2>
1415
<div class="worker"></div>
16+
<h2>Main thread</h2>
17+
<div class="main-thread"></div>
1518
</body>
1619
</html>

demo/wrapped-worker.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { sqlite3Worker1Promiser } from '../index.mjs';
2+
3+
(async () => {
4+
const container = document.querySelector('.worker-promiser');
5+
6+
const logHtml = function (cssClass, ...args) {
7+
const div = document.createElement('div');
8+
if (cssClass) div.classList.add(cssClass);
9+
div.append(document.createTextNode(args.join(' ')));
10+
container.append(div);
11+
};
12+
13+
try {
14+
logHtml('', 'Loading and initializing SQLite3 module...');
15+
16+
const promiser = await new Promise((resolve) => {
17+
const _promiser = sqlite3Worker1Promiser({
18+
onready: () => {
19+
resolve(_promiser);
20+
},
21+
});
22+
});
23+
24+
logHtml('', 'Done initializing. Running demo...');
25+
26+
let response;
27+
28+
response = await promiser('config-get', {});
29+
logHtml('', 'Running SQLite3 version', response.result.version.libVersion);
30+
31+
response = await promiser('open', {
32+
filename: 'file:worker-promiser.sqlite3?vfs=opfs',
33+
});
34+
const { dbId } = response;
35+
logHtml(
36+
'',
37+
'OPFS is available, created persisted database at',
38+
response.result.filename.replace(/^file:(.*?)\?vfs=opfs/, '$1'),
39+
);
40+
41+
await promiser('exec', { dbId, sql: 'CREATE TABLE IF NOT EXISTS t(a,b)' });
42+
logHtml('', 'Creating a table...');
43+
44+
logHtml('', 'Insert some data using exec()...');
45+
for (let i = 20; i <= 25; ++i) {
46+
await promiser('exec', {
47+
dbId,
48+
sql: 'INSERT INTO t(a,b) VALUES (?,?)',
49+
bind: [i, i * 2],
50+
});
51+
}
52+
53+
logHtml('', 'Query data with exec()');
54+
await promiser('exec', {
55+
dbId,
56+
sql: 'SELECT a FROM t ORDER BY a LIMIT 3',
57+
callback: (result) => {
58+
if (!result.row) {
59+
return;
60+
}
61+
logHtml('', result.row);
62+
},
63+
});
64+
65+
await promiser('close', { dbId });
66+
} catch (err) {
67+
if (!(err instanceof Error)) {
68+
err = new Error(err.result.message);
69+
}
70+
console.error(err.name, err.message);
71+
}
72+
})();

index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,6 +1887,14 @@ declare type Sqlite3Static = {
18871887
DB: typeof Database;
18881888
};
18891889

1890+
/** Version numbers */
1891+
version: {
1892+
libVersion: string;
1893+
libVersionNumber: number;
1894+
sourceId: string;
1895+
downloadVersion: number;
1896+
};
1897+
18901898
/**
18911899
* Initializes the Worker API.
18921900
*

index.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
import { default as sqlite3InitModule } from './sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs';
2+
import './sqlite-wasm/jswasm/sqlite3-worker1-promiser-bundler-friendly.js';
3+
4+
const sqlite3Worker1Promiser = self.sqlite3Worker1Promiser;
25

36
export default sqlite3InitModule;
7+
export { sqlite3Worker1Promiser };

0 commit comments

Comments
 (0)