Comparing version 4.0.0-beta.2 to 4.0.0
# Changes in 4.x | ||
TODO: These are just notes, I need to expand on them. | ||
## Breaking changes | ||
Breaking changes: | ||
### Opening a database | ||
* `openDb` and `deleteDb` are now `openDB` and `deleteDB`. More consistent with DOM naming. | ||
* `iterateCursor` is gone, since browsers do the right thing with promises. | ||
* 'Private' properties that link to real IDB objects are gone. Use `unwrap` instead. | ||
* Methods that return promises may also throw. This is unnoticeable with async functions. | ||
* Dropped support for IE. | ||
```js | ||
// Old 3.x way | ||
import { openDb } from 'idb'; | ||
New stuff: | ||
openDb('db-name', 1, (upgradeDb) => { | ||
console.log(upgradeDb.oldVersion); | ||
console.log(upgradeDb.transaction); | ||
}); | ||
``` | ||
* Objects now proxy IDB objects, so no properties/methods are missing from the originals. | ||
* Improved TypeScript. | ||
* Async iterators. | ||
* Helper methods for one-off actions. | ||
* `tx.store`. | ||
* Smaller in size. | ||
```js | ||
// New 4.x way | ||
import { openDB } from 'idb'; | ||
openDB('db-name', 1, { | ||
upgrade(db, oldVersion, newVersion, transaction) { | ||
console.log(oldVersion); | ||
console.log(transaction); | ||
}, | ||
}); | ||
``` | ||
* `openDb` and `deleteDb` were renamed `openDB` and `deleteDB` to be more consistent with DOM naming. | ||
* The signature of `openDB` changed. The third parameter used to be the upgrade callback, it's now an option object which can include an `upgrade` method. | ||
* There's no `UpgradeDB` anymore. You get the same database `openDB` resolves with. Versions numbers and the upgrade transaction are included as additional parameters. | ||
### Promises & throwing | ||
The library turns all `IDBRequest` objects into promises, but it doesn't know in advance which methods may return promises. | ||
As a result, methods such as `store.put` may throw instead of returning a promise. | ||
If you're using async functions, there isn't a difference. | ||
### Other breaking changes | ||
* `iterateCursor` and `iterateKeyCursor` have been removed. These existed to work around browsers microtask issues which have since been fixed. Async iterators provide similar functionality. | ||
* All pseudo-private properties (those beginning with an underscore) are gone. Use `unwrap()` to get access to bare IDB objects. | ||
* `transaction.complete` was renamed to `transaction.done` to be shorter and more consistent with the DOM. | ||
* `getAll` is no longer polyfilled on indexes and stores. | ||
* The library no longer officially supports IE11. | ||
## New stuff | ||
* The library now uses proxies, so objects will include everything from their plain-IDB equivalents. | ||
* TypeScript support has massively improved, including the ability to provide types for your database. | ||
* Optional support for async iterators, which makes handling cursors much easier. | ||
* Database objects now have shortcuts for single actions (like `get`, `put`, `add`, `getAll` etc etc). | ||
* For transactions that cover a single store `transaction.store` is a reference to that store. | ||
* `openDB` lets you add callbacks for when your database is blocking another connection, or when you're blocked by another connection. | ||
# Changes in 3.x | ||
The library is now a module. To take advantage of this, importing has changed slightly: | ||
The library became a module. | ||
@@ -26,0 +62,0 @@ ```js |
{ | ||
"name": "idb", | ||
"version": "4.0.0-beta.2", | ||
"version": "4.0.0", | ||
"description": "A small wrapper that makes IndexedDB usable", | ||
"main": "build/cjs/index.js", | ||
"module": "build/esm/index.mjs", | ||
"module": "build/esm/index.js", | ||
"typings": "build/esm/index.d.ts", | ||
@@ -8,0 +8,0 @@ "scripts": { |
147
README.md
@@ -26,3 +26,3 @@ # IndexedDB with usability. | ||
Then, assuming you're using a module-compatible system (like Webpack, Rollup etc): | ||
Then, assuming you're using a module-compatible system (like webpack, Rollup etc): | ||
@@ -37,5 +37,17 @@ ```js | ||
Or, use it directly via unpkg: | ||
```html | ||
<script type="module"> | ||
import { openDB, deleteDB, wrap, unwrap } from 'https://unpkg.com/idb?module'; | ||
async function doDatabaseStuff() { | ||
const db = await openDB(…); | ||
} | ||
</script> | ||
``` | ||
# Changes | ||
This is a rewrite from 3.x. [See changes](changes.md). | ||
This is a rewrite from 3.x with substantial changes. [See details](changes.md). | ||
@@ -64,13 +76,13 @@ # API | ||
* `version`: Schema version. | ||
* `upgrade` (optional): Called if this version of the database has never been opened before. Use it to specify the schema for the database. This is similar to the `upgradeneeded` event in plain IndexedDB. | ||
* `upgrade` (optional): Called if this version of the database has never been opened before. Use it to specify the schema for the database. This is similar to the [`upgradeneeded` event](https://developer.mozilla.org/en-US/docs/Web/API/IDBOpenDBRequest/upgradeneeded_event) in plain IndexedDB. | ||
* `db`: An enhanced `IDBDatabase`. | ||
* `oldVersion`: Last version of the database opened by the user. | ||
* `newVersion`: Whatever new version you provided. | ||
* `transaction`: The transaction for this upgrade. This is useful if you need to get data from other stores as part of a migration. | ||
* `blocked` (optional): Called if there are older versions of the database open on the origin, so this version cannot open. | ||
* `blocking` (optional): Called if this connection is blocking a future version of the database from opening. | ||
* `transaction`: An enhanced transaction for this upgrade. This is useful if you need to get data from other stores as part of a migration. | ||
* `blocked` (optional): Called if there are older versions of the database open on the origin, so this version cannot open. This is similar to the [`blocked` event](https://developer.mozilla.org/en-US/docs/Web/API/IDBOpenDBRequest/blocked_event) in plain IndexedDB. | ||
* `blocking` (optional): Called if this connection is blocking a future version of the database from opening. This is similar to the [`versionchange` event](https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/versionchange_event) in plain IndexedDB. | ||
## `deleteDB` | ||
Delete a database. | ||
Deletes a database. | ||
@@ -85,2 +97,4 @@ ```js | ||
Takes an enhanced IndexedDB object and returns the plain unmodified one. | ||
```js | ||
@@ -90,8 +104,8 @@ const unwrapped = unwrap(wrapped); | ||
If for some reason you want to drop back into plain IndexedDB, give one of the enhanced objects to `unwrap` and you'll get the unmodified version back. | ||
This is useful if, for some reason, you want to drop back into plain IndexedDB. Promises will also be converted back into `IDBRequest` objects. | ||
Promises will also be converted back into `IDBRequest` objects. | ||
## `wrap` | ||
Takes an IDB object and returns a version enhanced by this library. | ||
```js | ||
@@ -101,5 +115,5 @@ const wrapped = wrap(unwrapped); | ||
Use this to convert a plain IDB object to one enhanced by this library. This is useful if some third party code gives you an `IDBDatabase` object and you want it to have the features of this library. | ||
This is useful if some third party code gives you an `IDBDatabase` object and you want it to have the features of this library. | ||
This doesn't work with `IDBCursor`, [due to missing primitives](https://github.com/w3c/IndexedDB/issues/255). Also, if you wrap an `IDBTransaction`, `tx.store` and `tx.objectStoreNames` will not work in Edge. To avoid these issues, wrap the `IDBDatabase` object, and use the wrapped object to create a new transaction. | ||
This doesn't work with `IDBCursor`, [due to missing primitives](https://github.com/w3c/IndexedDB/issues/255). Also, if you wrap an `IDBTransaction`, `tx.store` and `tx.objectStoreNames` won't work in Edge. To avoid these issues, wrap the `IDBDatabase` object, and use the wrapped object to create a new transaction. | ||
@@ -110,3 +124,3 @@ ## General enhancements | ||
Any method that usually returns an `IDBRequest` object will now return a promise for the result. | ||
Firstly, any method that usually returns an `IDBRequest` object will now return a promise for the result. | ||
@@ -133,3 +147,3 @@ ```js | ||
These methods depend on the same methods on `IDBObjectStore`, therefore `getKey`, `getAll`, and `getAllKeys` are missing in Edge as it lacks support. | ||
These methods depend on the same methods on `IDBObjectStore`, therefore `getKey`, `getAll`, and `getAllKeys` are missing in Edge. | ||
@@ -158,7 +172,7 @@ ### Shortcuts to get from an index | ||
If a transaction involves multiple stores, `tx.store` is undefined. | ||
If a transaction involves multiple stores, `tx.store` is undefined, you need to use `tx.objectStore(storeName)` to get the stores. | ||
### `tx.done` | ||
Transactions have a `.done` promise which resolves when the transaction completes successfully, and otherwise rejects. | ||
Transactions have a `.done` promise which resolves when the transaction completes successfully, and otherwise rejects with the [transaction error](https://developer.mozilla.org/en-US/docs/Web/API/IDBTransaction/error). | ||
@@ -176,4 +190,3 @@ ```js | ||
```js | ||
const store = db.transaction(storeName).objectStore(storeName); | ||
let cursor = await store.openCursor(); | ||
let cursor = await db.transaction(storeName).store.openCursor(); | ||
@@ -188,3 +201,3 @@ while (cursor) { | ||
Async iterator support isn't included by default (Edge doesn't support them). To include them, import `idb/with-async-ittr.js` (~1.37k) instead of `idb`: | ||
Async iterator support isn't included by default (Edge doesn't support them). To include them, import `idb/with-async-ittr.js` instead of `idb` (this increases the library size to ~1.37k): | ||
@@ -219,7 +232,6 @@ ```js | ||
Stores and indexes also have an `iterate` method which has the same signiture as `openCursor`, but returns an async iterator: | ||
Stores and indexes also have an `iterate` method which has the same signature as `openCursor`, but returns an async iterator: | ||
```js | ||
const tx = db.transaction('books'); | ||
const index = tx.store.index('author'); | ||
const index = db.transaction('books').store.index('author'); | ||
@@ -233,5 +245,5 @@ for await (const cursor of index.iterate('Douglas Adams')) { | ||
## Keyval Store | ||
## Keyval store | ||
This is very similar to `localStorage`, but async. If this is *all* you need, you may be interested in [idb-keyval](https://www.npmjs.com/package/idb-keyval), you can always upgrade to this library later. | ||
This is very similar to `localStorage`, but async. If this is *all* you need, you may be interested in [idb-keyval](https://www.npmjs.com/package/idb-keyval). You can always upgrade to this library later. | ||
@@ -264,2 +276,62 @@ ```js | ||
## Article store | ||
```js | ||
async function demo() { | ||
const db = await openDB('Articles', 1, { | ||
upgrade(db) { | ||
// Create a store of objects | ||
const store = db.createObjectStore('articles', { | ||
// The 'id' property of the object will be the key. | ||
keyPath: 'id', | ||
// If it isn't explicitly set, create a value by auto incrementing. | ||
autoIncrement: true, | ||
}); | ||
// Create an index on the 'date' property of the objects. | ||
store.createIndex('date', 'date'); | ||
}, | ||
}); | ||
// Add an article: | ||
await db.add('articles', { | ||
title: 'Article 1', | ||
date: new Date('2019-01-01'), | ||
body: '…', | ||
}); | ||
// Add multiple articles in one transaction: | ||
{ | ||
const tx = db.transaction('articles', 'readwrite'); | ||
tx.store.add({ | ||
title: 'Article 2', | ||
date: new Date('2019-01-01'), | ||
body: '…', | ||
}); | ||
tx.store.add({ | ||
title: 'Article 3', | ||
date: new Date('2019-01-02'), | ||
body: '…', | ||
}); | ||
await tx.done; | ||
} | ||
// Get all the articles in date order: | ||
console.log(await db.getAllFromIndex('articles', 'date')); | ||
// Add 'And, happy new year!' to all articles on 2019-01-01: | ||
{ | ||
const tx = db.transaction('articles', 'readwrite'); | ||
const index = tx.store.index('date'); | ||
for await (const cursor of index.iterate(new Date('2019-01-01'))) { | ||
const article = { ...cursor.value }; | ||
article.body += ' And, happy new year!'; | ||
cursor.update(article); | ||
} | ||
await tx.done; | ||
} | ||
} | ||
``` | ||
# TypeScript | ||
@@ -320,3 +392,3 @@ | ||
```ts | ||
import { openDB, DBSchema, IDBPDatabase, IDBPTransaction } from 'idb'; | ||
import { openDB, DBSchema, IDBPDatabase } from 'idb'; | ||
@@ -348,1 +420,26 @@ interface MyDBV1 extends DBSchema { | ||
You can also cast to a typeless database by omiting the type, eg `db as IDBPDatabase`. | ||
Note: Types like `IDBPDatabase` are used by TypeScript only. The implementation uses proxies under the hood. | ||
# Transaction lifetime | ||
IDB transactions auto-close if it doesn't have anything left do once microtasks have been processed. As a result, this works fine: | ||
```js | ||
const tx = db.transaction('keyval', 'readwrite'); | ||
const val = await tx.store.get('counter') || 0; | ||
tx.store.put(val + 1, 'counter'); | ||
await tx.done; | ||
``` | ||
But this doesn't: | ||
```js | ||
const tx = db.transaction('keyval', 'readwrite'); | ||
const val = await tx.store.get('counter') || 0; | ||
const newVal = await fetch('/increment?val=' + val) | ||
tx.store.put(newVal, 'counter'); | ||
await tx.done; | ||
``` | ||
In this case, the transaction closes while the browser is fetching, so `tx.store.put` fails. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
199914
38
1
430