A Minimalistic Wrapper for IndexedDB
APACHE-2.0 License
Bot releases are hidden (Show)
Published by dfahlander almost 3 years ago
This is probably the last release candidate before releasing a stable 3.2.0.
Published by dfahlander about 3 years ago
Two minor changes:
Published by dfahlander about 3 years ago
This release is candidate for a new stable dexie release with liveQuery()
support.
Documentation is underway.
Published by dfahlander about 3 years ago
Support for Chrome's transaction durability option in Dexie constructor
const db = new Dexie("TestDBTrans", { chromeTransactionDurability: 'relaxed' });
PR #1367
Published by dfahlander over 3 years ago
Minor updates required for addons to integrate easier in db.on('ready') to give special (vip) access to the db while initial sync or authentication is still going on (before db.open() promise finally resolves, as it won't resolve until all db.on('ready') subscribers finish their work, but they themselves will need to interact with the db to finish their work).
We are still in beta until decided whether PR #1244 should be completed before determining the official API for the undocumented liveQuery()
and txcommitted
event.
Note however that the useLiveQuery() API is stable no matter where we decide with PR #1244 and the not yet settled API with the similar name liveQuery()
that backs useLiveQuery ().
Published by dfahlander over 3 years ago
This release contains the changes and bugfixes needed to make dexie-cloud-addon able do its job. Se details below.
Bumping middle version number due to subtle changes in a few API:s.
Before, we didn't call DBCore.transaction() internally to allow middlewares to intercept transaction creation. This PR corrects that and also added a second argument for which tables / object stores to include in the transaction. This allows for DBCore middlewares to inject code into both implicit and explicit transactions.
DBCoreMutateRequest has been extended with optional parameters criteria
and changeSpec
. This allows for middlewares to understand the intent of the mutation (which range-query that was the criteria for the change, and which properties that is meant to be updated). For Dexie Cloud, this feature makes it possible perform consistent operations across peers and maintain offline consistency for range- or index based calls to Collection.modify() and Collection.delete().
Couldn't reuse parts of primary keys - only parts of indexes.
Dexie's liveQuery() functionality broadcasts changes using BroadcastChannel which is not supported on Safari. To workaround this, we've so far been using localStorage/onstorage to communicate changes across tabs. This workaround was eventually broken with the latest release of Safari where localStorage became broken when having multiple tabs open. Also the workarond didn't solve broadcasting changes between service worker and tabs/windows. This change makes mutations that are made in the service worker propagate to all service worker clients - which can be tabs/windows or other workers, so that liveQuery() observables will emit correctly when changes are made in the service worker - also on Safari. For other browsers, this hasn't been a problem.
Published by dfahlander over 3 years ago
Bugfix: Transaction.abort() does not rollback changes (filed as a repro PR in #1329)
Published by dfahlander over 3 years ago
Fix #1236 - problems updating FileSystemFileHandle properties.
Published by dfahlander over 3 years ago
This release is just to mark the change of status from alpha to beta.
Will soon take a next step and release a version with stable state (to get useLiveQuery()
out in the stable release).
Just need to take a decision on how to export { liveQuery } directly from dexie or via a new library.
See PR #1244. It would be best to avoid releasing a stable before letting #1244 be committed to avoid API changes.
Published by dfahlander over 3 years ago
This fix is highly recommended for all 3.1.0-alpha.x users as it contains the important fix for #1268.
Fix version signatures (PR #1287)
#1268 Maximum call stack size exceeded (a bug introduced in Dexie 3.1.0-alpha.x)
#1280 Cannot add CryptoKeys to table with auto-incrementing primary key
Published by dfahlander over 3 years ago
Bugfixes:
Published by dfahlander over 3 years ago
Published by dfahlander over 3 years ago
Two bugfixes:
To install:
npm i [email protected]
Published by dfahlander almost 4 years ago
liveQuery()
was explained in this blog post some weeks before this release.
The new liveQuery()
and the corresponding react hook useLiveQuery()
have been improved using a Btree structure to track and match queried ranges against mutated ranges on primary keys and indices.
This release improves liveQuery()
in the following ways:
Live queries are more fine-grained. In previous version, index-based queries where always rerun on any mutation. Only primary key based queries were selectively re-run. In this version, index based queries only re-run when the mutation would affect the result of that query.
// The following query will emit new results when todoItems on that todoList are updated.
// ...but not if a todo item on another list is updated.
// ...but if a todo item is moved into our out from the list, the query will also emit new result.
liveQuery(()=> db.todoItems.where({todoListId: todoList.id}).toArray())
// The following query will emit new results when friends within the age range are updated.
// ...but not if a friend outside the range is updated.
// ...but if a friend's age is changes (moved into range or out from range), it will also emit result.
liveQuery(()=> db.friends.where('age').between(20, 20).toArray())
// Key-only queries will not emit new results for property updates - only when key is change
liveQuery(() => db.friends.where('age').between(20,30).keys())
liveQuery(() => db.friends.where('age').between(20,30).primaryKeys())
count() requests may still need to emit more often on Table.put() and Table.delete() operations as we cannot detect affected keys unless the mutation is a Table.add(), Table.update() or Collection.modify(), which gives more information to DBCore about the index values of the previous object in database.
Rx compatible (via Rx.from()).
import * as Rx from "rxjs";
import { map } from "rxjs/operators";
import { liveQuery } from "dexie";
const observable = Rx.from(liveQuery(
() => db.friends.count()
)).pipe(
map(friendCount => friendCount + 1)
);
{allKeys: true}
to bulkPut() and bulkAdd() will be equally fast as not providing that option.Published by dfahlander almost 4 years ago
This version broadcasts txcommitted events between tabs and workers within same origin. It does so using BroadcastChannel so that not only tabs/windows are involved but also workers. This makes the built-in observability in Dexie a nice replacement for dexie-observable addon - and better, as that addon doesnt support workers, you will probably not need the dexie-observable addon anymore unless you use it as a base for dexie-syncable. Note also that dexie-observable slows down write performance a lot while the new built-in liveQuery feature does not.
Any part of an origin (a tab, a frame, a window, a web worker, shared worker or service worker) can observe the database no matter where the database was modified. Any thread can be either producer or consumer. If one peer writes to a Dexie instance, the other part can subscribe and get notified when something change.
Hidden tabs and minimized windows are not being bothered. Instead they get notified when they are visible again - with an accumulated result so nothing that had happened while being asleep will get lost.
The implementation falls back to using storage event and localStorage if browser doesnt support BroadcastChannel (Safari). The fallback implementation does only propagate changes across windows/tabs - not workers. It would however possible to make a standalone polyfill for BroadcastChannel that would support this for workers also. I currently don't know of any such polyfill except broadcastchannel-polyfill that currently not supports workers either. If I will have time I may complement it to support all kinds of workers as well as the structuring cloning.
importScripts("https://unpkg.com/[email protected]");
const db = new Dexie('mydb');
db.version(1).stores({
logItems: '++id'
});
// Write to DB now and then...
setInterval (()=>{
db.logItems.add({foo: "bar", time: new Date()});
}, 1000);
import React from "react";
import Dexie from "dexie";
import { useLiveQuery } from "dexie-react-hooks";
const db = new Dexie('mydb');
db.version(1).stores({
logItems: '++id'
});
function LogWatcherComponent({limit = 50}) {
// Observe the last {limit} items in log:
const logItems = useLiveQuery(
() => db.logItems.reverse().limit(limit).toArray()
);
return <div>
<h1>Log viewer</h1>
<ul>
{logItems.map(logItem => <li key={logItem.id}>
{logItem.time.toLocaleTimeString()} {logItem.foo}
</li>)}
</ul>
</div>;
}
Awesome React integration coming (Blog post)
Published by dfahlander almost 4 years ago
Just a bugfix for Dexie v3.1.0-alpha.1 and some typing corrections for dexie-react-hooks.
The big news are in Dexie v3.1.0-alpha.1!
Published by dfahlander almost 4 years ago
This version gives Dexie.js built-in observability which has been one of the Visions for dexie, earlier named db.observe().
It's called liveQuery() instead because it is not tied to a single db instance but it is capable of turning an expression or a async function with several statements and a final return value, into a observable (compatible with the es-observable spec).
import Dexie, { liveQuery } from "dexie";
// Turn any promise-returning function into an observable:
const observable = liveQuery(
() => getFriendsWithContactInfos({minAge: 18, maxAge: 64})
);
// The function can do several requests in a flow and/or in paralell
// and finally return a result.
// The result is what is being observed:
async function getFriendsWithContactInfos ({minAge, maxAge}) {
// Get all friends within range:
const friends = await db.friends
.where('age').between(minAge, maxAge, true, true)
.toArray();
// Map an array of contactInfos related to each friend:
const contactInfos = await Promise.all(friends =>
db.contactInfos.where({friendId: friend.id})
.toArray()
);
// Put the resolved contactInfos as an array prop on each friend to return
friends.forEach((friend, idx) => friend.contactInfos = contactInfos[idx]);
return friends; // This result is what will be observed by the observable.
}
Ok, so now we have an observable of this. Let's subscribe to it:
const subscription = observable.subscribe({
next: result => console.log("Got result:", result),
error: console.error
});
Lets update something that would affect the result of the query:
db.contactInfos.add({friendId: 2, type: "phoneNo", value: "1234567"});
When the above statement has been successfully committed to the DB, the function will re-execute if and only if friend with id 2 is within the queried age range (!), and our subscriber will be called with the new result of the callback.
The main reason for this new feature is better integration with frontend libraries like angular and react.
Especially for react, I've also release a new library dexie-react-hooks
with the hook useLiveQuery()
that will make data reactive data-fetching from IndexedDB very easy. Angular uses observables natively - so probably our ES-compliant observable can be used as it is.
This library integrates React with the new liveQuery functionality described above
export function useLiveQuery<T, TDefault=undefined> (
querier: () => Promise<T> | T,
deps?: any[], // ...like deps for useMemo(). Defaults to empty array.
defaultResult?: TDefault // Default value returned while data is loading
) : T | TDefault;
const db = new Dexie('news-db');
db.version(1).stores({
articles: '++id, title',
articleLikes: '[articleId+userId]'
});
function MyComponent({articleId, currentUser}) {
const article = useLiveQuery(() => db.articles.get(articleId), [articleId]);
const numLikes = useLiveQuery(() => db.articleLikes.where({articleId: articleId}).count(), [articleId]);
return <>
<Article article={article} numLikes={numLikes} />
<button onClick={() => db.articleLikes.put({userId: currentUser.id, articleId})}>
Like! {/* clicking button will increase like count if current user hadnt liked it before */}
</button>
</>;
}
See more examples in dexie-react-hooks
Published by dfahlander almost 4 years ago
This release contains fixes that improves error resilience, typing correctness and bug fixes for some edge cases.
NOTE: Conditional types is now being used in dist/dexie.d.ts. If you are on an ancient typescript version (below 2.8) you will need to update typescript in your dev deps!
npm i [email protected]
npm i [email protected]
Bugfix of #1154 (PR #1155): WhereClause.equals(undefined) should fail, but it does not fail in dexie 3.0.0-3.0.2. It behaved correctly in dexie 2.x so it's a regression. It is important that libraries fail on invalid arguments so that subtle application bugs are nailed down more easily.