summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalen Guyer <galen@galenguyer.com>2022-11-07 23:07:32 -0500
committerGalen Guyer <galen@galenguyer.com>2022-11-07 23:07:32 -0500
commit0dea469a59b14905a81dd97dc2e3d026d9f02250 (patch)
treecdc8bb4f5b4b450f3b228acaf72f7dd9280387e8
parent9cb2d410c8cb602197f0c9206538f3fab2581449 (diff)
SQLite works
-rw-r--r--.gitignore2
-rw-r--r--package.json5
-rw-r--r--pnpm-lock.yaml133
-rw-r--r--public/index.html2
-rwxr-xr-xpublic/split-db.sh28
-rw-r--r--src/App.js54
-rw-r--r--webpack.config.js12
7 files changed, 230 insertions, 6 deletions
diff --git a/.gitignore b/.gitignore
index b947077..96db806 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
node_modules/
dist/
+
+public/data/
diff --git a/package.json b/package.json
index 3c12833..9c4fe7f 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"@babel/preset-react": "^7.18.6",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.8",
"babel-loader": "^9.1.0",
+ "copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.1",
"prettier": "^2.7.1",
"react-refresh": "^0.14.0",
@@ -27,7 +28,9 @@
"webpack-dev-server": "^4.11.1"
},
"dependencies": {
+ "lodash": "^4.17.21",
"react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react-dom": "^18.2.0",
+ "sql.js-httpvfs": "^0.8.12"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e8930de..c13b802 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -7,19 +7,24 @@ specifiers:
'@babel/preset-react': ^7.18.6
'@pmmmwh/react-refresh-webpack-plugin': ^0.5.8
babel-loader: ^9.1.0
+ copy-webpack-plugin: ^11.0.0
css-loader: ^6.7.1
+ lodash: ^4.17.21
prettier: ^2.7.1
react: ^18.2.0
react-dom: ^18.2.0
react-refresh: ^0.14.0
+ sql.js-httpvfs: ^0.8.12
style-loader: ^3.3.1
webpack: ^5.74.0
webpack-cli: ^4.10.0
webpack-dev-server: ^4.11.1
dependencies:
+ lodash: 4.17.21
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
+ sql.js-httpvfs: 0.8.12
devDependencies:
'@babel/cli': 7.19.3_@babel+core@7.20.2
@@ -28,6 +33,7 @@ devDependencies:
'@babel/preset-react': 7.18.6_@babel+core@7.20.2
'@pmmmwh/react-refresh-webpack-plugin': 0.5.8_pvgfg2i233iclh4uhrrgev3t5a
babel-loader: 9.1.0_hkczypimj4evef4hfazf6yfxte
+ copy-webpack-plugin: 11.0.0_webpack@5.74.0
css-loader: 6.7.1_webpack@5.74.0
prettier: 2.7.1
react-refresh: 0.14.0
@@ -1333,6 +1339,27 @@ packages:
dev: true
optional: true
+ /@nodelib/fs.scandir/2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+ dev: true
+
+ /@nodelib/fs.stat/2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /@nodelib/fs.walk/1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.13.0
+ dev: true
+
/@pmmmwh/react-refresh-webpack-plugin/0.5.8_pvgfg2i233iclh4uhrrgev3t5a:
resolution: {integrity: sha512-wxXRwf+IQ6zvHSJZ+5T2RQNEsq+kx4jKRXfFvdt3nBIUzJUAvXEFsUeoaohDe/Kr84MTjGwcuIUPNcstNJORsA==}
engines: {node: '>= 10.13'}
@@ -1930,6 +1957,10 @@ packages:
resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==}
dev: true
+ /comlink/4.3.1:
+ resolution: {integrity: sha512-+YbhUdNrpBZggBAHWcgQMLPLH1KDF3wJpeqrCKieWQ8RL7atmgsgTQko1XEBK6PsecfopWNntopJ+ByYG1lRaA==}
+ dev: false
+
/commander/2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
dev: true
@@ -2008,6 +2039,21 @@ packages:
engines: {node: '>= 0.6'}
dev: true
+ /copy-webpack-plugin/11.0.0_webpack@5.74.0:
+ resolution: {integrity: sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==}
+ engines: {node: '>= 14.15.0'}
+ peerDependencies:
+ webpack: ^5.1.0
+ dependencies:
+ fast-glob: 3.2.12
+ glob-parent: 6.0.2
+ globby: 13.1.2
+ normalize-path: 3.0.0
+ schema-utils: 4.0.0
+ serialize-javascript: 6.0.0
+ webpack: 5.74.0_webpack-cli@4.10.0
+ dev: true
+
/core-js-compat/3.26.0:
resolution: {integrity: sha512-piOX9Go+Z4f9ZiBFLnZ5VrOpBl0h7IGCkiFUN11QTe6LjAvOT3ifL/5TdoizMh99hcGy5SoLyWbapIY/PIb/3A==}
dependencies:
@@ -2109,6 +2155,13 @@ packages:
resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
dev: true
+ /dir-glob/3.0.1:
+ resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+ engines: {node: '>=8'}
+ dependencies:
+ path-type: 4.0.0
+ dev: true
+
/dns-equal/1.0.0:
resolution: {integrity: sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==}
dev: true
@@ -2278,6 +2331,17 @@ packages:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
dev: true
+ /fast-glob/3.2.12:
+ resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+ dev: true
+
/fast-json-stable-stringify/2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
dev: true
@@ -2287,6 +2351,12 @@ packages:
engines: {node: '>= 4.9.1'}
dev: true
+ /fastq/1.13.0:
+ resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
+ dependencies:
+ reusify: 1.0.4
+ dev: true
+
/faye-websocket/0.11.4:
resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==}
engines: {node: '>=0.8.0'}
@@ -2410,6 +2480,13 @@ packages:
is-glob: 4.0.3
dev: true
+ /glob-parent/6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
/glob-to-regexp/0.4.1:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
dev: true
@@ -2430,6 +2507,17 @@ packages:
engines: {node: '>=4'}
dev: true
+ /globby/13.1.2:
+ resolution: {integrity: sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ dir-glob: 3.0.1
+ fast-glob: 3.2.12
+ ignore: 5.2.0
+ merge2: 1.4.1
+ slash: 4.0.0
+ dev: true
+
/graceful-fs/4.2.10:
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
dev: true
@@ -2553,6 +2641,11 @@ packages:
postcss: 8.4.18
dev: true
+ /ignore/5.2.0:
+ resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==}
+ engines: {node: '>= 4'}
+ dev: true
+
/import-local/3.1.0:
resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==}
engines: {node: '>=8'}
@@ -2743,6 +2836,10 @@ packages:
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
dev: true
+ /lodash/4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+ dev: false
+
/loose-envify/1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
@@ -2792,6 +2889,11 @@ packages:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
dev: true
+ /merge2/1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+ dev: true
+
/methods/1.1.2:
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
engines: {node: '>= 0.6'}
@@ -3005,6 +3107,11 @@ packages:
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
dev: true
+ /path-type/4.0.0:
+ resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+ engines: {node: '>=8'}
+ dev: true
+
/picocolors/1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
dev: true
@@ -3118,6 +3225,10 @@ packages:
side-channel: 1.0.4
dev: true
+ /queue-microtask/1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ dev: true
+
/randombytes/2.1.0:
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
dependencies:
@@ -3275,6 +3386,11 @@ packages:
engines: {node: '>= 4'}
dev: true
+ /reusify/1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ dev: true
+
/rimraf/3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
hasBin: true
@@ -3282,6 +3398,12 @@ packages:
glob: 7.2.3
dev: true
+ /run-parallel/1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+ dev: true
+
/safe-buffer/5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
dev: true
@@ -3446,6 +3568,11 @@ packages:
engines: {node: '>=6'}
dev: true
+ /slash/4.0.0:
+ resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==}
+ engines: {node: '>=12'}
+ dev: true
+
/sockjs/0.3.24:
resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==}
dependencies:
@@ -3502,6 +3629,12 @@ packages:
- supports-color
dev: true
+ /sql.js-httpvfs/0.8.12:
+ resolution: {integrity: sha512-lcEBc2q0psFRfdCx8Di22oUIkkv5MUIaVO/fGCj/Jjx6YQDKVylQEcjd7NSSbmINHTRwVkm/vWP8uuevT7Rkkw==}
+ dependencies:
+ comlink: 4.3.1
+ dev: false
+
/stackframe/1.3.4:
resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==}
dev: true
diff --git a/public/index.html b/public/index.html
index 1087814..d0bcf17 100644
--- a/public/index.html
+++ b/public/index.html
@@ -13,7 +13,7 @@
<noscript>
You need to enable JavaScript to run this app.
</noscript>
- <script src="../dist/bundle.js"></script>
+ <script src="../bundle.js"></script>
</body>
</html>
diff --git a/public/split-db.sh b/public/split-db.sh
new file mode 100755
index 0000000..e43b131
--- /dev/null
+++ b/public/split-db.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+indb="$1"
+outdir="$2"
+
+# for chunked mode, we need to know the database size in bytes beforehand
+bytes="$(stat --printf="%s" "$indb")"
+# set chunk size to 4MiB (needs to be a multiple of the `pragma page_size`!)
+serverChunkSize=$((4 * 1024 * 1024))
+suffixLength=4
+rm -f "$outdir/db.sqlite3"*
+split "$indb" --bytes=$serverChunkSize "$outdir/db.sqlite3." --suffix-length=$suffixLength --numeric-suffixes
+
+# set request chunk size to match page size
+requestChunkSize="$(sqlite3 --noheader "$indb" 'pragma page_size')"
+
+# write a json config
+echo '
+{
+ "serverMode": "chunked",
+ "requestChunkSize": '$requestChunkSize',
+ "databaseLengthBytes": '$bytes',
+ "serverChunkSize": '$serverChunkSize',
+ "urlPrefix": "db.sqlite3.",
+ "suffixLength": '$suffixLength'
+}
+' > "$outdir/config.json"
diff --git a/src/App.js b/src/App.js
index 1dda981..beb4bf7 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,10 +1,60 @@
-import React from 'react';
+import { useEffect, useState } from 'react';
import './App.css';
+import { createDbWorker } from 'sql.js-httpvfs';
+import { debounce } from 'lodash';
+
+// sadly there's no good way to package workers and wasm directly so you need a way to get these two URLs from your bundler.
+// This is the webpack5 way to create a asset bundle of the worker and wasm:
+const workerUrl = new URL(
+ 'sql.js-httpvfs/dist/sqlite.worker.js',
+ import.meta.url
+);
+const wasmUrl = new URL('sql.js-httpvfs/dist/sql-wasm.wasm', import.meta.url);
+
+const config = {
+ from: 'jsonconfig',
+ configUrl: '/data/config.json',
+};
+
+const worker = createDbWorker(
+ [config],
+ workerUrl.toString(),
+ wasmUrl.toString()
+);
+
+const doQuery = (query, callback) => {
+ worker.then((worker) => {
+ worker.db.query(query).then((results) => {
+ callback(results);
+ localStorage.setItem('query', query);
+ }).catch((error) => {
+ console.error(error);
+ });
+ });
+};
+
+const handleKeyUp = debounce((event, callback) => {
+ callback(event.target.innerText);
+}, /*wait:*/ 1000);
export default function App() {
+ const [results, setResults] = useState([]);
+ const [query, setQuery] = useState(
+ localStorage.getItem("query") || "SELECT first_name, last_name FROM entities WHERE call_sign = 'K9FGT'"
+ );
+
+ useEffect(() => {
+ document.getElementById("query").innerText = query;
+ }, []);
+
+ useEffect(() => {
+ doQuery(query, setResults);
+ }, [query]);
+
return (
<div className="App">
- <h1>Hello, World!</h1>
+ <pre id="query" contentEditable onKeyUp={(e) => handleKeyUp(e, setQuery)}></pre>
+ <pre>{JSON.stringify(results)}</pre>
</div>
);
}
diff --git a/webpack.config.js b/webpack.config.js
index b406cc3..fc52c2b 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,5 +1,6 @@
const path = require('path')
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')
+const CopyPlugin = require("copy-webpack-plugin");
const isDevelopment = process.env.NODE_ENV !== 'production'
@@ -23,11 +24,18 @@ module.exports = {
resolve: { extensions: ['*', '.js', '.jsx'] },
output: {
path: path.resolve(__dirname, 'dist/'),
- publicPath: '/dist/',
+ publicPath: '/',
filename: 'bundle.js'
},
devServer: {
client: { overlay: false }
},
- plugins: [isDevelopment && new ReactRefreshWebpackPlugin()].filter(Boolean)
+ plugins: [
+ new CopyPlugin({
+ patterns: [
+ { from: "public" },
+ ],
+ }),
+ isDevelopment && new ReactRefreshWebpackPlugin(),
+ ].filter(Boolean)
}