diff --git a/docz/docs/03-demos/04-static/01-lume.md b/docz/docs/03-demos/04-static/01-lume.md index ffab21a..97b1842 100644 --- a/docz/docs/03-demos/04-static/01-lume.md +++ b/docz/docs/03-demos/04-static/01-lume.md @@ -129,7 +129,7 @@ site.use(sheets({ :::note -This demo was last tested against `lume v1.17.5` on 2023 June 25. +This demo was last tested against `lume v1.19.1` on 2023 October 14. This example uses the Nunjucks template format. Lume plugins support additional template formats, including Markdown and JSX. @@ -195,7 +195,7 @@ page will show the contents of the spreadsheet. 5) While the server is still running, open `_data/pres.xlsx` in a spreadsheet editor and add a new row at the bottom of the sheet. -The page will refresh and show the new contents. +After saving the spreadsheet, the page will refresh and show the new contents. ### Static Site diff --git a/docz/docs/03-demos/06-desktop/06-reactnative.md b/docz/docs/03-demos/06-desktop/06-reactnative.md index c4ab3e9..9c55954 100644 --- a/docz/docs/03-demos/06-desktop/06-reactnative.md +++ b/docz/docs/03-demos/06-desktop/06-reactnative.md @@ -47,7 +47,7 @@ This demo was tested in the following environments: | OS and Version | Arch | RN Platform | Date | |:---------------|:-----|:------------|:-----------| | Windows 10 | x64 | `v0.71.25` | 2023-07-24 | -| Windows 11 | x64 | `v0.71.11` | 2023-05-11 | +| Windows 11 | x64 | `v0.72.12` | 2023-10-14 | | Windows 11 | ARM | `v0.72.9` | 2023-09-18 | | MacOS 12.6 | x64 | `v0.71.26` | 2023-07-23 | | MacOS 13.5.2 | ARM | `v0.72.4` | 2023-09-18 | @@ -394,16 +394,30 @@ been tested against both application types. ::: -0) Follow the ["Getting Started" guide](https://microsoft.github.io/react-native-windows/docs/getting-started) +0) Install the [development dependencies](https://microsoft.github.io/react-native-windows/docs/rnw-dependencies). :::caution pass -At the time of testing, NodeJS `v16` was required. A tool like +In earlier versions of React Native, NodeJS `v16` was required. A tool like [`nvm-windows`](https://github.com/coreybutler/nvm-windows/releases) should be used to switch the NodeJS version. ::: +
Installation Notes (click to show) + +When the demo was last tested, a PowerShell script installed dependencies: + +```powershell +Set-ExecutionPolicy Unrestricted -Scope Process -Force; +iex (New-Object System.Net.WebClient).DownloadString('https://aka.ms/rnw-vs2022-deps.ps1'); +``` + +If any step fails to install, open the dependencies page and expand "Manual +setup instructions" to find instructions for manual installation. + +
+ ### Project Setup 1) Create a new project using React Native `0.72`: @@ -578,7 +592,7 @@ curl -LO https://docs.sheetjs.com/reactnative/rnw/App.tsx -8) Test the app again: +8) Launch the app again: @@ -611,10 +625,10 @@ When this demo was last tested on Windows 11 ARM, the build failed. -Download . +9) Download . -Click "Click here to Open File!" and use the file picker to select `pres.xlsx` . -The app will refresh and display the data from the file. +10) In the app, click "Click here to Open File!" and use the file picker to +select `pres.xlsx` . The app will refresh and display the data from the file. ## macOS Demo diff --git a/docz/docs/03-demos/06-desktop/09-cli.md b/docz/docs/03-demos/06-desktop/09-cli.md index 34045bd..82825f8 100644 --- a/docz/docs/03-demos/06-desktop/09-cli.md +++ b/docz/docs/03-demos/06-desktop/09-cli.md @@ -242,7 +242,7 @@ This demo was last tested in the following deployments: | `darwin-x64` | `11.8.172.13` | `0.79.2` | 2023-10-12 | | `darwin-arm` | `11.4.183.2` | `0.71.2` | 2023-05-22 | | `win10-x64` | `11.8.172.13` | `0.79.2` | 2023-10-09 | -| `win11-x64` | `11.7.439.6` | `0.75.1` | 2023-08-31 | +| `win11-x64` | `11.8.172.13` | `0.79.2` | 2023-10-14 | | `linux-x64` | `11.8.172.13` | `0.79.2` | 2023-10-11 | | `linux-arm` | `11.7.439.6` | `0.75.1` | 2023-08-30 | @@ -353,6 +353,7 @@ This demo was last tested in the following deployments: | `darwin-x64` | `1.37.1` | 2023-10-12 | | `darwin-arm` | `1.34.1` | 2023-06-05 | | `win10-x64` | `1.37.1` | 2023-10-09 | +| `win11-x64` | `1.37.2` | 2023-10-14 | | `win11-arm` | `1.37.0` | 2023-09-26 | | `linux-x64` | `1.37.1` | 2023-10-11 | | `linux-arm` | `1.36.3` | 2023-08-30 | diff --git a/docz/docs/03-demos/07-data/01-websql.md b/docz/docs/03-demos/07-data/01-websql.md deleted file mode 100644 index 5ab6faa..0000000 --- a/docz/docs/03-demos/07-data/01-websql.md +++ /dev/null @@ -1,258 +0,0 @@ ---- -title: WebSQL and SQLite -pagination_prev: demos/desktop/index -pagination_next: demos/local/index -sidebar_custom_props: - type: web - sql: true ---- - -import current from '/version.js'; -import CodeBlock from '@theme/CodeBlock'; - -WebSQL is a popular SQL-based in-browser database available on Chrome. In -practice, it is powered by SQLite, and most simple SQLite-compatible queries -work as-is in WebSQL. - -The public demo generates a database from workbook. - -:::caution pass - -WebSQL is only supported in Chromium-based browsers including Chrome. - -Safari historically supported WebSQL but Safari 13 dropped support. Legacy -browsers including Internet Explorer and Firefox never added support. - -::: - -## WebSQL Details - -Importing data from spreadsheets is straightforward using the `generate_sql` -helper function from ["Generating Tables"](/docs/demos/data/sql#generating-tables). - -The Web SQL Database API is callback-based. The following snippet wraps -transactions in Promise objects: - -```js -const db = openDatabase('sheetql', '1.0', 'SheetJS WebSQL Test', 2097152); -const stmts = generate_sql(ws, wsname); - -// NOTE: tx.executeSql and db.transaction use callbacks. This wraps in Promises -for(var stmt of stmts) await new Promise((res, rej) => { - db.transaction(tx => - tx.executeSql(stmt, [], - (tx, data) => res(data), // if the query is successful, return the data - (tx, err) => rej(err) // if the query fails, reject with the error - )); -}); -``` - -The result of a SQL SELECT statement is a `SQLResultSet`. The `rows` property -is a `SQLResultSetRowList`. It is an "array-like" structure that has `length` -and properties like `0`, `1`, etc. However, this is not a real Array object! - -A real Array can be created using `Array.from`: - -```js -db.readTransaction(tx => - tx.executeSQL("SELECT * FROM DatabaseTable", [], (tx, data) => { - // data.rows is "array-like", so `Array.from` can make it a real array - const aoo = Array.from(data.rows); - const ws = XLSX.utils.json_to_sheet(aoo); - // ... perform an export here OR wrap in a Promise - }) -); -``` - -### Live Demo - -:::note - -This browser demo was tested in the following environments: - -| Browser | Date | -|:------------|:-----------| -| Chrome 117 | 2023-10-11 | - -Some lesser-used browsers do not support WebSQL: - -| Browser | Date | Support | -|:------------|:-----------|:------------------------------------| -| Safari 17.0 | 2023-10-11 | Error `Web SQL is deprecated` | -| Firefox 118 | 2023-10-11 | Error `openDatabase is not defined` | - -::: - -The following demo generates a database with 5 fixed SQL statements. Queries -can be changed in the Live Editor. The WebSQL database can be inspected in the -"WebSQL" section of the "Application" Tab of Developer Tools: - -![WebSQL view in Developer Tools](pathname:///files/websql.png) - -```jsx live -function SheetQL() { - const [out, setOut] = React.useState(""); - const queries = [ - 'DROP TABLE IF EXISTS Presidents', - 'CREATE TABLE Presidents (Name TEXT, Idx REAL)', - 'INSERT INTO Presidents (Name, Idx) VALUES ("Barack Obama", 44)', - 'INSERT INTO Presidents (Name, Idx) VALUES ("Donald Trump", 45)', - 'INSERT INTO Presidents (Name, Idx) VALUES ("Joseph Biden", 46)' - ]; - const xport = React.useCallback(async() => { - /* prep database */ - const db = openDatabase('sheetql', '1.0', 'SheetJS WebSQL Test', 2097152); - - for(var q of queries) await new Promise((res, rej) => { - db.transaction((tx) => { - tx.executeSql(q, [], (tx, data) => res(data), (tx, err) => rej(err)); - }); - }); - - /* pull data and generate rows */ - db.readTransaction(tx => { - tx.executeSql("SELECT * FROM Presidents", [], (tx, data) => { - const aoo = Array.from(data.rows); - setOut("QUERY RESULT:\n" + aoo.map(r => JSON.stringify(r)).join("\n") + "\n") - const ws = XLSX.utils.json_to_sheet(aoo); - const wb = XLSX.utils.book_new(); - XLSX.utils.book_append_sheet(wb, ws, "Presidents"); - XLSX.writeFile(wb, "SheetQL.xlsx"); - }); - }); - }); - return (
{out}
); -} -``` - -## Server-Side SQLite - -Most platforms offer a simple way to query SQLite database files. - -The following example shows how to query for each table in an SQLite database, -query for the data for each table, add each non-empty table to a workbook, and -export as XLSX. - -The Chinook database is a MIT-licensed sample database. The original source code -repository `http://chinookdatabase.codeplex.com` is no longer available, so the -[raw SQL queries are mirrored here](pathname:///sqlite/chinook.sql). - -:::note - -This demo was last tested on 2023 May 28 - -::: - -### NodeJS - -The `better-sqlite3` module provides an API for working with SQLite databases. -`Statement#all` runs a prepared statement and returns an array of objects: - -```js -import Database from "better-sqlite3"; -import * as XLSX from "xlsx"; - -/* open database */ -var db = Database("chinook.db"); - -/* get data from the `Invoice` table */ -var aoo = db.prepare("SELECT * FROM 'Invoice' LIMIT 100000").all(); - -/* create worksheet from the row objects */ -var ws = XLSX.utils.json_to_sheet(aoo, {dense: true}); -``` - -0) Build `chinook.db` from [the SQL statements](pathname:///sqlite/chinook.sql): - -```bash -curl -LO https://docs.sheetjs.com/sqlite/chinook.sql -sqlite3 chinook.db ".read chinook.sql" -``` - -1) Install the dependencies: - -{`\ -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz better-sqlite3@8.1.0`} - - -2) Download [`SheetJSQLiteNode.mjs`](pathname:///sqlite/SheetJSQLiteNode.mjs): - -```bash -curl -LO https://docs.sheetjs.com/sqlite/SheetJSQLiteNode.mjs -``` - -3) Run `node SheetJSQLiteNode.mjs` and open `SheetJSQLiteNode.xlsx` - -### Bun - -Bun ships with a built-in high-performance module `bun:sqlite`: - -```js -import { Database } from "bun:sqlite"; -import * as XLSX from "xlsx"; - -/* open database */ -var db = Database.open("chinook.db"); - -/* get data from the `Invoice` table */ -var aoo = db.prepare("SELECT * FROM 'Invoice' LIMIT 100000").all(); - -/* create worksheet from the row objects */ -var ws = XLSX.utils.json_to_sheet(aoo, {dense: true}); -``` - -0) Build `chinook.db` from [the SQL statements](pathname:///sqlite/chinook.sql): - -```bash -curl -LO https://docs.sheetjs.com/sqlite/chinook.sql -sqlite3 chinook.db ".read chinook.sql" -``` - -1) Install the dependencies: - -{`\ -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} - - -2) Download [`SheetJSQLiteBun.mjs`](pathname:///sqlite/SheetJSQLiteBun.mjs): - -```bash -curl -LO https://docs.sheetjs.com/sqlite/SheetJSQLiteBun.mjs -``` - -3) Run `bun run SheetJSQLiteBun.mjs` and open `SheetJSQLiteBun.xlsx` - -### Deno - -Deno `sqlite` library returns raw arrays of arrays: - -{`\ -import { DB } from "https://deno.land/x/sqlite/mod.ts"; -// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts" -import * as XLSX from "https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs"; -\n\ -/* open database */ -var db = new DB("chinook.db"); -\n\ -/* get data from the \`Invoice\` table */ -var aoa = db.prepareQuery("SELECT * FROM 'Invoice' LIMIT 100000").all(); -\n\ -/* create worksheet from the row objects */ -var data = [query.columns().map(x => x.name)].concat(aoa); -var ws = XLSX.utils.aoa_to_sheet(data, {dense: true});`} - - -0) Build `chinook.db` from [the SQL statements](pathname:///sqlite/chinook.sql): - -```bash -curl -LO https://docs.sheetjs.com/sqlite/chinook.sql -sqlite3 chinook.db ".read chinook.sql" -``` - -1) Download [`SheetJSQLiteDeno.ts`](pathname:///sqlite/SheetJSQLiteDeno.ts): - -```bash -curl -LO https://docs.sheetjs.com/sqlite/SheetJSQLiteDeno.ts -``` - -2) Run `deno run --allow-read --allow-write SheetJSQLiteDeno.ts` and open `SheetJSQLiteDeno.xlsx` diff --git a/docz/docs/03-demos/07-data/11-sqlite.md b/docz/docs/03-demos/07-data/11-sqlite.md new file mode 100644 index 0000000..db761bd --- /dev/null +++ b/docz/docs/03-demos/07-data/11-sqlite.md @@ -0,0 +1,314 @@ +--- +title: Sheets with SQLite +sidebar_label: SQLite +pagination_prev: demos/desktop/index +pagination_next: demos/local/index +sidebar_custom_props: + sql: true +--- + + + + + +import current from '/version.js'; +import CodeBlock from '@theme/CodeBlock'; + +[SQLite](https://sqlite.org/) is a lightweight embeddable SQL database engine. +There are connector libraries for many popular JavaScript server-side platforms. + +[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing +data from spreadsheets. + +This demo uses SQLite and SheetJS to exchange data between spreadsheets and SQL +servers. We'll explore how to use save tables from a database to spreadsheets +and how to add data from spreadsheets into a database. + +:::note + +This demo was last tested on 2023 October 13 + +::: + +:::info pass + +This demo covers SQLite `.db` file processing. + +The [WebSQL demo](/docs/demos/local/websql) covers the Web SQL Database API, a +SQLite-compatible database built into Chromium and Google Chrome. + +::: + +## Demo + +The following examples show how to query for each table in an SQLite database, +query for the data for each table, add each non-empty table to a workbook, and +export as XLSX. + +#### Sample Database + +The Chinook database is a MIT-licensed sample database. The original source code +repository `http://chinookdatabase.codeplex.com` is no longer available, so the +[raw SQL queries are mirrored here](pathname:///sqlite/chinook.sql). + +### Exporting Data + +Connector libraries typically provide a way to generate an array of objects from +the result of a `SELECT` query. For example, using `better-sqlite3` in NodeJS: + +```js +import Database from "better-sqlite3"; + +/* open database */ +var db = Database("chinook.db"); + +/* get data from the `Invoice` table */ +var aoo = db.prepare("SELECT * FROM 'Invoice' LIMIT 100000").all(); +``` + +The SheetJS `json_to_sheet` method[^1] can take the result and generate a +worksheet object[^2]. The `book_new` and `book_append_sheet` methods[^3] help +build a workbook object[^4]. The `writeFile` method[^5] generates a file: + +```js +import * as XLSX from "xlsx"; + +/* Create Worksheet from the row objects */ +var ws = XLSX.utils.json_to_sheet(aoo, {dense: true}); + +/* Add to Workbook */ +XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); + +/* Write File */ +XLSX.writeFile(wb, "SheetJSQLiteNode.xlsx"); +``` + +### Importing Data + +The ["Generating Tables"](/docs/demos/data/sql#generating-tables) section +includes a code snippet for generating SQLite-compatible SQL queries from a +SheetJS worksheet object. Each query can be run sequentially. + +## Browser + +`sql.js`[^6] is a compiled version of SQLite into WebAssembly, making it usable +in web browsers. + +SQLite database files can be `fetch`ed and loaded: + +```js +/* Load sql.js library */ +const SQL = await initSqlJs(config); +/* fetch sqlite database */ +const ab = await (await fetch("/sqlite/chinook.db")).arrayBuffer(); +/* connect to DB */ +const db = new SQL.Database(new Uint8Array(ab)); +``` + +The `sql.js` connector library uses an iterator-like interface. After preparing +a statement, `Statement#step` loops over the result and `Statement#getAsObject` +pulls each row as a row object: + +```js +/* perform query and get iterator */ +const sql = db.prepare("SELECT * FROM 'Invoice' LIMIT 100000").all(); + +/* create worksheet from the row objects */ +let ws; + +while(sql.step()) { + const row = sql.getAsObject(); + + if(!ws) ws = XLSX.utils.json_to_sheet([row], {dense: true, header}); + else XLSX.utils.sheet_add_json(ws, [row], { header, origin: -1, skipHeader: true}); +} +``` + +### Demo + +This demo fetches [`chinook.db`](pathname:///sqlite/chinook.db), loads into the +SQLite engine and performs a series of queries to extract the data. Worksheets +are created from the data. A workbook is created from the worksheets and +exported to a XLSX file. + +```jsx live +function SheetJSQLJS() { return () } +``` + +## Server-Side Platforms + +### NodeJS + +The `better-sqlite3`[^7] native module embeds the SQLite C library. +`Statement#all` runs a prepared statement and returns an array of objects: + +```js +import Database from "better-sqlite3"; +import * as XLSX from "xlsx"; + +/* open database */ +var db = Database("chinook.db"); + +/* get data from the `Invoice` table */ +var aoo = db.prepare("SELECT * FROM 'Invoice' LIMIT 100000").all(); + +/* create worksheet from the row objects */ +var ws = XLSX.utils.json_to_sheet(aoo, {dense: true}); +``` + +0) Build `chinook.db` from [the SQL statements](pathname:///sqlite/chinook.sql): + +```bash +curl -LO https://docs.sheetjs.com/sqlite/chinook.sql +sqlite3 chinook.db ".read chinook.sql" +``` + +1) Install the dependencies: + +{`\ +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz better-sqlite3@9.0.0`} + + +2) Download [`SheetJSQLiteNode.mjs`](pathname:///sqlite/SheetJSQLiteNode.mjs): + +```bash +curl -LO https://docs.sheetjs.com/sqlite/SheetJSQLiteNode.mjs +``` + +3) Run the script: + +```bash +node SheetJSQLiteNode.mjs +``` + +Open `SheetJSQLiteNode.xlsx` with a spreadsheet editor. + +### Bun + +Bun ships with a built-in high-performance module `bun:sqlite`[^8]: + +```js +import { Database } from "bun:sqlite"; +import * as XLSX from "xlsx"; + +/* open database */ +var db = Database.open("chinook.db"); + +/* get data from the `Invoice` table */ +var aoo = db.prepare("SELECT * FROM 'Invoice' LIMIT 100000").all(); + +/* create worksheet from the row objects */ +var ws = XLSX.utils.json_to_sheet(aoo, {dense: true}); +``` + +0) Build `chinook.db` from [the SQL statements](pathname:///sqlite/chinook.sql): + +```bash +curl -LO https://docs.sheetjs.com/sqlite/chinook.sql +sqlite3 chinook.db ".read chinook.sql" +``` + +1) Install the dependencies: + +{`\ +bun install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} + + +2) Download [`SheetJSQLiteBun.mjs`](pathname:///sqlite/SheetJSQLiteBun.mjs): + +```bash +curl -LO https://docs.sheetjs.com/sqlite/SheetJSQLiteBun.mjs +``` + +3) Run the script: + +```bash +bun run SheetJSQLiteBun.mjs +``` + +Open `SheetJSQLiteBun.xlsx` with a spreadsheet editor. + +### Deno + +Deno `sqlite` library[^9] returns raw arrays of arrays: + +{`\ +import { DB } from "https://deno.land/x/sqlite/mod.ts"; +// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts" +import * as XLSX from "https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs"; +\n\ +/* open database */ +var db = new DB("chinook.db"); +\n\ +/* get data from the \`Invoice\` table */ +var aoa = db.prepareQuery("SELECT * FROM 'Invoice' LIMIT 100000").all(); +\n\ +/* create worksheet from the row objects */ +var data = [query.columns().map(x => x.name)].concat(aoa); +var ws = XLSX.utils.aoa_to_sheet(data, {dense: true});`} + + +0) Build `chinook.db` from [the SQL statements](pathname:///sqlite/chinook.sql): + +```bash +curl -LO https://docs.sheetjs.com/sqlite/chinook.sql +sqlite3 chinook.db ".read chinook.sql" +``` + +1) Download [`SheetJSQLiteDeno.ts`](pathname:///sqlite/SheetJSQLiteDeno.ts): + +```bash +curl -LO https://docs.sheetjs.com/sqlite/SheetJSQLiteDeno.ts +``` + +2) Run the script: + +```bash +deno run --allow-read --allow-write SheetJSQLiteDeno.ts +``` + +Open `SheetJSQLiteDeno.xlsx` with a spreadsheet editor. + +[^1]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input) +[^2]: See ["Sheet Objects"](/docs/csf/sheet) in "SheetJS Data Model" for more details. +[^3]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`. +[^4]: See ["Workbook Objects"](/docs/csf/book) in "SheetJS Data Model" for more details. +[^5]: See [`writeFile` in "Writing Files"](/docs/api/write-options) +[^6]: See [the `sql.js` documentation](https://sql.js.org/documentation/) +[^7]: The [documentation](https://github.com/WiseLibs/better-sqlite3/blob/master/docs/api.md) can be found in the project repository. +[^8]: See ["SQLite"](https://bun.sh/docs/api/sqlite) in the BunJS documentation. +[^9]: See [the `sqlite` module](https://deno.land/x/sqlite) on the Deno module registry. \ No newline at end of file diff --git a/docz/docs/03-demos/07-data/index.md b/docz/docs/03-demos/07-data/index.md index 68bbea1..d55842f 100644 --- a/docz/docs/03-demos/07-data/index.md +++ b/docz/docs/03-demos/07-data/index.md @@ -183,6 +183,7 @@ The following Web APIs are featured in separate demos: {item.label}{item.customProps?.summary && (" - " + item.customProps.summary)} ); })} +
  • Web SQL Database
  • Local Storage API
  • IndexedDB API
  • diff --git a/docz/docs/03-demos/08-local/01-websql.md b/docz/docs/03-demos/08-local/01-websql.md new file mode 100644 index 0000000..97af103 --- /dev/null +++ b/docz/docs/03-demos/08-local/01-websql.md @@ -0,0 +1,217 @@ +--- +title: Sheets with WebSQL +sidebar_label: Web SQL Database +pagination_prev: demos/data/index +pagination_next: demos/cloud/index +sidebar_custom_props: + summary: Reading and writing data in an in-browser SQL database +--- + +import CodeBlock from '@theme/CodeBlock'; + +WebSQL (formally "Web SQL Database") is a popular SQL-based in-browser database +available in Chromium and related browsers including Google Chrome. In practice, +it is powered by SQLite. Many SQLite-compatible queries work as-is in WebSQL. + +The public demo generates a database from workbook. + +:::caution pass + +WebSQL is only supported in Chromium-based browsers including Chrome. + +Safari historically supported WebSQL but Safari 13 dropped support. + +Legacy browsers including Internet Explorer and Firefox never added support. + +::: + +:::info pass + +WebSQL is not commonly available on server-side platforms. Typically scripts +will directly query SQLite databases using connector modules. + +[The "SQLite" demo](/docs/demos/data/sqlite) covers NodeJS and other platforms. + +::: + +## Overview + +Environments that support WebSQL expose the `openDatabase` global method. It +takes 4 arguments: +- internal database name +- version string (`1.0`) +- public display name +- database size (measured in bytes) + +The following command attempts to connect to the database named `sheetql`. If +the database does not exist, it will create a new database with a hint to +allocate 2MB of space. + +```js +const db = openDatabase('sheetql', '1.0', 'SheetJS WebSQL Test', 2097152); +``` + +### Transactions and Queries + +Queries are performed within transactions. + +`Database#transaction` passes a transaction object to the callback argument: + +```js +db.transaction(function(tx) { + /* tx is a transaction object */ +}); +``` + +Within a transaction, queries are performed with `Transaction#executeSql`. The +method takes 4 arguments: +- SQL statement stored in a string +- Array of parameterized query arguments +- Success callback +- Error callback + +If the query succeeds, the success callback will be invoked with two arguments: +- Transaction object +- Result of the query + +If the query fails, the error callback will be invoked with two arguments: +- Transaction object +- Error information + +The Web SQL Database API is callback-based. The following snippet runs one query +and wraps the execution in a promise that resolves to the query result or +rejects with the error: + +```js +function execute_simple_query(db, query) { + return new Promise((resolve, reject) => { + db.transaction(tx => + tx.executeSQL(query, [], + (tx, data) => resolve(data), + (tx, err) => reject(err) + ) + ); + }); +} +``` + +### Importing Data + +Importing data from spreadsheets is straightforward using the `generate_sql` +helper function from ["Generating Tables"](/docs/demos/data/sql#generating-tables) + +```js +const stmts = generate_sql(ws, wsname); + +// NOTE: tx.executeSql and db.transaction use callbacks. This wraps in Promises +for(var stmt of stmts) await new Promise((res, rej) => { + db.transaction(tx => + tx.executeSql(stmt, [], + (tx, data) => res(data), // if the query is successful, return the data + (tx, err) => rej(err) // if the query fails, reject with the error + )); +}); +``` + +Typically worksheet objects are extracted from workbook objects[^1] generated +from the SheetJS `read` or `readFile` methods[^2]. + +### Exporting Data + +The result of a SQL SELECT statement is a `SQLResultSet`. The `rows` property +is a `SQLResultSetRowList`. It is an "array-like" structure that has `length` +and properties like `0`, `1`, etc. However, this is not a real Array object! + +A real Array can be created using `Array.from`. The SheetJS `json_to_sheet` +method[^3] can generate a worksheet object[^4] from the real array: + +```js +db.readTransaction(tx => + tx.executeSQL("SELECT * FROM DatabaseTable", [], (tx, data) => { + // data.rows is "array-like", so `Array.from` can make it a real array + const aoo = Array.from(data.rows); + const ws = XLSX.utils.json_to_sheet(aoo); + // ... perform an export here OR wrap in a Promise + }) +); +``` + +Using `book_new` and `book_append_sheet`[^5], a workbook object can be created. +This workbook is typically exported to the filesystem with `writeFile`[^6]. + + + + +## Live Demo + +:::note + +This browser demo was tested in the following environments: + +| Browser | Date | +|:------------|:-----------| +| Chrome 117 | 2023-10-13 | + +Some lesser-used browsers do not support WebSQL: + +| Browser | Date | Support | +|:------------|:-----------|:------------------------------------| +| Safari 17.0 | 2023-10-13 | Error `Web SQL is deprecated` | +| Firefox 118 | 2023-10-13 | Error `openDatabase is not defined` | + +::: + +### Export Demo + +The following demo generates a database with 5 fixed SQL statements. Queries +can be changed in the Live Editor. The WebSQL database can be inspected in the +"WebSQL" section of the "Application" Tab of Developer Tools: + +![WebSQL view in Developer Tools](pathname:///files/websql.png) + +```jsx live +function SheetQL() { + const [out, setOut] = React.useState(""); + const queries = [ + 'DROP TABLE IF EXISTS Presidents', + 'CREATE TABLE Presidents (Name TEXT, Idx REAL)', + 'INSERT INTO Presidents (Name, Idx) VALUES ("Barack Obama", 44)', + 'INSERT INTO Presidents (Name, Idx) VALUES ("Donald Trump", 45)', + 'INSERT INTO Presidents (Name, Idx) VALUES ("Joseph Biden", 46)' + ]; + const xport = React.useCallback(async() => { + /* prep database */ + const db = openDatabase('sheetql', '1.0', 'SheetJS WebSQL Test', 2097152); + + for(var q of queries) await new Promise((res, rej) => { + db.transaction((tx) => { + tx.executeSql(q, [], (tx, data) => res(data), (tx, err) => rej(err)); + }); + }); + + /* pull data and generate rows */ + db.readTransaction(tx => { + tx.executeSql("SELECT * FROM Presidents", [], (tx, data) => { + const aoo = Array.from(data.rows); + setOut("QUERY RESULT:\n" + aoo.map(r => JSON.stringify(r)).join("\n") + "\n") + const ws = XLSX.utils.json_to_sheet(aoo); + const wb = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, "Presidents"); + XLSX.writeFile(wb, "SheetQL.xlsx"); + }); + }); + }); + return (
    {out}
    ); +} +``` + +## Server-Side SQLite + +**[The exposition has been moved to a separate page.](/docs/demos/data/sqlite)** + +[^1]: See ["Workbook Object"](/docs/csf/book) +[^2]: See [`read` and `readFile` in "Reading Files"](/docs/api/parse-options) +[^3]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input) +[^4]: See ["Sheet Objects"](/docs/csf/sheet) +[^5]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`. +[^6]: See [`writeFile` in "Writing Files"](/docs/api/write-options) \ No newline at end of file diff --git a/docz/docs/03-demos/32-extensions/02-chromium.md b/docz/docs/03-demos/32-extensions/02-chromium.md index 6487a38..c15f66c 100644 --- a/docz/docs/03-demos/32-extensions/02-chromium.md +++ b/docz/docs/03-demos/32-extensions/02-chromium.md @@ -22,7 +22,7 @@ tables with a content script and a background script. :::note -This demo was last tested on 2023 June 06 against Chrome 114 +This demo was last tested on 2023 October 14 against Chrome 117. ::: diff --git a/docz/docs/03-demos/42-engines/06-goja.md b/docz/docs/03-demos/42-engines/06-goja.md index 001f13f..f94f8d6 100644 --- a/docz/docs/03-demos/42-engines/06-goja.md +++ b/docz/docs/03-demos/42-engines/06-goja.md @@ -94,7 +94,7 @@ This demo was tested in the following deployments: | Architecture | Git Commit | Go version | Date | |:-------------|:-----------|:-----------|:-----------| -| `darwin-x64` | `28ee0ee` | `1.19.3` | 2023-06-05 | +| `darwin-x64` | `873a149` | `1.21.3` | 2023-10-14 | | `darwin-arm` | `28ee0ee` | `1.20.4` | 2023-06-05 | | `win10-x64` | `81d7606` | `1.20.2` | 2023-08-27 | | `win11-arm` | `fc55792` | `1.21.1` | 2023-09-25 | diff --git a/docz/docs/09-miscellany/05-contributing.md b/docz/docs/09-miscellany/05-contributing.md index ba3fae9..5b555bb 100644 --- a/docz/docs/09-miscellany/05-contributing.md +++ b/docz/docs/09-miscellany/05-contributing.md @@ -44,7 +44,7 @@ These instructions were tested on the following platforms: | MacOS 10.13.6 (x64) | 2023-09-30 | | MacOS 13.6 (ARM64) | 2023-09-30 | | Windows 10 (x64) + WSL Ubuntu | 2023-07-23 | -| Windows 11 (x64) + WSL Ubuntu | 2023-08-31 | +| Windows 11 (x64) + WSL Ubuntu | 2023-10-14 | | Windows 11 (ARM) + WSL Ubuntu | 2023-09-18 | With some additional dependencies, the unminified scripts are reproducible and @@ -64,7 +64,50 @@ import TabItem from '@theme/TabItem'; A) Ensure WSL ("WSL 2" in Windows 10) and the Ubuntu distribution are installed. -B) Install mercurial and subversion: +
    Installation Notes (click to hide) + +In "Turn Windows features on or off", the following features must be enabled: + +- "Hyper-V" (including every sub-feature) +- "Virtual Machine Platform" +- "Windows Hypervisor Platform" +- "Windows Subsystem for Linux" + +The following command installs Ubuntu within WSL: + +```powershell +wsl --install Ubuntu +``` + +:::caution pass + +In the last Windows 11 test, there was a `WSL_E_DEFAULT_DISTRO_NOT_FOUND` error. + +The resolution is to switch to WSL1, install, and switch back to WSL2: + +``` +wsl --set-default-version 1 +wsl --install Ubuntu +wsl --set-default-version 2 +wsl --install Ubuntu +``` + +::: + +:::warning pass + +**WSL will not run in a Windows on ARM VM on computers with the M1 CPU** + +Apple Silicon M1 processors do not support nested virtualization. + +M2 processors do support nested virtualization. SheetJS users have reported +success with Windows on ARM running on computers with the M2 Max CPU. + +::: + +
    + +B) Install mercurial and subversion from within WSL: ```bash sudo apt-get update @@ -93,7 +136,7 @@ sudo add-apt-repository --remove ppa:mercurial-ppa/releases ::: -C) Install NodeJS +C) Install NodeJS within WSL: :::info pass @@ -112,7 +155,9 @@ curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt-get install -y nodejs ``` -Exit the WSL window and open a new one before proceeding: +D) Exit the WSL session and start a new session + +E) Install the `n` package and switch NodeJS vesrions: ```bash # Switch to `n`-managed NodeJS @@ -130,12 +175,14 @@ sudo apt-get install -y npm ::: -D) Test clone the [`js-crc32` repo](https://git.sheetjs.com/sheetjs/js-crc32) +F) Clone the [`js-crc32` repo](https://git.sheetjs.com/sheetjs/js-crc32) ```bash git clone https://git.sheetjs.com/sheetjs/js-crc32 ``` +:::note pass + If this clone fails with an error message that mentions SSL or secure connection or certificates, build and install a version of Git with proper SSL support: @@ -146,7 +193,9 @@ chmod +x compile-git-with-openssl.sh ./compile-git-with-openssl.sh ``` -E) Set `git` config `core.autocrlf` setting to `false`. The following commands +::: + +G) Set `git` config `core.autocrlf` setting to `false`. The following commands should be run twice, once within PowerShell (if Git for Windows is installed) and once within WSL bash: @@ -155,10 +204,16 @@ git config --global --add core.autocrlf false git config --global --unset core.autocrlf true ``` -F) Run `unzip`. If the program is missing, install manually: +H) Run `unzip`. If the program is missing, install manually: ```bash sudo apt-get install -y unzip +``` + +I) Run `make`. If the program is missing, install manually: + +```bash +sudo apt-get install -y make ``` @@ -207,7 +262,7 @@ for "LTS" and "Current" releases. The "LTS" version should be installed. In local testing, macOS 10.13 required NodeJS version `12.22.12`: ```bash -curl -LO https://nodejs.org/download/release/v12.22.12/node-v12.22.12.pkg +curl -LO https://nodejs.org/download/release/v12.22.12/node-v12.22.12.pkg open node-v12.22.12.pkg ``` diff --git a/docz/docusaurus.config.js b/docz/docusaurus.config.js index bb7c94c..f201bf5 100644 --- a/docz/docusaurus.config.js +++ b/docz/docusaurus.config.js @@ -216,6 +216,7 @@ const config = { { from: '/docs/demos/localfile', to: '/docs/demos/local/file/' }, { from: '/docs/demos/data/indexeddb', to: '/docs/demos/local/indexeddb/' }, { from: '/docs/demos/data/storageapi', to: '/docs/demos/local/storageapi/' }, + { from: '/docs/demos/data/websql', to: '/docs/demos/local/websql/' }, /* desktop */ { from: '/docs/demos/cli', to: '/docs/demos/desktop/cli/' }, { from: '/docs/getting-started/demos/cli', to: '/docs/demos/desktop/cli/' }, diff --git a/docz/static/sqlite/chinook.db b/docz/static/sqlite/chinook.db new file mode 100644 index 0000000..f853411 Binary files /dev/null and b/docz/static/sqlite/chinook.db differ