├── .gitignore
├── .prettierrc
├── README.md
├── bin
└── index.js
├── demo
├── index.html
├── main-thread.js
├── module-workers-polyfill.min.js
├── script.js
├── worker.js
└── wrapped-worker.js
├── index.d.ts
├── index.mjs
├── package-lock.json
├── package.json
└── sqlite-wasm
├── .gitignore
└── jswasm
├── sqlite3-bundler-friendly.mjs
├── sqlite3-node.mjs
├── sqlite3-opfs-async-proxy.js
├── sqlite3-worker1-bundler-friendly.mjs
├── sqlite3-worker1-promiser-bundler-friendly.js
├── sqlite3-worker1-promiser.js
├── sqlite3-worker1.js
├── sqlite3.js
├── sqlite3.mjs
└── sqlite3.wasm
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 | # Compiled output
3 | /dist
4 | /tmp
5 | /out-tsc
6 | /bazel-out
7 |
8 | # Node
9 | /node_modules
10 | npm-debug.log
11 | yarn-error.log
12 |
13 | # IDEs and editors
14 | .idea/
15 | .project
16 | .classpath
17 | .c9/
18 | *.launch
19 | .settings/
20 | *.sublime-workspace
21 |
22 | # Visual Studio Code
23 | .vscode/*
24 | !.vscode/settings.json
25 | !.vscode/tasks.json
26 | !.vscode/launch.json
27 | !.vscode/extensions.json
28 | .history/*
29 |
30 | # Miscellaneous
31 | /connect.lock
32 | /coverage
33 | /libpeerconnection.log
34 | testem.log
35 | /typings
36 |
37 | # System files
38 | .DS_Store
39 | Thumbs.db
40 |
41 | node_modules/*
42 | dist/
43 | bundle
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "arrowParens": "always",
3 | "bracketSpacing": true,
4 | "embeddedLanguageFormatting": "auto",
5 | "htmlWhitespaceSensitivity": "css",
6 | "insertPragma": false,
7 | "bracketSameLine": false,
8 | "jsxSingleQuote": false,
9 | "printWidth": 80,
10 | "proseWrap": "always",
11 | "quoteProps": "as-needed",
12 | "requirePragma": false,
13 | "semi": true,
14 | "singleQuote": true,
15 | "tabWidth": 2,
16 | "trailingComma": "all",
17 | "useTabs": false,
18 | "vueIndentScriptAndStyle": false,
19 | "plugins": ["prettier-plugin-jsdoc"]
20 | }
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > NOTE This fork enables the SQLite [bytecode](byte) and
2 | > [session](https://www.sqlite.org/sessionintro.html) extension.
3 |
4 | ## Changes
5 |
6 | - Adds Node compatibility to regular entry point:
7 |
8 | ```ts
9 | function instantiateAsync(binary, binaryFile, imports, callback) {
10 | if (
11 | !binary &&
12 | typeof WebAssembly.instantiateStreaming == 'function' &&
13 | !isDataURI(binaryFile) &&
14 | typeof fetch == 'function'
15 | ) {
16 | // added in this fork
17 | const isNode =
18 | typeof process !== 'undefined' &&
19 | process.versions != null &&
20 | process.versions.node != null;
21 | if (isNode) {
22 | return import('fs').then((fs) => {
23 | const buffer = fs.readFileSync(binaryFile.replace('file://', ''));
24 | const bytes = new Uint8Array(buffer);
25 | return WebAssembly.instantiate(bytes, imports).then(callback);
26 | });
27 | }
28 |
29 | return fetch(binaryFile, { credentials: 'same-origin' }).then(
30 | // ...
31 |
32 | ```
33 |
34 | ---
35 |
36 | # SQLite Wasm
37 |
38 | SQLite Wasm conveniently wrapped as an ES Module.
39 |
40 | > **Warning**
41 | >
42 | > This project wraps the code of
43 | > [SQLite Wasm](https://sqlite.org/wasm/doc/trunk/index.md) with _no_ changes,
44 | > apart from added TypeScript types. Please do _not_ file issues or feature
45 | > requests regarding the underlying SQLite Wasm code here. Instead, please
46 | > follow the
47 | > [SQLite bug filing instructions](https://www.sqlite.org/src/wiki?name=Bug+Reports).
48 | > Filing TypeScript type related issues and feature requests is fine.
49 |
50 | ## Installation
51 |
52 | ```bash
53 | npm install @sqlite.org/sqlite-wasm
54 | ```
55 |
56 | ## Usage
57 |
58 | There are three ways to use SQLite Wasm:
59 |
60 | - [in the main thread with a wrapped worker](#in-a-wrapped-worker-with-opfs-if-available)
61 | (🏆 preferred option)
62 | - [in a worker](#in-a-worker-with-opfs-if-available)
63 | - [in the main thread](#in-the-main-thread-without-opfs)
64 |
65 | Only the worker versions allow you to use the origin private file system (OPFS)
66 | storage back-end.
67 |
68 | ### In a wrapped worker (with OPFS if available):
69 |
70 | > **Warning**
71 | >
72 | > For this to work, you need to set the following headers on your server:
73 | >
74 | > `Cross-Origin-Opener-Policy: same-origin`
75 | >
76 | > `Cross-Origin-Embedder-Policy: require-corp`
77 |
78 | ```js
79 | import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';
80 |
81 | const log = (...args) => console.log(...args);
82 | const error = (...args) => console.error(...args);
83 |
84 | (async () => {
85 | try {
86 | log('Loading and initializing SQLite3 module...');
87 |
88 | const promiser = await new Promise((resolve) => {
89 | const _promiser = sqlite3Worker1Promiser({
90 | onready: () => {
91 | resolve(_promiser);
92 | },
93 | });
94 | });
95 |
96 | log('Done initializing. Running demo...');
97 |
98 | let response;
99 |
100 | response = await promiser('config-get', {});
101 | log('Running SQLite3 version', response.result.version.libVersion);
102 |
103 | response = await promiser('open', {
104 | filename: 'file:mydb.sqlite3?vfs=opfs',
105 | });
106 | const { dbId } = response;
107 | log(
108 | 'OPFS is available, created persisted database at',
109 | response.result.filename.replace(/^file:(.*?)\?vfs=opfs$/, '$1'),
110 | );
111 | // Your SQLite code here.
112 | } catch (err) {
113 | if (!(err instanceof Error)) {
114 | err = new Error(err.result.message);
115 | }
116 | error(err.name, err.message);
117 | }
118 | })();
119 | ```
120 |
121 | The `promiser` object above implements the
122 | [Worker1 API](https://sqlite.org/wasm/doc/trunk/api-worker1.md#worker1-methods).
123 |
124 | ### In a worker (with OPFS if available):
125 |
126 | > **Warning**
127 | >
128 | > For this to work, you need to set the following headers on your server:
129 | >
130 | > `Cross-Origin-Opener-Policy: same-origin`
131 | >
132 | > `Cross-Origin-Embedder-Policy: require-corp`
133 |
134 | ```js
135 | // In `main.js`.
136 | const worker = new Worker('worker.js', { type: 'module' });
137 | ```
138 |
139 | ```js
140 | // In `worker.js`.
141 | import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
142 |
143 | const log = (...args) => console.log(...args);
144 | const error = (...args) => console.error(...args);
145 |
146 | const start = function (sqlite3) {
147 | log('Running SQLite3 version', sqlite3.version.libVersion);
148 | let db;
149 | if ('opfs' in sqlite3) {
150 | db = new sqlite3.oo1.OpfsDb('/mydb.sqlite3');
151 | log('OPFS is available, created persisted database at', db.filename);
152 | } else {
153 | db = new sqlite3.oo1.DB('/mydb.sqlite3', 'ct');
154 | log('OPFS is not available, created transient database', db.filename);
155 | }
156 | // Your SQLite code here.
157 | };
158 |
159 | log('Loading and initializing SQLite3 module...');
160 | sqlite3InitModule({
161 | print: log,
162 | printErr: error,
163 | }).then((sqlite3) => {
164 | log('Done initializing. Running demo...');
165 | try {
166 | start(sqlite3);
167 | } catch (err) {
168 | error(err.name, err.message);
169 | }
170 | });
171 | ```
172 |
173 | The `db` object above implements the
174 | [Object Oriented API #1](https://sqlite.org/wasm/doc/trunk/api-oo1.md).
175 |
176 | ### In the main thread (without OPFS):
177 |
178 | ```js
179 | import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
180 |
181 | const log = (...args) => console.log(...args);
182 | const error = (...args) => console.error(...args);
183 |
184 | const start = function (sqlite3) {
185 | log('Running SQLite3 version', sqlite3.version.libVersion);
186 | const db = new sqlite3.oo1.DB('/mydb.sqlite3', 'ct');
187 | // Your SQLite code here.
188 | };
189 |
190 | log('Loading and initializing SQLite3 module...');
191 | sqlite3InitModule({
192 | print: log,
193 | printErr: error,
194 | }).then((sqlite3) => {
195 | try {
196 | log('Done initializing. Running demo...');
197 | start(sqlite3);
198 | } catch (err) {
199 | error(err.name, err.message);
200 | }
201 | });
202 | ```
203 |
204 | The `db` object above implements the
205 | [Object Oriented API #1](https://sqlite.org/wasm/doc/trunk/api-oo1.md).
206 |
207 | ## Usage with vite
208 |
209 | If you are using [vite](https://vitejs.dev/), you need to add the following
210 | config option in `vite.config.js`:
211 |
212 | ```js
213 | import { defineConfig } from 'vite';
214 |
215 | export default defineConfig({
216 | server: {
217 | headers: {
218 | 'Cross-Origin-Opener-Policy': 'same-origin',
219 | 'Cross-Origin-Embedder-Policy': 'require-corp',
220 | },
221 | },
222 | optimizeDeps: {
223 | exclude: ['@sqlite.org/sqlite-wasm'],
224 | },
225 | });
226 | ```
227 |
228 | Check out a
229 | [sample project](https://stackblitz.com/edit/vitejs-vite-ttrbwh?file=main.js)
230 | that shows this in action.
231 |
232 | ## Demo
233 |
234 | See the [demo](https://github.com/sqlite/sqlite-wasm/tree/main/demo) folder for
235 | examples of how to use this in the main thread and in a worker. (Note that the
236 | worker variant requires special HTTP headers, so it can't be hosted on GitHub
237 | Pages.) An example that shows how to use this with vite is available on
238 | [StackBlitz](https://stackblitz.com/edit/vitejs-vite-ttrbwh?file=main.js).
239 |
240 | ## Projects using this package
241 |
242 | See the list of
243 | [npm dependents](https://www.npmjs.com/browse/depended/@sqlite.org/sqlite-wasm)
244 | for this package.
245 |
246 | ## Deploying a new version
247 |
248 | (These steps can only be executed by maintainers.)
249 |
250 | 1. Update the version number in `package.json` reflecting the current
251 | [SQLite version number](https://sqlite.org/download.html) and add a build
252 | identifier suffix like `-build1`. The complete version number should read
253 | something like `3.41.2-build1`.
254 | 1. Run `npm run build` to build the ES Module. This downloads the latest SQLite
255 | Wasm binary and builds the ES Module.
256 | 1. Run `npm run deploy` to commit the changes, push to GitHub, and publish the
257 | new version to npm.
258 |
259 | ## License
260 |
261 | Apache 2.0.
262 |
263 | ## Acknowledgements
264 |
265 | This project is based on [SQLite Wasm](https://sqlite.org/wasm), which it
266 | conveniently wraps as an ES Module and publishes to npm as
267 | [`@sqlite.org/sqlite-wasm`](https://www.npmjs.com/package/@sqlite.org/sqlite-wasm).
268 |
--------------------------------------------------------------------------------
/bin/index.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import fetch from 'node-fetch';
3 | import decompress from 'decompress';
4 |
5 | async function getSqliteWasmDownloadLink() {
6 | const response = await fetch('https://sqlite.org/download.html');
7 | const html = await response.text();
8 | const sqliteWasmLink =
9 | 'https://sqlite.org/' +
10 | html
11 | .replace(
12 | /^.*?.*?$/gms,
13 | '$1',
14 | )
15 | .split(/\n/)
16 | .filter((row) => /sqlite-wasm/.test(row))[0]
17 | .split(/,/)[2];
18 | console.log(`Found SQLite Wasm download link: ${sqliteWasmLink}`);
19 | return sqliteWasmLink;
20 | }
21 |
22 | async function downloadAndUnzipSqliteWasm(sqliteWasmDownloadLink) {
23 | if (!sqliteWasmDownloadLink) {
24 | throw new Error('Unable to find SQLite Wasm download link');
25 | }
26 | console.log('Downloading and unzipping SQLite Wasm...');
27 | 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 | }
33 | const buffer = await response.arrayBuffer();
34 | fs.writeFileSync('sqlite-wasm.zip', Buffer.from(buffer));
35 | const files = await decompress('sqlite-wasm.zip', 'sqlite-wasm', {
36 | strip: 1,
37 | filter: (file) =>
38 | /jswasm/.test(file.path) && /(\.mjs|\.wasm|\.js)$/.test(file.path),
39 | });
40 | console.log(
41 | `Downloaded and unzipped:\n${files
42 | .map((file) => (/\//.test(file.path) ? '‣ ' + file.path + '\n' : ''))
43 | .join('')}`,
44 | );
45 | fs.rmSync('sqlite-wasm.zip');
46 | }
47 |
48 | async function main() {
49 | try {
50 | const sqliteWasmLink = await getSqliteWasmDownloadLink();
51 | await downloadAndUnzipSqliteWasm(sqliteWasmLink);
52 | fs.copyFileSync(
53 | './node_modules/module-workers-polyfill/module-workers-polyfill.min.js',
54 | './demo/module-workers-polyfill.min.js',
55 | );
56 | } catch (err) {
57 | console.error(err.name, err.message);
58 | }
59 | }
60 |
61 | main();
62 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SQLite Wasm Demo
6 |
7 |
8 |
9 |
10 |
11 | SQLite Wasm Demo
12 | Wrapped Worker
13 |
14 | Worker
15 |
16 | Main thread
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/demo/main-thread.js:
--------------------------------------------------------------------------------
1 | import sqlite3InitModule from '../index.mjs';
2 |
3 | const container = document.querySelector('.main-thread');
4 |
5 | const logHtml = function (cssClass, ...args) {
6 | const div = document.createElement('div');
7 | if (cssClass) div.classList.add(cssClass);
8 | div.append(document.createTextNode(args.join(' ')));
9 | container.append(div);
10 | };
11 |
12 | const log = (...args) => logHtml('', ...args);
13 | const error = (...args) => logHtml('error', ...args);
14 |
15 | const start = function (sqlite3) {
16 | log('Running SQLite3 version', sqlite3.version.libVersion);
17 | const db = new sqlite3.oo1.DB('/mydb.sqlite3', 'ct');
18 | log('Created transient database', db.filename);
19 |
20 | try {
21 | log('Creating a table...');
22 | db.exec('CREATE TABLE IF NOT EXISTS t(a,b)');
23 | log('Insert some data using exec()...');
24 | for (let i = 20; i <= 25; ++i) {
25 | db.exec({
26 | sql: 'INSERT INTO t(a,b) VALUES (?,?)',
27 | bind: [i, i * 2],
28 | });
29 | }
30 | log('Query data with exec()...');
31 | db.exec({
32 | sql: 'SELECT a FROM t ORDER BY a LIMIT 3',
33 | callback: (row) => {
34 | log(row);
35 | },
36 | });
37 | } finally {
38 | db.close();
39 | }
40 | };
41 |
42 | log('Loading and initializing SQLite3 module...');
43 | sqlite3InitModule({
44 | print: log,
45 | printErr: error,
46 | }).then((sqlite3) => {
47 | log('Done initializing. Running demo...');
48 | try {
49 | start(sqlite3);
50 | } catch (err) {
51 | error(err.name, err.message);
52 | }
53 | });
54 |
--------------------------------------------------------------------------------
/demo/module-workers-polyfill.min.js:
--------------------------------------------------------------------------------
1 | !(function (e) {
2 | if (!e || !0 !== e._$P) {
3 | if (e) {
4 | var n,
5 | r = Object.defineProperty({}, 'type', {
6 | get: function () {
7 | n = !0;
8 | },
9 | });
10 | try {
11 | var t = URL.createObjectURL(
12 | new Blob([''], { type: 'text/javascript' }),
13 | );
14 | new e(t, r).terminate(), URL.revokeObjectURL(t);
15 | } catch (e) {}
16 | if (!n)
17 | try {
18 | new e('data:text/javascript,', r).terminate();
19 | } catch (e) {}
20 | if (n) return;
21 | (self.Worker = function (n, r) {
22 | return (
23 | r &&
24 | 'module' == r.type &&
25 | ((r = { name: n + '\n' + (r.name || '') }),
26 | (n =
27 | 'undefined' == typeof document
28 | ? location.href
29 | : (document.currentScript && document.currentScript.src) ||
30 | new Error().stack.match(
31 | /[(@]((file|https?):\/\/[^)]+?):\d+(:\d+)?(?:\)|$)/m,
32 | )[1])),
33 | new e(n, r)
34 | );
35 | })._$P = !0;
36 | }
37 | 'undefined' == typeof document &&
38 | (function () {
39 | var e = {},
40 | n = {};
41 | function r(e, n) {
42 | for (
43 | n = n.replace(/^(\.\.\/|\.\/)/, e.replace(/[^/]+$/g, '') + '$1');
44 | n !== (n = n.replace(/[^/]+\/\.\.\//g, ''));
45 |
46 | );
47 | return n.replace(/\.\//g, '');
48 | }
49 | var t = [],
50 | s = t.push.bind(t);
51 | addEventListener('message', s);
52 | var a = self.name.match(/^[^\n]+/)[0];
53 | (self.name = self.name.replace(/^[^\n]*\n/g, '')),
54 | (function t(s, a) {
55 | var u,
56 | o = s;
57 | return (
58 | a && (s = r(a, s)),
59 | e[s] ||
60 | (e[s] = fetch(s).then(function (a) {
61 | if ((o = a.url) !== s) {
62 | if (null != e[o]) return e[o];
63 | e[o] = e[s];
64 | }
65 | return a.text().then(function (e) {
66 | if (!a.ok) throw e;
67 | var c = { exports: {} };
68 | u = n[o] || (n[o] = c.exports);
69 | var i = function (e) {
70 | return t(e, o);
71 | },
72 | f = [];
73 | return (
74 | (e = (function (e, n) {
75 | n = n || [];
76 | var r,
77 | t = [],
78 | a = 0;
79 | function u(e, n) {
80 | for (
81 | var s,
82 | a = /(?:^|,)\s*([\w$]+)(?:\s+as\s+([\w$]+))?\s*/g,
83 | u = [];
84 | (s = a.exec(e));
85 |
86 | )
87 | n
88 | ? t.push((s[2] || s[1]) + ':' + s[1])
89 | : u.push((s[2] || s[1]) + '=' + r + '.' + s[1]);
90 | return u;
91 | }
92 | return (
93 | (e = e
94 | .replace(
95 | /(^\s*|[;}\s\n]\s*)import\s*(?:(?:([\w$]+)(?:\s*\,\s*\{([^}]+)\})?|(?:\*\s*as\s+([\w$]+))|\{([^}]*)\})\s*from)?\s*(['"])(.+?)\6/g,
96 | function (e, t, s, o, c, i, f, p) {
97 | return (
98 | n.push(p),
99 | (t +=
100 | 'var ' +
101 | (r = '$im$' + ++a) +
102 | '=$require(' +
103 | f +
104 | p +
105 | f +
106 | ')'),
107 | s &&
108 | (t +=
109 | ';var ' +
110 | s +
111 | " = 'default' in " +
112 | r +
113 | ' ? ' +
114 | r +
115 | '.default : ' +
116 | r),
117 | c && (t += ';var ' + c + ' = ' + r),
118 | (o = o || i) && (t += ';var ' + u(o, !1)),
119 | t
120 | );
121 | },
122 | )
123 | .replace(
124 | /((?:^|[;}\s\n])\s*)export\s*(?:\s+(default)\s+|((?:async\s+)?function\s*\*?|class|const\s|let\s|var\s)\s*([a-zA-Z0-9$_{[]+))/g,
125 | function (e, n, r, s, u) {
126 | if (r) {
127 | var o = '$im$' + ++a;
128 | return (
129 | t.push('default:' + o), n + 'var ' + o + '='
130 | );
131 | }
132 | return t.push(u + ':' + u), n + s + ' ' + u;
133 | },
134 | )
135 | .replace(
136 | /((?:^|[;}\s\n])\s*)export\s*\{([^}]+)\}\s*;?/g,
137 | function (e, n, r) {
138 | return u(r, !0), n;
139 | },
140 | )
141 | .replace(
142 | /((?:^|[^a-zA-Z0-9$_@`'".])\s*)(import\s*\([\s\S]+?\))/g,
143 | '$1$$$2',
144 | )).replace(
145 | /((?:^|[^a-zA-Z0-9$_@`'".])\s*)import\.meta\.url/g,
146 | '$1' + JSON.stringify(s),
147 | ) +
148 | '\n$module.exports={' +
149 | t.join(',') +
150 | '}'
151 | );
152 | })(e, f)),
153 | Promise.all(
154 | f.map(function (e) {
155 | var s = r(o, e);
156 | return s in n ? n[s] : t(s);
157 | }),
158 | ).then(function (n) {
159 | e += '\n//# sourceURL=' + s;
160 | try {
161 | var r = new Function(
162 | '$import',
163 | '$require',
164 | '$module',
165 | '$exports',
166 | e,
167 | );
168 | } catch (n) {
169 | var t = n.line - 1,
170 | a = n.column,
171 | o = e.split('\n'),
172 | p =
173 | (o[t - 2] || '') +
174 | '\n' +
175 | o[t - 1] +
176 | '\n' +
177 | (null == a
178 | ? ''
179 | : new Array(a).join('-') + '^\n') +
180 | (o[t] || ''),
181 | l = new Error(n.message + '\n\n' + p, s, t);
182 | throw (
183 | ((l.sourceURL = l.fileName = s),
184 | (l.line = t),
185 | (l.column = a),
186 | l)
187 | );
188 | }
189 | var m = r(
190 | i,
191 | function (e) {
192 | return n[f.indexOf(e)];
193 | },
194 | c,
195 | c.exports,
196 | );
197 | return (
198 | null != m && (c.exports = m),
199 | Object.assign(u, c.exports),
200 | c.exports
201 | );
202 | })
203 | );
204 | });
205 | }))
206 | );
207 | })(a)
208 | .then(function () {
209 | removeEventListener('message', s), t.map(dispatchEvent);
210 | })
211 | .catch(function (e) {
212 | setTimeout(function () {
213 | throw e;
214 | });
215 | });
216 | })();
217 | }
218 | })(self.Worker);
219 |
--------------------------------------------------------------------------------
/demo/script.js:
--------------------------------------------------------------------------------
1 | const container = document.querySelector('.worker');
2 |
3 | const logHtml = (cssClass, ...args) => {
4 | const div = document.createElement('div');
5 | if (cssClass) div.classList.add(cssClass);
6 | div.append(document.createTextNode(args.join(' ')));
7 | container.append(div);
8 | };
9 |
10 | (async () => {
11 | // Module Worker polyfill from https://stackoverflow.com/a/62963963/6255000.
12 | const supportsWorkerType = () => {
13 | let supports = false;
14 | const tester = {
15 | get type() {
16 | supports = true;
17 | },
18 | };
19 | try {
20 | new Worker('data:,""', tester);
21 | } finally {
22 | return supports;
23 | }
24 | };
25 | if (!supportsWorkerType()) {
26 | await import('./module-workers-polyfill.min.js');
27 | }
28 |
29 | const worker = new Worker('/demo/worker.js', {
30 | type: 'module',
31 | });
32 |
33 | worker.addEventListener('message', ({ data }) => {
34 | switch (data.type) {
35 | case 'log':
36 | logHtml(data.payload.cssClass, ...data.payload.args);
37 | break;
38 | default:
39 | logHtml('error', 'Unhandled message:', data.type);
40 | }
41 | });
42 | })();
43 |
--------------------------------------------------------------------------------
/demo/worker.js:
--------------------------------------------------------------------------------
1 | import sqlite3InitModule from '../index.mjs';
2 |
3 | const logHtml = function (cssClass, ...args) {
4 | postMessage({
5 | type: 'log',
6 | payload: { cssClass, args },
7 | });
8 | };
9 |
10 | const log = (...args) => logHtml('', ...args);
11 | const error = (...args) => logHtml('error', ...args);
12 |
13 | const start = function (sqlite3) {
14 | log('Running SQLite3 version', sqlite3.version.libVersion);
15 | let db;
16 | if ('opfs' in sqlite3) {
17 | db = new sqlite3.oo1.OpfsDb('/mydb.sqlite3');
18 | log('OPFS is available, created persisted database at', db.filename);
19 | } else {
20 | db = new sqlite3.oo1.DB('/mydb.sqlite3', 'ct');
21 | log('OPFS is not available, created transient database', db.filename);
22 | }
23 | try {
24 | log('Creating a table...');
25 | db.exec('CREATE TABLE IF NOT EXISTS t(a,b)');
26 | log('Insert some data using exec()...');
27 | for (let i = 20; i <= 25; ++i) {
28 | db.exec({
29 | sql: 'INSERT INTO t(a,b) VALUES (?,?)',
30 | bind: [i, i * 2],
31 | });
32 | }
33 | log('Query data with exec()...');
34 | db.exec({
35 | sql: 'SELECT a FROM t ORDER BY a LIMIT 3',
36 | callback: (row) => {
37 | log(row);
38 | },
39 | });
40 | } finally {
41 | db.close();
42 | }
43 | };
44 |
45 | log('Loading and initializing SQLite3 module...');
46 | sqlite3InitModule({
47 | print: log,
48 | printErr: error,
49 | }).then((sqlite3) => {
50 | log('Done initializing. Running demo...');
51 | try {
52 | start(sqlite3);
53 | } catch (err) {
54 | error(err.name, err.message);
55 | }
56 | });
57 |
--------------------------------------------------------------------------------
/demo/wrapped-worker.js:
--------------------------------------------------------------------------------
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 | })();
73 |
--------------------------------------------------------------------------------
/index.mjs:
--------------------------------------------------------------------------------
1 | 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 = globalThis.sqlite3Worker1Promiser;
5 |
6 | export default sqlite3InitModule;
7 | export { sqlite3Worker1Promiser };
8 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@livestore/sqlite-wasm",
3 | "version": "3.46.0-build1",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "@livestore/sqlite-wasm",
9 | "version": "3.46.0-build1",
10 | "license": "Apache-2.0",
11 | "bin": {
12 | "sqlite-wasm": "bin/index.js"
13 | },
14 | "devDependencies": {
15 | "decompress": "^4.2.1",
16 | "http-server": "github:vapier/http-server",
17 | "module-workers-polyfill": "^0.3.2",
18 | "node-fetch": "^3.3.2",
19 | "prettier": "^3.2.4",
20 | "prettier-plugin-jsdoc": "^1.3.0",
21 | "publint": "^0.2.7",
22 | "shx": "^0.3.4"
23 | }
24 | },
25 | "node_modules/@types/debug": {
26 | "version": "4.1.9",
27 | "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz",
28 | "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==",
29 | "dev": true,
30 | "dependencies": {
31 | "@types/ms": "*"
32 | }
33 | },
34 | "node_modules/@types/mdast": {
35 | "version": "4.0.1",
36 | "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.1.tgz",
37 | "integrity": "sha512-IlKct1rUTJ1T81d8OHzyop15kGv9A/ff7Gz7IJgrk6jDb4Udw77pCJ+vq8oxZf4Ghpm+616+i1s/LNg/Vh7d+g==",
38 | "dev": true,
39 | "dependencies": {
40 | "@types/unist": "*"
41 | }
42 | },
43 | "node_modules/@types/ms": {
44 | "version": "0.7.32",
45 | "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.32.tgz",
46 | "integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==",
47 | "dev": true
48 | },
49 | "node_modules/@types/unist": {
50 | "version": "3.0.0",
51 | "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.0.tgz",
52 | "integrity": "sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==",
53 | "dev": true
54 | },
55 | "node_modules/ansi-styles": {
56 | "version": "4.3.0",
57 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
58 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
59 | "dev": true,
60 | "dependencies": {
61 | "color-convert": "^2.0.1"
62 | },
63 | "engines": {
64 | "node": ">=8"
65 | },
66 | "funding": {
67 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
68 | }
69 | },
70 | "node_modules/async": {
71 | "version": "2.6.4",
72 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
73 | "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
74 | "dev": true,
75 | "dependencies": {
76 | "lodash": "^4.17.14"
77 | }
78 | },
79 | "node_modules/balanced-match": {
80 | "version": "1.0.2",
81 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
82 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
83 | "dev": true
84 | },
85 | "node_modules/base64-js": {
86 | "version": "1.5.1",
87 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
88 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
89 | "dev": true,
90 | "funding": [
91 | {
92 | "type": "github",
93 | "url": "https://github.com/sponsors/feross"
94 | },
95 | {
96 | "type": "patreon",
97 | "url": "https://www.patreon.com/feross"
98 | },
99 | {
100 | "type": "consulting",
101 | "url": "https://feross.org/support"
102 | }
103 | ]
104 | },
105 | "node_modules/basic-auth": {
106 | "version": "2.0.1",
107 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
108 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
109 | "dev": true,
110 | "dependencies": {
111 | "safe-buffer": "5.1.2"
112 | },
113 | "engines": {
114 | "node": ">= 0.8"
115 | }
116 | },
117 | "node_modules/binary-searching": {
118 | "version": "2.0.5",
119 | "resolved": "https://registry.npmjs.org/binary-searching/-/binary-searching-2.0.5.tgz",
120 | "integrity": "sha512-v4N2l3RxL+m4zDxyxz3Ne2aTmiPn8ZUpKFpdPtO+ItW1NcTCXA7JeHG5GMBSvoKSkQZ9ycS+EouDVxYB9ufKWA==",
121 | "dev": true
122 | },
123 | "node_modules/bl": {
124 | "version": "1.2.3",
125 | "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz",
126 | "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",
127 | "dev": true,
128 | "dependencies": {
129 | "readable-stream": "^2.3.5",
130 | "safe-buffer": "^5.1.1"
131 | }
132 | },
133 | "node_modules/brace-expansion": {
134 | "version": "2.0.1",
135 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
136 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
137 | "dev": true,
138 | "dependencies": {
139 | "balanced-match": "^1.0.0"
140 | }
141 | },
142 | "node_modules/buffer": {
143 | "version": "5.7.1",
144 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
145 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
146 | "dev": true,
147 | "funding": [
148 | {
149 | "type": "github",
150 | "url": "https://github.com/sponsors/feross"
151 | },
152 | {
153 | "type": "patreon",
154 | "url": "https://www.patreon.com/feross"
155 | },
156 | {
157 | "type": "consulting",
158 | "url": "https://feross.org/support"
159 | }
160 | ],
161 | "dependencies": {
162 | "base64-js": "^1.3.1",
163 | "ieee754": "^1.1.13"
164 | }
165 | },
166 | "node_modules/buffer-alloc": {
167 | "version": "1.2.0",
168 | "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
169 | "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
170 | "dev": true,
171 | "dependencies": {
172 | "buffer-alloc-unsafe": "^1.1.0",
173 | "buffer-fill": "^1.0.0"
174 | }
175 | },
176 | "node_modules/buffer-alloc-unsafe": {
177 | "version": "1.1.0",
178 | "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
179 | "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
180 | "dev": true
181 | },
182 | "node_modules/buffer-crc32": {
183 | "version": "0.2.13",
184 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
185 | "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
186 | "dev": true,
187 | "engines": {
188 | "node": "*"
189 | }
190 | },
191 | "node_modules/buffer-fill": {
192 | "version": "1.0.0",
193 | "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
194 | "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==",
195 | "dev": true
196 | },
197 | "node_modules/call-bind": {
198 | "version": "1.0.2",
199 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
200 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
201 | "dev": true,
202 | "dependencies": {
203 | "function-bind": "^1.1.1",
204 | "get-intrinsic": "^1.0.2"
205 | },
206 | "funding": {
207 | "url": "https://github.com/sponsors/ljharb"
208 | }
209 | },
210 | "node_modules/chalk": {
211 | "version": "4.1.2",
212 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
213 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
214 | "dev": true,
215 | "dependencies": {
216 | "ansi-styles": "^4.1.0",
217 | "supports-color": "^7.1.0"
218 | },
219 | "engines": {
220 | "node": ">=10"
221 | },
222 | "funding": {
223 | "url": "https://github.com/chalk/chalk?sponsor=1"
224 | }
225 | },
226 | "node_modules/character-entities": {
227 | "version": "2.0.2",
228 | "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
229 | "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
230 | "dev": true,
231 | "funding": {
232 | "type": "github",
233 | "url": "https://github.com/sponsors/wooorm"
234 | }
235 | },
236 | "node_modules/color-convert": {
237 | "version": "2.0.1",
238 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
239 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
240 | "dev": true,
241 | "dependencies": {
242 | "color-name": "~1.1.4"
243 | },
244 | "engines": {
245 | "node": ">=7.0.0"
246 | }
247 | },
248 | "node_modules/color-name": {
249 | "version": "1.1.4",
250 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
251 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
252 | "dev": true
253 | },
254 | "node_modules/commander": {
255 | "version": "2.20.3",
256 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
257 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
258 | "dev": true
259 | },
260 | "node_modules/comment-parser": {
261 | "version": "1.4.0",
262 | "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz",
263 | "integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==",
264 | "dev": true,
265 | "engines": {
266 | "node": ">= 12.0.0"
267 | }
268 | },
269 | "node_modules/concat-map": {
270 | "version": "0.0.1",
271 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
272 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
273 | "dev": true
274 | },
275 | "node_modules/core-util-is": {
276 | "version": "1.0.2",
277 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
278 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
279 | "dev": true
280 | },
281 | "node_modules/corser": {
282 | "version": "2.0.1",
283 | "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
284 | "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==",
285 | "dev": true,
286 | "engines": {
287 | "node": ">= 0.4.0"
288 | }
289 | },
290 | "node_modules/data-uri-to-buffer": {
291 | "version": "4.0.1",
292 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
293 | "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
294 | "dev": true,
295 | "engines": {
296 | "node": ">= 12"
297 | }
298 | },
299 | "node_modules/debug": {
300 | "version": "3.2.7",
301 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
302 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
303 | "dev": true,
304 | "dependencies": {
305 | "ms": "^2.1.1"
306 | }
307 | },
308 | "node_modules/decode-named-character-reference": {
309 | "version": "1.0.2",
310 | "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz",
311 | "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==",
312 | "dev": true,
313 | "dependencies": {
314 | "character-entities": "^2.0.0"
315 | },
316 | "funding": {
317 | "type": "github",
318 | "url": "https://github.com/sponsors/wooorm"
319 | }
320 | },
321 | "node_modules/decompress": {
322 | "version": "4.2.1",
323 | "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz",
324 | "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==",
325 | "dev": true,
326 | "dependencies": {
327 | "decompress-tar": "^4.0.0",
328 | "decompress-tarbz2": "^4.0.0",
329 | "decompress-targz": "^4.0.0",
330 | "decompress-unzip": "^4.0.1",
331 | "graceful-fs": "^4.1.10",
332 | "make-dir": "^1.0.0",
333 | "pify": "^2.3.0",
334 | "strip-dirs": "^2.0.0"
335 | },
336 | "engines": {
337 | "node": ">=4"
338 | }
339 | },
340 | "node_modules/decompress-tar": {
341 | "version": "4.1.1",
342 | "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz",
343 | "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==",
344 | "dev": true,
345 | "dependencies": {
346 | "file-type": "^5.2.0",
347 | "is-stream": "^1.1.0",
348 | "tar-stream": "^1.5.2"
349 | },
350 | "engines": {
351 | "node": ">=4"
352 | }
353 | },
354 | "node_modules/decompress-tarbz2": {
355 | "version": "4.1.1",
356 | "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
357 | "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
358 | "dev": true,
359 | "dependencies": {
360 | "decompress-tar": "^4.1.0",
361 | "file-type": "^6.1.0",
362 | "is-stream": "^1.1.0",
363 | "seek-bzip": "^1.0.5",
364 | "unbzip2-stream": "^1.0.9"
365 | },
366 | "engines": {
367 | "node": ">=4"
368 | }
369 | },
370 | "node_modules/decompress-tarbz2/node_modules/file-type": {
371 | "version": "6.2.0",
372 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz",
373 | "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==",
374 | "dev": true,
375 | "engines": {
376 | "node": ">=4"
377 | }
378 | },
379 | "node_modules/decompress-targz": {
380 | "version": "4.1.1",
381 | "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz",
382 | "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==",
383 | "dev": true,
384 | "dependencies": {
385 | "decompress-tar": "^4.1.1",
386 | "file-type": "^5.2.0",
387 | "is-stream": "^1.1.0"
388 | },
389 | "engines": {
390 | "node": ">=4"
391 | }
392 | },
393 | "node_modules/decompress-unzip": {
394 | "version": "4.0.1",
395 | "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
396 | "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==",
397 | "dev": true,
398 | "dependencies": {
399 | "file-type": "^3.8.0",
400 | "get-stream": "^2.2.0",
401 | "pify": "^2.3.0",
402 | "yauzl": "^2.4.2"
403 | },
404 | "engines": {
405 | "node": ">=4"
406 | }
407 | },
408 | "node_modules/decompress-unzip/node_modules/file-type": {
409 | "version": "3.9.0",
410 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
411 | "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==",
412 | "dev": true,
413 | "engines": {
414 | "node": ">=0.10.0"
415 | }
416 | },
417 | "node_modules/dequal": {
418 | "version": "2.0.3",
419 | "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
420 | "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
421 | "dev": true,
422 | "engines": {
423 | "node": ">=6"
424 | }
425 | },
426 | "node_modules/devlop": {
427 | "version": "1.1.0",
428 | "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
429 | "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
430 | "dev": true,
431 | "dependencies": {
432 | "dequal": "^2.0.0"
433 | },
434 | "funding": {
435 | "type": "github",
436 | "url": "https://github.com/sponsors/wooorm"
437 | }
438 | },
439 | "node_modules/end-of-stream": {
440 | "version": "1.4.4",
441 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
442 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
443 | "dev": true,
444 | "dependencies": {
445 | "once": "^1.4.0"
446 | }
447 | },
448 | "node_modules/eventemitter3": {
449 | "version": "4.0.7",
450 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
451 | "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
452 | "dev": true
453 | },
454 | "node_modules/fd-slicer": {
455 | "version": "1.1.0",
456 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
457 | "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
458 | "dev": true,
459 | "dependencies": {
460 | "pend": "~1.2.0"
461 | }
462 | },
463 | "node_modules/fetch-blob": {
464 | "version": "3.2.0",
465 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
466 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
467 | "dev": true,
468 | "funding": [
469 | {
470 | "type": "github",
471 | "url": "https://github.com/sponsors/jimmywarting"
472 | },
473 | {
474 | "type": "paypal",
475 | "url": "https://paypal.me/jimmywarting"
476 | }
477 | ],
478 | "dependencies": {
479 | "node-domexception": "^1.0.0",
480 | "web-streams-polyfill": "^3.0.3"
481 | },
482 | "engines": {
483 | "node": "^12.20 || >= 14.13"
484 | }
485 | },
486 | "node_modules/file-type": {
487 | "version": "5.2.0",
488 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
489 | "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==",
490 | "dev": true,
491 | "engines": {
492 | "node": ">=4"
493 | }
494 | },
495 | "node_modules/follow-redirects": {
496 | "version": "1.15.5",
497 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
498 | "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
499 | "dev": true,
500 | "funding": [
501 | {
502 | "type": "individual",
503 | "url": "https://github.com/sponsors/RubenVerborgh"
504 | }
505 | ],
506 | "engines": {
507 | "node": ">=4.0"
508 | },
509 | "peerDependenciesMeta": {
510 | "debug": {
511 | "optional": true
512 | }
513 | }
514 | },
515 | "node_modules/formdata-polyfill": {
516 | "version": "4.0.10",
517 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
518 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
519 | "dev": true,
520 | "dependencies": {
521 | "fetch-blob": "^3.1.2"
522 | },
523 | "engines": {
524 | "node": ">=12.20.0"
525 | }
526 | },
527 | "node_modules/fs-constants": {
528 | "version": "1.0.0",
529 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
530 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
531 | "dev": true
532 | },
533 | "node_modules/fs.realpath": {
534 | "version": "1.0.0",
535 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
536 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
537 | "dev": true
538 | },
539 | "node_modules/function-bind": {
540 | "version": "1.1.1",
541 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
542 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
543 | "dev": true
544 | },
545 | "node_modules/get-intrinsic": {
546 | "version": "1.2.0",
547 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
548 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
549 | "dev": true,
550 | "dependencies": {
551 | "function-bind": "^1.1.1",
552 | "has": "^1.0.3",
553 | "has-symbols": "^1.0.3"
554 | },
555 | "funding": {
556 | "url": "https://github.com/sponsors/ljharb"
557 | }
558 | },
559 | "node_modules/get-stream": {
560 | "version": "2.3.1",
561 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
562 | "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==",
563 | "dev": true,
564 | "dependencies": {
565 | "object-assign": "^4.0.1",
566 | "pinkie-promise": "^2.0.0"
567 | },
568 | "engines": {
569 | "node": ">=0.10.0"
570 | }
571 | },
572 | "node_modules/glob": {
573 | "version": "8.1.0",
574 | "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
575 | "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
576 | "dev": true,
577 | "dependencies": {
578 | "fs.realpath": "^1.0.0",
579 | "inflight": "^1.0.4",
580 | "inherits": "2",
581 | "minimatch": "^5.0.1",
582 | "once": "^1.3.0"
583 | },
584 | "engines": {
585 | "node": ">=12"
586 | },
587 | "funding": {
588 | "url": "https://github.com/sponsors/isaacs"
589 | }
590 | },
591 | "node_modules/graceful-fs": {
592 | "version": "4.2.11",
593 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
594 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
595 | "dev": true
596 | },
597 | "node_modules/has": {
598 | "version": "1.0.3",
599 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
600 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
601 | "dev": true,
602 | "dependencies": {
603 | "function-bind": "^1.1.1"
604 | },
605 | "engines": {
606 | "node": ">= 0.4.0"
607 | }
608 | },
609 | "node_modules/has-flag": {
610 | "version": "4.0.0",
611 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
612 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
613 | "dev": true,
614 | "engines": {
615 | "node": ">=8"
616 | }
617 | },
618 | "node_modules/has-symbols": {
619 | "version": "1.0.3",
620 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
621 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
622 | "dev": true,
623 | "engines": {
624 | "node": ">= 0.4"
625 | },
626 | "funding": {
627 | "url": "https://github.com/sponsors/ljharb"
628 | }
629 | },
630 | "node_modules/he": {
631 | "version": "1.2.0",
632 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
633 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
634 | "dev": true,
635 | "bin": {
636 | "he": "bin/he"
637 | }
638 | },
639 | "node_modules/html-encoding-sniffer": {
640 | "version": "3.0.0",
641 | "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
642 | "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
643 | "dev": true,
644 | "dependencies": {
645 | "whatwg-encoding": "^2.0.0"
646 | },
647 | "engines": {
648 | "node": ">=12"
649 | }
650 | },
651 | "node_modules/http-proxy": {
652 | "version": "1.18.1",
653 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
654 | "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
655 | "dev": true,
656 | "dependencies": {
657 | "eventemitter3": "^4.0.0",
658 | "follow-redirects": "^1.0.0",
659 | "requires-port": "^1.0.0"
660 | },
661 | "engines": {
662 | "node": ">=8.0.0"
663 | }
664 | },
665 | "node_modules/http-server": {
666 | "version": "14.1.0",
667 | "resolved": "git+ssh://git@github.com/vapier/http-server.git#35fad5cd29005748916d1bca24db83ab6976ba41",
668 | "dev": true,
669 | "license": "MIT",
670 | "dependencies": {
671 | "basic-auth": "^2.0.1",
672 | "chalk": "^4.1.2",
673 | "corser": "^2.0.1",
674 | "he": "^1.2.0",
675 | "html-encoding-sniffer": "^3.0.0",
676 | "http-proxy": "^1.18.1",
677 | "mime": "^1.6.0",
678 | "minimist": "^1.2.6",
679 | "opener": "^1.5.1",
680 | "portfinder": "^1.0.28",
681 | "secure-compare": "3.0.1",
682 | "union": "~0.5.0",
683 | "url-join": "^4.0.1"
684 | },
685 | "bin": {
686 | "http-server": "bin/http-server"
687 | },
688 | "engines": {
689 | "node": ">=12"
690 | }
691 | },
692 | "node_modules/iconv-lite": {
693 | "version": "0.6.3",
694 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
695 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
696 | "dev": true,
697 | "dependencies": {
698 | "safer-buffer": ">= 2.1.2 < 3.0.0"
699 | },
700 | "engines": {
701 | "node": ">=0.10.0"
702 | }
703 | },
704 | "node_modules/ieee754": {
705 | "version": "1.2.1",
706 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
707 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
708 | "dev": true,
709 | "funding": [
710 | {
711 | "type": "github",
712 | "url": "https://github.com/sponsors/feross"
713 | },
714 | {
715 | "type": "patreon",
716 | "url": "https://www.patreon.com/feross"
717 | },
718 | {
719 | "type": "consulting",
720 | "url": "https://feross.org/support"
721 | }
722 | ]
723 | },
724 | "node_modules/ignore-walk": {
725 | "version": "5.0.1",
726 | "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz",
727 | "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==",
728 | "dev": true,
729 | "dependencies": {
730 | "minimatch": "^5.0.1"
731 | },
732 | "engines": {
733 | "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
734 | }
735 | },
736 | "node_modules/inflight": {
737 | "version": "1.0.6",
738 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
739 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
740 | "dev": true,
741 | "dependencies": {
742 | "once": "^1.3.0",
743 | "wrappy": "1"
744 | }
745 | },
746 | "node_modules/inherits": {
747 | "version": "2.0.4",
748 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
749 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
750 | "dev": true
751 | },
752 | "node_modules/interpret": {
753 | "version": "1.4.0",
754 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
755 | "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
756 | "dev": true,
757 | "engines": {
758 | "node": ">= 0.10"
759 | }
760 | },
761 | "node_modules/is-core-module": {
762 | "version": "2.12.1",
763 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
764 | "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
765 | "dev": true,
766 | "dependencies": {
767 | "has": "^1.0.3"
768 | },
769 | "funding": {
770 | "url": "https://github.com/sponsors/ljharb"
771 | }
772 | },
773 | "node_modules/is-natural-number": {
774 | "version": "4.0.1",
775 | "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
776 | "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==",
777 | "dev": true
778 | },
779 | "node_modules/is-stream": {
780 | "version": "1.1.0",
781 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
782 | "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
783 | "dev": true,
784 | "engines": {
785 | "node": ">=0.10.0"
786 | }
787 | },
788 | "node_modules/isarray": {
789 | "version": "1.0.0",
790 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
791 | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
792 | "dev": true
793 | },
794 | "node_modules/lodash": {
795 | "version": "4.17.21",
796 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
797 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
798 | "dev": true
799 | },
800 | "node_modules/make-dir": {
801 | "version": "1.3.0",
802 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
803 | "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
804 | "dev": true,
805 | "dependencies": {
806 | "pify": "^3.0.0"
807 | },
808 | "engines": {
809 | "node": ">=4"
810 | }
811 | },
812 | "node_modules/make-dir/node_modules/pify": {
813 | "version": "3.0.0",
814 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
815 | "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
816 | "dev": true,
817 | "engines": {
818 | "node": ">=4"
819 | }
820 | },
821 | "node_modules/mdast-util-from-markdown": {
822 | "version": "2.0.0",
823 | "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz",
824 | "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==",
825 | "dev": true,
826 | "dependencies": {
827 | "@types/mdast": "^4.0.0",
828 | "@types/unist": "^3.0.0",
829 | "decode-named-character-reference": "^1.0.0",
830 | "devlop": "^1.0.0",
831 | "mdast-util-to-string": "^4.0.0",
832 | "micromark": "^4.0.0",
833 | "micromark-util-decode-numeric-character-reference": "^2.0.0",
834 | "micromark-util-decode-string": "^2.0.0",
835 | "micromark-util-normalize-identifier": "^2.0.0",
836 | "micromark-util-symbol": "^2.0.0",
837 | "micromark-util-types": "^2.0.0",
838 | "unist-util-stringify-position": "^4.0.0"
839 | },
840 | "funding": {
841 | "type": "opencollective",
842 | "url": "https://opencollective.com/unified"
843 | }
844 | },
845 | "node_modules/mdast-util-to-string": {
846 | "version": "4.0.0",
847 | "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
848 | "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
849 | "dev": true,
850 | "dependencies": {
851 | "@types/mdast": "^4.0.0"
852 | },
853 | "funding": {
854 | "type": "opencollective",
855 | "url": "https://opencollective.com/unified"
856 | }
857 | },
858 | "node_modules/micromark": {
859 | "version": "4.0.0",
860 | "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz",
861 | "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==",
862 | "dev": true,
863 | "funding": [
864 | {
865 | "type": "GitHub Sponsors",
866 | "url": "https://github.com/sponsors/unifiedjs"
867 | },
868 | {
869 | "type": "OpenCollective",
870 | "url": "https://opencollective.com/unified"
871 | }
872 | ],
873 | "dependencies": {
874 | "@types/debug": "^4.0.0",
875 | "debug": "^4.0.0",
876 | "decode-named-character-reference": "^1.0.0",
877 | "devlop": "^1.0.0",
878 | "micromark-core-commonmark": "^2.0.0",
879 | "micromark-factory-space": "^2.0.0",
880 | "micromark-util-character": "^2.0.0",
881 | "micromark-util-chunked": "^2.0.0",
882 | "micromark-util-combine-extensions": "^2.0.0",
883 | "micromark-util-decode-numeric-character-reference": "^2.0.0",
884 | "micromark-util-encode": "^2.0.0",
885 | "micromark-util-normalize-identifier": "^2.0.0",
886 | "micromark-util-resolve-all": "^2.0.0",
887 | "micromark-util-sanitize-uri": "^2.0.0",
888 | "micromark-util-subtokenize": "^2.0.0",
889 | "micromark-util-symbol": "^2.0.0",
890 | "micromark-util-types": "^2.0.0"
891 | }
892 | },
893 | "node_modules/micromark-core-commonmark": {
894 | "version": "2.0.0",
895 | "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz",
896 | "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==",
897 | "dev": true,
898 | "funding": [
899 | {
900 | "type": "GitHub Sponsors",
901 | "url": "https://github.com/sponsors/unifiedjs"
902 | },
903 | {
904 | "type": "OpenCollective",
905 | "url": "https://opencollective.com/unified"
906 | }
907 | ],
908 | "dependencies": {
909 | "decode-named-character-reference": "^1.0.0",
910 | "devlop": "^1.0.0",
911 | "micromark-factory-destination": "^2.0.0",
912 | "micromark-factory-label": "^2.0.0",
913 | "micromark-factory-space": "^2.0.0",
914 | "micromark-factory-title": "^2.0.0",
915 | "micromark-factory-whitespace": "^2.0.0",
916 | "micromark-util-character": "^2.0.0",
917 | "micromark-util-chunked": "^2.0.0",
918 | "micromark-util-classify-character": "^2.0.0",
919 | "micromark-util-html-tag-name": "^2.0.0",
920 | "micromark-util-normalize-identifier": "^2.0.0",
921 | "micromark-util-resolve-all": "^2.0.0",
922 | "micromark-util-subtokenize": "^2.0.0",
923 | "micromark-util-symbol": "^2.0.0",
924 | "micromark-util-types": "^2.0.0"
925 | }
926 | },
927 | "node_modules/micromark-factory-destination": {
928 | "version": "2.0.0",
929 | "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz",
930 | "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==",
931 | "dev": true,
932 | "funding": [
933 | {
934 | "type": "GitHub Sponsors",
935 | "url": "https://github.com/sponsors/unifiedjs"
936 | },
937 | {
938 | "type": "OpenCollective",
939 | "url": "https://opencollective.com/unified"
940 | }
941 | ],
942 | "dependencies": {
943 | "micromark-util-character": "^2.0.0",
944 | "micromark-util-symbol": "^2.0.0",
945 | "micromark-util-types": "^2.0.0"
946 | }
947 | },
948 | "node_modules/micromark-factory-label": {
949 | "version": "2.0.0",
950 | "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz",
951 | "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==",
952 | "dev": true,
953 | "funding": [
954 | {
955 | "type": "GitHub Sponsors",
956 | "url": "https://github.com/sponsors/unifiedjs"
957 | },
958 | {
959 | "type": "OpenCollective",
960 | "url": "https://opencollective.com/unified"
961 | }
962 | ],
963 | "dependencies": {
964 | "devlop": "^1.0.0",
965 | "micromark-util-character": "^2.0.0",
966 | "micromark-util-symbol": "^2.0.0",
967 | "micromark-util-types": "^2.0.0"
968 | }
969 | },
970 | "node_modules/micromark-factory-space": {
971 | "version": "2.0.0",
972 | "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz",
973 | "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==",
974 | "dev": true,
975 | "funding": [
976 | {
977 | "type": "GitHub Sponsors",
978 | "url": "https://github.com/sponsors/unifiedjs"
979 | },
980 | {
981 | "type": "OpenCollective",
982 | "url": "https://opencollective.com/unified"
983 | }
984 | ],
985 | "dependencies": {
986 | "micromark-util-character": "^2.0.0",
987 | "micromark-util-types": "^2.0.0"
988 | }
989 | },
990 | "node_modules/micromark-factory-title": {
991 | "version": "2.0.0",
992 | "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz",
993 | "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==",
994 | "dev": true,
995 | "funding": [
996 | {
997 | "type": "GitHub Sponsors",
998 | "url": "https://github.com/sponsors/unifiedjs"
999 | },
1000 | {
1001 | "type": "OpenCollective",
1002 | "url": "https://opencollective.com/unified"
1003 | }
1004 | ],
1005 | "dependencies": {
1006 | "micromark-factory-space": "^2.0.0",
1007 | "micromark-util-character": "^2.0.0",
1008 | "micromark-util-symbol": "^2.0.0",
1009 | "micromark-util-types": "^2.0.0"
1010 | }
1011 | },
1012 | "node_modules/micromark-factory-whitespace": {
1013 | "version": "2.0.0",
1014 | "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz",
1015 | "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==",
1016 | "dev": true,
1017 | "funding": [
1018 | {
1019 | "type": "GitHub Sponsors",
1020 | "url": "https://github.com/sponsors/unifiedjs"
1021 | },
1022 | {
1023 | "type": "OpenCollective",
1024 | "url": "https://opencollective.com/unified"
1025 | }
1026 | ],
1027 | "dependencies": {
1028 | "micromark-factory-space": "^2.0.0",
1029 | "micromark-util-character": "^2.0.0",
1030 | "micromark-util-symbol": "^2.0.0",
1031 | "micromark-util-types": "^2.0.0"
1032 | }
1033 | },
1034 | "node_modules/micromark-util-character": {
1035 | "version": "2.0.1",
1036 | "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz",
1037 | "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==",
1038 | "dev": true,
1039 | "funding": [
1040 | {
1041 | "type": "GitHub Sponsors",
1042 | "url": "https://github.com/sponsors/unifiedjs"
1043 | },
1044 | {
1045 | "type": "OpenCollective",
1046 | "url": "https://opencollective.com/unified"
1047 | }
1048 | ],
1049 | "dependencies": {
1050 | "micromark-util-symbol": "^2.0.0",
1051 | "micromark-util-types": "^2.0.0"
1052 | }
1053 | },
1054 | "node_modules/micromark-util-chunked": {
1055 | "version": "2.0.0",
1056 | "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz",
1057 | "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==",
1058 | "dev": true,
1059 | "funding": [
1060 | {
1061 | "type": "GitHub Sponsors",
1062 | "url": "https://github.com/sponsors/unifiedjs"
1063 | },
1064 | {
1065 | "type": "OpenCollective",
1066 | "url": "https://opencollective.com/unified"
1067 | }
1068 | ],
1069 | "dependencies": {
1070 | "micromark-util-symbol": "^2.0.0"
1071 | }
1072 | },
1073 | "node_modules/micromark-util-classify-character": {
1074 | "version": "2.0.0",
1075 | "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz",
1076 | "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==",
1077 | "dev": true,
1078 | "funding": [
1079 | {
1080 | "type": "GitHub Sponsors",
1081 | "url": "https://github.com/sponsors/unifiedjs"
1082 | },
1083 | {
1084 | "type": "OpenCollective",
1085 | "url": "https://opencollective.com/unified"
1086 | }
1087 | ],
1088 | "dependencies": {
1089 | "micromark-util-character": "^2.0.0",
1090 | "micromark-util-symbol": "^2.0.0",
1091 | "micromark-util-types": "^2.0.0"
1092 | }
1093 | },
1094 | "node_modules/micromark-util-combine-extensions": {
1095 | "version": "2.0.0",
1096 | "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz",
1097 | "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==",
1098 | "dev": true,
1099 | "funding": [
1100 | {
1101 | "type": "GitHub Sponsors",
1102 | "url": "https://github.com/sponsors/unifiedjs"
1103 | },
1104 | {
1105 | "type": "OpenCollective",
1106 | "url": "https://opencollective.com/unified"
1107 | }
1108 | ],
1109 | "dependencies": {
1110 | "micromark-util-chunked": "^2.0.0",
1111 | "micromark-util-types": "^2.0.0"
1112 | }
1113 | },
1114 | "node_modules/micromark-util-decode-numeric-character-reference": {
1115 | "version": "2.0.0",
1116 | "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.0.tgz",
1117 | "integrity": "sha512-pIgcsGxpHEtTG/rPJRz/HOLSqp5VTuIIjXlPI+6JSDlK2oljApusG6KzpS8AF0ENUMCHlC/IBb5B9xdFiVlm5Q==",
1118 | "dev": true,
1119 | "funding": [
1120 | {
1121 | "type": "GitHub Sponsors",
1122 | "url": "https://github.com/sponsors/unifiedjs"
1123 | },
1124 | {
1125 | "type": "OpenCollective",
1126 | "url": "https://opencollective.com/unified"
1127 | }
1128 | ],
1129 | "dependencies": {
1130 | "micromark-util-symbol": "^2.0.0"
1131 | }
1132 | },
1133 | "node_modules/micromark-util-decode-string": {
1134 | "version": "2.0.0",
1135 | "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz",
1136 | "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==",
1137 | "dev": true,
1138 | "funding": [
1139 | {
1140 | "type": "GitHub Sponsors",
1141 | "url": "https://github.com/sponsors/unifiedjs"
1142 | },
1143 | {
1144 | "type": "OpenCollective",
1145 | "url": "https://opencollective.com/unified"
1146 | }
1147 | ],
1148 | "dependencies": {
1149 | "decode-named-character-reference": "^1.0.0",
1150 | "micromark-util-character": "^2.0.0",
1151 | "micromark-util-decode-numeric-character-reference": "^2.0.0",
1152 | "micromark-util-symbol": "^2.0.0"
1153 | }
1154 | },
1155 | "node_modules/micromark-util-encode": {
1156 | "version": "2.0.0",
1157 | "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz",
1158 | "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==",
1159 | "dev": true,
1160 | "funding": [
1161 | {
1162 | "type": "GitHub Sponsors",
1163 | "url": "https://github.com/sponsors/unifiedjs"
1164 | },
1165 | {
1166 | "type": "OpenCollective",
1167 | "url": "https://opencollective.com/unified"
1168 | }
1169 | ]
1170 | },
1171 | "node_modules/micromark-util-html-tag-name": {
1172 | "version": "2.0.0",
1173 | "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz",
1174 | "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==",
1175 | "dev": true,
1176 | "funding": [
1177 | {
1178 | "type": "GitHub Sponsors",
1179 | "url": "https://github.com/sponsors/unifiedjs"
1180 | },
1181 | {
1182 | "type": "OpenCollective",
1183 | "url": "https://opencollective.com/unified"
1184 | }
1185 | ]
1186 | },
1187 | "node_modules/micromark-util-normalize-identifier": {
1188 | "version": "2.0.0",
1189 | "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz",
1190 | "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==",
1191 | "dev": true,
1192 | "funding": [
1193 | {
1194 | "type": "GitHub Sponsors",
1195 | "url": "https://github.com/sponsors/unifiedjs"
1196 | },
1197 | {
1198 | "type": "OpenCollective",
1199 | "url": "https://opencollective.com/unified"
1200 | }
1201 | ],
1202 | "dependencies": {
1203 | "micromark-util-symbol": "^2.0.0"
1204 | }
1205 | },
1206 | "node_modules/micromark-util-resolve-all": {
1207 | "version": "2.0.0",
1208 | "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz",
1209 | "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==",
1210 | "dev": true,
1211 | "funding": [
1212 | {
1213 | "type": "GitHub Sponsors",
1214 | "url": "https://github.com/sponsors/unifiedjs"
1215 | },
1216 | {
1217 | "type": "OpenCollective",
1218 | "url": "https://opencollective.com/unified"
1219 | }
1220 | ],
1221 | "dependencies": {
1222 | "micromark-util-types": "^2.0.0"
1223 | }
1224 | },
1225 | "node_modules/micromark-util-sanitize-uri": {
1226 | "version": "2.0.0",
1227 | "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz",
1228 | "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==",
1229 | "dev": true,
1230 | "funding": [
1231 | {
1232 | "type": "GitHub Sponsors",
1233 | "url": "https://github.com/sponsors/unifiedjs"
1234 | },
1235 | {
1236 | "type": "OpenCollective",
1237 | "url": "https://opencollective.com/unified"
1238 | }
1239 | ],
1240 | "dependencies": {
1241 | "micromark-util-character": "^2.0.0",
1242 | "micromark-util-encode": "^2.0.0",
1243 | "micromark-util-symbol": "^2.0.0"
1244 | }
1245 | },
1246 | "node_modules/micromark-util-subtokenize": {
1247 | "version": "2.0.0",
1248 | "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz",
1249 | "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==",
1250 | "dev": true,
1251 | "funding": [
1252 | {
1253 | "type": "GitHub Sponsors",
1254 | "url": "https://github.com/sponsors/unifiedjs"
1255 | },
1256 | {
1257 | "type": "OpenCollective",
1258 | "url": "https://opencollective.com/unified"
1259 | }
1260 | ],
1261 | "dependencies": {
1262 | "devlop": "^1.0.0",
1263 | "micromark-util-chunked": "^2.0.0",
1264 | "micromark-util-symbol": "^2.0.0",
1265 | "micromark-util-types": "^2.0.0"
1266 | }
1267 | },
1268 | "node_modules/micromark-util-symbol": {
1269 | "version": "2.0.0",
1270 | "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz",
1271 | "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==",
1272 | "dev": true,
1273 | "funding": [
1274 | {
1275 | "type": "GitHub Sponsors",
1276 | "url": "https://github.com/sponsors/unifiedjs"
1277 | },
1278 | {
1279 | "type": "OpenCollective",
1280 | "url": "https://opencollective.com/unified"
1281 | }
1282 | ]
1283 | },
1284 | "node_modules/micromark-util-types": {
1285 | "version": "2.0.0",
1286 | "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz",
1287 | "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==",
1288 | "dev": true,
1289 | "funding": [
1290 | {
1291 | "type": "GitHub Sponsors",
1292 | "url": "https://github.com/sponsors/unifiedjs"
1293 | },
1294 | {
1295 | "type": "OpenCollective",
1296 | "url": "https://opencollective.com/unified"
1297 | }
1298 | ]
1299 | },
1300 | "node_modules/micromark/node_modules/debug": {
1301 | "version": "4.3.4",
1302 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
1303 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
1304 | "dev": true,
1305 | "dependencies": {
1306 | "ms": "2.1.2"
1307 | },
1308 | "engines": {
1309 | "node": ">=6.0"
1310 | },
1311 | "peerDependenciesMeta": {
1312 | "supports-color": {
1313 | "optional": true
1314 | }
1315 | }
1316 | },
1317 | "node_modules/micromark/node_modules/ms": {
1318 | "version": "2.1.2",
1319 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1320 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
1321 | "dev": true
1322 | },
1323 | "node_modules/mime": {
1324 | "version": "1.6.0",
1325 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
1326 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
1327 | "dev": true,
1328 | "bin": {
1329 | "mime": "cli.js"
1330 | },
1331 | "engines": {
1332 | "node": ">=4"
1333 | }
1334 | },
1335 | "node_modules/minimatch": {
1336 | "version": "5.1.6",
1337 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
1338 | "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
1339 | "dev": true,
1340 | "dependencies": {
1341 | "brace-expansion": "^2.0.1"
1342 | },
1343 | "engines": {
1344 | "node": ">=10"
1345 | }
1346 | },
1347 | "node_modules/minimist": {
1348 | "version": "1.2.8",
1349 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
1350 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
1351 | "dev": true,
1352 | "funding": {
1353 | "url": "https://github.com/sponsors/ljharb"
1354 | }
1355 | },
1356 | "node_modules/mkdirp": {
1357 | "version": "0.5.6",
1358 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
1359 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
1360 | "dev": true,
1361 | "dependencies": {
1362 | "minimist": "^1.2.6"
1363 | },
1364 | "bin": {
1365 | "mkdirp": "bin/cmd.js"
1366 | }
1367 | },
1368 | "node_modules/module-workers-polyfill": {
1369 | "version": "0.3.2",
1370 | "resolved": "https://registry.npmjs.org/module-workers-polyfill/-/module-workers-polyfill-0.3.2.tgz",
1371 | "integrity": "sha512-zcEMj8vUGYu1Tc5s2GK84MBzRSweec/Ef6F7phRF8QlTfTf2upFNsR3W0lDhvN2E6o1TTXbFIYynD0rQSlynPw==",
1372 | "dev": true
1373 | },
1374 | "node_modules/mri": {
1375 | "version": "1.2.0",
1376 | "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
1377 | "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
1378 | "dev": true,
1379 | "engines": {
1380 | "node": ">=4"
1381 | }
1382 | },
1383 | "node_modules/ms": {
1384 | "version": "2.1.3",
1385 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1386 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1387 | "dev": true
1388 | },
1389 | "node_modules/node-domexception": {
1390 | "version": "1.0.0",
1391 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
1392 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
1393 | "dev": true,
1394 | "funding": [
1395 | {
1396 | "type": "github",
1397 | "url": "https://github.com/sponsors/jimmywarting"
1398 | },
1399 | {
1400 | "type": "github",
1401 | "url": "https://paypal.me/jimmywarting"
1402 | }
1403 | ],
1404 | "engines": {
1405 | "node": ">=10.5.0"
1406 | }
1407 | },
1408 | "node_modules/node-fetch": {
1409 | "version": "3.3.2",
1410 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
1411 | "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
1412 | "dev": true,
1413 | "dependencies": {
1414 | "data-uri-to-buffer": "^4.0.0",
1415 | "fetch-blob": "^3.1.4",
1416 | "formdata-polyfill": "^4.0.10"
1417 | },
1418 | "engines": {
1419 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
1420 | },
1421 | "funding": {
1422 | "type": "opencollective",
1423 | "url": "https://opencollective.com/node-fetch"
1424 | }
1425 | },
1426 | "node_modules/npm-bundled": {
1427 | "version": "2.0.1",
1428 | "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz",
1429 | "integrity": "sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==",
1430 | "dev": true,
1431 | "dependencies": {
1432 | "npm-normalize-package-bin": "^2.0.0"
1433 | },
1434 | "engines": {
1435 | "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
1436 | }
1437 | },
1438 | "node_modules/npm-normalize-package-bin": {
1439 | "version": "2.0.0",
1440 | "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz",
1441 | "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==",
1442 | "dev": true,
1443 | "engines": {
1444 | "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
1445 | }
1446 | },
1447 | "node_modules/npm-packlist": {
1448 | "version": "5.1.3",
1449 | "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz",
1450 | "integrity": "sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==",
1451 | "dev": true,
1452 | "dependencies": {
1453 | "glob": "^8.0.1",
1454 | "ignore-walk": "^5.0.1",
1455 | "npm-bundled": "^2.0.0",
1456 | "npm-normalize-package-bin": "^2.0.0"
1457 | },
1458 | "bin": {
1459 | "npm-packlist": "bin/index.js"
1460 | },
1461 | "engines": {
1462 | "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
1463 | }
1464 | },
1465 | "node_modules/object-assign": {
1466 | "version": "4.1.1",
1467 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1468 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
1469 | "dev": true,
1470 | "engines": {
1471 | "node": ">=0.10.0"
1472 | }
1473 | },
1474 | "node_modules/object-inspect": {
1475 | "version": "1.12.3",
1476 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
1477 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
1478 | "dev": true,
1479 | "funding": {
1480 | "url": "https://github.com/sponsors/ljharb"
1481 | }
1482 | },
1483 | "node_modules/once": {
1484 | "version": "1.4.0",
1485 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1486 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1487 | "dev": true,
1488 | "dependencies": {
1489 | "wrappy": "1"
1490 | }
1491 | },
1492 | "node_modules/opener": {
1493 | "version": "1.5.2",
1494 | "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
1495 | "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
1496 | "dev": true,
1497 | "bin": {
1498 | "opener": "bin/opener-bin.js"
1499 | }
1500 | },
1501 | "node_modules/path-is-absolute": {
1502 | "version": "1.0.1",
1503 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1504 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
1505 | "dev": true,
1506 | "engines": {
1507 | "node": ">=0.10.0"
1508 | }
1509 | },
1510 | "node_modules/path-parse": {
1511 | "version": "1.0.7",
1512 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
1513 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
1514 | "dev": true
1515 | },
1516 | "node_modules/pend": {
1517 | "version": "1.2.0",
1518 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
1519 | "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
1520 | "dev": true
1521 | },
1522 | "node_modules/picocolors": {
1523 | "version": "1.0.0",
1524 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
1525 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
1526 | "dev": true
1527 | },
1528 | "node_modules/pify": {
1529 | "version": "2.3.0",
1530 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
1531 | "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
1532 | "dev": true,
1533 | "engines": {
1534 | "node": ">=0.10.0"
1535 | }
1536 | },
1537 | "node_modules/pinkie": {
1538 | "version": "2.0.4",
1539 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
1540 | "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
1541 | "dev": true,
1542 | "engines": {
1543 | "node": ">=0.10.0"
1544 | }
1545 | },
1546 | "node_modules/pinkie-promise": {
1547 | "version": "2.0.1",
1548 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
1549 | "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
1550 | "dev": true,
1551 | "dependencies": {
1552 | "pinkie": "^2.0.0"
1553 | },
1554 | "engines": {
1555 | "node": ">=0.10.0"
1556 | }
1557 | },
1558 | "node_modules/portfinder": {
1559 | "version": "1.0.32",
1560 | "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
1561 | "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==",
1562 | "dev": true,
1563 | "dependencies": {
1564 | "async": "^2.6.4",
1565 | "debug": "^3.2.7",
1566 | "mkdirp": "^0.5.6"
1567 | },
1568 | "engines": {
1569 | "node": ">= 0.12.0"
1570 | }
1571 | },
1572 | "node_modules/prettier": {
1573 | "version": "3.2.4",
1574 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz",
1575 | "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==",
1576 | "dev": true,
1577 | "bin": {
1578 | "prettier": "bin/prettier.cjs"
1579 | },
1580 | "engines": {
1581 | "node": ">=14"
1582 | },
1583 | "funding": {
1584 | "url": "https://github.com/prettier/prettier?sponsor=1"
1585 | }
1586 | },
1587 | "node_modules/prettier-plugin-jsdoc": {
1588 | "version": "1.3.0",
1589 | "resolved": "https://registry.npmjs.org/prettier-plugin-jsdoc/-/prettier-plugin-jsdoc-1.3.0.tgz",
1590 | "integrity": "sha512-cQm8xIa0fN9ieJFMXACQd6JPycl+8ouOijAqUqu44EF/s4fXL3Wi9sKXuEaodsEWgCN42Xby/bNhqgM1iWx4uw==",
1591 | "dev": true,
1592 | "dependencies": {
1593 | "binary-searching": "^2.0.5",
1594 | "comment-parser": "^1.4.0",
1595 | "mdast-util-from-markdown": "^2.0.0"
1596 | },
1597 | "engines": {
1598 | "node": ">=14.13.1 || >=16.0.0"
1599 | },
1600 | "peerDependencies": {
1601 | "prettier": "^3.0.0"
1602 | }
1603 | },
1604 | "node_modules/process-nextick-args": {
1605 | "version": "2.0.1",
1606 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
1607 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
1608 | "dev": true
1609 | },
1610 | "node_modules/publint": {
1611 | "version": "0.2.7",
1612 | "resolved": "https://registry.npmjs.org/publint/-/publint-0.2.7.tgz",
1613 | "integrity": "sha512-tLU4ee3110BxWfAmCZggJmCUnYWgPTr0QLnx08sqpLYa8JHRiOudd+CgzdpfU5x5eOaW2WMkpmOrFshRFYK7Mw==",
1614 | "dev": true,
1615 | "dependencies": {
1616 | "npm-packlist": "^5.1.3",
1617 | "picocolors": "^1.0.0",
1618 | "sade": "^1.8.1"
1619 | },
1620 | "bin": {
1621 | "publint": "lib/cli.js"
1622 | },
1623 | "engines": {
1624 | "node": ">=16"
1625 | },
1626 | "funding": {
1627 | "url": "https://bjornlu.com/sponsor"
1628 | }
1629 | },
1630 | "node_modules/qs": {
1631 | "version": "6.11.1",
1632 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz",
1633 | "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==",
1634 | "dev": true,
1635 | "dependencies": {
1636 | "side-channel": "^1.0.4"
1637 | },
1638 | "engines": {
1639 | "node": ">=0.6"
1640 | },
1641 | "funding": {
1642 | "url": "https://github.com/sponsors/ljharb"
1643 | }
1644 | },
1645 | "node_modules/readable-stream": {
1646 | "version": "2.3.8",
1647 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
1648 | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
1649 | "dev": true,
1650 | "dependencies": {
1651 | "core-util-is": "~1.0.0",
1652 | "inherits": "~2.0.3",
1653 | "isarray": "~1.0.0",
1654 | "process-nextick-args": "~2.0.0",
1655 | "safe-buffer": "~5.1.1",
1656 | "string_decoder": "~1.1.1",
1657 | "util-deprecate": "~1.0.1"
1658 | }
1659 | },
1660 | "node_modules/rechoir": {
1661 | "version": "0.6.2",
1662 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
1663 | "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
1664 | "dev": true,
1665 | "dependencies": {
1666 | "resolve": "^1.1.6"
1667 | },
1668 | "engines": {
1669 | "node": ">= 0.10"
1670 | }
1671 | },
1672 | "node_modules/requires-port": {
1673 | "version": "1.0.0",
1674 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
1675 | "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
1676 | "dev": true
1677 | },
1678 | "node_modules/resolve": {
1679 | "version": "1.22.2",
1680 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
1681 | "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
1682 | "dev": true,
1683 | "dependencies": {
1684 | "is-core-module": "^2.11.0",
1685 | "path-parse": "^1.0.7",
1686 | "supports-preserve-symlinks-flag": "^1.0.0"
1687 | },
1688 | "bin": {
1689 | "resolve": "bin/resolve"
1690 | },
1691 | "funding": {
1692 | "url": "https://github.com/sponsors/ljharb"
1693 | }
1694 | },
1695 | "node_modules/sade": {
1696 | "version": "1.8.1",
1697 | "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
1698 | "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
1699 | "dev": true,
1700 | "dependencies": {
1701 | "mri": "^1.1.0"
1702 | },
1703 | "engines": {
1704 | "node": ">=6"
1705 | }
1706 | },
1707 | "node_modules/safe-buffer": {
1708 | "version": "5.1.2",
1709 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
1710 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
1711 | "dev": true
1712 | },
1713 | "node_modules/safer-buffer": {
1714 | "version": "2.1.2",
1715 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1716 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
1717 | "dev": true
1718 | },
1719 | "node_modules/secure-compare": {
1720 | "version": "3.0.1",
1721 | "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
1722 | "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==",
1723 | "dev": true
1724 | },
1725 | "node_modules/seek-bzip": {
1726 | "version": "1.0.6",
1727 | "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz",
1728 | "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==",
1729 | "dev": true,
1730 | "dependencies": {
1731 | "commander": "^2.8.1"
1732 | },
1733 | "bin": {
1734 | "seek-bunzip": "bin/seek-bunzip",
1735 | "seek-table": "bin/seek-bzip-table"
1736 | }
1737 | },
1738 | "node_modules/shelljs": {
1739 | "version": "0.8.5",
1740 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
1741 | "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
1742 | "dev": true,
1743 | "dependencies": {
1744 | "glob": "^7.0.0",
1745 | "interpret": "^1.0.0",
1746 | "rechoir": "^0.6.2"
1747 | },
1748 | "bin": {
1749 | "shjs": "bin/shjs"
1750 | },
1751 | "engines": {
1752 | "node": ">=4"
1753 | }
1754 | },
1755 | "node_modules/shelljs/node_modules/brace-expansion": {
1756 | "version": "1.1.11",
1757 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1758 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1759 | "dev": true,
1760 | "dependencies": {
1761 | "balanced-match": "^1.0.0",
1762 | "concat-map": "0.0.1"
1763 | }
1764 | },
1765 | "node_modules/shelljs/node_modules/glob": {
1766 | "version": "7.2.3",
1767 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
1768 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
1769 | "dev": true,
1770 | "dependencies": {
1771 | "fs.realpath": "^1.0.0",
1772 | "inflight": "^1.0.4",
1773 | "inherits": "2",
1774 | "minimatch": "^3.1.1",
1775 | "once": "^1.3.0",
1776 | "path-is-absolute": "^1.0.0"
1777 | },
1778 | "engines": {
1779 | "node": "*"
1780 | },
1781 | "funding": {
1782 | "url": "https://github.com/sponsors/isaacs"
1783 | }
1784 | },
1785 | "node_modules/shelljs/node_modules/minimatch": {
1786 | "version": "3.1.2",
1787 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1788 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1789 | "dev": true,
1790 | "dependencies": {
1791 | "brace-expansion": "^1.1.7"
1792 | },
1793 | "engines": {
1794 | "node": "*"
1795 | }
1796 | },
1797 | "node_modules/shx": {
1798 | "version": "0.3.4",
1799 | "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz",
1800 | "integrity": "sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==",
1801 | "dev": true,
1802 | "dependencies": {
1803 | "minimist": "^1.2.3",
1804 | "shelljs": "^0.8.5"
1805 | },
1806 | "bin": {
1807 | "shx": "lib/cli.js"
1808 | },
1809 | "engines": {
1810 | "node": ">=6"
1811 | }
1812 | },
1813 | "node_modules/side-channel": {
1814 | "version": "1.0.4",
1815 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
1816 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
1817 | "dev": true,
1818 | "dependencies": {
1819 | "call-bind": "^1.0.0",
1820 | "get-intrinsic": "^1.0.2",
1821 | "object-inspect": "^1.9.0"
1822 | },
1823 | "funding": {
1824 | "url": "https://github.com/sponsors/ljharb"
1825 | }
1826 | },
1827 | "node_modules/string_decoder": {
1828 | "version": "1.1.1",
1829 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
1830 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
1831 | "dev": true,
1832 | "dependencies": {
1833 | "safe-buffer": "~5.1.0"
1834 | }
1835 | },
1836 | "node_modules/strip-dirs": {
1837 | "version": "2.1.0",
1838 | "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz",
1839 | "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==",
1840 | "dev": true,
1841 | "dependencies": {
1842 | "is-natural-number": "^4.0.1"
1843 | }
1844 | },
1845 | "node_modules/supports-color": {
1846 | "version": "7.2.0",
1847 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1848 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1849 | "dev": true,
1850 | "dependencies": {
1851 | "has-flag": "^4.0.0"
1852 | },
1853 | "engines": {
1854 | "node": ">=8"
1855 | }
1856 | },
1857 | "node_modules/supports-preserve-symlinks-flag": {
1858 | "version": "1.0.0",
1859 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1860 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1861 | "dev": true,
1862 | "engines": {
1863 | "node": ">= 0.4"
1864 | },
1865 | "funding": {
1866 | "url": "https://github.com/sponsors/ljharb"
1867 | }
1868 | },
1869 | "node_modules/tar-stream": {
1870 | "version": "1.6.2",
1871 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
1872 | "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
1873 | "dev": true,
1874 | "dependencies": {
1875 | "bl": "^1.0.0",
1876 | "buffer-alloc": "^1.2.0",
1877 | "end-of-stream": "^1.0.0",
1878 | "fs-constants": "^1.0.0",
1879 | "readable-stream": "^2.3.0",
1880 | "to-buffer": "^1.1.1",
1881 | "xtend": "^4.0.0"
1882 | },
1883 | "engines": {
1884 | "node": ">= 0.8.0"
1885 | }
1886 | },
1887 | "node_modules/through": {
1888 | "version": "2.3.8",
1889 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
1890 | "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
1891 | "dev": true
1892 | },
1893 | "node_modules/to-buffer": {
1894 | "version": "1.1.1",
1895 | "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
1896 | "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==",
1897 | "dev": true
1898 | },
1899 | "node_modules/unbzip2-stream": {
1900 | "version": "1.4.3",
1901 | "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
1902 | "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
1903 | "dev": true,
1904 | "dependencies": {
1905 | "buffer": "^5.2.1",
1906 | "through": "^2.3.8"
1907 | }
1908 | },
1909 | "node_modules/union": {
1910 | "version": "0.5.0",
1911 | "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz",
1912 | "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==",
1913 | "dev": true,
1914 | "dependencies": {
1915 | "qs": "^6.4.0"
1916 | },
1917 | "engines": {
1918 | "node": ">= 0.8.0"
1919 | }
1920 | },
1921 | "node_modules/unist-util-stringify-position": {
1922 | "version": "4.0.0",
1923 | "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
1924 | "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
1925 | "dev": true,
1926 | "dependencies": {
1927 | "@types/unist": "^3.0.0"
1928 | },
1929 | "funding": {
1930 | "type": "opencollective",
1931 | "url": "https://opencollective.com/unified"
1932 | }
1933 | },
1934 | "node_modules/url-join": {
1935 | "version": "4.0.1",
1936 | "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
1937 | "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
1938 | "dev": true
1939 | },
1940 | "node_modules/util-deprecate": {
1941 | "version": "1.0.2",
1942 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1943 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
1944 | "dev": true
1945 | },
1946 | "node_modules/web-streams-polyfill": {
1947 | "version": "3.2.1",
1948 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
1949 | "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
1950 | "dev": true,
1951 | "engines": {
1952 | "node": ">= 8"
1953 | }
1954 | },
1955 | "node_modules/whatwg-encoding": {
1956 | "version": "2.0.0",
1957 | "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
1958 | "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
1959 | "dev": true,
1960 | "dependencies": {
1961 | "iconv-lite": "0.6.3"
1962 | },
1963 | "engines": {
1964 | "node": ">=12"
1965 | }
1966 | },
1967 | "node_modules/wrappy": {
1968 | "version": "1.0.2",
1969 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1970 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
1971 | "dev": true
1972 | },
1973 | "node_modules/xtend": {
1974 | "version": "4.0.2",
1975 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
1976 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
1977 | "dev": true,
1978 | "engines": {
1979 | "node": ">=0.4"
1980 | }
1981 | },
1982 | "node_modules/yauzl": {
1983 | "version": "2.10.0",
1984 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
1985 | "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
1986 | "dev": true,
1987 | "dependencies": {
1988 | "buffer-crc32": "~0.2.3",
1989 | "fd-slicer": "~1.1.0"
1990 | }
1991 | }
1992 | }
1993 | }
1994 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@livestore/sqlite-wasm",
3 | "version": "3.46.0-build4",
4 | "description": "SQLite Wasm conveniently wrapped as an ES Module.",
5 | "keywords": [
6 | "sqlite",
7 | "sqlite3",
8 | "sqlite-wasm",
9 | "sqlite3-wasm",
10 | "webassembly",
11 | "wasm",
12 | "esm",
13 | "opfs",
14 | "origin-private-file-system"
15 | ],
16 | "main": "index.mjs",
17 | "type": "module",
18 | "files": [
19 | "index.d.ts",
20 | "index.mjs",
21 | "sqlite-wasm/"
22 | ],
23 | "types": "index.d.ts",
24 | "exports": {
25 | ".": {
26 | "types": "./index.d.ts",
27 | "import": "./index.mjs",
28 | "main": "./index.mjs",
29 | "node": "./sqlite-wasm/jswasm/sqlite3-node.mjs",
30 | "browser": "./index.mjs"
31 | },
32 | "./node": {
33 | "types": "./index.d.ts",
34 | "default": "./sqlite-wasm/jswasm/sqlite3-node.mjs"
35 | },
36 | "./package.json": "./package.json"
37 | },
38 | "bin": {
39 | "sqlite-wasm": "bin/index.js"
40 | },
41 | "scripts": {
42 | "publint": "npx publint",
43 | "clean": "shx rm -rf sqlite-wasm",
44 | "build": "echo Already manually built SQLite Wasm.",
45 | "start": "npx http-server --coop",
46 | "fix": "npx prettier . --write",
47 | "prepare": "npm run build && npm run fix && npm run publint",
48 | "deploy": "npm run prepare && git add . && git commit -am 'New release' && git push && npm publish --access public"
49 | },
50 | "repository": {
51 | "type": "git",
52 | "url": "git+https://github.com/sqlite/sqlite-wasm.git"
53 | },
54 | "author": "Johannes Schickling",
55 | "license": "Apache-2.0",
56 | "bugs": {
57 | "url": "https://github.com/sqlite/sqlite-wasm/issues"
58 | },
59 | "homepage": "https://github.com/sqlite/sqlite-wasm#readme",
60 | "devDependencies": {
61 | "decompress": "^4.2.1",
62 | "http-server": "github:vapier/http-server",
63 | "module-workers-polyfill": "^0.3.2",
64 | "node-fetch": "^3.3.2",
65 | "prettier": "^3.2.4",
66 | "publint": "^0.2.7",
67 | "prettier-plugin-jsdoc": "^1.3.0",
68 | "shx": "^0.3.4"
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/sqlite-wasm/.gitignore:
--------------------------------------------------------------------------------
1 | speedtest*
2 | sqlite3-api*
--------------------------------------------------------------------------------
/sqlite-wasm/jswasm/sqlite3-opfs-async-proxy.js:
--------------------------------------------------------------------------------
1 | /*
2 | 2022-09-16
3 |
4 | The author disclaims copyright to this source code. In place of a
5 | legal notice, here is a blessing:
6 |
7 | * May you do good and not evil.
8 | * May you find forgiveness for yourself and forgive others.
9 | * May you share freely, never taking more than you give.
10 |
11 | ***********************************************************************
12 |
13 | A Worker which manages asynchronous OPFS handles on behalf of a
14 | synchronous API which controls it via a combination of Worker
15 | messages, SharedArrayBuffer, and Atomics. It is the asynchronous
16 | counterpart of the API defined in sqlite3-vfs-opfs.js.
17 |
18 | Highly indebted to:
19 |
20 | https://github.com/rhashimoto/wa-sqlite/blob/master/src/examples/OriginPrivateFileSystemVFS.js
21 |
22 | for demonstrating how to use the OPFS APIs.
23 |
24 | This file is to be loaded as a Worker. It does not have any direct
25 | access to the sqlite3 JS/WASM bits, so any bits which it needs (most
26 | notably SQLITE_xxx integer codes) have to be imported into it via an
27 | initialization process.
28 |
29 | This file represents an implementation detail of a larger piece of
30 | code, and not a public interface. Its details may change at any time
31 | and are not intended to be used by any client-level code.
32 |
33 | 2022-11-27: Chrome v108 changes some async methods to synchronous, as
34 | documented at:
35 |
36 | https://developer.chrome.com/blog/sync-methods-for-accesshandles/
37 |
38 | Firefox v111 and Safari 16.4, both released in March 2023, also
39 | include this.
40 |
41 | We cannot change to the sync forms at this point without breaking
42 | clients who use Chrome v104-ish or higher. truncate(), getSize(),
43 | flush(), and close() are now (as of v108) synchronous. Calling them
44 | with an "await", as we have to for the async forms, is still legal
45 | with the sync forms but is superfluous. Calling the async forms with
46 | theFunc().then(...) is not compatible with the change to
47 | synchronous, but we do do not use those APIs that way. i.e. we don't
48 | _need_ to change anything for this, but at some point (after Chrome
49 | versions (approximately) 104-107 are extinct) should change our
50 | usage of those methods to remove the "await".
51 | */
52 | 'use strict';
53 | const wPost = (type, ...args) => postMessage({ type, payload: args });
54 | const installAsyncProxy = function (self) {
55 | const toss = function (...args) {
56 | throw new Error(args.join(' '));
57 | };
58 | if (globalThis.window === globalThis) {
59 | toss(
60 | 'This code cannot run from the main thread.',
61 | 'Load it as a Worker from a separate Worker.',
62 | );
63 | } else if (!navigator?.storage?.getDirectory) {
64 | toss('This API requires navigator.storage.getDirectory.');
65 | }
66 |
67 | /** Will hold state copied to this object from the syncronous side of this API. */
68 | const state = Object.create(null);
69 |
70 | /**
71 | * Verbose:
72 | *
73 | * 0 = no logging output
74 | * 1 = only errors
75 | * 2 = warnings and errors
76 | * 3 = debug, warnings, and errors
77 | */
78 | state.verbose = 1;
79 |
80 | const loggers = {
81 | 0: console.error.bind(console),
82 | 1: console.warn.bind(console),
83 | 2: console.log.bind(console),
84 | };
85 | const logImpl = (level, ...args) => {
86 | if (state.verbose > level) loggers[level]('OPFS asyncer:', ...args);
87 | };
88 | const log = (...args) => logImpl(2, ...args);
89 | const warn = (...args) => logImpl(1, ...args);
90 | const error = (...args) => logImpl(0, ...args);
91 | const metrics = Object.create(null);
92 | metrics.reset = () => {
93 | let k;
94 | const r = (m) => (m.count = m.time = m.wait = 0);
95 | for (k in state.opIds) {
96 | r((metrics[k] = Object.create(null)));
97 | }
98 | let s = (metrics.s11n = Object.create(null));
99 | s = s.serialize = Object.create(null);
100 | s.count = s.time = 0;
101 | s = metrics.s11n.deserialize = Object.create(null);
102 | s.count = s.time = 0;
103 | };
104 | metrics.dump = () => {
105 | let k,
106 | n = 0,
107 | t = 0,
108 | w = 0;
109 | for (k in state.opIds) {
110 | const m = metrics[k];
111 | n += m.count;
112 | t += m.time;
113 | w += m.wait;
114 | m.avgTime = m.count && m.time ? m.time / m.count : 0;
115 | }
116 | console.log(
117 | globalThis?.location?.href,
118 | 'metrics for',
119 | globalThis?.location?.href,
120 | ':\n',
121 | metrics,
122 | '\nTotal of',
123 | n,
124 | 'op(s) for',
125 | t,
126 | 'ms',
127 | 'approx',
128 | w,
129 | 'ms spent waiting on OPFS APIs.',
130 | );
131 | console.log('Serialization metrics:', metrics.s11n);
132 | };
133 |
134 | /**
135 | * __openFiles is a map of sqlite3_file pointers (integers) to metadata
136 | * related to a given OPFS file handles. The pointers are, in this side of the
137 | * interface, opaque file handle IDs provided by the synchronous part of this
138 | * constellation. Each value is an object with a structure demonstrated in the
139 | * xOpen() impl.
140 | */
141 | const __openFiles = Object.create(null);
142 | /**
143 | * __implicitLocks is a Set of sqlite3_file pointers (integers) which were
144 | * "auto-locked". i.e. those for which we obtained a sync access handle
145 | * without an explicit xLock() call. Such locks will be released during db
146 | * connection idle time, whereas a sync access handle obtained via xLock(), or
147 | * subsequently xLock()'d after auto-acquisition, will not be released until
148 | * xUnlock() is called.
149 | *
150 | * Maintenance reminder: if we relinquish auto-locks at the end of the
151 | * operation which acquires them, we pay a massive performance
152 | * penalty: speedtest1 benchmarks take up to 4x as long. By delaying
153 | * the lock release until idle time, the hit is negligible.
154 | */
155 | const __implicitLocks = new Set();
156 |
157 | /**
158 | * Expects an OPFS file path. It gets resolved, such that ".." components are
159 | * properly expanded, and returned. If the 2nd arg is true, the result is
160 | * returned as an array of path elements, else an absolute path string is
161 | * returned.
162 | */
163 | const getResolvedPath = function (filename, splitIt) {
164 | const p = new URL(filename, 'file://irrelevant').pathname;
165 | return splitIt ? p.split('/').filter((v) => !!v) : p;
166 | };
167 |
168 | /**
169 | * Takes the absolute path to a filesystem element. Returns an array of
170 | * [handleOfContainingDir, filename]. If the 2nd argument is truthy then each
171 | * directory element leading to the file is created along the way. Throws if
172 | * any creation or resolution fails.
173 | */
174 | const getDirForFilename = async function f(absFilename, createDirs = false) {
175 | const path = getResolvedPath(absFilename, true);
176 | const filename = path.pop();
177 | let dh = state.rootDir;
178 | for (const dirName of path) {
179 | if (dirName) {
180 | dh = await dh.getDirectoryHandle(dirName, { create: !!createDirs });
181 | }
182 | }
183 | return [dh, filename];
184 | };
185 |
186 | /**
187 | * If the given file-holding object has a sync handle attached to it, that
188 | * handle is remove and asynchronously closed. Though it may sound sensible to
189 | * continue work as soon as the close() returns (noting that it's
190 | * asynchronous), doing so can cause operations performed soon afterwards,
191 | * e.g. a call to getSyncHandle() to fail because they may happen out of order
192 | * from the close(). OPFS does not guaranty that the actual order of
193 | * operations is retained in such cases. i.e. always "await" on the result of
194 | * this function.
195 | */
196 | const closeSyncHandle = async (fh) => {
197 | if (fh.syncHandle) {
198 | log('Closing sync handle for', fh.filenameAbs);
199 | const h = fh.syncHandle;
200 | delete fh.syncHandle;
201 | delete fh.xLock;
202 | __implicitLocks.delete(fh.fid);
203 | return h.close();
204 | }
205 | };
206 |
207 | /**
208 | * A proxy for closeSyncHandle() which is guaranteed to not throw.
209 | *
210 | * This function is part of a lock/unlock step in functions which
211 | * require a sync access handle but may be called without xLock()
212 | * having been called first. Such calls need to release that
213 | * handle to avoid locking the file for all of time. This is an
214 | * _attempt_ at reducing cross-tab contention but it may prove
215 | * to be more of a problem than a solution and may need to be
216 | * removed.
217 | */
218 | const closeSyncHandleNoThrow = async (fh) => {
219 | try {
220 | await closeSyncHandle(fh);
221 | } catch (e) {
222 | warn('closeSyncHandleNoThrow() ignoring:', e, fh);
223 | }
224 | };
225 |
226 | /* Release all auto-locks. */
227 | const releaseImplicitLocks = async () => {
228 | if (__implicitLocks.size) {
229 | /* Release all auto-locks. */
230 | for (const fid of __implicitLocks) {
231 | const fh = __openFiles[fid];
232 | await closeSyncHandleNoThrow(fh);
233 | log('Auto-unlocked', fid, fh.filenameAbs);
234 | }
235 | }
236 | };
237 |
238 | /**
239 | * An experiment in improving concurrency by freeing up implicit locks sooner.
240 | * This is known to impact performance dramatically but it has also shown to
241 | * improve concurrency considerably.
242 | *
243 | * If fh.releaseImplicitLocks is truthy and fh is in __implicitLocks,
244 | * this routine returns closeSyncHandleNoThrow(), else it is a no-op.
245 | */
246 | const releaseImplicitLock = async (fh) => {
247 | if (fh.releaseImplicitLocks && __implicitLocks.has(fh.fid)) {
248 | return closeSyncHandleNoThrow(fh);
249 | }
250 | };
251 |
252 | /**
253 | * An error class specifically for use with getSyncHandle(), the goal of which
254 | * is to eventually be able to distinguish unambiguously between
255 | * locking-related failures and other types, noting that we cannot currently
256 | * do so because createSyncAccessHandle() does not define its exceptions in
257 | * the required level of detail.
258 | *
259 | * 2022-11-29: according to:
260 | *
261 | * https://github.com/whatwg/fs/pull/21
262 | *
263 | * NoModificationAllowedError will be the standard exception thrown
264 | * when acquisition of a sync access handle fails due to a locking
265 | * error. As of this writing, that error type is not visible in the
266 | * dev console in Chrome v109, nor is it documented in MDN, but an
267 | * error with that "name" property is being thrown from the OPFS
268 | * layer.
269 | */
270 | class GetSyncHandleError extends Error {
271 | constructor(errorObject, ...msg) {
272 | super(
273 | [...msg, ': ' + errorObject.name + ':', errorObject.message].join(' '),
274 | {
275 | cause: errorObject,
276 | },
277 | );
278 | this.name = 'GetSyncHandleError';
279 | }
280 | }
281 | GetSyncHandleError.convertRc = (e, rc) => {
282 | if (1) {
283 | return e instanceof GetSyncHandleError &&
284 | (e.cause.name === 'NoModificationAllowedError' ||
285 | /* Inconsistent exception.name from Chrome/ium with the
286 | same exception.message text: */
287 | (e.cause.name === 'DOMException' &&
288 | 0 === e.cause.message.indexOf('Access Handles cannot')))
289 | ? /*console.warn("SQLITE_BUSY",e),*/
290 | state.sq3Codes.SQLITE_BUSY
291 | : rc;
292 | } else {
293 | return rc;
294 | }
295 | };
296 | /**
297 | * Returns the sync access handle associated with the given file handle object
298 | * (which must be a valid handle object, as created by xOpen()), lazily
299 | * opening it if needed.
300 | *
301 | * In order to help alleviate cross-tab contention for a dabase, if
302 | * an exception is thrown while acquiring the handle, this routine
303 | * will wait briefly and try again, up to some fixed number of
304 | * times. If acquisition still fails at that point it will give up
305 | * and propagate the exception. Client-level code will see that as
306 | * an I/O error.
307 | */
308 | const getSyncHandle = async (fh, opName) => {
309 | if (!fh.syncHandle) {
310 | const t = performance.now();
311 | log('Acquiring sync handle for', fh.filenameAbs);
312 | const maxTries = 6,
313 | msBase = state.asyncIdleWaitTime * 2;
314 | let i = 1,
315 | ms = msBase;
316 | for (; true; ms = msBase * ++i) {
317 | try {
318 | //if(i<3) toss("Just testing getSyncHandle() wait-and-retry.");
319 | //TODO? A config option which tells it to throw here
320 | //randomly every now and then, for testing purposes.
321 | fh.syncHandle = await fh.fileHandle.createSyncAccessHandle();
322 | break;
323 | } catch (e) {
324 | if (i === maxTries) {
325 | throw new GetSyncHandleError(
326 | e,
327 | 'Error getting sync handle for',
328 | opName + '().',
329 | maxTries,
330 | 'attempts failed.',
331 | fh.filenameAbs,
332 | );
333 | }
334 | warn(
335 | 'Error getting sync handle for',
336 | opName + '(). Waiting',
337 | ms,
338 | 'ms and trying again.',
339 | fh.filenameAbs,
340 | e,
341 | );
342 | Atomics.wait(state.sabOPView, state.opIds.retry, 0, ms);
343 | }
344 | }
345 | log(
346 | 'Got',
347 | opName + '() sync handle for',
348 | fh.filenameAbs,
349 | 'in',
350 | performance.now() - t,
351 | 'ms',
352 | );
353 | if (!fh.xLock) {
354 | __implicitLocks.add(fh.fid);
355 | log(
356 | 'Acquired implicit lock for',
357 | opName + '()',
358 | fh.fid,
359 | fh.filenameAbs,
360 | );
361 | }
362 | }
363 | return fh.syncHandle;
364 | };
365 |
366 | /**
367 | * Stores the given value at state.sabOPView[state.opIds.rc] and then
368 | * Atomics.notify()'s it.
369 | */
370 | const storeAndNotify = (opName, value) => {
371 | log(opName + '() => notify(', value, ')');
372 | Atomics.store(state.sabOPView, state.opIds.rc, value);
373 | Atomics.notify(state.sabOPView, state.opIds.rc);
374 | };
375 |
376 | /** Throws if fh is a file-holding object which is flagged as read-only. */
377 | const affirmNotRO = function (opName, fh) {
378 | if (fh.readOnly) toss(opName + '(): File is read-only: ' + fh.filenameAbs);
379 | };
380 |
381 | /**
382 | * We track 2 different timers: the "metrics" timer records how much time we
383 | * spend performing work. The "wait" timer records how much time we spend
384 | * waiting on the underlying OPFS timer. See the calls to mTimeStart(),
385 | * mTimeEnd(), wTimeStart(), and wTimeEnd() throughout this file to see how
386 | * they're used.
387 | */
388 | const __mTimer = Object.create(null);
389 | __mTimer.op = undefined;
390 | __mTimer.start = undefined;
391 | const mTimeStart = (op) => {
392 | __mTimer.start = performance.now();
393 | __mTimer.op = op;
394 | //metrics[op] || toss("Maintenance required: missing metrics for",op);
395 | ++metrics[op].count;
396 | };
397 | const mTimeEnd = () =>
398 | (metrics[__mTimer.op].time += performance.now() - __mTimer.start);
399 | const __wTimer = Object.create(null);
400 | __wTimer.op = undefined;
401 | __wTimer.start = undefined;
402 | const wTimeStart = (op) => {
403 | __wTimer.start = performance.now();
404 | __wTimer.op = op;
405 | //metrics[op] || toss("Maintenance required: missing metrics for",op);
406 | };
407 | const wTimeEnd = () =>
408 | (metrics[__wTimer.op].wait += performance.now() - __wTimer.start);
409 |
410 | /**
411 | * Gets set to true by the 'opfs-async-shutdown' command to quit the wait
412 | * loop. This is only intended for debugging purposes: we cannot inspect this
413 | * file's state while the tight waitLoop() is running and need a way to stop
414 | * that loop for introspection purposes.
415 | */
416 | let flagAsyncShutdown = false;
417 |
418 | /**
419 | * Asynchronous wrappers for sqlite3_vfs and sqlite3_io_methods methods, as
420 | * well as helpers like mkdir(). Maintenance reminder: members are in
421 | * alphabetical order to simplify finding them.
422 | */
423 | const vfsAsyncImpls = {
424 | 'opfs-async-metrics': async () => {
425 | mTimeStart('opfs-async-metrics');
426 | metrics.dump();
427 | storeAndNotify('opfs-async-metrics', 0);
428 | mTimeEnd();
429 | },
430 | 'opfs-async-shutdown': async () => {
431 | flagAsyncShutdown = true;
432 | storeAndNotify('opfs-async-shutdown', 0);
433 | },
434 | mkdir: async (dirname) => {
435 | mTimeStart('mkdir');
436 | let rc = 0;
437 | wTimeStart('mkdir');
438 | try {
439 | await getDirForFilename(dirname + '/filepart', true);
440 | } catch (e) {
441 | state.s11n.storeException(2, e);
442 | rc = state.sq3Codes.SQLITE_IOERR;
443 | } finally {
444 | wTimeEnd();
445 | }
446 | storeAndNotify('mkdir', rc);
447 | mTimeEnd();
448 | },
449 | xAccess: async (filename) => {
450 | mTimeStart('xAccess');
451 | /* OPFS cannot support the full range of xAccess() queries
452 | sqlite3 calls for. We can essentially just tell if the file
453 | is accessible, but if it is then it's automatically writable
454 | (unless it's locked, which we cannot(?) know without trying
455 | to open it). OPFS does not have the notion of read-only.
456 |
457 | The return semantics of this function differ from sqlite3's
458 | xAccess semantics because we are limited in what we can
459 | communicate back to our synchronous communication partner: 0 =
460 | accessible, non-0 means not accessible.
461 | */
462 | let rc = 0;
463 | wTimeStart('xAccess');
464 | try {
465 | const [dh, fn] = await getDirForFilename(filename);
466 | await dh.getFileHandle(fn);
467 | } catch (e) {
468 | state.s11n.storeException(2, e);
469 | rc = state.sq3Codes.SQLITE_IOERR;
470 | } finally {
471 | wTimeEnd();
472 | }
473 | storeAndNotify('xAccess', rc);
474 | mTimeEnd();
475 | },
476 | xClose: async function (fid /*sqlite3_file pointer*/) {
477 | const opName = 'xClose';
478 | mTimeStart(opName);
479 | __implicitLocks.delete(fid);
480 | const fh = __openFiles[fid];
481 | let rc = 0;
482 | wTimeStart(opName);
483 | if (fh) {
484 | delete __openFiles[fid];
485 | await closeSyncHandle(fh);
486 | if (fh.deleteOnClose) {
487 | try {
488 | await fh.dirHandle.removeEntry(fh.filenamePart);
489 | } catch (e) {
490 | warn('Ignoring dirHandle.removeEntry() failure of', fh, e);
491 | }
492 | }
493 | } else {
494 | state.s11n.serialize();
495 | rc = state.sq3Codes.SQLITE_NOTFOUND;
496 | }
497 | wTimeEnd();
498 | storeAndNotify(opName, rc);
499 | mTimeEnd();
500 | },
501 | xDelete: async function (...args) {
502 | mTimeStart('xDelete');
503 | const rc = await vfsAsyncImpls.xDeleteNoWait(...args);
504 | storeAndNotify('xDelete', rc);
505 | mTimeEnd();
506 | },
507 | xDeleteNoWait: async function (filename, syncDir = 0, recursive = false) {
508 | /* The syncDir flag is, for purposes of the VFS API's semantics,
509 | ignored here. However, if it has the value 0x1234 then: after
510 | deleting the given file, recursively try to delete any empty
511 | directories left behind in its wake (ignoring any errors and
512 | stopping at the first failure).
513 |
514 | That said: we don't know for sure that removeEntry() fails if
515 | the dir is not empty because the API is not documented. It has,
516 | however, a "recursive" flag which defaults to false, so
517 | presumably it will fail if the dir is not empty and that flag
518 | is false.
519 | */
520 | let rc = 0;
521 | wTimeStart('xDelete');
522 | try {
523 | while (filename) {
524 | const [hDir, filenamePart] = await getDirForFilename(filename, false);
525 | if (!filenamePart) break;
526 | await hDir.removeEntry(filenamePart, { recursive });
527 | if (0x1234 !== syncDir) break;
528 | recursive = false;
529 | filename = getResolvedPath(filename, true);
530 | filename.pop();
531 | filename = filename.join('/');
532 | }
533 | } catch (e) {
534 | state.s11n.storeException(2, e);
535 | rc = state.sq3Codes.SQLITE_IOERR_DELETE;
536 | }
537 | wTimeEnd();
538 | return rc;
539 | },
540 | xFileSize: async function (fid /*sqlite3_file pointer*/) {
541 | mTimeStart('xFileSize');
542 | const fh = __openFiles[fid];
543 | let rc = 0;
544 | wTimeStart('xFileSize');
545 | try {
546 | const sz = await (await getSyncHandle(fh, 'xFileSize')).getSize();
547 | state.s11n.serialize(Number(sz));
548 | } catch (e) {
549 | state.s11n.storeException(1, e);
550 | rc = GetSyncHandleError.convertRc(e, state.sq3Codes.SQLITE_IOERR);
551 | }
552 | await releaseImplicitLock(fh);
553 | wTimeEnd();
554 | storeAndNotify('xFileSize', rc);
555 | mTimeEnd();
556 | },
557 | xLock: async function (
558 | fid /*sqlite3_file pointer*/,
559 | lockType /*SQLITE_LOCK_...*/,
560 | ) {
561 | mTimeStart('xLock');
562 | const fh = __openFiles[fid];
563 | let rc = 0;
564 | const oldLockType = fh.xLock;
565 | fh.xLock = lockType;
566 | if (!fh.syncHandle) {
567 | wTimeStart('xLock');
568 | try {
569 | await getSyncHandle(fh, 'xLock');
570 | __implicitLocks.delete(fid);
571 | } catch (e) {
572 | state.s11n.storeException(1, e);
573 | rc = GetSyncHandleError.convertRc(
574 | e,
575 | state.sq3Codes.SQLITE_IOERR_LOCK,
576 | );
577 | fh.xLock = oldLockType;
578 | }
579 | wTimeEnd();
580 | }
581 | storeAndNotify('xLock', rc);
582 | mTimeEnd();
583 | },
584 | xOpen: async function (
585 | fid /*sqlite3_file pointer*/,
586 | filename,
587 | flags /*SQLITE_OPEN_...*/,
588 | opfsFlags /*OPFS_...*/,
589 | ) {
590 | const opName = 'xOpen';
591 | mTimeStart(opName);
592 | const create = state.sq3Codes.SQLITE_OPEN_CREATE & flags;
593 | wTimeStart('xOpen');
594 | try {
595 | let hDir, filenamePart;
596 | try {
597 | [hDir, filenamePart] = await getDirForFilename(filename, !!create);
598 | } catch (e) {
599 | state.s11n.storeException(1, e);
600 | storeAndNotify(opName, state.sq3Codes.SQLITE_NOTFOUND);
601 | mTimeEnd();
602 | wTimeEnd();
603 | return;
604 | }
605 | const hFile = await hDir.getFileHandle(filenamePart, { create });
606 | wTimeEnd();
607 | const fh = Object.assign(Object.create(null), {
608 | fid: fid,
609 | filenameAbs: filename,
610 | filenamePart: filenamePart,
611 | dirHandle: hDir,
612 | fileHandle: hFile,
613 | sabView: state.sabFileBufView,
614 | readOnly: create
615 | ? false
616 | : state.sq3Codes.SQLITE_OPEN_READONLY & flags,
617 | deleteOnClose: !!(state.sq3Codes.SQLITE_OPEN_DELETEONCLOSE & flags),
618 | });
619 | fh.releaseImplicitLocks =
620 | opfsFlags & state.opfsFlags.OPFS_UNLOCK_ASAP ||
621 | state.opfsFlags.defaultUnlockAsap;
622 | if (
623 | 0 /* this block is modelled after something wa-sqlite
624 | does but it leads to immediate contention on journal files.
625 | Update: this approach reportedly only works for DELETE journal
626 | mode. */ &&
627 | 0 === (flags & state.sq3Codes.SQLITE_OPEN_MAIN_DB)
628 | ) {
629 | /* sqlite does not lock these files, so go ahead and grab an OPFS
630 | lock. */
631 | fh.xLock = 'xOpen' /* Truthy value to keep entry from getting
632 | flagged as auto-locked. String value so
633 | that we can easily distinguish is later
634 | if needed. */;
635 | await getSyncHandle(fh, 'xOpen');
636 | }
637 | __openFiles[fid] = fh;
638 | storeAndNotify(opName, 0);
639 | } catch (e) {
640 | wTimeEnd();
641 | error(opName, e);
642 | state.s11n.storeException(1, e);
643 | storeAndNotify(opName, state.sq3Codes.SQLITE_IOERR);
644 | }
645 | mTimeEnd();
646 | },
647 | xRead: async function (fid /*sqlite3_file pointer*/, n, offset64) {
648 | mTimeStart('xRead');
649 | let rc = 0,
650 | nRead;
651 | const fh = __openFiles[fid];
652 | try {
653 | wTimeStart('xRead');
654 | nRead = (await getSyncHandle(fh, 'xRead')).read(
655 | fh.sabView.subarray(0, n),
656 | { at: Number(offset64) },
657 | );
658 | wTimeEnd();
659 | if (nRead < n) {
660 | /* Zero-fill remaining bytes */
661 | fh.sabView.fill(0, nRead, n);
662 | rc = state.sq3Codes.SQLITE_IOERR_SHORT_READ;
663 | }
664 | } catch (e) {
665 | if (undefined === nRead) wTimeEnd();
666 | error('xRead() failed', e, fh);
667 | state.s11n.storeException(1, e);
668 | rc = GetSyncHandleError.convertRc(e, state.sq3Codes.SQLITE_IOERR_READ);
669 | }
670 | await releaseImplicitLock(fh);
671 | storeAndNotify('xRead', rc);
672 | mTimeEnd();
673 | },
674 | xSync: async function (fid /*sqlite3_file pointer*/, flags /*ignored*/) {
675 | mTimeStart('xSync');
676 | const fh = __openFiles[fid];
677 | let rc = 0;
678 | if (!fh.readOnly && fh.syncHandle) {
679 | try {
680 | wTimeStart('xSync');
681 | await fh.syncHandle.flush();
682 | } catch (e) {
683 | state.s11n.storeException(2, e);
684 | rc = state.sq3Codes.SQLITE_IOERR_FSYNC;
685 | }
686 | wTimeEnd();
687 | }
688 | storeAndNotify('xSync', rc);
689 | mTimeEnd();
690 | },
691 | xTruncate: async function (fid /*sqlite3_file pointer*/, size) {
692 | mTimeStart('xTruncate');
693 | let rc = 0;
694 | const fh = __openFiles[fid];
695 | wTimeStart('xTruncate');
696 | try {
697 | affirmNotRO('xTruncate', fh);
698 | await (await getSyncHandle(fh, 'xTruncate')).truncate(size);
699 | } catch (e) {
700 | error('xTruncate():', e, fh);
701 | state.s11n.storeException(2, e);
702 | rc = GetSyncHandleError.convertRc(
703 | e,
704 | state.sq3Codes.SQLITE_IOERR_TRUNCATE,
705 | );
706 | }
707 | await releaseImplicitLock(fh);
708 | wTimeEnd();
709 | storeAndNotify('xTruncate', rc);
710 | mTimeEnd();
711 | },
712 | xUnlock: async function (
713 | fid /*sqlite3_file pointer*/,
714 | lockType /*SQLITE_LOCK_...*/,
715 | ) {
716 | mTimeStart('xUnlock');
717 | let rc = 0;
718 | const fh = __openFiles[fid];
719 | if (state.sq3Codes.SQLITE_LOCK_NONE === lockType && fh.syncHandle) {
720 | wTimeStart('xUnlock');
721 | try {
722 | await closeSyncHandle(fh);
723 | } catch (e) {
724 | state.s11n.storeException(1, e);
725 | rc = state.sq3Codes.SQLITE_IOERR_UNLOCK;
726 | }
727 | wTimeEnd();
728 | }
729 | storeAndNotify('xUnlock', rc);
730 | mTimeEnd();
731 | },
732 | xWrite: async function (fid /*sqlite3_file pointer*/, n, offset64) {
733 | mTimeStart('xWrite');
734 | let rc;
735 | const fh = __openFiles[fid];
736 | wTimeStart('xWrite');
737 | try {
738 | affirmNotRO('xWrite', fh);
739 | rc =
740 | n ===
741 | (await getSyncHandle(fh, 'xWrite')).write(fh.sabView.subarray(0, n), {
742 | at: Number(offset64),
743 | })
744 | ? 0
745 | : state.sq3Codes.SQLITE_IOERR_WRITE;
746 | } catch (e) {
747 | error('xWrite():', e, fh);
748 | state.s11n.storeException(1, e);
749 | rc = GetSyncHandleError.convertRc(e, state.sq3Codes.SQLITE_IOERR_WRITE);
750 | }
751 | await releaseImplicitLock(fh);
752 | wTimeEnd();
753 | storeAndNotify('xWrite', rc);
754 | mTimeEnd();
755 | },
756 | }; /*vfsAsyncImpls*/
757 |
758 | const initS11n = () => {
759 | /**
760 | * ACHTUNG: this code is 100% duplicated in the other half of this proxy!
761 | * The documentation is maintained in the "synchronous half".
762 | */
763 | if (state.s11n) return state.s11n;
764 | const textDecoder = new TextDecoder(),
765 | textEncoder = new TextEncoder('utf-8'),
766 | viewU8 = new Uint8Array(
767 | state.sabIO,
768 | state.sabS11nOffset,
769 | state.sabS11nSize,
770 | ),
771 | viewDV = new DataView(
772 | state.sabIO,
773 | state.sabS11nOffset,
774 | state.sabS11nSize,
775 | );
776 | state.s11n = Object.create(null);
777 | const TypeIds = Object.create(null);
778 | TypeIds.number = {
779 | id: 1,
780 | size: 8,
781 | getter: 'getFloat64',
782 | setter: 'setFloat64',
783 | };
784 | TypeIds.bigint = {
785 | id: 2,
786 | size: 8,
787 | getter: 'getBigInt64',
788 | setter: 'setBigInt64',
789 | };
790 | TypeIds.boolean = {
791 | id: 3,
792 | size: 4,
793 | getter: 'getInt32',
794 | setter: 'setInt32',
795 | };
796 | TypeIds.string = { id: 4 };
797 | const getTypeId = (v) =>
798 | TypeIds[typeof v] ||
799 | toss('Maintenance required: this value type cannot be serialized.', v);
800 | const getTypeIdById = (tid) => {
801 | switch (tid) {
802 | case TypeIds.number.id:
803 | return TypeIds.number;
804 | case TypeIds.bigint.id:
805 | return TypeIds.bigint;
806 | case TypeIds.boolean.id:
807 | return TypeIds.boolean;
808 | case TypeIds.string.id:
809 | return TypeIds.string;
810 | default:
811 | toss('Invalid type ID:', tid);
812 | }
813 | };
814 | state.s11n.deserialize = function (clear = false) {
815 | ++metrics.s11n.deserialize.count;
816 | const t = performance.now();
817 | const argc = viewU8[0];
818 | const rc = argc ? [] : null;
819 | if (argc) {
820 | const typeIds = [];
821 | let offset = 1,
822 | i,
823 | n,
824 | v;
825 | for (i = 0; i < argc; ++i, ++offset) {
826 | typeIds.push(getTypeIdById(viewU8[offset]));
827 | }
828 | for (i = 0; i < argc; ++i) {
829 | const t = typeIds[i];
830 | if (t.getter) {
831 | v = viewDV[t.getter](offset, state.littleEndian);
832 | offset += t.size;
833 | } else {
834 | /*String*/
835 | n = viewDV.getInt32(offset, state.littleEndian);
836 | offset += 4;
837 | v = textDecoder.decode(viewU8.slice(offset, offset + n));
838 | offset += n;
839 | }
840 | rc.push(v);
841 | }
842 | }
843 | if (clear) viewU8[0] = 0;
844 | //log("deserialize:",argc, rc);
845 | metrics.s11n.deserialize.time += performance.now() - t;
846 | return rc;
847 | };
848 | state.s11n.serialize = function (...args) {
849 | const t = performance.now();
850 | ++metrics.s11n.serialize.count;
851 | if (args.length) {
852 | //log("serialize():",args);
853 | const typeIds = [];
854 | let i = 0,
855 | offset = 1;
856 | viewU8[0] = args.length & 0xff /* header = # of args */;
857 | for (; i < args.length; ++i, ++offset) {
858 | /* Write the TypeIds.id value into the next args.length
859 | bytes. */
860 | typeIds.push(getTypeId(args[i]));
861 | viewU8[offset] = typeIds[i].id;
862 | }
863 | for (i = 0; i < args.length; ++i) {
864 | /* Deserialize the following bytes based on their
865 | corresponding TypeIds.id from the header. */
866 | const t = typeIds[i];
867 | if (t.setter) {
868 | viewDV[t.setter](offset, args[i], state.littleEndian);
869 | offset += t.size;
870 | } else {
871 | /*String*/
872 | const s = textEncoder.encode(args[i]);
873 | viewDV.setInt32(offset, s.byteLength, state.littleEndian);
874 | offset += 4;
875 | viewU8.set(s, offset);
876 | offset += s.byteLength;
877 | }
878 | }
879 | //log("serialize() result:",viewU8.slice(0,offset));
880 | } else {
881 | viewU8[0] = 0;
882 | }
883 | metrics.s11n.serialize.time += performance.now() - t;
884 | };
885 |
886 | state.s11n.storeException = state.asyncS11nExceptions
887 | ? (priority, e) => {
888 | if (priority <= state.asyncS11nExceptions) {
889 | state.s11n.serialize([e.name, ': ', e.message].join(''));
890 | }
891 | }
892 | : () => {};
893 |
894 | return state.s11n;
895 | }; /*initS11n()*/
896 |
897 | const waitLoop = async function f() {
898 | const opHandlers = Object.create(null);
899 | for (let k of Object.keys(state.opIds)) {
900 | const vi = vfsAsyncImpls[k];
901 | if (!vi) continue;
902 | const o = Object.create(null);
903 | opHandlers[state.opIds[k]] = o;
904 | o.key = k;
905 | o.f = vi;
906 | }
907 | while (!flagAsyncShutdown) {
908 | try {
909 | if (
910 | 'not-equal' !==
911 | Atomics.wait(
912 | state.sabOPView,
913 | state.opIds.whichOp,
914 | 0,
915 | state.asyncIdleWaitTime,
916 | )
917 | ) {
918 | /* Maintenance note: we compare against 'not-equal' because
919 |
920 | https://github.com/tomayac/sqlite-wasm/issues/12
921 |
922 | is reporting that this occassionally, under high loads,
923 | returns 'ok', which leads to the whichOp being 0 (which
924 | isn't a valid operation ID and leads to an exception,
925 | along with a corresponding ugly console log
926 | message). Unfortunately, the conditions for that cannot
927 | be reliably reproduced. The only place in our code which
928 | writes a 0 to the state.opIds.whichOp SharedArrayBuffer
929 | index is a few lines down from here, and that instance
930 | is required in order for clear communication between
931 | the sync half of this proxy and this half.
932 | */
933 | await releaseImplicitLocks();
934 | continue;
935 | }
936 | const opId = Atomics.load(state.sabOPView, state.opIds.whichOp);
937 | Atomics.store(state.sabOPView, state.opIds.whichOp, 0);
938 | const hnd =
939 | opHandlers[opId] ?? toss('No waitLoop handler for whichOp #', opId);
940 | const args =
941 | state.s11n.deserialize(
942 | true /* clear s11n to keep the caller from confusing this with
943 | an exception string written by the upcoming
944 | operation */,
945 | ) || [];
946 | //warn("waitLoop() whichOp =",opId, hnd, args);
947 | if (hnd.f) await hnd.f(...args);
948 | else error('Missing callback for opId', opId);
949 | } catch (e) {
950 | error('in waitLoop():', e);
951 | }
952 | }
953 | };
954 |
955 | navigator.storage
956 | .getDirectory()
957 | .then(function (d) {
958 | state.rootDir = d;
959 | globalThis.onmessage = function ({ data }) {
960 | switch (data.type) {
961 | case 'opfs-async-init': {
962 | /* Receive shared state from synchronous partner */
963 | const opt = data.args;
964 | for (const k in opt) state[k] = opt[k];
965 | state.verbose = opt.verbose ?? 1;
966 | state.sabOPView = new Int32Array(state.sabOP);
967 | state.sabFileBufView = new Uint8Array(
968 | state.sabIO,
969 | 0,
970 | state.fileBufferSize,
971 | );
972 | state.sabS11nView = new Uint8Array(
973 | state.sabIO,
974 | state.sabS11nOffset,
975 | state.sabS11nSize,
976 | );
977 | Object.keys(vfsAsyncImpls).forEach((k) => {
978 | if (!Number.isFinite(state.opIds[k])) {
979 | toss('Maintenance required: missing state.opIds[', k, ']');
980 | }
981 | });
982 | initS11n();
983 | metrics.reset();
984 | log('init state', state);
985 | wPost('opfs-async-inited');
986 | waitLoop();
987 | break;
988 | }
989 | case 'opfs-async-restart':
990 | if (flagAsyncShutdown) {
991 | warn(
992 | 'Restarting after opfs-async-shutdown. Might or might not work.',
993 | );
994 | flagAsyncShutdown = false;
995 | waitLoop();
996 | }
997 | break;
998 | case 'opfs-async-metrics':
999 | metrics.dump();
1000 | break;
1001 | }
1002 | };
1003 | wPost('opfs-async-loaded');
1004 | })
1005 | .catch((e) => error('error initializing OPFS asyncer:', e));
1006 | }; /*installAsyncProxy()*/
1007 | if (!globalThis.SharedArrayBuffer) {
1008 | wPost(
1009 | 'opfs-unavailable',
1010 | 'Missing SharedArrayBuffer API.',
1011 | 'The server must emit the COOP/COEP response headers to enable that.',
1012 | );
1013 | } else if (!globalThis.Atomics) {
1014 | wPost(
1015 | 'opfs-unavailable',
1016 | 'Missing Atomics API.',
1017 | 'The server must emit the COOP/COEP response headers to enable that.',
1018 | );
1019 | } else if (
1020 | !globalThis.FileSystemHandle ||
1021 | !globalThis.FileSystemDirectoryHandle ||
1022 | !globalThis.FileSystemFileHandle ||
1023 | !globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle ||
1024 | !navigator?.storage?.getDirectory
1025 | ) {
1026 | wPost('opfs-unavailable', 'Missing required OPFS APIs.');
1027 | } else {
1028 | installAsyncProxy(self);
1029 | }
1030 |
--------------------------------------------------------------------------------
/sqlite-wasm/jswasm/sqlite3-worker1-bundler-friendly.mjs:
--------------------------------------------------------------------------------
1 | /*
2 | 2022-05-23
3 |
4 | The author disclaims copyright to this source code. In place of a
5 | legal notice, here is a blessing:
6 |
7 | * May you do good and not evil.
8 | * May you find forgiveness for yourself and forgive others.
9 | * May you share freely, never taking more than you give.
10 |
11 | ***********************************************************************
12 |
13 | This is a JS Worker file for the main sqlite3 api. It loads
14 | sqlite3.js, initializes the module, and postMessage()'s a message
15 | after the module is initialized:
16 |
17 | {type: 'sqlite3-api', result: 'worker1-ready'}
18 |
19 | This seemingly superfluous level of indirection is necessary when
20 | loading sqlite3.js via a Worker. Instantiating a worker with new
21 | Worker("sqlite.js") will not (cannot) call sqlite3InitModule() to
22 | initialize the module due to a timing/order-of-operations conflict
23 | (and that symbol is not exported in a way that a Worker loading it
24 | that way can see it). Thus JS code wanting to load the sqlite3
25 | Worker-specific API needs to pass _this_ file (or equivalent) to the
26 | Worker constructor and then listen for an event in the form shown
27 | above in order to know when the module has completed initialization.
28 |
29 | This file accepts a URL arguments to adjust how it loads sqlite3.js:
30 |
31 | - `sqlite3.dir`, if set, treats the given directory name as the
32 | directory from which `sqlite3.js` will be loaded.
33 | */
34 | import { default as sqlite3InitModule } from './sqlite3-bundler-friendly.mjs';
35 | sqlite3InitModule().then((sqlite3) => sqlite3.initWorker1API());
36 |
--------------------------------------------------------------------------------
/sqlite-wasm/jswasm/sqlite3-worker1-promiser-bundler-friendly.js:
--------------------------------------------------------------------------------
1 | /*
2 | 2022-08-24
3 |
4 | The author disclaims copyright to this source code. In place of a
5 | legal notice, here is a blessing:
6 |
7 | * May you do good and not evil.
8 | * May you find forgiveness for yourself and forgive others.
9 | * May you share freely, never taking more than you give.
10 |
11 | ***********************************************************************
12 |
13 | This file implements a Promise-based proxy for the sqlite3 Worker
14 | API #1. It is intended to be included either from the main thread or
15 | a Worker, but only if (A) the environment supports nested Workers
16 | and (B) it's _not_ a Worker which loads the sqlite3 WASM/JS
17 | module. This file's features will load that module and provide a
18 | slightly simpler client-side interface than the slightly-lower-level
19 | Worker API does.
20 |
21 | This script necessarily exposes one global symbol, but clients may
22 | freely `delete` that symbol after calling it.
23 | */
24 | 'use strict';
25 | /**
26 | * Configures an sqlite3 Worker API #1 Worker such that it can be manipulated
27 | * via a Promise-based interface and returns a factory function which returns
28 | * Promises for communicating with the worker. This proxy has an _almost_
29 | * identical interface to the normal worker API, with any exceptions documented
30 | * below.
31 | *
32 | * It requires a configuration object with the following properties:
33 | *
34 | * - `worker` (required): a Worker instance which loads `sqlite3-worker1.js` or a
35 | * functional equivalent. Note that the promiser factory replaces the
36 | * worker.onmessage property. This config option may alternately be a
37 | * function, in which case this function re-assigns this property with the
38 | * result of calling that function, enabling delayed instantiation of a
39 | * Worker.
40 | * - `onready` (optional, but...): this callback is called with no arguments when
41 | * the worker fires its initial 'sqlite3-api'/'worker1-ready' message, which
42 | * it does when sqlite3.initWorker1API() completes its initialization. This is
43 | * the simplest way to tell the worker to kick off work at the earliest
44 | * opportunity.
45 | * - `onunhandled` (optional): a callback which gets passed the message event
46 | * object for any worker.onmessage() events which are not handled by this
47 | * proxy. Ideally that "should" never happen, as this proxy aims to handle all
48 | * known message types.
49 | * - `generateMessageId` (optional): a function which, when passed an
50 | * about-to-be-posted message object, generates a _unique_ message ID for the
51 | * message, which this API then assigns as the messageId property of the
52 | * message. It _must_ generate unique IDs on each call so that dispatching can
53 | * work. If not defined, a default generator is used (which should be
54 | * sufficient for most or all cases).
55 | * - `debug` (optional): a console.debug()-style function for logging information
56 | * about messages.
57 | *
58 | * This function returns a stateful factory function with the following
59 | * interfaces:
60 | *
61 | * - Promise function(messageType, messageArgs)
62 | * - Promise function({message object})
63 | *
64 | * The first form expects the "type" and "args" values for a Worker message. The
65 | * second expects an object in the form {type:..., args:...} plus any other
66 | * properties the client cares to set. This function will always set the
67 | * `messageId` property on the object, even if it's already set, and will set
68 | * the `dbId` property to the current database ID if it is _not_ set in the
69 | * message object.
70 | *
71 | * The function throws on error.
72 | *
73 | * The function installs a temporary message listener, posts a message to the
74 | * configured Worker, and handles the message's response via the temporary
75 | * message listener. The then() callback of the returned Promise is passed the
76 | * `message.data` property from the resulting message, i.e. the payload from the
77 | * worker, stripped of the lower-level event state which the onmessage() handler
78 | * receives.
79 | *
80 | * Example usage:
81 | *
82 | * const config = {...};
83 | * const sq3Promiser = sqlite3Worker1Promiser(config);
84 | * sq3Promiser('open', {filename:"/foo.db"}).then(function(msg){
85 | * console.log("open response",msg); // => {type:'open', result: {filename:'/foo.db'}, ...}
86 | * });
87 | * sq3Promiser({type:'close'}).then((msg)=>{
88 | * console.log("close response",msg); // => {type:'close', result: {filename:'/foo.db'}, ...}
89 | * });
90 | *
91 | * Differences from Worker API #1:
92 | *
93 | * - Exec's {callback: STRING} option does not work via this interface (it
94 | * triggers an exception), but {callback: function} does and works exactly
95 | * like the STRING form does in the Worker: the callback is called one time
96 | * for each row of the result set, passed the same worker message format as
97 | * the worker API emits:
98 | *
99 | * {type:typeString, row:VALUE, rowNumber:1-based-#, columnNames: array}
100 | *
101 | * Where `typeString` is an internally-synthesized message type string used
102 | * temporarily for worker message dispatching. It can be ignored by all client
103 | * code except that which tests this API. The `row` property contains the row
104 | * result in the form implied by the `rowMode` option (defaulting to `'array'`).
105 | * The `rowNumber` is a 1-based integer value incremented by 1 on each call into
106 | * the callback.
107 | *
108 | * At the end of the result set, the same event is fired with (row=undefined,
109 | * rowNumber=null) to indicate that the end of the result set has been reached.
110 | * Note that the rows arrive via worker-posted messages, with all the
111 | * implications of that.
112 | *
113 | * Notable shortcomings:
114 | *
115 | * - This API was not designed with ES6 modules in mind. Neither Firefox nor
116 | * Safari support, as of March 2023, the {type:"module"} flag to the Worker
117 | * constructor, so that particular usage is not something we're going to
118 | * target for the time being:
119 | *
120 | * https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker
121 | */
122 | globalThis.sqlite3Worker1Promiser = function callee(
123 | config = callee.defaultConfig,
124 | ) {
125 | // Inspired by: https://stackoverflow.com/a/52439530
126 | if (1 === arguments.length && 'function' === typeof arguments[0]) {
127 | const f = config;
128 | config = Object.assign(Object.create(null), callee.defaultConfig);
129 | config.onready = f;
130 | } else {
131 | config = Object.assign(Object.create(null), callee.defaultConfig, config);
132 | }
133 | const handlerMap = Object.create(null);
134 | const noop = function () {};
135 | const err =
136 | config.onerror || noop; /* config.onerror is intentionally undocumented
137 | pending finding a less ambiguous name */
138 | const debug = config.debug || noop;
139 | const idTypeMap = config.generateMessageId ? undefined : Object.create(null);
140 | const genMsgId =
141 | config.generateMessageId ||
142 | function (msg) {
143 | return (
144 | msg.type + '#' + (idTypeMap[msg.type] = (idTypeMap[msg.type] || 0) + 1)
145 | );
146 | };
147 | const toss = (...args) => {
148 | throw new Error(args.join(' '));
149 | };
150 | if (!config.worker) config.worker = callee.defaultConfig.worker;
151 | if ('function' === typeof config.worker) config.worker = config.worker();
152 | let dbId;
153 | let promiserFunc;
154 | config.worker.onmessage = function (ev) {
155 | ev = ev.data;
156 | debug('worker1.onmessage', ev);
157 | let msgHandler = handlerMap[ev.messageId];
158 | if (!msgHandler) {
159 | if (ev && 'sqlite3-api' === ev.type && 'worker1-ready' === ev.result) {
160 | /*fired one time when the Worker1 API initializes*/
161 | if (config.onready) config.onready(promiserFunc);
162 | return;
163 | }
164 | msgHandler = handlerMap[ev.type] /* check for exec per-row callback */;
165 | if (msgHandler && msgHandler.onrow) {
166 | msgHandler.onrow(ev);
167 | return;
168 | }
169 | if (config.onunhandled) config.onunhandled(arguments[0]);
170 | else err('sqlite3Worker1Promiser() unhandled worker message:', ev);
171 | return;
172 | }
173 | delete handlerMap[ev.messageId];
174 | switch (ev.type) {
175 | case 'error':
176 | msgHandler.reject(ev);
177 | return;
178 | case 'open':
179 | if (!dbId) dbId = ev.dbId;
180 | break;
181 | case 'close':
182 | if (ev.dbId === dbId) dbId = undefined;
183 | break;
184 | default:
185 | break;
186 | }
187 | try {
188 | msgHandler.resolve(ev);
189 | } catch (e) {
190 | msgHandler.reject(e);
191 | }
192 | } /*worker.onmessage()*/;
193 | return (promiserFunc = function (/*(msgType, msgArgs) || (msgEnvelope)*/) {
194 | let msg;
195 | if (1 === arguments.length) {
196 | msg = arguments[0];
197 | } else if (2 === arguments.length) {
198 | msg = Object.create(null);
199 | msg.type = arguments[0];
200 | msg.args = arguments[1];
201 | msg.dbId = msg.args.dbId;
202 | } else {
203 | toss('Invalid arugments for sqlite3Worker1Promiser()-created factory.');
204 | }
205 | if (!msg.dbId && msg.type !== 'open') msg.dbId = dbId;
206 | msg.messageId = genMsgId(msg);
207 | msg.departureTime = performance.now();
208 | const proxy = Object.create(null);
209 | proxy.message = msg;
210 | let rowCallbackId /* message handler ID for exec on-row callback proxy */;
211 | if ('exec' === msg.type && msg.args) {
212 | if ('function' === typeof msg.args.callback) {
213 | rowCallbackId = msg.messageId + ':row';
214 | proxy.onrow = msg.args.callback;
215 | msg.args.callback = rowCallbackId;
216 | handlerMap[rowCallbackId] = proxy;
217 | } else if ('string' === typeof msg.args.callback) {
218 | toss(
219 | 'exec callback may not be a string when using the Promise interface.',
220 | );
221 | /**
222 | * Design note: the reason for this limitation is that this API takes
223 | * over worker.onmessage() and the client has no way of adding their own
224 | * message-type handlers to it. Per-row callbacks are implemented as
225 | * short-lived message.type mappings for worker.onmessage().
226 | *
227 | * We "could" work around this by providing a new
228 | * config.fallbackMessageHandler (or some such) which contains
229 | * a map of event type names to callbacks. Seems like overkill
230 | * for now, seeing as the client can pass callback functions
231 | * to this interface (whereas the string-form "callback" is
232 | * needed for the over-the-Worker interface).
233 | */
234 | }
235 | }
236 | //debug("requestWork", msg);
237 | let p = new Promise(function (resolve, reject) {
238 | proxy.resolve = resolve;
239 | proxy.reject = reject;
240 | handlerMap[msg.messageId] = proxy;
241 | debug(
242 | 'Posting',
243 | msg.type,
244 | 'message to Worker dbId=' + (dbId || 'default') + ':',
245 | msg,
246 | );
247 | config.worker.postMessage(msg);
248 | });
249 | if (rowCallbackId) p = p.finally(() => delete handlerMap[rowCallbackId]);
250 | return p;
251 | });
252 | } /*sqlite3Worker1Promiser()*/;
253 | globalThis.sqlite3Worker1Promiser.defaultConfig = {
254 | worker: function () {
255 | return new Worker(
256 | new URL('sqlite3-worker1-bundler-friendly.mjs', import.meta.url),
257 | {
258 | type: 'module',
259 | },
260 | );
261 | },
262 | onerror: (...args) => console.error('worker1 promiser error', ...args),
263 | };
264 |
--------------------------------------------------------------------------------
/sqlite-wasm/jswasm/sqlite3-worker1-promiser.js:
--------------------------------------------------------------------------------
1 | /*
2 | 2022-08-24
3 |
4 | The author disclaims copyright to this source code. In place of a
5 | legal notice, here is a blessing:
6 |
7 | * May you do good and not evil.
8 | * May you find forgiveness for yourself and forgive others.
9 | * May you share freely, never taking more than you give.
10 |
11 | ***********************************************************************
12 |
13 | This file implements a Promise-based proxy for the sqlite3 Worker
14 | API #1. It is intended to be included either from the main thread or
15 | a Worker, but only if (A) the environment supports nested Workers
16 | and (B) it's _not_ a Worker which loads the sqlite3 WASM/JS
17 | module. This file's features will load that module and provide a
18 | slightly simpler client-side interface than the slightly-lower-level
19 | Worker API does.
20 |
21 | This script necessarily exposes one global symbol, but clients may
22 | freely `delete` that symbol after calling it.
23 | */
24 | 'use strict';
25 | /**
26 | * Configures an sqlite3 Worker API #1 Worker such that it can be manipulated
27 | * via a Promise-based interface and returns a factory function which returns
28 | * Promises for communicating with the worker. This proxy has an _almost_
29 | * identical interface to the normal worker API, with any exceptions documented
30 | * below.
31 | *
32 | * It requires a configuration object with the following properties:
33 | *
34 | * - `worker` (required): a Worker instance which loads `sqlite3-worker1.js` or a
35 | * functional equivalent. Note that the promiser factory replaces the
36 | * worker.onmessage property. This config option may alternately be a
37 | * function, in which case this function re-assigns this property with the
38 | * result of calling that function, enabling delayed instantiation of a
39 | * Worker.
40 | * - `onready` (optional, but...): this callback is called with no arguments when
41 | * the worker fires its initial 'sqlite3-api'/'worker1-ready' message, which
42 | * it does when sqlite3.initWorker1API() completes its initialization. This is
43 | * the simplest way to tell the worker to kick off work at the earliest
44 | * opportunity.
45 | * - `onunhandled` (optional): a callback which gets passed the message event
46 | * object for any worker.onmessage() events which are not handled by this
47 | * proxy. Ideally that "should" never happen, as this proxy aims to handle all
48 | * known message types.
49 | * - `generateMessageId` (optional): a function which, when passed an
50 | * about-to-be-posted message object, generates a _unique_ message ID for the
51 | * message, which this API then assigns as the messageId property of the
52 | * message. It _must_ generate unique IDs on each call so that dispatching can
53 | * work. If not defined, a default generator is used (which should be
54 | * sufficient for most or all cases).
55 | * - `debug` (optional): a console.debug()-style function for logging information
56 | * about messages.
57 | *
58 | * This function returns a stateful factory function with the following
59 | * interfaces:
60 | *
61 | * - Promise function(messageType, messageArgs)
62 | * - Promise function({message object})
63 | *
64 | * The first form expects the "type" and "args" values for a Worker message. The
65 | * second expects an object in the form {type:..., args:...} plus any other
66 | * properties the client cares to set. This function will always set the
67 | * `messageId` property on the object, even if it's already set, and will set
68 | * the `dbId` property to the current database ID if it is _not_ set in the
69 | * message object.
70 | *
71 | * The function throws on error.
72 | *
73 | * The function installs a temporary message listener, posts a message to the
74 | * configured Worker, and handles the message's response via the temporary
75 | * message listener. The then() callback of the returned Promise is passed the
76 | * `message.data` property from the resulting message, i.e. the payload from the
77 | * worker, stripped of the lower-level event state which the onmessage() handler
78 | * receives.
79 | *
80 | * Example usage:
81 | *
82 | * const config = {...};
83 | * const sq3Promiser = sqlite3Worker1Promiser(config);
84 | * sq3Promiser('open', {filename:"/foo.db"}).then(function(msg){
85 | * console.log("open response",msg); // => {type:'open', result: {filename:'/foo.db'}, ...}
86 | * });
87 | * sq3Promiser({type:'close'}).then((msg)=>{
88 | * console.log("close response",msg); // => {type:'close', result: {filename:'/foo.db'}, ...}
89 | * });
90 | *
91 | * Differences from Worker API #1:
92 | *
93 | * - Exec's {callback: STRING} option does not work via this interface (it
94 | * triggers an exception), but {callback: function} does and works exactly
95 | * like the STRING form does in the Worker: the callback is called one time
96 | * for each row of the result set, passed the same worker message format as
97 | * the worker API emits:
98 | *
99 | * {type:typeString, row:VALUE, rowNumber:1-based-#, columnNames: array}
100 | *
101 | * Where `typeString` is an internally-synthesized message type string used
102 | * temporarily for worker message dispatching. It can be ignored by all client
103 | * code except that which tests this API. The `row` property contains the row
104 | * result in the form implied by the `rowMode` option (defaulting to `'array'`).
105 | * The `rowNumber` is a 1-based integer value incremented by 1 on each call into
106 | * the callback.
107 | *
108 | * At the end of the result set, the same event is fired with (row=undefined,
109 | * rowNumber=null) to indicate that the end of the result set has been reached.
110 | * Note that the rows arrive via worker-posted messages, with all the
111 | * implications of that.
112 | *
113 | * Notable shortcomings:
114 | *
115 | * - This API was not designed with ES6 modules in mind. Neither Firefox nor
116 | * Safari support, as of March 2023, the {type:"module"} flag to the Worker
117 | * constructor, so that particular usage is not something we're going to
118 | * target for the time being:
119 | *
120 | * https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker
121 | */
122 | globalThis.sqlite3Worker1Promiser = function callee(
123 | config = callee.defaultConfig,
124 | ) {
125 | // Inspired by: https://stackoverflow.com/a/52439530
126 | if (1 === arguments.length && 'function' === typeof arguments[0]) {
127 | const f = config;
128 | config = Object.assign(Object.create(null), callee.defaultConfig);
129 | config.onready = f;
130 | } else {
131 | config = Object.assign(Object.create(null), callee.defaultConfig, config);
132 | }
133 | const handlerMap = Object.create(null);
134 | const noop = function () {};
135 | const err =
136 | config.onerror || noop; /* config.onerror is intentionally undocumented
137 | pending finding a less ambiguous name */
138 | const debug = config.debug || noop;
139 | const idTypeMap = config.generateMessageId ? undefined : Object.create(null);
140 | const genMsgId =
141 | config.generateMessageId ||
142 | function (msg) {
143 | return (
144 | msg.type + '#' + (idTypeMap[msg.type] = (idTypeMap[msg.type] || 0) + 1)
145 | );
146 | };
147 | const toss = (...args) => {
148 | throw new Error(args.join(' '));
149 | };
150 | if (!config.worker) config.worker = callee.defaultConfig.worker;
151 | if ('function' === typeof config.worker) config.worker = config.worker();
152 | let dbId;
153 | let promiserFunc;
154 | config.worker.onmessage = function (ev) {
155 | ev = ev.data;
156 | debug('worker1.onmessage', ev);
157 | let msgHandler = handlerMap[ev.messageId];
158 | if (!msgHandler) {
159 | if (ev && 'sqlite3-api' === ev.type && 'worker1-ready' === ev.result) {
160 | /*fired one time when the Worker1 API initializes*/
161 | if (config.onready) config.onready(promiserFunc);
162 | return;
163 | }
164 | msgHandler = handlerMap[ev.type] /* check for exec per-row callback */;
165 | if (msgHandler && msgHandler.onrow) {
166 | msgHandler.onrow(ev);
167 | return;
168 | }
169 | if (config.onunhandled) config.onunhandled(arguments[0]);
170 | else err('sqlite3Worker1Promiser() unhandled worker message:', ev);
171 | return;
172 | }
173 | delete handlerMap[ev.messageId];
174 | switch (ev.type) {
175 | case 'error':
176 | msgHandler.reject(ev);
177 | return;
178 | case 'open':
179 | if (!dbId) dbId = ev.dbId;
180 | break;
181 | case 'close':
182 | if (ev.dbId === dbId) dbId = undefined;
183 | break;
184 | default:
185 | break;
186 | }
187 | try {
188 | msgHandler.resolve(ev);
189 | } catch (e) {
190 | msgHandler.reject(e);
191 | }
192 | } /*worker.onmessage()*/;
193 | return (promiserFunc = function (/*(msgType, msgArgs) || (msgEnvelope)*/) {
194 | let msg;
195 | if (1 === arguments.length) {
196 | msg = arguments[0];
197 | } else if (2 === arguments.length) {
198 | msg = Object.create(null);
199 | msg.type = arguments[0];
200 | msg.args = arguments[1];
201 | msg.dbId = msg.args.dbId;
202 | } else {
203 | toss('Invalid arugments for sqlite3Worker1Promiser()-created factory.');
204 | }
205 | if (!msg.dbId && msg.type !== 'open') msg.dbId = dbId;
206 | msg.messageId = genMsgId(msg);
207 | msg.departureTime = performance.now();
208 | const proxy = Object.create(null);
209 | proxy.message = msg;
210 | let rowCallbackId /* message handler ID for exec on-row callback proxy */;
211 | if ('exec' === msg.type && msg.args) {
212 | if ('function' === typeof msg.args.callback) {
213 | rowCallbackId = msg.messageId + ':row';
214 | proxy.onrow = msg.args.callback;
215 | msg.args.callback = rowCallbackId;
216 | handlerMap[rowCallbackId] = proxy;
217 | } else if ('string' === typeof msg.args.callback) {
218 | toss(
219 | 'exec callback may not be a string when using the Promise interface.',
220 | );
221 | /**
222 | * Design note: the reason for this limitation is that this API takes
223 | * over worker.onmessage() and the client has no way of adding their own
224 | * message-type handlers to it. Per-row callbacks are implemented as
225 | * short-lived message.type mappings for worker.onmessage().
226 | *
227 | * We "could" work around this by providing a new
228 | * config.fallbackMessageHandler (or some such) which contains
229 | * a map of event type names to callbacks. Seems like overkill
230 | * for now, seeing as the client can pass callback functions
231 | * to this interface (whereas the string-form "callback" is
232 | * needed for the over-the-Worker interface).
233 | */
234 | }
235 | }
236 | //debug("requestWork", msg);
237 | let p = new Promise(function (resolve, reject) {
238 | proxy.resolve = resolve;
239 | proxy.reject = reject;
240 | handlerMap[msg.messageId] = proxy;
241 | debug(
242 | 'Posting',
243 | msg.type,
244 | 'message to Worker dbId=' + (dbId || 'default') + ':',
245 | msg,
246 | );
247 | config.worker.postMessage(msg);
248 | });
249 | if (rowCallbackId) p = p.finally(() => delete handlerMap[rowCallbackId]);
250 | return p;
251 | });
252 | } /*sqlite3Worker1Promiser()*/;
253 | globalThis.sqlite3Worker1Promiser.defaultConfig = {
254 | worker: function () {
255 | let theJs = 'sqlite3-worker1.js';
256 | if (this.currentScript) {
257 | const src = this.currentScript.src.split('/');
258 | src.pop();
259 | theJs = src.join('/') + '/' + theJs;
260 | //sqlite3.config.warn("promiser currentScript, theJs =",this.currentScript,theJs);
261 | } else if (globalThis.location) {
262 | //sqlite3.config.warn("promiser globalThis.location =",globalThis.location);
263 | const urlParams = new URL(globalThis.location.href).searchParams;
264 | if (urlParams.has('sqlite3.dir')) {
265 | theJs = urlParams.get('sqlite3.dir') + '/' + theJs;
266 | }
267 | }
268 | return new Worker(theJs + globalThis.location.search);
269 | }.bind({
270 | currentScript: globalThis?.document?.currentScript,
271 | }),
272 | onerror: (...args) => console.error('worker1 promiser error', ...args),
273 | };
274 |
--------------------------------------------------------------------------------
/sqlite-wasm/jswasm/sqlite3-worker1.js:
--------------------------------------------------------------------------------
1 | /*
2 | 2022-05-23
3 |
4 | The author disclaims copyright to this source code. In place of a
5 | legal notice, here is a blessing:
6 |
7 | * May you do good and not evil.
8 | * May you find forgiveness for yourself and forgive others.
9 | * May you share freely, never taking more than you give.
10 |
11 | ***********************************************************************
12 |
13 | This is a JS Worker file for the main sqlite3 api. It loads
14 | sqlite3.js, initializes the module, and postMessage()'s a message
15 | after the module is initialized:
16 |
17 | {type: 'sqlite3-api', result: 'worker1-ready'}
18 |
19 | This seemingly superfluous level of indirection is necessary when
20 | loading sqlite3.js via a Worker. Instantiating a worker with new
21 | Worker("sqlite.js") will not (cannot) call sqlite3InitModule() to
22 | initialize the module due to a timing/order-of-operations conflict
23 | (and that symbol is not exported in a way that a Worker loading it
24 | that way can see it). Thus JS code wanting to load the sqlite3
25 | Worker-specific API needs to pass _this_ file (or equivalent) to the
26 | Worker constructor and then listen for an event in the form shown
27 | above in order to know when the module has completed initialization.
28 |
29 | This file accepts a URL arguments to adjust how it loads sqlite3.js:
30 |
31 | - `sqlite3.dir`, if set, treats the given directory name as the
32 | directory from which `sqlite3.js` will be loaded.
33 | */
34 | 'use strict';
35 | {
36 | const urlParams = globalThis.location
37 | ? new URL(globalThis.location.href).searchParams
38 | : new URLSearchParams();
39 | let theJs = 'sqlite3.js';
40 | if (urlParams.has('sqlite3.dir')) {
41 | theJs = urlParams.get('sqlite3.dir') + '/' + theJs;
42 | }
43 | //console.warn("worker1 theJs =",theJs);
44 | importScripts(theJs);
45 | }
46 | sqlite3InitModule().then((sqlite3) => sqlite3.initWorker1API());
47 |
--------------------------------------------------------------------------------
/sqlite-wasm/jswasm/sqlite3.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/livestorejs/sqlite-wasm/5a83497e5c36289ac4475ceacf0e72ea6af493b7/sqlite-wasm/jswasm/sqlite3.wasm
--------------------------------------------------------------------------------