Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/tndrle/node-sqlite3-wasm
WebAssembly port of SQLite3 for Node.js with file system access
https://github.com/tndrle/node-sqlite3-wasm
database electron filesystem javascript nodejs persistent platform-independent sql sqlite sqlite3 typescript wasm webassembly
Last synced: 12 days ago
JSON representation
WebAssembly port of SQLite3 for Node.js with file system access
- Host: GitHub
- URL: https://github.com/tndrle/node-sqlite3-wasm
- Owner: tndrle
- License: mit
- Created: 2022-12-11T10:05:18.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-04-20T16:15:08.000Z (7 months ago)
- Last Synced: 2024-05-20T21:57:34.070Z (6 months ago)
- Topics: database, electron, filesystem, javascript, nodejs, persistent, platform-independent, sql, sqlite, sqlite3, typescript, wasm, webassembly
- Language: JavaScript
- Homepage:
- Size: 6.95 MB
- Stars: 48
- Watchers: 3
- Forks: 7
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
**_node-sqlite3-wasm_**
[![npm](https://img.shields.io/npm/v/node-sqlite3-wasm.svg)](https://www.npmjs.com/package/node-sqlite3-wasm)
[![SQLite](https://img.shields.io/badge/SQLite-3.47.0-blue)](https://www.sqlite.org/index.html)# WebAssembly build of SQLite3 for Node.js
**_node-sqlite3-wasm_** is a port of [SQLite3](https://www.sqlite.org/) to
[WebAssembly](https://webassembly.org/) for [Node.js](https://nodejs.org/) with
file system access. _node-sqlite3-wasm_ brings
[SQLite3](https://www.sqlite.org/) to your [Node.js](https://nodejs.org/)
environment without recompiling on every target platform. This is especially
useful for [Electron](https://www.electronjs.org/) applications.The port to WebAssembly that SQLite introduced in version 3.40.0 only targets
web browsers but not Node.js. Other WebAssembly ports also target Node.js, most
notably [sql.js](https://github.com/sql-js/sql.js/), but none supports
persistent storage with direct file access. There also exist native bindings
like [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) or
[node-sqlite3](https://github.com/TryGhost/node-sqlite3). However, native
bindings must be recompiled for every target platform or pre-built binaries must
be shipped. This is tedious, especially for Electron deployments._node-sqlite3-wasm_ supports persistent storage with direct file access by
implementing an [SQLite OS Interface or "VFS"](https://www.sqlite.org/vfs.html)
that translates SQLite file access to [Node.js' file system
API](https://nodejs.org/api/fs.html)._node-sqlite3-wasm_ is currently based on SQLite 3.47.0.
## Getting Started
To install _node-sqlite3-wasm_, run
```
npm install node-sqlite3-wasm
```To use it, run
```js
const { Database } = require("node-sqlite3-wasm");
const db = new Database("database.db");
```**Important:** _node-sqlite3-wasm_ is not fully garbage-collected. You **have to
manually close** a database, otherwise you risk **memory leaks** (see
[`Database.close()`](#databaseclose)). Also, if you use prepared statements explicitly (see
[`Database.prepare()`](#databasepreparesql---statement)), you **have to manually finalize** them. Alternatively, the
[``Database``](#class-database) class provides the convenience methods- [`Database.all()`](#databaseallsql-values-options---rows)
- [`Database.get()`](#databasegetsql-values-options---row)
- [`Database.run()`](#databaserunsql-values---info)These convenience methods use a prepared statement internally and take care of
finalizing it.**Note:** Foreign key support is enabled by default.
## Example
```js
const { Database } = require("node-sqlite3-wasm");
const db = new Database("database.db");db.exec(
"DROP TABLE IF EXISTS employees; " +
"CREATE TABLE IF NOT EXISTS employees (name TEXT, salary INTEGER)"
);db.run("INSERT INTO employees VALUES (:n, :s)", {
":n": "James",
":s": 50000,
});const r = db.all("SELECT * from employees");
console.log(r);
// [ { name: 'James', salary: 50000 } ]db.close();
```## API
- [`class Database`](#class-database)
- [`class Statement`](#class-statement)
- [`class SQLite3Error`](#class-sqlite3error)### `class Database`
Constructor
- [`new Database()`](#new-databasepath-options)
Methods
- [`Database.all()`](#databaseallsql-values-options---rows)
- [`Database.close()`](#databaseclose)
- [`Database.exec()`](#databaseexecsql)
- [`Database.function()`](#databasefunctionname-func-options---this)
- [`Database.get()`](#databasegetsql-values-options---row)
- [`Database.prepare()`](#databasepreparesql---statement)
- [`Database.run()`](#databaserunsql-values---info)Properties
- [`Database.inTransaction`](#databaseintransaction)
- [`Database.isOpen`](#databaseisopen)### `new Database(path, [options])`
Creates a new database connection. By default, the database file is created if
it doesn't exist.**Important:** You **have to manually close** the database, otherwise you risk
**memory leaks** (see [`Database.close()`](#databaseclose)).Arguments
- `path`: the path to the database file
- `options` (optional)
- `fileMustExist` (default: `false`): if the database file does not exist it
will not be created. Instead an [``SQLite3Error``](#class-sqlite3error) will
be thrown. This option is ignored if `readOnly` is `true`.
- `readOnly` (default: `false`): opens the database in read-only mode```js
const db = new Database("database.db");
``````js
const db = new Database("database.db", { fileMustExist: true });
```### `Database.all(sql, [values, options]) -> rows`
Creates a prepared statement, executes it with the given values and returns the
resulting rows as an array of objects. The prepared statement is finalized
automatically.Arguments
- `sql`: string containing the SQL statement
- `values` (optional): values to bind to the statement's parameters. Either a
single value, an array, or an object in case of named parameters.
- `options` (optional)
- `expand` (default: `false`): if `true`, each returned row is a nested object
with keys corresponding to tables in the query. If a result column is an
expression or subquery, it will be returned under the key `$`.```js
db.all("SELECT * FROM book");
``````js
db.all("SELECT * FROM book WHERE title = ?", "The Little Prince");
``````js
db.all("SELECT * FROM book WHERE title = :t", { ":t": "The Little Prince" });
``````js
db.all("SELECT * FROM book WHERE title IN (?, ?)", [
"The Little Prince",
"The Hobbit",
]);
```### `Database.close()`
Closes the database.
**Important:** You **have to manually close** the database, otherwise you risk
**memory leaks**.**Important:** Closing the database with [`Database.close()`](#databaseclose) does not automatically
finalize pending prepared statements.```js
db.close();
```### `Database.exec(sql)`
Executes the given SQL string. The SQL string may contain several
semicolon-separated statements.```js
db.exec(
"DROP TABLE IF EXISTS book; CREATE TABLE book (id INTEGER PRIMARY KEY, title TEXT)"
);
```### `Database.function(name, func, [options]) -> this`
Registers a user-defined function.
Arguments
- `name`: the name of the function
- `func`: the implementation of the function
- `options` (optional)
- `deterministic` (default: `false`): if `true`, the function is considered
[deterministic](https://www.sqlite.org/deterministic.html)```js
db.function("regexp", (y, x) => new RegExp(y, "i").test(x), {
deterministic: true,
});
db.all("SELECT * FROM book WHERE title REGEXP ?", ".*little.*");
```### `Database.get(sql, [values, options]) -> row`
Creates a prepared statement, executes it with the given values and returns the
first resulting row as an object. The prepared statement is finalized
automatically.Arguments
- `sql`: string containing the SQL statement
- `values` (optional): values to bind to the statement's parameters. Either a
single value, an array, or an object in case of named parameters.
- `options` (optional)
- `expand` (default: `false`): if `true`, the returned row is a nested object
with keys corresponding to tables in the query. If a result column is an
expression or subquery, it will be returned under the key `$`.```js
db.get("SELECT * FROM book WHERE id = ?", 7);
``````js
db.get("SELECT * FROM book WHERE id = $id", { $id: 7 });
``````js
db.get("SELECT * FROM book WHERE id = ? AND title = ?", [
3,
"The Little Prince",
]);
```### `Database.prepare(sql) -> Statement`
Creates a prepared statement from the given SQL string.
**Important:** You **have to manually finalize** a statement, otherwise you risk
**memory leaks**. See [``Statement``](#class-statement) and, in particular,
[`Statement.finalize()`](#statementfinalize).```js
const stmt = db.prepare("INSERT INTO book (title) VALUES (?)");
try {
// do something with the statement here
} finally {
stmt.finalize();
}
```The [``Database``](#class-database) class provides the convenience methods
- [`Database.all()`](#databaseallsql-values-options---rows)
- [`Database.get()`](#databasegetsql-values-options---row)
- [`Database.run()`](#databaserunsql-values---info)These convenience methods use a prepared statement internally and take care of
finalizing it.### `Database.run(sql, [values]) -> info`
Creates a prepared statement, executes it with the given values and returns an
object with the properties `changes` and `lastInsertRowid` describing the number
of modified rows and the id of the last row inserted. `lastInsertRowid` is a
[`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
if its value exceeds
[`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER).
The prepared statement is finalized automatically.Arguments
- `sql`: string containing the SQL statement
- `values` (optional): values to bind to the statement's parameters. Either a
single value, an array, or an object in case of named parameters.```js
db.run("INSERT INTO book (title) VALUES (?)", "The Little Prince");
``````js
db.run("INSERT INTO book VALUES (?, ?)", [10, "The Little Prince"]);
``````js
db.run("INSERT INTO book VALUES (@id, :title)", {
"@id": 10,
":title": "The Little Prince",
});
```### `Database.inTransaction`
Property determining whether the database is currently in a transaction.
```js
const stmt = db.prepare("INSERT INTO book (title) VALUES (?)");
try {
db.exec("BEGIN TRANSACTION");
stmt.run("The Little Prince");
stmt.run("The Hobbit");
db.exec("COMMIT");
} catch (err) {
if (db.inTransaction) db.exec("ROLLBACK");
console.log(err);
} finally {
stmt.finalize();
}
```### `Database.isOpen`
Property determining whether the database is currently open.
### `class Statement`
Methods
- [`Statement.all()`](#statementallvalues-options---rows)
- [`Statement.finalize()`](#statementfinalize)
- [`Statement.get()`](#statementgetvalues-options---row)
- [`Statement.iterate()`](#statementiteratevalues-options---iterableiteratorrow)
- [`Statement.run()`](#statementrunvalues---info)Properties
- [`Statement.database`](#statementdatabase)
- [`Statement.isFinalized`](#statementisfinalized)**Important:** You **have to manually finalize** a statement, otherwise you risk
**memory leaks** (see [`Statement.finalize()`](#statementfinalize)).```js
const stmt = db.prepare("SELECT * FROM book WHERE id = ?");
try {
// do something with the statement here
} finally {
stmt.finalize();
}
```As an alternative, the [``Database``](#class-database) class provides the
convenience methods- [`Database.all()`](#databaseallsql-values-options---rows)
- [`Database.get()`](#databasegetsql-values-options---row)
- [`Database.run()`](#databaserunsql-values---info)These convenience methods use a prepared statement internally and take care of
finalizing it.### `Statement.all([values, options]) -> rows`
Executes the prepared statement with the given values and returns the resulting
rows as an array of objects.Arguments
- `values` (optional): values to bind to the statement's parameters. Either a
single value, an array, or an object in case of named parameters.
- `options` (optional)
- `expand` (default: `false`): if `true`, each returned row is a nested object
with keys corresponding to tables in the query. If a result column is an
expression or subquery, it will be returned under the key `$`.See also [`Database.all()`](#databaseallsql-values-options---rows)
### `Statement.finalize()`
Finalizes the statement and frees all allocated memory. Once a statement has
been finalized, it cannot be used anymore.**Important:** You **have to manually finalize** a statement, otherwise you risk
**memory leaks**.**Important:** Closing the database with [`Database.close()`](#databaseclose) does not automatically
finalize pending prepared statements.### `Statement.get([values, options]) -> row`
Executes the prepared statement with the given values and returns the first
resulting row as an object.Arguments
- `values` (optional): values to bind to the statement's parameters. Either a
single value, an array, or an object in case of named parameters.
- `options` (optional)
- `expand` (default: `false`): if `true`, the returned row is a nested object
with keys corresponding to tables in the query. If a result column is an
expression or subquery, it will be returned under the key `$`.See also [`Database.get()`](#databasegetsql-values-options---row)
### `Statement.iterate([values, options]) -> IterableIterator`
Executes the prepared statement with the given values and returns the resulting
rows as an iterator of objects.Arguments
- `values` (optional): values to bind to the statement's parameters. Either a
single value, an array, or an object in case of named parameters.
- `options` (optional)
- `expand` (default: `false`): if `true`, each returned row is a nested object
with keys corresponding to tables in the query. If a result column is an
expression or subquery, it will be returned under the key `$`.### `Statement.run([values]) -> info`
Executes the prepared statement with the given values and returns an object with
the properties `changes` and `lastInsertRowid` describing the number of modified
rows and the id of the last row inserted. `lastInsertRowid` is a
[`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
if its value exceeds
[`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER).Arguments
- `values` (optional): values to bind to the statement's parameters. Either a
single value, an array, or an object in case of named parameters.See also [`Database.run()`](#databaserunsql-values---info)
### `Statement.database`
The [``Database``](#class-database) object that instantiated this statement.
### `Statement.isFinalized`
Property determining whether the statement has been finalized using
[`Statement.finalize()`](#statementfinalize). A finalized statement must not be used anymore.### `class SQLite3Error`
_node-sqlite3-wasm_ throws an `SQLite3Error` whenever an error in SQLite
or in the API occurs. `SQLite3Error` is a subclass of `Error`.## Notes About Types
### Numbers
JavaScript's
[`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number?retiredLocale=de)
type is a double-precision 64-bit binary format IEEE 754 value. Integers can
only be represented without loss of precision in the range -253 + 1
to 253 - 1, inclusive. SQLite3 works with [8-byte signed
integers](https://www.sqlite.org/datatype3.html) with a range of -263
to 263 - 1, inclusive. Since this range exceeds the range of safe
integers in JavaScript, _node-sqlite3-wasm_ automatically converts integers
outside this safe range to
[`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
It is your responsibility to ensure that you handle the returned values, whether
`Number` or `BigInt`, correctly. _node-sqlite3-wasm_ also allows you to input
`BigInt` values as query parameters, or arguments or return values of
user-defined functions.### Binary Large Objects (BLOBs)
An SQLite Binary Large Object (BLOB) is represented by a
[`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)
in JavaScript.## Building
[Docker](https://www.docker.com) and [npm](https://www.npmjs.com) are required
for building. [Mocha](https://mochajs.org) is required to run tests.To build _node-sqlite3-wasm_, simply run
```
npm run build
```This will download the [emscripten Docker
image](https://hub.docker.com/r/emscripten/emsdk) and the [SQLite source
files](https://www.sqlite.org/download.html). Then it will compile the project
source files and generate `dist/node-sqlite3-wasm.js` and
`dist/node-sqlite3-wasm.wasm`.## License
_node-sqlite3-wasm_ is
[MIT](https://github.com/tndrle/node-sqlite3-wasm/blob/main/LICENSE) licensed.Parts of the code are from [sql.js](https://github.com/sql-js/sql.js), which is
also MIT licensed. SQLite is in the [public
domain](https://www.sqlite.org/copyright.html).