├── .nvmrc ├── .gitignore ├── src ├── index.js ├── styles.css └── App.js ├── craco.config.js ├── README.md ├── package.json ├── LICENSE └── public └── index.html /.nvmrc: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | node_modules/ 4 | build 5 | .DS_Store 6 | *.tgz 7 | my-app* 8 | template/src/__tests__/__snapshots__/ 9 | lerna-debug.log 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | /.changelog 14 | .npm/ 15 | yarn.lock 16 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | import App from "./App"; 5 | 6 | const rootElement = document.getElementById("root"); 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | rootElement 12 | ); 13 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | font-size: 1.5em; 4 | } 5 | 6 | textarea { 7 | font-size: 1.1em; 8 | width: 70%; 9 | display: block; 10 | margin: auto; 11 | } 12 | 13 | table { 14 | border: 1px solid #1c6ea4; 15 | background-color: #eeeeee; 16 | width: 40%; 17 | margin: 1.5em auto; 18 | text-align: left; 19 | border-collapse: collapse; 20 | text-align: right; 21 | } 22 | 23 | thead { 24 | font-weight: bold; 25 | text-align: center; 26 | border: 2px solid #999; 27 | } 28 | 29 | th, 30 | td { 31 | border: 1px solid #aaa; 32 | } 33 | 34 | .error { 35 | color: #922; 36 | } 37 | -------------------------------------------------------------------------------- /craco.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpack: { 3 | configure: (webpackConfig) => { 4 | // Add the following lines to handle 'crypto' and 'fs' dependencies 5 | webpackConfig.resolve.fallback = { 6 | fs: require.resolve("browserify-fs"), // or 'empty' if you prefer an empty module 7 | crypto: require.resolve('crypto-browserify'), 8 | stream: require.resolve('stream-browserify'), 9 | }; 10 | 11 | // Add the 'module' configuration for handling .wasm files 12 | webpackConfig.module.rules.push({ 13 | test: /\.wasm$/, 14 | type: 'javascript/auto', 15 | }); 16 | 17 | return webpackConfig; 18 | }, 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # demonstration of [react](https://reactjs.org/) + [sql.js](https://github.com/sql-js/sql.js) 2 | 3 | This is a template repository demonstrating the use of sql.js with create-react-app. 4 | 5 | The only differences with a traditional create-react-app application are : 6 | - The usage of [craco](https://github.com/gsoft-inc/craco) to allow providing a custom [webpack](https://webpack.js.org/) configuration 7 | - a small custom webpack configuration in [`craco.config.js`](./craco.config.js) to copy the wasm module from sql.js to the distributed assets 8 | 9 | Note that you should make sure your server serves `.wasm` files with the right mimetype, that is: `application/wasm`. Otherwise, you'll see the following error: `TypeError: Response has unsupported MIME type` 10 | 11 | See [`src/App.js`](./src/App.js) for the code. 12 | 13 | ### [view the live demo](https://react-sqljs-demo.ophir.dev/) 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-sqljs-demo", 3 | "version": "1.0.0", 4 | "description": "sql.js + react example starter project", 5 | "keywords": [ 6 | "react", 7 | "starter" 8 | ], 9 | "main": "src/index.js", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@babel/plugin-proposal-private-property-in-object": "^7.21.11", 13 | "browserify-fs": "^1.0.0", 14 | "crypto-browserify": "^3.12.0", 15 | "react": "^17.0.2", 16 | "react-dom": "^17.0.2", 17 | "sql.js": "^1.6.2", 18 | "stream-browserify": "^3.0.0" 19 | }, 20 | "devDependencies": { 21 | "@craco/craco": "^5.9.0", 22 | "react-scripts": "^5.0.1", 23 | "typescript": "^4.5.5" 24 | }, 25 | "scripts": { 26 | "start": "craco start", 27 | "build": "craco build", 28 | "test": "craco test --env=jsdom", 29 | "eject": "craco eject" 30 | }, 31 | "browserslist": [ 32 | ">0.2%", 33 | "not dead", 34 | "not ie <= 11", 35 | "not op_mini all" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 SQL.JS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 23 | React App 24 | 25 | 26 | 27 | 30 |
31 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import "./styles.css"; 3 | import initSqlJs from "sql.js"; 4 | 5 | // Required to let webpack 4 know it needs to copy the wasm file to our assets 6 | import sqlWasm from "!!file-loader?name=sql-wasm-[contenthash].wasm!sql.js/dist/sql-wasm.wasm"; 7 | 8 | export default function App() { 9 | const [db, setDb] = useState(null); 10 | const [error, setError] = useState(null); 11 | 12 | useEffect(async () => { 13 | // sql.js needs to fetch its wasm file, so we cannot immediately instantiate the database 14 | // without any configuration, initSqlJs will fetch the wasm files directly from the same path as the js 15 | // see ../craco.config.js 16 | try { 17 | const SQL = await initSqlJs({ locateFile: () => sqlWasm }); 18 | setDb(new SQL.Database()); 19 | } catch (err) { 20 | setError(err); 21 | } 22 | }, []); 23 | 24 | if (error) return
{error.toString()}
; 25 | else if (!db) return
Loading...
; 26 | else return ; 27 | } 28 | 29 | /** 30 | * A simple SQL read-eval-print-loop 31 | * @param {{db: import("sql.js").Database}} props 32 | */ 33 | function SQLRepl({ db }) { 34 | const [error, setError] = useState(null); 35 | const [results, setResults] = useState([]); 36 | 37 | function exec(sql) { 38 | try { 39 | // The sql is executed synchronously on the UI thread. 40 | // You may want to use a web worker here instead 41 | setResults(db.exec(sql)); // an array of objects is returned 42 | setError(null); 43 | } catch (err) { 44 | // exec throws an error when the SQL statement is invalid 45 | setError(err); 46 | setResults([]); 47 | } 48 | } 49 | 50 | return ( 51 |
52 |

React SQL interpreter

53 | 54 | 58 | 59 |
{(error || "").toString()}
60 | 61 |
 62 |         {
 63 |           // results contains one object per select statement in the query
 64 |           results.map(({ columns, values }, i) => (
 65 |             
 66 |           ))
 67 |         }
 68 |       
69 |
70 | ); 71 | } 72 | 73 | /** 74 | * Renders a single value of the array returned by db.exec(...) as a table 75 | * @param {import("sql.js").QueryExecResult} props 76 | */ 77 | function ResultsTable({ columns, values }) { 78 | return ( 79 | 80 | 81 | 82 | {columns.map((columnName, i) => ( 83 | 84 | ))} 85 | 86 | 87 | 88 | 89 | { 90 | // values is an array of arrays representing the results of the query 91 | values.map((row, i) => ( 92 | 93 | {row.map((value, i) => ( 94 | 95 | ))} 96 | 97 | )) 98 | } 99 | 100 |
{columnName}
{value}
101 | ); 102 | } 103 | --------------------------------------------------------------------------------