Skip to content

Schema changes and migrations ​

In raw IndexedDB, every schema change means bumping a version number and writing an onupgradeneeded handler. doxor compares your declaration with the database instead, and upgrades it for you.

Adding collections and indexes ​

Adding a collection or an index needs no ceremony: change the declaration, and doxor applies it on the next load, once, keeping the existing data.

Changing data ​

Changing data, or removing and renaming things, goes in migrations, numbered from 1:

ts
export const 
db
=
createDB
({
name
: 'app',
collections
: {
users
:
collection
<
User
>().
key
('id', {
autoIncrement
: true }).
index
('email'),
},
migrations
: {
1: async (
m
) => {
await
m
.
collection
<
User
>('users').
modify
((
user
) => {
user
.
email
=
user
.
email
.
toLowerCase
()
}) }, 2: (
m
) => {
m
.
deleteIndex
('users', 'email') // re-created from the declaration (now without `unique`)
}, }, })

Rules ​

  • Each migration runs once per database, in order, inside the upgrade transaction. A new database gets the final schema directly and skips migrations, since there is no data to migrate.
  • Keys must be 1, 2, 3, …. Never renumber or remove a published migration: some users may not have run it yet. To retire one, replace its body with () => {}.
  • If a migration throws, the whole upgrade (schema and data) is rolled back and the operation rejects with the code Migration. As with transactions, only await doxor operations inside a migration.
  • doxor never deletes a collection or index on its own. Changing a key path, or an index's unique or multiEntry option, is rejected with the code SchemaConflict until a migration deletes the old one. It is then rebuilt from the declaration.

The migration context ​

A migration receives m, with:

Member
m.collection(name)get, put, delete, toArray and modify on a collection
m.createStore, m.deleteStore, m.renameStoreCreate, delete or rename a collection
m.createIndex, m.deleteIndexCreate or delete an index

When an upgrade happens while the site is open in other tabs, see Multiple tabs.

Released under the MIT License.