Giter Site home page Giter Site logo

kinto / kinto.js Goto Github PK

View Code? Open in Web Editor NEW
315.0 14.0 72.0 16.31 MB

An Offline-First JavaScript Client for Kinto.

Home Page: http://kintojs.readthedocs.io/

License: Other

JavaScript 0.55% TypeScript 99.45%
kinto http client sync synchronization offline offline-first cache hacktoberfest

kinto.js's Introduction

Kinto.js

Greenkeeper badge

Build Status Coverage Status

An Offline-First JavaScript client for Kinto.

Note: This library also includes a pure JS HTTP client for Kinto. You can learn more in the docs.

The idea is to persist data locally in the browser by default, then synchronizing them with the server explicitly when connectivity is guaranteed:

const kinto = new Kinto({ remote: "https://demo.kinto-storage.org/v1/" });
const posts = kinto.collection("posts");

// Create and store a new post in the browser local database
await posts.create({ title: "first post" });

// Publish all local data to the server, import remote changes
await posts.sync();

Documentation

kinto.js's People

Contributors

aebrathia avatar agawish avatar ajmeese7 avatar almet avatar andresmurguido001 avatar cgs-jack-bashford avatar cristicismas avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar dstaley avatar elelay avatar francois2metz avatar glasserc avatar grahamalama avatar greenkeeper[bot] avatar greenkeeperio-bot avatar happy-tanuki avatar lavish205 avatar leplatrem avatar magopian avatar markellisdev avatar matt-boris avatar michielbdejong avatar mozmark avatar n1k0 avatar natim avatar pdehaan avatar quentinroy avatar zakaluka avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kinto.js's Issues

Expose events for server backoff

Refs #68, #82. We should expose public events for server backoff, so users can subscribe to them to handle UI changes accordingly, eg:

kinto.on("server-backoff", seconds => {
  if (seconds > 0) 
    $("#sync-btn").disable();
  else 
    $("#sync-btn").enable();
});

Improve error reporting when fetching changes failed.

   71            return {items: []};
   72          } else if (res.status >= 400) {
   73:           // TODO: attach better error reporting
   74            throw new Error("Fetching changes failed: HTTP " + res.status);
   75          } else {

We'd need to distinguish between possible 4xx and 5xx status codes so the end user knows more precisely what happened.

Error when server returns 400 error response

Cannot read property 'errno' of null

To reproduce:

var collection = kinto.collection("ZjE1ZjgxODMtOTcyNy00ZDgzLWE2MDEtOTUyMTFlYTIzMzQ5OnMzY3IzdA==-items");
collection.sync();

Server will respond:

GET https://kinto.dev.mozaws.net/v1/buckets/default/collections/ZjE1ZjgxODMtOTcyNy00ZDgzLWE2MDEtOTUyMTFlYTIzMzQ5OnMzY3IzdA==-items/records

Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Length:167
Content-Type:application/json; charset=UTF-8
Date:Wed, 12 Aug 2015 07:24:54 GMT
Server:nginx/1.4.6 (Ubuntu)

{"errno":107,"message":"path: Invalid record id","code":400,"details":[{"location":"path","name":null,"description":"Invalid record id"}],"error":"Invalid parameters"}

Curiously, it looks like in kinto.js code response.json() is null.

Cached Kinto collections instances are not uniquely identified

This doesn't comply with setting the bucket name, so a collection sharing a common name with another one from another bucket will override it.

    if (!this._collections.hasOwnProperty(collName)) {
      this._collections[collName] = new Collection(bucket, collName, api, {
        events: this.events
      });
    }

We need to cache these using keys including the bucket name as well.

Maybe add fetch-only / push-only option in Collection#sync()

The way we use kinto.js for syncing browser history is:

data on remote FxSync
<--network-->
data exposed by syncto
<--kinto.js sync-->
local kinto.js collection
<--adapter-->
DataStore 'places' on the device

Since the device is already using the 'places' DataStore all over the place, we want to store all data twice, locally. Once in the kinto.js collection, and once in the 'places' DataStore. The 'adapter' compares the two, and decides how to import changes from the kinto.js collection into the DataStore, and export changes from the DataStore to the kinto.js collection.

Before this adapter runs, we want to make sure we have the latest data from remote, so we want to sync fetch-only.

After the adapter runs, we want to push out any changes it made in the kinto.js collection, so we want to sync push-only.

It's not so expensive to push zero changes in the pre-adapter sync and to pull (probably) zero changes in the post-adapter sync, but at the same time it would be nice to be able to just make the first sync fetch-only, and make the second sync push-only

Prevent concurrent conflicting transactions by incrementing a local revision number

Use case

  • We have an edition form for a given record in state A, and we don't have submitted the form yet;
  • Concurrently, a worker modifies this record and turns it into state B;
  • We now submit the form, which overrides what's just been updated by the worker, which is the problem we're trying to solve here.

Flow

  • Form loads existing record with local_rev==1 (eg. that value is contained in some hidden input field, CSRF-token protection style or any other way, eg in React component's props);
  • Worker loads existing record with local_rev==1;
  • Worker updates existing record, persistence layer bumps local_rev to 2;
  • Form is submitted, data are sent to the local persistence layer adapter;
  • Persistence layer knows that local_rev for that record is 2, but form has just sent local_rev==1: an error is raised.
Notes
  • Do not synchronize the local revision number to the server;
  • Each time we synchronize a remote record from the server to the local database, we reset its local revision number;
  • Any synchronized remote records should bump matching local equivalent record's local_rev number.

We'd love hearing thoughts and feedback from @daleharvey, @leplatrem, @Natim, @michielbdejong

Sync flow should stop when pushing changes fails

Current flow is:

    return this.db.getLastModified()
      .then(lastModified => this._lastModified = lastModified)
      .then(_ => this.pullChanges(result, options))
      .then(result => {
        if (!result.ok) {
          return result;
        } else {
          return this.pushChanges(result, options)
            .then(result => this.pullChanges(result, options));
        }
      });

We should probably resolve early when pushChanges result isn't ok as well. This is how the final flowchart should look like:

kinto js sync flow

Install from github branch

With the current strategy (see #105), kinto cannot be installed from a github branch.

diff --git a/package.json b/package.json
index 1f15289..fe037bf 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,7 @@
     "karma-webpack": "^1.7.0",
-    "kinto": "^1.0.0-rc.3",
+    "kinto": "git://github.com/mozilla-services/kinto.js.git#db-prefix",
     "mocha": "^2.2.5",

Module not found: Error: Cannot resolve module 'kinto'.

Implement conflict resolution helper

Suggested API:

collection.sync().then(res => {
  if (res.conflicts.length === 0)
    return;
  return Promise.all(res.conflicts.map(conflict => {
    const resolution = 
    return collection.resolve(conflict, resolution);
  })).then(res => collection.sync());
});

Collection#resolve should return a Promise being the result of a sucesful local update.

Note: Maybe we should add a new resolved entry to SyncResultObject to list these?

What are the work in progress and limitations ?

It would be relevant to explicit somewhere:

  • the intended limitations (aka. naive approach)
    • no revision tree
    • no magic for conflict merge
    • server/client wins
    • ...
  • the current limitations (aka. work in progress)
    • no local revisions
    • no lock for concurrent updates
    • ...
  • ideas for the long-term vision (aka. fantasy)
    • Kinto futon
    • crypto layer
    • ...

Handle synchronization when the server was flushed.

The development server is flushed every day.

At first, we could think that the JS client would just reupload everything stored locally. Is it really the case?

Hints:

  • If the server is flushed, the timestamps are reinitialized.
  • If the server is flushed, the permissions will be too (off topic?)

Just close this issue if cliquetis behaves as expected :)

Host static assets on a CDN

Hotlinking to Github static assets hosting doesn't work well with browsers having strong mimetype checks. Also that's probably unfair to Github, so we have to find a proper solution.

Add checks for unsupported Cliquet protocol version.

Goals

The client should:

  • check that the protocol version defined by the remote server url matches the one it actually supports;
  • check that for every HTTP request made to the server, the protocol version matches its own expectations.

Tasks

  • Define and export a SUPPORTED_PROTOCOL_VERSION constant defining the protocol version the client actually supports; eg. export const SUPPORTED_PROTOCOL_VERSION = "v1";
  • Ensure the version passed in the remote property matches that constant value; raise on mismatch with an appropriate error message;
  • Request server endpoints using that SUPPORTED_PROTOCOL_VERSION value;
  • On each request made, check for 404 status code with an errno set to VERSION_NOT_AVAILABLE; reject with an explicit message in such case;
  • Update docs.

Validate passed uuids

This would apply to #get(), #update(), #delete() and #resolve(). We should throw when an id doesn't match the UUID format. Tests would have to be updated accordingly.

For #resolve(), we should also validate that the resolution object uuid matches the one from the conflict, and reject accordingly.

Support unlimited batch requests

In Kinto, if the setting cliquet.batch_max_requests is set to None, then the server has no limit for batch requests.

Currently, Kinto.js expects a value for this setting.

Clarify if 'clearing the collection' affects only client, or client+server

Sometimes I will want to remove all the items from the collection on the server.
Other times (actually, probably only when debugging, or maybe when offline and offering the user something like git checkout -- . to discard unpushed changes), I only want to flush the cache, to make sync start from zero.
It is not clear to me which one of these two is done by http://kintojs.readthedocs.org/en/latest/api/#clearing-the-collection

Refactor generic HTTP error handling.

Current situation is a mess, eg duplicated code and most importantly, we're losing stack traces when throwing new errors instead of propagating them.

Implement local list filtering

Target API:

// Single filter
articles.list({
  filter: { unread: { $eq: true } }
}).then(console.log.bind(console));

// Combined field filtering
articles.list({
  filter: {
    added_on: { 
      $gt: 1432800794000, 
      $lt: 1432800795000 
    }
  }
}).then(console.log.bind(console));

// Multiple fields filtering (AND only)
articles.list({
  filter: { 
    unread: { $eq: true }, 
    added_on: { $gt: 1432800794000 } 
  }
}).then(console.log.bind(console));

First minimal batch of operators to support:

  • $eq: Strict equality check (strings, numbers);
  • $contains: Partial equality check (strings only);
  • $gt, $gte: Greater than, greater than equal (strings, numbers);
  • $lt, $lte: Lesser than, lesser than equal (strings, numbers).

Notes

  • As we're using schemaless stores, we can't rely on indexed fields here (because we can't predict them);
  • All queries are performed using the AND condition logic.

Versions should be handled in the client

Currently, Cliquetis handles the version in the host url, with a prefix (e.g. http://localhost:8888/v1).

It's important to have a way to tell which version of the protocol is supported by Cliquetis, in order to detect potential problems due to version mismatches.

To do so, I believe a request to the / endpoint of the server should be made, to get the protocol version, and then check that the protocol is the same as the one of Cliquetis.

Allow defining local indexes.

Filtering and ordering being currently achieved in-memory, the performance penalty can be important in case of large datasets.

We should allow users to create indexes on fields and rely on native IDB queries to speed things up.

Suggested API:

const db = new Kinto();
const tasks = db.collection("tasks");
tasks.ensureIndexed("label", "done");

Or even:

const tasks = db.collection("tasks", {
  indexes: ["label", "done"]
});

Thoughts? @Natim @leplatrem

Fetch remote server settings.

Goals

The client should retrieve server settings from the /vX endpoint; for now, the only setting we need is the batch_limit one.

Tasks

  • On each outgoing HTTP request, first ensure we already have retrieved the settings information;
  • If we haven't yet, request that information from the /vX endpoint, then store the settings in a local Api property;
  • On subsequent requests, reuse the cached settings property to avoid hammering the server for no reason.
Notes
  • The implementation shouldn't impact existing documentation;
  • Batch limit support should be done along #13, not here.

Provide a hook to interecept deprecation warnings.

Follow-up of #79.

We need to provide a way for the user to intercept deprecation warnings to they can handle them however they want.

It feels like we should rely on an event, eg.:

const kinto = new Kinto({remote: "http://deprecated.server/v0"});
kinto.on("deprecated", (message, url) => {
   // don't take this example too seriously please :)
  alert(message);
  window.open(url);
});

Be able to provide the Collection URL in order to get Kinto.js compatible with Cliquet specific app.

On my way to build Syncto and after reading the specification document for Kinto integration with Balrog, I think we should extends Kinto to let people choose their collection URL in case it doesn't follow the exact Kinto formalism.

The rest of the protocol is the one Cliquet uses.

The configuration could be something like:

  var db = new Kinto({remote: "https://syncto.dev.mozaws.net/v1"});
  var history = db.collection("history", url="/history", use_middlewares=[SyncCrypto]);

Or for the readinglist:

  var db = new Kinto({remote: "https://readinglist.services.mozilla.com/v1"});
  var history = db.collection("history", url="/articles");

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.