UNPKG

14.9 kBMarkdownView Raw
1# SQLite Client for Node.js Apps
2
3[![NPM version](https://img.shields.io/npm/v/sqlite.svg?style=flat-square)](https://www.npmjs.com/package/sqlite)
4[![CircleCI](https://circleci.com/gh/kriasoft/node-sqlite.svg?style=svg)](https://circleci.com/gh/kriasoft/node-sqlite)
5![built with typescript](https://camo.githubusercontent.com/92e9f7b1209bab9e3e9cd8cdf62f072a624da461/68747470733a2f2f666c61742e62616467656e2e6e65742f62616467652f4275696c74253230576974682f547970655363726970742f626c7565)
6[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
7
8> A wrapper library written in Typescript with **ZERO** dependencies that adds ES6 promises
9> and SQL-based migrations API to [sqlite3](https://github.com/mapbox/node-sqlite3/) ([docs](https://github.com/mapbox/node-sqlite3/wiki)).
10
11**note** v4 of `sqlite` has breaking changes compared to v3! Please see `CHANGELOG.md` for more details.
12
13<!-- TOC -->
14
15- [Installation](#installation)
16 - [Install `sqlite3`](#install-sqlite3)
17 - [Install `sqlite`](#install-sqlite)
18- [Usage](#usage)
19 - [Opening the database](#opening-the-database)
20 - [Without caching](#without-caching)
21 - [With caching](#with-caching)
22 - [Enable verbose / debug mode](#enable-verbose--debug-mode)
23 - [Tracing SQL errors](#tracing-sql-errors)
24 - [With a custom driver](#with-a-custom-driver)
25 - [Opening multiple databases](#opening-multiple-databases)
26 - [`open` config params](#open-config-params)
27 - [Examples](#examples)
28 - [Creating a table and inserting data](#creating-a-table-and-inserting-data)
29 - [Getting a single row](#getting-a-single-row)
30 - [Getting many rows](#getting-many-rows)
31 - [Inserting rows](#inserting-rows)
32 - [Updating rows](#updating-rows)
33 - [Prepared statement](#prepared-statement)
34 - [`each()`](#each)
35 - [Get the driver instance](#get-the-driver-instance)
36 - [Closing the database](#closing-the-database)
37 - [ES6 tagged template strings](#es6-tagged-template-strings)
38 - [Migrations](#migrations)
39- [Typescript tricks](#typescript-tricks)
40 - [Import interfaces from sqlite](#import-interfaces-from-sqlite)
41 - [Specify typings for a specific database driver](#specify-typings-for-a-specific-database-driver)
42 - [Use generics to get better typings on your rows](#use-generics-to-get-better-typings-on-your-rows)
43 - [Get example](#get-example)
44 - [All example](#all-example)
45- [API Documentation](#api-documentation)
46- [Management Tools](#management-tools)
47- [Alternative SQLite libraries](#alternative-sqlite-libraries)
48- [References](#references)
49- [License](#license)
50
51<!-- TOC END -->
52
53## Installation
54
55### Install `sqlite3`
56
57Most people who use this library will use [sqlite3](https://github.com/mapbox/node-sqlite3/)
58as the database driver.
59
60Any library that conforms to the `sqlite3` ([API](https://github.com/mapbox/node-sqlite3/wiki/API))
61should also work.
62
63`$ npm install sqlite3 --save`
64
65### Install `sqlite`
66
67```sh
68# v4 of sqlite is targeted for nodejs 10 and on.
69$ npm install sqlite --save
70
71# If you need a legacy version for an older version of nodejs
72# install v3 instead, and look at the v3 branch readme for usage details
73$ npm install sqlite@3 --save
74```
75
76## Usage
77
78This module has the same API as the original `sqlite3` library ([docs](https://github.com/mapbox/node-sqlite3/wiki/API)),
79except that all its API methods return ES6 Promises and do not accept callback arguments (with the exception of `each()`).
80
81### Opening the database
82
83#### Without caching
84
85```typescript
86import sqlite3 from 'sqlite3'
87import { open } from 'sqlite'
88
89// this is a top-level await
90(async () => {
91 // open the database
92 const db = await open({
93 filename: '/tmp/database.db',
94 driver: sqlite3.Database
95 })
96})()
97```
98or
99
100```typescript
101import sqlite3 from 'sqlite3'
102import { open } from 'sqlite'
103
104open({
105 filename: '/tmp/database.db',
106 driver: sqlite3.Database
107}).then((db) => {
108 // do your thing
109})
110```
111
112or
113
114```typescript
115import sqlite3 from 'sqlite3'
116import { open } from 'sqlite'
117
118// you would have to import / invoke this in another file
119export async function openDb () {
120 return open({
121 filename: '/tmp/database.db',
122 driver: sqlite3.Database
123 })
124}
125```
126
127#### With caching
128
129If you want to enable the [database object cache](https://github.com/mapbox/node-sqlite3/wiki/Caching)
130
131```typescript
132import sqlite3 from 'sqlite3'
133import { open } from 'sqlite'
134
135(async () => {
136 const db = await open({
137 filename: '/tmp/database.db',
138 driver: sqlite3.cached.Database
139 })
140})()
141```
142
143#### Enable verbose / debug mode
144
145```typescript
146import sqlite3 from 'sqlite3'
147
148sqlite3.verbose()
149```
150
151#### Tracing SQL errors
152
153For more info, see this [doc](https://github.com/mapbox/node-sqlite3/wiki/Debugging#databaseontrace-callback).
154
155```typescript
156db.on('trace', (data) => {
157
158})
159```
160
161#### With a custom driver
162
163You can use an alternative library to `sqlite3` as long as it conforms to the `sqlite3` [API](https://github.com/mapbox/node-sqlite3/wiki/API).
164
165For example, using `sqlite3-offline-next`:
166
167```typescript
168import sqlite3Offline from 'sqlite3-offline-next'
169import { open } from 'sqlite'
170
171(async () => {
172 const db = await open({
173 filename: '/tmp/database.db',
174 driver: sqlite3Offline.Database
175 })
176})()
177```
178
179#### Opening multiple databases
180
181```typescript
182import sqlite3 from 'sqlite3'
183import { open } from 'sqlite'
184
185(async () => {
186 const [db1, db2] = await Promise.all([
187 open({
188 filename: '/tmp/database.db',
189 driver: sqlite3.Database
190 }),
191 open({
192 filename: '/tmp/database2.db',
193 driver: sqlite3.Database
194 }),
195 ])
196
197 await db1.migrate({
198 migrationsPath: '...'
199 })
200
201 await db2.migrate({
202 migrationsPath: '...'
203 })
204})()
205```
206
207#### `open` config params
208
209```typescript
210
211// db is an instance of `sqlite#Database`
212// which is a wrapper around `sqlite3#Database`
213const db = await open({
214 /**
215 * Valid values are filenames, ":memory:" for an anonymous in-memory
216 * database and an empty string for an anonymous disk-based database.
217 * Anonymous databases are not persisted and when closing the database
218 * handle, their contents are lost.
219 */
220 filename: string
221
222 /**
223 * One or more of sqlite3.OPEN_READONLY, sqlite3.OPEN_READWRITE and
224 * sqlite3.OPEN_CREATE. The default value is OPEN_READWRITE | OPEN_CREATE.
225 */
226 mode?: number
227
228 /**
229 * The database driver. Most will install `sqlite3` and use the `Database` class from it.
230 * As long as the library you are using conforms to the `sqlite3` API, you can use it as
231 * the driver.
232 *
233 * @example
234 *
235 * ```
236 * import sqlite from 'sqlite3'
237 *
238 * const driver = sqlite.Database
239 * ```
240 */
241 driver: any
242})
243```
244
245### Examples
246
247- See the `src/**/__tests__` directory for more example usages
248- See the `docs/` directory for full documentation.
249- Also visit the `sqlite3` library [API docs](https://github.com/mapbox/node-sqlite3/wiki/API)
250
251#### Creating a table and inserting data
252
253```typescript
254await db.exec('CREATE TABLE tbl (col TEXT)')
255await db.exec('INSERT INTO tbl VALUES ("test")')
256```
257
258#### Getting a single row
259
260```typescript
261const result = await db.get('SELECT col FROM tbl WHERE col = ?', 'test')
262
263// { col: 'test' }
264```
265
266```typescript
267const result = await db.get('SELECT col FROM tbl WHERE col = ?', ['test'])
268
269// { col: 'test' }
270```
271
272```typescript
273const result = await db.get('SELECT col FROM tbl WHERE col = :test', {
274 ':test': 'test'
275})
276
277// { col: 'test' }
278```
279
280#### Getting many rows
281
282```typescript
283const result = await db.all('SELECT col FROM tbl')
284
285// [{ col: 'test' }]
286```
287
288#### Inserting rows
289
290```typescript
291const result = await db.run(
292 'INSERT INTO tbl (col) VALUES (?)',
293 'foo'
294)
295
296/*
297{
298 // row ID of the inserted row
299 lastID: 1,
300 // instance of `sqlite#Statement`
301 // which is a wrapper around `sqlite3#Statement`
302 stmt: <Statement>
303}
304*/
305```
306
307```typescript
308const result = await db.run('INSERT INTO tbl(col) VALUES (:col)', {
309 ':col': 'something'
310})
311```
312
313#### Updating rows
314
315```typescript
316const result = await db.run(
317 'UPDATE tbl SET col = ? WHERE col = ?',
318 'foo',
319 'test'
320)
321
322/*
323{
324 // number of rows changed
325 changes: 1,
326 // instance of `sqlite#Statement`
327 // which is a wrapper around `sqlite3#Statement`
328 stmt: <Statement>
329}
330*/
331```
332
333#### Prepared statement
334
335```typescript
336// stmt is an instance of `sqlite#Statement`
337// which is a wrapper around `sqlite3#Statement`
338const stmt = await db.prepare('SELECT col FROM tbl WHERE 1 = ? AND 5 = ?5')
339await stmt.bind({ 1: 1, 5: 5 })
340let result = await stmt.get()
341// { col: 'some text' }
342```
343
344```typescript
345const stmt = await db.prepare(
346 'SELECT col FROM tbl WHERE 13 = @thirteen ORDER BY col DESC'
347)
348
349const result = await stmt.all({ '@thirteen': 13 })
350```
351
352#### `each()`
353
354`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).
355
356The function signature looks like this:
357
358`async each (sql, [...params], callback)`
359
360- `callback(err, row)` is triggered when the database has a row to return
361- The promise resolves when all rows have returned with the number of rows returned.
362
363```typescript
364try {
365 // You need to wrap this in a try / catch for SQL parse / connection errors
366 const rowsCount = await db.each(
367 'SELECT col FROM tbl WHERE ROWID = ?',
368 [2],
369 (err, row) => {
370 if (err) {
371 // This would be if there is an error specific to the row result
372 throw err
373 }
374
375 // row = { col: 'other thing' }
376 }
377 )
378} catch (e) {
379 throw e
380}
381
382// rowsCount = 1
383```
384
385#### Get the driver instance
386
387Useful if you need to call methods that are not supported yet.
388
389```typescript
390const rawDb = db.getDatabaseInstance()
391const rawStatement = stmt.getStatementInstance()
392```
393
394#### Closing the database
395
396```typescript
397await db.close()
398```
399
400### ES6 tagged template strings
401
402This module is compatible with [sql-template-strings](https://www.npmjs.com/package/sql-template-strings).
403
404```js
405import SQL from 'sql-template-strings'
406
407const book = 'harry potter';
408const author = 'J. K. Rowling';
409
410const data = await db.all(SQL`SELECT author FROM books WHERE name = ${book} AND author = ${author}`);
411```
412
413### Migrations
414
415This module comes with a lightweight migrations API that works with [SQL-based migration files](https://github.com/kriasoft/node-sqlite/tree/master/migrations)
416
417With default configuration, you can create a `migrations/` directory in your project with SQL files,
418and call the `migrate()` method to run the SQL in the directory against the database.
419
420See this project's `migrations/` folder for examples.
421
422```typescript
423await db.migrate({
424 /**
425 * If true, will force the migration API to rollback and re-apply the latest migration over
426 * again each time when Node.js app launches.
427 */
428 force?: boolean
429 /**
430 * Migrations table name. Default is 'migrations'
431 */
432 table?: string
433 /**
434 * Path to the migrations folder. Default is `path.join(process.cwd(), 'migrations')`
435 */
436 migrationsPath?: string
437})
438```
439
440## Typescript tricks
441
442### Import interfaces from sqlite
443
444`import { ISqlite, IMigrate } from 'sqlite'`
445
446See the definitions for more details.
447
448### Specify typings for a specific database driver
449
450```typescript
451// Assuming you have @types/sqlite3 installed
452import sqlite3 from 'sqlite3'
453
454// sqlite3.Database, sqlite3.Statement is the default if no explicit generic is specified
455await open<sqlite3.Database, sqlite3.Statement>({
456 filename: ':memory'
457})
458```
459
460### Use generics to get better typings on your rows
461
462Most methods allow for the use of [generics](https://www.typescriptlang.org/docs/handbook/generics.html)
463to specify the data type of your returned data. This allows your IDE to perform better autocomplete
464and the typescript compiler to perform better static type analysis.
465
466#### Get example
467
468```typescript
469
470interface Row {
471 col: string
472}
473
474// result will be of type Row, allowing Typescript supported IDEs to autocomplete on the properties!
475const result = await db.get<Row>('SELECT col FROM tbl WHERE col = ?', 'test')
476```
477
478#### All example
479
480```typescript
481interface Row {
482 col: string
483}
484
485// Result is an array of rows, you can now have array-autocompletion data
486const result = await db.all<Row[]>('SELECT col FROM tbl')
487
488result.each((row) => {
489 // row should have type information now!
490})
491```
492
493## API Documentation
494
495See the [`docs`](docs/globals.md) directory for full documentation.
496
497## Management Tools
498
499- [Beekeeper Studio](https://www.beekeeperstudio.io/): Open Source SQL Editor and Database Manager
500- [DB Browser for SQLite](https://github.com/sqlitebrowser/sqlitebrowser): Desktop-based browser.
501- [datasette](https://github.com/simonw/datasette): Datasette is a tool for exploring and publishing
502data. Starts up a server that provides a web interface to your SQLite data.
503- [SQLite Studio](https://github.com/pawelsalawa/sqlitestudio): A free, open source, multi-platform SQLite database manager written in C++, with use of Qt framework.
504- [HeidiSQL](https://www.heidisql.com/): Full-featured database editor.
505- [DBeaver](https://dbeaver.io/): Full-featured multi-platform database tool and designer.
506
507## Alternative SQLite libraries
508
509This library and the library it primarily supports, `sqlite3`, may not be the best library that
510fits your use-case. You might want to try these other SQLite libraries:
511
512- [better-sqlite3](https://github.com/JoshuaWise/better-sqlite3): Totes itself as the fastest and
513simplest library for SQLite3 in Node.js.
514- [Bun sqlite3](https://github.com/Jarred-Sumner/bun#bunsqlite-sqlite3-module): `bun:sqlite` is a high-performance builtin SQLite3 module for `bun.js`.
515- [sql.js](https://github.com/sql-js/sql.js): SQLite compiled to Webassembly.
516- [sqlite3-offline-next](https://github.com/nicolaiort/sqlite3-offline-next): Offers pre-compiled `sqlite3`
517binaries if your machine cannot compile it. Should be mostly compatible with this library.
518
519If you know of any others, feel free to open a PR to add them to the list.
520
521## References
522
523* [Using SQLite with Node.js for Rapid Prototyping](https://medium.com/@tarkus/node-js-and-sqlite-for-rapid-prototyping-bc9cf1f26f10) on Medium.com
524* [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
525* ES6 tagged [sql-template-strings](https://www.npmjs.com/package/sql-template-strings).
526
527## License
528
529The MIT License © 2020-present Kriasoft / Theo Gravity. All rights reserved.
530
531---
532Made 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)