Mercury provides an asynchronous CRUD data abstraction layer that can be used to isolate your code from specific methods of different data origins.
Provides:
- "Origin" class from which your own specific origin implementation should extend.
- CRUD. Define different methods for
read
,create
,update
,delete
actions. - Asynchronous. Three properties are available for each method:
value
,loading
,error
. - Queryable. Applies queries to your CRUD methods using the built-in
query
method. - Chainable. Queries can be chained, the resultant query will be the extension of all.
- Customizable. Custom queries can be added to the instances.
- Cache. Use built-in cache to avoid the same query being executed more than once if not necessary.
- Clean cache on demand with the built-in
clean
method. - Events emitter.You can add listeners to changes and cache events.
- Extensible. Implement your own origins connectors, or use one of the already existant:
- CRUD. Define different methods for
- "Selector" constructor for combining or transforming the result of one or many origins.
- Declarative. Declare which Origins your Selector needs to consume. Mercury will do the rest for you.
- Composable. Can fetch data from Origins or from another Selectors.
- Homogeneus. Provides exactly the same interface than origins. Consumers don't need to know if they are consuming an Origin or a Selector.
- Cache. Implements a cache that avoids the execution of the same Selector and query more than once.
- Reactive. When one of the related sources cache is cleaned, the Selector cache is cleaned too.
- Switchable. Consumed "source" can be changed programatically.
- Parallellizable. Can fetch data from declared sources in series or in parallel.
- Queryable. Queries can be applied as in Origins. You can pass the
query
data to sources, or use it in theparser
function, after all related sources data have been fetched.
- "sources" singleton containing methods for managing all created mercury sources at a time.
- Tags Mercury instances can be tagged to create "management" groups. "Cleaning" cache of all mercury sources tagged with "api" tag calling to a single method is easy, for example.
npm i @xbyorange/mercury --save
import { Selector, sources } from "@xbyorange/mercury";
import { Api } from "@xbyorange/mercury-api";
const booksCollection = new Api("http://api.library.com/books");
const authorsCollection = new Api("http://api.library.com/authors");
const booksWithAuthors = new Selector(
booksCollection,
authorsCollection,
(booksResults, authorsResults) =>
booksResults.map(book => ({
...book,
authorName: authorsResults.find(author => author.id === book.author)
}))
);
// Each book now includes an "authorName" property.
const results = await booksWithAuthors.read();
// Clean cache of books, authors, and booksWithAuthors at a time.
sources.clean();
This example uses the Api origin, which is not distributed in this package, but can clearly illustrate the usage of an Origin, and the intention of the library.
All examples in next docs will use the Api origin for a better comprehension of the library intention. Please refer to the mercury-api documentation for further info about an API origin usage.
Please read the full Origin api docs to learn how to create origins.
All examples in next docs will use the Api origin for a better comprehension of the library intention. Please refer to the mercury-api documentation for further info about an API origin usage.
- Asynchronous mutable properties
- Default value
- Cache
- Query
- Parallel sources
- Sources error handling
- Selectors returning sources
Read the full Selector API documentation.
Some utilities are provided to make easier the task of testing Selectors. Please red the testing selectors docs.
All created Mercury origins or selectors are registered in the "sources" object, which provides methods for managing them all together, or by groups based in tags.
import { sources } from "@xbyorange/mercury";
sources.clean();
sources.getByTag("need-auth").config({
headers: {
"authentication": "foo"
}
})
Read the full sources API documentation.
Please refer to the react-mercury documentation to see how simple is the data-binding between React Components and the Mercury Sources.
Connect a source to all components that need it. Mercury will fetch data only when needed, and will avoid making it more than once, no matter how many components need the data.
Components will became reactive to CRUD actions automatically (dispatch a create
action over a collection, and Mercury will refresh it automatically on any rendered binded component)
Contributors are welcome. Please read the contributing guidelines and code of conduct.