API documentation
The Cliquetis
constructor
const db = new Cliquetis(options);
options
is an object defining the following option values:
remote
: The remote Cliquet server endpoint root URL (eg."https://server/v1"
);headers
: The default headers to pass for every HTTP request performed to the Cliquet server (eg.{"Authorization": "Basic bWF0Og=="}
);
Collections
Collections are persisted locally in indexedDB.
Selecting a collection is done by calling the collection()
method, passing it the resource name:
const articles = db.collection("articles");
The collection object has the following (read-only) attribute:
- lastModified: last synchronization timestamp,
null
if never sync'ed.
Notes
- A single dedicated database and store are created per collection.
- All transactional operations are asynchronous and rely on Promises.
Creating a record
articles.create({title: "foo"})
.then(console.log.bind(console))
.catch(console.error.bind(console));
Result is:
// result
{
data: {
id: "2dcd0e65-468c-4655-8015-30c8b3a1c8f8",
title: "foo",
}
}
Notes
- Records identifiers are generated locally using UUID v4.
Retrieving a single record
articles.get("2dcd0e65-468c-4655-8015-30c8b3a1c8f8")
.then(console.log.bind(console))
.catch(console.error.bind(console));
Result:
{
data: [
{
id: "2dcd0e65-468c-4655-8015-30c8b3a1c8f8",
title: "bar"
}
]
}
Notes
- The promise will be rejected if no record is found for that id.
Updating a record
var existing = {
id: "2dcd0e65-468c-4655-8015-30c8b3a1c8f8",
title: "bar"
};
var updated = Object.assign(existing, {
title: "baz"
});
articles.update(updated)
.then(console.log.bind(console));
Result is:
{
data: {
id: "2dcd0e65-468c-4655-8015-30c8b3a1c8f8",
title: "baz",
last_modified: 1432222889337
}
}
Notes
- An id is required, otherwise the promise will be rejected.
Deleting records
By default, local deletion is performed virtually, until the collection is actually synced to the remote server.
articles.delete("2dcd0e65-468c-4655-8015-30c8b3a1c8f8")
.then(console.log.bind(console));
Result:
{
data: [
{
id: "2dcd0e65-468c-4655-8015-30c8b3a1c8f8",
title: "foo",
_status: "deleted"
}
]
}
Notes
- An id is required, otherwise the promise will be rejected;
- Virtual deletions aren't retrieved when calling
#get()
and#list()
.
Listing records
articles.list()
.then(console.log.bind(console));
Result is:
{
data: [
{
id: "705b17be-e957-4c14-8f4c-86f8eaac29c0",
title: "foo"
},
{
id: "68e63131-3859-40cc-a4f7-b237ca179329",
last_modified: 1432222889336,
title: "Web page"
},
]
}
Notes
- Records with
last_modified
attribute were sync'ed on a server.
Clearing the collection
This will remove all existing records from the collection:
articles.clear()
.then(console.log.bind(console));
Result:
{
data: [],
permissions: {}
}
Fetching and publishing changes
Synchronizing local data with remote ones is performed by calling the #sync()
method.
Synopsis:
- Fetch remote changes since last synchronization;
- Fail on any conflict encountered;
- The developer has to handle them manually using
#resolve()
, and call#sync()
again when done;
- The developer has to handle them manually using
- If everything went fine, publish local changes;
- Fail on any publication conflict detected;
- If
strategy
is set toCollection.strategy.SERVER_WINS
, no remote data override will be performed by the server; - If
strategy
is set toCollection.strategy.CLIENT_WINS
, conflicting server records will be overriden with local changes; - If
strategy
is set toCollection.strategy.MANUAL
, conflicts will be reported in a dedicated array.
- If
- Fail on any publication conflict detected;
articles.sync()
.then(console.log.bind(console))
.catch(console.error.bind(console));
Synchronization strategies
The sync()
method accepts a strategy
option, which itself accepts the following values:
Collection.strategy.MANUAL
(default): Conflicts are reflected in aconflicts
array as a result, and need to be resolved manually.Collection.strategy.SERVER_WINS
: Server data will be preserved;Collection.strategy.CLIENT_WINS
: Client data will be preserved.
You can override default options by passing #sync()
a new options
object; Cliquetis will merge these new values with the default ones:
articles.sync({
strategy: Collection.strategy.CLIENT_WINS,
headers: {Authorization: "Basic bWF0Og=="}
})
.then(console.log.bind(console));
.catch(console.error.bind(console));
Sample result:
{
ok: true,
lastModified: 1434270764485,
errors: [], // Errors encountered, if any
created: [], // Created locally
updated: [], // Updated locally
deleted: [], // Deleted locally
conflicts: [], // Import conflicts
skipped: [], // Skipped imports
published: [] // Successfully published
}
If conflicts occured, they're listed in the conflicts
property; they must be resolved locally and sync()
called again.
The conflicts
array is in this form:
{
// …
conflicts: [
{
type: "incoming", // can also be "outgoing"
local: {
_status: "created",
id: "233a018a-fd2b-4d39-ba85-8bf3e13d73ec",
title: "local title",
},
remote: {
id: "233a018a-fd2b-4d39-ba85-8bf3e13d73ec",
title: "remote title",
}
}
]
}
Resolving conflicts
Conflict resolution is achieved using the #resolve()
method:
articles.sync()
.then(res => {
if (!conflicts.length)
return res;
return Promise.all(conflicts.map(conflict => {
return articles.resolve(conflict, conflict.remote);
}));
})
.then(_ => articles.sync())
.catch(console.error.bind(console));
Here we're solving encountered conflicts by picking all remote versions. After conflicts being properly addressed, we're syncing the collection again.