Skip to content

v0.14.0-rc.0

Pre-release
Pre-release

Choose a tag to compare

@haveyaseen haveyaseen released this 11 May 20:14
· 195 commits to master since this release

Easy-to-use selector API!

Breaking changes:

  • The state slice selector is no longer used in createSelector. Pass it to the ORM constructor instead:
-const someSelector = createSelector(orm, state => state.orm, …);
+const someSelector = createSelector(orm, …);
-const orm = new ORM();
+const orm = new ORM({
+    stateSelector: state => state.orm,
+});

New features:

  • Pass a single primary key, and array of primary keys or nothing as an argument:
const movies = createSelector(orm.Movie);
movies(state);            // ref array of all movies
movies(state, 1);         // ref of movie with ID 1
movies(state, [1, 2, 3]); // ref array of movies with ID 1, 2 and 3
  • Map models to their fields:
const moviePublisher = createSelector(orm.Movie.publisher);
moviePublisher(state);            // ref array of each movie's publisher
moviePublisher(state, 1);         // ref of the first movie's publisher
moviePublisher(state, [1, 2, 3]); // publisher ref array of each of the movies with ID 1, 2 and 3
  • This works in a chained way as well:
const coverBookAuthors = createSelector(orm.Cover.book.authors);
// If the cover or its book don't exist, null is returned:
coverBookAuthors(orm.getEmptyState());            // []
coverBookAuthors(orm.getEmptyState(), 1);         // null
coverBookAuthors(orm.getEmptyState(), [1, 2, 3]); // [null, null, null]
  • Map selectors to model collections:
const bookAuthors = createSelector(orm.Book.authors);
const genreAuthors = createSelector(orm.Genre.books.map(bookAuthors));

The following would work as well and is equivalent:

const genreAuthors = createSelector(orm.Genre.books.map(orm.Book.authors));
  • With a custom result function:
const avg = arr => arr.reduce((a, b) => a + b, 0) / arr.length;
const publisherAverageRating = createSelector(
    orm.Publisher.movies.map(orm.Movie.rating),
    ratings => ratings && (ratings.length ? avg(ratings) : 'no movies')
);
  • Pass your ORM instance at any position of createSelector and get a session at the corresponding position in the result function's argument list:
const someSelector = createSelector(
    [ a,  b,     orm,  d], // a, b and d being selectors
    (_a, _b, session, _d) => session.User.count()
);

Caveats

  • You need to pass at least one selector beginning with orm to createSelector() as a replacement for passing the previous state selector function.
  • You need to handle different values of the primary key argument yourself if you want to support them:
const publisherAverageRating = createSelector(
    orm.Publisher.movies.map(orm.Movie.rating),
    (state, idArg) => idArg,
    (ratingsArg, idArg) => {
        if (typeof idArg === 'undefined' || Array.isArray(idArg)) {
            // only state was passed, or an array of IDs
            return ratingsArg.map(
                ratings => ratings && ratings.length ? avg(ratings) : 'no movies'
            );
        }
        // single publisher ID was passed
        return ratingsArg && (ratingsArg.length ? avg(ratingsArg) : 'no movies');
    }
);