Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kriasoft/node-sqlite

SQLite client wrapper around sqlite3 for Node.js applications with SQL-based migrations API written in Typescript
https://github.com/kriasoft/node-sqlite

async database db es7-async migrate migration migrations nodejs sql sqlite typescript

Last synced: 2 days ago
JSON representation

SQLite client wrapper around sqlite3 for Node.js applications with SQL-based migrations API written in Typescript

Awesome Lists containing this project

README

        

# SQLite Client for Node.js Apps

[![NPM version](https://img.shields.io/npm/v/sqlite.svg?style=flat-square)](https://www.npmjs.com/package/sqlite)
[![CircleCI](https://circleci.com/gh/kriasoft/node-sqlite.svg?style=svg)](https://circleci.com/gh/kriasoft/node-sqlite)
![built with typescript](https://camo.githubusercontent.com/92e9f7b1209bab9e3e9cd8cdf62f072a624da461/68747470733a2f2f666c61742e62616467656e2e6e65742f62616467652f4275696c74253230576974682f547970655363726970742f626c7565)
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)

> A wrapper library written in Typescript with **ZERO** dependencies that adds ES6 promises
> and SQL-based migrations API to [sqlite3](https://github.com/mapbox/node-sqlite3/) ([docs](https://github.com/mapbox/node-sqlite3/wiki)).

**note** v4 of `sqlite` has breaking changes compared to v3! Please see `CHANGELOG.md` for more details.

- [Installation](#installation)
- [Install `sqlite3`](#install-sqlite3)
- [Install `sqlite`](#install-sqlite)
- [Usage](#usage)
- [Opening the database](#opening-the-database)
- [Without caching](#without-caching)
- [With caching](#with-caching)
- [Enable verbose / debug mode](#enable-verbose--debug-mode)
- [Tracing SQL errors](#tracing-sql-errors)
- [With a custom driver](#with-a-custom-driver)
- [Opening multiple databases](#opening-multiple-databases)
- [`open` config params](#open-config-params)
- [Examples](#examples)
- [Creating a table and inserting data](#creating-a-table-and-inserting-data)
- [Getting a single row](#getting-a-single-row)
- [Getting many rows](#getting-many-rows)
- [Inserting rows](#inserting-rows)
- [Updating rows](#updating-rows)
- [Prepared statement](#prepared-statement)
- [`each()`](#each)
- [Get the driver instance](#get-the-driver-instance)
- [Closing the database](#closing-the-database)
- [ES6 tagged template strings](#es6-tagged-template-strings)
- [Migrations](#migrations)
- [Typescript tricks](#typescript-tricks)
- [Import interfaces from sqlite](#import-interfaces-from-sqlite)
- [Specify typings for a specific database driver](#specify-typings-for-a-specific-database-driver)
- [Use generics to get better typings on your rows](#use-generics-to-get-better-typings-on-your-rows)
- [Get example](#get-example)
- [All example](#all-example)
- [API Documentation](#api-documentation)
- [Management Tools](#management-tools)
- [Alternative SQLite libraries](#alternative-sqlite-libraries)
- [References](#references)
- [License](#license)

## Installation

### Install `sqlite3`

Most people who use this library will use [sqlite3](https://github.com/mapbox/node-sqlite3/)
as the database driver.

Any library that conforms to the `sqlite3` ([API](https://github.com/mapbox/node-sqlite3/wiki/API))
should also work.

`$ npm install sqlite3 --save`

### Install `sqlite`

```sh
# v4 of sqlite is targeted for nodejs 10 and on.
$ npm install sqlite --save

# If you need a legacy version for an older version of nodejs
# install v3 instead, and look at the v3 branch readme for usage details
$ npm install sqlite@3 --save
```

## Usage

This module has the same API as the original `sqlite3` library ([docs](https://github.com/mapbox/node-sqlite3/wiki/API)),
except that all its API methods return ES6 Promises and do not accept callback arguments (with the exception of `each()`).

### Opening the database

#### Without caching

```typescript
import sqlite3 from 'sqlite3'
import { open } from 'sqlite'

// this is a top-level await
(async () => {
// open the database
const db = await open({
filename: '/tmp/database.db',
driver: sqlite3.Database
})
})()
```
or

```typescript
import sqlite3 from 'sqlite3'
import { open } from 'sqlite'

open({
filename: '/tmp/database.db',
driver: sqlite3.Database
}).then((db) => {
// do your thing
})
```

or

```typescript
import sqlite3 from 'sqlite3'
import { open } from 'sqlite'

// you would have to import / invoke this in another file
export async function openDb () {
return open({
filename: '/tmp/database.db',
driver: sqlite3.Database
})
}
```

#### With caching

If you want to enable the [database object cache](https://github.com/mapbox/node-sqlite3/wiki/Caching)

```typescript
import sqlite3 from 'sqlite3'
import { open } from 'sqlite'

(async () => {
const db = await open({
filename: '/tmp/database.db',
driver: sqlite3.cached.Database
})
})()
```

#### Enable verbose / debug mode

```typescript
import sqlite3 from 'sqlite3'

sqlite3.verbose()
```

#### Tracing SQL errors

For more info, see this [doc](https://github.com/mapbox/node-sqlite3/wiki/Debugging#databaseontrace-callback).

```typescript
db.on('trace', (data) => {

})
```

#### With a custom driver

You can use an alternative library to `sqlite3` as long as it conforms to the `sqlite3` [API](https://github.com/mapbox/node-sqlite3/wiki/API).

For example, using `sqlite3-offline-next`:

```typescript
import sqlite3Offline from 'sqlite3-offline-next'
import { open } from 'sqlite'

(async () => {
const db = await open({
filename: '/tmp/database.db',
driver: sqlite3Offline.Database
})
})()
```

#### Opening multiple databases

```typescript
import sqlite3 from 'sqlite3'
import { open } from 'sqlite'

(async () => {
const [db1, db2] = await Promise.all([
open({
filename: '/tmp/database.db',
driver: sqlite3.Database
}),
open({
filename: '/tmp/database2.db',
driver: sqlite3.Database
}),
])

await db1.migrate({
migrationsPath: '...'
})

await db2.migrate({
migrationsPath: '...'
})
})()
```

#### `open` config params

```typescript

// db is an instance of `sqlite#Database`
// which is a wrapper around `sqlite3#Database`
const db = await open({
/**
* Valid values are filenames, ":memory:" for an anonymous in-memory
* database and an empty string for an anonymous disk-based database.
* Anonymous databases are not persisted and when closing the database
* handle, their contents are lost.
*/
filename: string

/**
* One or more of sqlite3.OPEN_READONLY, sqlite3.OPEN_READWRITE and
* sqlite3.OPEN_CREATE. The default value is OPEN_READWRITE | OPEN_CREATE.
*/
mode?: number

/**
* The database driver. Most will install `sqlite3` and use the `Database` class from it.
* As long as the library you are using conforms to the `sqlite3` API, you can use it as
* the driver.
*
* @example
*
* ```
* import sqlite from 'sqlite3'
*
* const driver = sqlite.Database
* ```
*/
driver: any
})
```

### Examples

- See the `src/**/__tests__` directory for more example usages
- See the `docs/` directory for full documentation.
- Also visit the `sqlite3` library [API docs](https://github.com/mapbox/node-sqlite3/wiki/API)

#### Creating a table and inserting data

```typescript
await db.exec('CREATE TABLE tbl (col TEXT)')
await db.exec('INSERT INTO tbl VALUES ("test")')
```

#### Getting a single row

```typescript
const result = await db.get('SELECT col FROM tbl WHERE col = ?', 'test')

// { col: 'test' }
```

```typescript
const result = await db.get('SELECT col FROM tbl WHERE col = ?', ['test'])

// { col: 'test' }
```

```typescript
const result = await db.get('SELECT col FROM tbl WHERE col = :test', {
':test': 'test'
})

// { col: 'test' }
```

#### Getting many rows

```typescript
const result = await db.all('SELECT col FROM tbl')

// [{ col: 'test' }]
```

#### Inserting rows

```typescript
const result = await db.run(
'INSERT INTO tbl (col) VALUES (?)',
'foo'
)

/*
{
// row ID of the inserted row
lastID: 1,
// instance of `sqlite#Statement`
// which is a wrapper around `sqlite3#Statement`
stmt:
}
*/
```

```typescript
const result = await db.run('INSERT INTO tbl(col) VALUES (:col)', {
':col': 'something'
})
```

#### Updating rows

```typescript
const result = await db.run(
'UPDATE tbl SET col = ? WHERE col = ?',
'foo',
'test'
)

/*
{
// number of rows changed
changes: 1,
// instance of `sqlite#Statement`
// which is a wrapper around `sqlite3#Statement`
stmt:
}
*/
```

#### Prepared statement

```typescript
// stmt is an instance of `sqlite#Statement`
// which is a wrapper around `sqlite3#Statement`
const stmt = await db.prepare('SELECT col FROM tbl WHERE 1 = ? AND 5 = ?5')
await stmt.bind({ 1: 1, 5: 5 })
let result = await stmt.get()
// { col: 'some text' }
```

```typescript
const stmt = await db.prepare(
'SELECT col FROM tbl WHERE 13 = @thirteen ORDER BY col DESC'
)

const result = await stmt.all({ '@thirteen': 13 })
```

#### `each()`

`each()` is a bit different compared to the other operations due to its underlying [implementation](https://github.com/TryGhost/node-sqlite3/wiki/API#databaseeachsql-param--callback-complete).

The function signature looks like this:

`async each (sql, [...params], callback)`

- `callback(err, row)` is triggered when the database has a row to return
- The promise resolves when all rows have returned with the number of rows returned.

```typescript
try {
// You need to wrap this in a try / catch for SQL parse / connection errors
const rowsCount = await db.each(
'SELECT col FROM tbl WHERE ROWID = ?',
[2],
(err, row) => {
if (err) {
// This would be if there is an error specific to the row result
throw err
}

// row = { col: 'other thing' }
}
)
} catch (e) {
throw e
}

// rowsCount = 1
```

#### Get the driver instance

Useful if you need to call methods that are not supported yet.

```typescript
const rawDb = db.getDatabaseInstance()
const rawStatement = stmt.getStatementInstance()
```

#### Closing the database

```typescript
await db.close()
```

### ES6 tagged template strings

This module is compatible with [sql-template-strings](https://www.npmjs.com/package/sql-template-strings).

```js
import SQL from 'sql-template-strings'

const book = 'harry potter';
const author = 'J. K. Rowling';

const data = await db.all(SQL`SELECT author FROM books WHERE name = ${book} AND author = ${author}`);
```

### Migrations

This module comes with a lightweight migrations API that works with [SQL-based migration files](https://github.com/kriasoft/node-sqlite/tree/master/migrations)

With default configuration, you can create a `migrations/` directory in your project with SQL files,
and call the `migrate()` method to run the SQL in the directory against the database.

See this project's `migrations/` folder for examples.

```typescript
await db.migrate({
/**
* If true, will force the migration API to rollback and re-apply the latest migration over
* again each time when Node.js app launches.
*/
force?: boolean
/**
* Migrations table name. Default is 'migrations'
*/
table?: string
/**
* Path to the migrations folder. Default is `path.join(process.cwd(), 'migrations')`
*/
migrationsPath?: string
})
```

## Typescript tricks

### Import interfaces from sqlite

`import { ISqlite, IMigrate } from 'sqlite'`

See the definitions for more details.

### Specify typings for a specific database driver

```typescript
// Assuming you have @types/sqlite3 installed
import sqlite3 from 'sqlite3'

// sqlite3.Database, sqlite3.Statement is the default if no explicit generic is specified
await open({
filename: ':memory'
})
```

### Use generics to get better typings on your rows

Most methods allow for the use of [generics](https://www.typescriptlang.org/docs/handbook/generics.html)
to specify the data type of your returned data. This allows your IDE to perform better autocomplete
and the typescript compiler to perform better static type analysis.

#### Get example

```typescript

interface Row {
col: string
}

// result will be of type Row, allowing Typescript supported IDEs to autocomplete on the properties!
const result = await db.get('SELECT col FROM tbl WHERE col = ?', 'test')
```

#### All example

```typescript
interface Row {
col: string
}

// Result is an array of rows, you can now have array-autocompletion data
const result = await db.all('SELECT col FROM tbl')

result.each((row) => {
// row should have type information now!
})
```

## API Documentation

See the [`docs`](docs/globals.md) directory for full documentation.

## Management Tools

- [Beekeeper Studio](https://www.beekeeperstudio.io/): Open Source SQL Editor and Database Manager
- [DB Browser for SQLite](https://github.com/sqlitebrowser/sqlitebrowser): Desktop-based browser.
- [datasette](https://github.com/simonw/datasette): Datasette is a tool for exploring and publishing
data. Starts up a server that provides a web interface to your SQLite data.
- [SQLite Studio](https://github.com/pawelsalawa/sqlitestudio): A free, open source, multi-platform SQLite database manager written in C++, with use of Qt framework.
- [HeidiSQL](https://www.heidisql.com/): Full-featured database editor.
- [DBeaver](https://dbeaver.io/): Full-featured multi-platform database tool and designer.

## Alternative SQLite libraries

This library and the library it primarily supports, `sqlite3`, may not be the best library that
fits your use-case. You might want to try these other SQLite libraries:

- [better-sqlite3](https://github.com/JoshuaWise/better-sqlite3): Totes itself as the fastest and
simplest library for SQLite3 in Node.js.
- [Bun sqlite3](https://github.com/Jarred-Sumner/bun#bunsqlite-sqlite3-module): `bun:sqlite` is a high-performance builtin SQLite3 module for `bun.js`.
- [sql.js](https://github.com/sql-js/sql.js): SQLite compiled to Webassembly.
- [sqlite3-offline-next](https://github.com/nicolaiort/sqlite3-offline-next): Offers pre-compiled `sqlite3`
binaries if your machine cannot compile it. Should be mostly compatible with this library.

If you know of any others, feel free to open a PR to add them to the list.

## References

* [Using SQLite with Node.js for Rapid Prototyping](https://medium.com/@tarkus/node-js-and-sqlite-for-rapid-prototyping-bc9cf1f26f10) on Medium.com
* [SQLite Documentation](https://www.sqlite.org/docs.html), e.g. [SQL Syntax](https://www.sqlite.org/lang.html), [Data Types](https://www.sqlite.org/datatype3.html) etc. on SQLite.org
* ES6 tagged [sql-template-strings](https://www.npmjs.com/package/sql-template-strings).

## License

The MIT License © 2020-present Kriasoft / Theo Gravity. All rights reserved.

---
Made with ♥ by [Konstantin Tarkus](https://github.com/koistya) ([@koistya](https://twitter.com/koistya)), [Theo Gravity](https://github.com/theogravity) and [contributors](https://github.com/kriasoft/node-sqlite/graphs/contributors)