Skip to content

doxor.jsTyped collections for IndexedDB

Declare your collections once. doxor infers the types, creates the indexes and upgrades the database for you.

npm i doxor.js
doxor.js logo

One declaration, all the types ​

Describe each collection with its key and indexes. Everything after that is typed: what you insert, the keys you get back, the indexes you can query and the records a query returns.

ts
import { 
collection
,
createDB
} from 'doxor.js'
type
User
= {
id
: number;
name
: string;
email
: string;
age
: number }
const
db
=
createDB
({
name
: 'app',
collections
: {
users
:
collection
<
User
>()
.
key
('id', {
autoIncrement
: true })
.
index
('email', {
unique
: true })
.
index
('age'),
}, }) const
id
= await
db
.
users
.
insert
({
name
: 'Ali',
email
: 'ali@example.com',
age
: 30 })
const id: number
const
adults
= await
db
.
users
.
where
('age').
gte
(18).
limit
(20).
toArray
()
const adults: User[]

Why doxor ​

  • Typed from one declarationRecord types, key types, index names and query values all come from collection<User>(). A typo in a collection or index name is a compile error.
  • No version numbers to manageAdd a collection or an index and doxor upgrades the database on the next load. Data changes go in numbered migrations that run exactly once.
  • Promises that resolve after commitEvery operation resolves once the data is committed, or rejects with a DoxorError that has a stable code.
  • Safe across tabsA tab never blocks another tab's upgrade, and a tab running old code is told it is outdated instead of writing over newer data.
min + brotli
4.4 kB
dependencies
0
browser engines tested on every change
3

When doxor is not the right choice ​

doxor sits between raw IndexedDB and a full client-side database. If you only store a few values by key, idb-keyval is smaller. If you need live queries or sync between devices, Dexie.js does more. If you want thin promises over the raw API, idb is the closest to the metal. See the full comparison.

Released under the MIT License.