dfahlander

View on GitHub

Projects

Name Description Features Votes
dfahlander/Dexie.js A Minimalistic Wrapper for IndexedDB 10 64

Features suggested

Project Feature Score Description
feathub/feathub Be able to vote for comments on features 1 A feature is often followed by comments. A user may suggest a detail of how it should work while others may complain about it and suggest alternatives. Would be nice to be able to vote up or down comments within a feature.
dfahlander/Dexie.js Asynchronic hooks 2 As requested in [Dexie issue 14](https://github.com/dfahlander/Dexie.js/issues/14) and [Dexie issue 372](https://github.com/dfahlander/Dexie.js/issues/), it would be very powerful if the hooks could return a promise and perform asynchronic tasks before resuming the underlying operation. If we enable this, addons could implement constraints on foreign keys (ON DELETE CASCADE etc). A reading hook could resolve foreign keyed members on returned instances. There are other use cases as well. However to optimize performance for bulk operations, the hooks should rather take an array of operations than being called operation-by-operation. See [Vision for Dexie](https://github.com/dfahlander/Dexie.js/issues/427)
dfahlander/Dexie.js Conflict-free sync 10 ### Current Status Current version of [dexie-syncable ](https://www.npmjs.com/package/dexie-syncable) support [Eventual consistency](https://en.wikipedia.org/wiki/Eventual_consistency) by automatically resolves conflicts using *last writer wins*. This simplifies a lot for 90% cases such as updating a property of an object, adding object or deleting objects. We currently have nothing to offer for the few cases where conflicts could break consistency (like updating an array property, or for example a counter) except than putting the hard work on the application developer to implement some kind of [CRDT types](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type) or solving it in another custom way. PouchDB has the option to provide a custom conflict handler for those cases, but as I have understood, that doesn't solve the whole issue either. It also puts the burden on to the app developer. ### Strong-Eventual Consistency / Conflict-free sync A lot of research has been made about [Conflict-free replication data](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type). We could allow a super-simple way to accomplish conflict-free replication without the requirement to use state-based [CRDT types](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type). What we need is a server-side implementation of the Dexie API along with a framework for decorating methods to become conflict-free database operations. The idea is this: * Application Developer encapsulates database-facing code in a class (a service) * Each method can optionally be [decorated](http://tc39.github.io/proposal-decorators/) for conflict-free replication. * When called, the decorator generates an entry in the change log about the operation and the parameters given to it (rather than just registering CREATE/UPDATE/DELETEs). When changes reach the server, it executes the same operation using the same parameters. This is possible only if the server can lookup the same code to execute. The method could be identified by Class name + "." + method name (ny default). Server also need to support transactions (as indexedDB does). When implementing this, we must not forget a common requirement of multi-tenancy support on the server. An ideal solution is a server-implementation of the Dexie API that also maintains access control, only replicates data that the user has access to, and only allows queries on data that the user has access to. This is not part of this feature request, but I mention it so that it could be brought up when designing a server with Dexie API.
dfahlander/Dexie.js Collection.orderBy() 2 Today [orderBy()](https://github.com/dfahlander/Dexie.js/wiki/Table.orderBy()) is only available on [Table](https://github.com/dfahlander/Dexie.js/wiki/Table). To sort a query result, the user is encouraged to use [Collection.sortBy()](https://github.com/dfahlander/Dexie.js/wiki/Collection.sortBy()) instead. sortBy() is not lazily invoked, like orderBy() is, and it could be confusing having to choose which one to use. However, if compound indexes has been defined, there would be a possiblity to utilize them and allow orderBy() on a Collection. We could otherwise emulate orderBy() by using sortBy() internally.
dfahlander/Dexie.js db.observe() 8 ### Background The feature request [Collection.observe()](http://feathub.com/dfahlander/Dexie.js/+7) suggests an API to turn a Collection instance into a live query. This feature request goes a step further and enables to observe the end-result of an arbitary chain of promises, originated from Collection.toArray(), Collection.each(), Collection.count() etc. ### Usage Could be using any Promise-returning function for this usage sample. Let's take a sample from API Reference: ```js var db = new Dexie('music'); db.version(1).stores({ genres: '++id,name', albums: '++id,name,year,*tracks', bands: '++id,name,*albumIds,genreId' }); // This method is non-reactive. It produces a Promise. Not an Observable. function getBandsStartingWithA () { // Query return db.bands.where('name').startsWith('A').toArray(bands => { return Promise.all (bands.map (band => Promise.all([ db.genres.get (band.genreId), db.albums.where('id').anyOf(band.albumIds).toArray() ]).then (result => { // Set genre and albums as direct properties on each result [band.genre, band.albums] = result; return band; }); )); }); } ``` The sample above is nothing new. Now what we want to do, is to turn getBandsStartingWithA() into a live query. For that purpose, I am suggesting a new method on Dexie instances: observe(). Note that it would require [dexie-observable](https://www.npmjs.com/package/dexie-observable) to be imported. Dexie-observable would add the new method onto Dexie instances. ```js let subscription = db.observe(getBandsStartingWithA).subscribe({ next(bands) { if (!stillWantToObserve) return subscription.unsubscribe(); updateBandsListDiv(bands); // Update view. }, error () { // fail! } }); ``` How would it be implemented? 1. db.observe() creates a new [zone](https://github.com/dfahlander/Dexie.js/wiki/Promise.PSD) with state saying "we are in observation mode". 2. db.observe() calls given callback to generate the (initial) result. 3. During the execution of this callback, when any collection within the zone is realized into a promise, it checks if current zone is an observation zone. If so, it will record the expression that was executed in a list of observed expressions. 4. The result of the callback's end-promise is propagated to the subscriber of db.observe(). 5. When anything changes that matches any of the list of observed expressions, the following happens: A. The list of observed expressions is emptied (to prepare to re-produce the list when callback is invoked again) B. The callback is re-invoked, (step 2). Note that db.observe() will only observe changes happen on invlolved key expressions. Take the following example: ```js db.observe(()=>db.friends.where({name: 'Foo'}).first()).subscribe({ next: foo => console.log("Foo looks like this currently: " + JSON.stringify(foo)); }); ``` This would be the detailed flow: 1. Zone state observing = true for current database instance. 2. While executing Collection.first(), it will notice the observing state of current zone and therefore register the collection's expression in an internal list of observed expressions. 3. The end-observer's next value will be called with Foo friend 4. When db.on('changes') is fired, each change is tested agains the list of observed expressions. A. If no match, nothing happens. B. If there is a match, the callback is executed again and the subscriber of db.observe() is called again Notes: * Write-operations within an observation callback must be forbidden. An observation zone must only read data and should not produce any side effects (except debug-logging). Reason: Callback may be called arbitrary number of times to check for a change. Invoking it must not affect the application state. * In the long run, it would actually be possible to optimize the implementation so that it never needs to re-execute expressions towards the backing database when something changes. Instead, it could apply the changes to the existing result in-memory and respond from memory when the a matching collection is executed by the callback. However, let's start with the simpler approach to get going.
dfahlander/Dexie.js Non-sparse indexes 5 As for now, Dexie will only use 'sparse indexes' - the property must be present and be an indexable type (number, Date, string or array of such). This is the way IndexedDB works, but it makes it impossible to index other types such as booleans, null or undefined Another implication is that querys like `db.friends.where('isCloseFriend').notEqual(1)` would not return objects where obj.isCloseFriend === undefined, which could seem a little confusing. Non-sparse indexes could be emulated by internally convert values to indexable types before storing and reconvert back whenever fetching from db. Example of schema defintion for non-sparse indexes: ```js const db = new Dexie("testdb"); db.version(1).stores({ friends: '++id, name, age, !isCloseFriend' }); ``` In this proposal, using exclamation mark to flag the index as non-sparse. Key use cases: 1. Be able to index booleans, null, undefined and object properties. 2. Make WhereClause.notEqual() and WhereClause.noneOf() work as expected when used on a non-sparse index, and return all objects where the property is not equal, including null, undefined, boolean and object values. See [Vision for Dexie](https://github.com/dfahlander/Dexie.js/issues/427)
dfahlander/Dexie.js Collection.observe() 5 Let [dexie-observable](https://www.npmjs.com/package/dexie-observable) add a mix-in method Collection.prototype.observe() that would let the query become a live query. In practice, it would subscribe to db.on('changes') and filter each change against the collection to find out whether the change would affect the result or not. If it would, re-execute the query (collection.toArray()) and notify the subscriber. API: Let Collection.prototype.observe() return an [Observable](https://github.com/tc39/proposal-observable) ```js const collection = db.orders.where({customerId: foo}); const observable = collection.observe(); const subscription = observable.subscribe({ next(value) { updateOrdersDiv(orders); // Update view. }, error(error) { console.error(error); } }); ``` By letting adapting to the [Observable](https://github.com/tc39/proposal-observable) protocol, other Observable implementations (including [Rx.Observable](https://github.com/Reactive-Extensions/RxJS)) will be able to convert the observable to its implementation and call further methods on it, like methods for combining several observables into a single one to use for view updating. Notes: * Could name it toObservable() rather than observe(), but it could possibly be confusing. A user could expect toObservable() return `Observable<T>` rather than `Observable<Array<T>>`, which is the thing we're talking about here. Observable.of(collection) would be natural to add support for in the future (by letting Collection have Symbol.observable) to allow an Observable of rows. Collection.observe() is semantically clearer than Collection.toObservable(). Other naming suggestions are welcome. Collection.live() or similar could be an alternative also.
dfahlander/Dexie.js Collection.where() 3 As of Dexie 2.0, expressions only allows using the where() method on the Table instance. ```js db.friends.where('age').above(25).toArray() ``` But you can't do: ```js db.friends.where('age').above(25).where('name').startsWith('a').toArray() ``` To have multiple criterias we have the following to offer (currently, in Dexie 2.0): 1. If all criterias are 'equals': ``` db.friends.where({firstName: 'Martin', lastName: 'Luther', age: 300}) ``` 2. If all criterias but one are 'equals' (name = 'Foo' AND age >= 25) ``` db.friends.where('[name+age]').between(['Foo', 25], ['Foo', Infinity]) ``` We currently do not support chaining arbritary where-clauses after each other. This idea is to support expressions like the following: ``` db.friends .where('name').startsWithIgnoreCase('a') .where('age').above(25) .toArray(); ``` Any where-clause could use any operation and Dexie would find out the most optimal way to execute the resulting expression. If compound indexes exists that would help indexedDB to execute the expression, use them. If not, warn on console with a hint on how to optimize the query by adding a compound index. Still execute the query using a JS filter. Same fallback on browsers that doesn't support compound indexes (IE and Edge) - the queries would be executed and work but without utilizing the compound indexes. See [Vision for Dexie](https://github.com/dfahlander/Dexie.js/issues/427)
dfahlander/Dexie.js Support for complex queries 12 Support arbritary queries that mix OR, AND and has parentheses. ```sql SELECT * FROM friends where (name = 'foo' AND (age = 99 OR (emailAddress = 'foo@bar' AND shoeSize < 7))) ``` Dexie query ```js db.friends.where({name: 'foo'}).and ( db.friends.where({age: 99}).or ( db.friends.where({emailAddress: 'foo@bar'}).and('shoeSize').below(7))) ``` See [Vision for Dexie](https://github.com/dfahlander/Dexie.js/issues/427) *EDIT 2018-05-28: The syntax may become a bit different than this example suggests. A new proposed syntax will be release later on.*

Comments

Project Feature Comment When
dfahlander/Dexie.js Add import/export support for a db Addon complete: https://www.npmjs.com/package/dexie-export-import Source on https://github.com/dfahlander/Dexie.js/tree/master/addons/dexie-export-import about 2 years ago
dfahlander/Dexie.js Add import/export support for a db Working on this feature as a dexie addon. Will basically be used like this: ```javascript import Dexie from 'dexie'; import 'dexie-export-import'; // Import and create Dexie instance in one call: const importedDb = await Dexie.import(blob); // Import into existing db: const db = new Dexie('dbname'); db.version(1).stores({foo: 'bar', ...}); await db.import(blob, [options]); // Export: const exportBlob = await importedDb.export(); ``` about 2 years ago
feathub/feathub DELETE PLEASE Not that I want to delete my project now, but it's a pain if I can't if I decide to. Please fix this! about 4 years ago

Votes

Vote When Project Feature
about 4 years ago feathub/feathub DELETE PLEASE
about 4 years ago feathub/feathub Be able to vote for comments on features
about 4 years ago feathub/feathub Rely on GitHub issues as a data source
about 4 years ago feathub/feathub Notify repository owner when new features are suggested