diff options
author | Galen Guyer <galen@galenguyer.com> | 2022-11-07 23:07:32 -0500 |
---|---|---|
committer | Galen Guyer <galen@galenguyer.com> | 2022-11-07 23:07:32 -0500 |
commit | 0dea469a59b14905a81dd97dc2e3d026d9f02250 (patch) | |
tree | cdc8bb4f5b4b450f3b228acaf72f7dd9280387e8 | |
parent | 9cb2d410c8cb602197f0c9206538f3fab2581449 (diff) |
SQLite works
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | package.json | 5 | ||||
-rw-r--r-- | pnpm-lock.yaml | 133 | ||||
-rw-r--r-- | public/index.html | 2 | ||||
-rwxr-xr-x | public/split-db.sh | 28 | ||||
-rw-r--r-- | src/App.js | 54 | ||||
-rw-r--r-- | webpack.config.js | 12 |
7 files changed, 230 insertions, 6 deletions
@@ -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" @@ -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) } |