hoodiehq / hoodie-client Goto Github PK
View Code? Open in Web Editor NEW:dog: Client API for the Hoodie server
License: Apache License 2.0
:dog: Client API for the Hoodie server
License: Apache License 2.0
follow up for hoodiehq/hoodie#358 and hoodiehq/hoodie#195
Currently fails with CustomPouchError: Database encountered an unknown error
Since #46 we had some refactoring and bugfixing, and the code coverage fell down to 91% (that was me, I’m sorry :( )
$ npm run test:coverage
=============================== Coverage summary ===============================
Statements : 91.61% ( 131/143 )
Branches : 87.18% ( 34/39 )
Functions : 84.38% ( 27/32 )
Lines : 91.61% ( 131/143 )
================================================================================
After you run npm run test:coverage
you can open coverage/lcov-report/index.html
in your browser, it will show a lot of details on which parts of the code is not yet covered. There are a few lines not covered in client/lib/init.js, here’s a preview
npm run test:coverage
Ping us in the Hoodie Chat or on Twitter if you have _any_ questions
follow up for #48
If the user is signed in we want to start syncing changes. The code for that looks something like this
if (hoodie.acount.isSignedIn()) {
hoodie.store.connect()
}
And it needs to run as part of the hoodie
initialisation
hoodie.store.connect()
is called when hoodie.account.isSignedIn()
returns true to tests/specs/init.jshoodie.store.connect()
is not called when hoodie.account.isSignedIn()
returns falsetest: hoodie.store.connect() on page load
fixes #54
to the descriptionhoodie.store.connect()
call on page load if user is signed infeat: hoodie.store.connect() on page load
via @rogeriochaves hoodiehq/hoodie-server#413
Hello,
So, I create a new instance of hoodie (new Hoodie('HOODIE_URL')) when the page is loaded, and I listen to error:unauthenticated events, but apparently this event is only triggered when the session is expired and the user reloads the page.
I put my couchdb session to expire in 15s just to test, and when the user is using the app, after 15s, the data syncing starts to throw 401s, and the user can't logout, but no error:unauthenticated is triggered, only if I reload the page.
Thanks!
Branch | Build failing 🚨 |
---|---|
Dependency | standard |
Current Version | 8.5.0 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
As standard is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.
I recommend you give this issue a high priority. I’m sure you can resolve this 💪
The new version differs by 10 commits .
3f88a12
8.6.0
b771408
changelog
4c82bc8
Remove standard-format references
938dcc3
[email protected]
21f0ca4
cross-spawn@5
451da5f
[email protected]
f27f1df
[email protected]
e542e03
[email protected]
66f1ead
Merge pull request #684 from capaj/patch-2
a0280a9
added vscode-standardjs-snippets
See the full diff.
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot 🌴
Branch | Build failing 🚨 |
---|---|
Dependency | uglify-js |
Current Version | 2.8.8 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
As uglify-js is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.
I recommend you give this issue a high priority. I’m sure you can resolve this 💪
The new version differs by 5 commits .
344d11d
v2.8.9
c7cdcf0
fix function name eliminiation (#1576)
3ee5574
only run benchmark & jetstream on CI (#1571)
dedbeef
plan B for IE8 do-while semi-colon fix (#1572)
bd6dee5
fix return from recursive IIFE (#1570)
See the full diff.
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot 🌴
Branch | Build failing 🚨 |
---|---|
Dependency | uglify-js |
Current Version | 2.8.7 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
As uglify-js is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.
I recommend you give this issue a high priority. I’m sure you can resolve this 💪
The new version differs by 7 commits .
144052c
v2.8.8
65c848c
include benchmark.js in test suite (#1564)
8a8a94a
fix deep cloning of labels (#1565)
8153b7b
transform function calls to IIFEs (#1560)
d787d70
avoid substitution of global variables (#1557)
3ac2421
collapse_vars: do not replace a constant in loop condition or init (#1562)
a9fc9dd
suppress semicolons after do/while (#1556)
See the full diff.
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot 🌴
Originally we expected @hoodie/client
to run in browsers only, but we realized that we have to make it compatible with ServiceWorker and Node.js, too (e.g. for server-side rendering).
Currently url
is optional and it defaults to location.origin
, which only exists in browsers. So instead we should make this a required option, and default options.url
to location.origin
in the hoodie’s bundle code for /hoodie/client.js
hoodie.plugin
takes a function which receives hoodie
as its first argument.
hoodie.plugin(function(hoodie) {
hoodie.sayHi = function() {
alert('say hi!');
};
});
hoodie.sayHi(); // shows alert
tests/specs/plugin
, require it in tests/index.js
npm test
lib/plugin.js
until tests are greenfollow up for #43
We currently call hoodie.store.clear()
on signout
in index.js. hoodie.store.clear
no longer exists, it was replaced with .reset(options)
so we can set a new db name after signout, as hoodie.account.id
changes as well.
"hoodie-client-store"
version in package.json to the latest (4.0.0
right now) unless it’s already updatedchore(package): hoodie-client-store@^4.0.0
(or whatever is the current version)hoodie.store.clear()
call with the .reset()
method and pass in the new hoodie.account.idfix: reset store on signout
If you have any questions, ping us at http://hood.ie/chat/ or https://twitter.com/hoodiehq
Reset hoodie client and emit reset
events so plugins can reset as well. Should implement a way so that plugins can hook into the reset with async operations
hoodie.reset().then(function () {
// clean slate again
})
And plugins could do something like
hoodie.on('reset', function (options) {
options.promise = options.promise.then(function () {
// do some async reset here
})
})
^^ This is just a suggestion, maybe there are better patterns for it :)
That should ™️ be it
Branch | Build failing 🚨 |
---|---|
Dependency | browserify |
Current Version | 14.1.0 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
As browserify is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.
I recommend you give this issue a high priority. I’m sure you can resolve this 💪
The new version differs by 5 commits .
18e1d65
14.2.0
0e1a7a0
add cli support for --transform-key to support mode's like production/staging/etc..
a5aa660
Merge pull request #1701 from wogsland/doc-fix
ae281bc
Fixed documentation formatting that was bugging me
fe8c57b
async test for node 7
See the full diff.
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot 🌴
Branch | Build failing 🚨 |
---|---|
Dependency | pouchdb-adapter-memory |
Current Version | 6.0.7 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
As pouchdb-adapter-memory is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.
I recommend you give this issue a high priority. I’m sure you can resolve this 💪
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot 🌴
The docs say we can pass in options to the Hoodie constructor:
var hoodie = new Hoodie(options)
and that these look something like this:
var options = {
account: {
id: '9h57fpa'
}
}
However, taking a look at https://github.com/hoodiehq/hoodie-client/blob/master/lib/get-state.js#L9-L16, all of these sub options described in the docs are ignored completely.
Our use case was that we wanted to open an existing user's DB in Service Worker. We did
const store = new Hoodie({
account: {
id: '9h57fpa'
}
})
but Hoodie ignores the options and creates a new user DB with a random ID instead.
The way hoodie-client
is currently being developed, we directly require pouchdb-hoodie-store
, account-client
and soon task-client
.
hoodie-server
requires the respective hapi-couchdb-store
, hapi-couchdb-account
, hapi-couchdb-task
modules which have the same dependencies respectively.
So in theory, hapi-couchdb-store
could require pouchdb-hoodie-store@3
, while hoodie-client
has a dependency on pouchdb-hoodie-store@4
.
How to avoid that from happening, or how to work around it?
You can see pouchdb-hoodie-api is doing it: https://github.com/hoodiehq/pouchdb-hoodie-api/blob/master/index.js#L25-L27
Should be something like
var Task = require('hoodie-client-task')
// ...
api.task = new Task(api.id, { url: '/hoodie/account/api' })
follow up for hoodiehq/hoodie#118
Basic idea is to pool GET request, e.g. when executing hoodie.request('/hoodie/api')
in quick succession it will not send multiple requests, but only send one request and return the promise for the others.
Let’s debate if this is still something we want. I’m not sure if this is still an issue with the new Hoodie at all, probably not
follow up for hoodiehq/hoodie#397
This would probably go into a plugin, but putting it here for the time being :)
We want the Hoodie Client to not only run in browsers, but also on servers (server-side rendering) and in Service Workers. We are currently removing @hoodie/client-store
's dependency on PouchDB
by replacing it with options.PouchDB
This will also give developers more control about the used PouchDB version and custom build. Only hoodie
should have a dependency on PouchDB, all lower-level dependencies should work with options.
Pull request: #107
I tried to set the cache
property for the account api through the hoodie client constructor. Unfortunately, the following snippet doesn't work:
const accountCache = {/* get, set, unset */}
const hoodie = new Hoodie({
url: 'arbitrary-hoodie-url',
account: {
cache: accountCache
}
});
It seems, that line 74 in @hoodie/client/lib/get-api.js
does not consider the options provided by the user. However, according to the lodash docs for defaultsDeep
this is correct behaviour:
// https://lodash.com/docs/#defaultsDeep
_.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
// => { 'a': { 'b': 2, 'c': 3 } }
Option a.b
from the second object isn't applied which would be stateOptions.cache
in my case. I'm not sure, but I think is isn't correct, is it? Would maybe lodash/merge
be a better fit (edit: or switch arguments)? Please let me know, if I got something wrong here.
Branch | Build failing 🚨 |
---|---|
Dependency | @hoodie/store-client |
Current Version | 6.0.1 |
Type | dependency |
This version is covered by your current version range and after updating it in your project the build failed.
As @hoodie/store-client is a direct dependency of this project this is very likely breaking your project right now. If other packages depend on you it’s very likely also breaking them.
I recommend you give this issue a very high priority. I’m sure you can resolve this 💪
The new version differs by 1 commits .
e950b17
fix: workaround PouchDB.plugin bug
See the full diff.
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot 🌴
Hoodie only needs the built version, it does not browserify hoodie-client on the fly. So how about we create another npm package which only has the built files and no dependencies or other code, to speed up the npm install
for hoodie and reduce dependencies?
@boennemann what do you think?
I've writen a script that requires @hoodie/client
, just as described in the readme, but it throwed an error on require:
>> Error: Cannot find module 'lodash/defaultsDeep'
I suppose that's because my app's dependency tree ends up including an older version on lodash, and once @hoodie/client
does not specify lodash as a dependency (only as a devDependency) it ends up using that older version, that does not have that file...
I tried to create a node_modules
dir inside node_mocules/@hoodie/client
and copy a newer version of lodash there and the error has gone.
Also, looking at the places where defaultsDeep
is used in this module, it seems to me it's actually not only a dev dependency..
hoodie.request(options)
Examples
// sends a GET request to hoodie.url + '/foo/api/bar'
hoodie.request('/foo/api/bar')
// sends a GET request to another host
hoodie.request('https://example.com/foo/bar')
// sends a PATCH request to /foo/api/bar
hoodie.request({
method: 'PATCH',
url: '/foo/api/bar',
data: {
foo: 'bar'
}
})
part of hoodiehq/camp#101. See hoodiehq/hoodie-account-client#124 for more details.
The current Hoodie has a moveData
option on hoodie.account.signIn
. When set to true
, the account triggers a movedata
event to which the store
module is listening, to move all data that was created anonymously before the sign into the user’s account, to avoid data loss. See http://docs.hood.ie/en/techdocs/api/client/hoodie.account.html#accountsignin (Notes) for more information.
With the new architecture, store & account are currently nicely separated from each other, adding a store
-related event to account
would break that. I'd like to think if we can find a cleaner way to achieve the same.
For example, we could add a before:signin
event to account, to which we could subscribe to when we integrate the modules in hoodie-client
. It would be triggered right before the signin
event, so the sessionProperties would already be available, and the options (besides the password) from the signIn
call could be passed to it, so we could do this
hoodie.on('account:before:signin', function(session, options) {
if (options.moveData) {
// do what ever it takes to not loose existing data, but migrate it to the new account
}
})
That means the moveData
option would remain, but we would get rid of the internal movedata
event, and would do the wiring outside of the two modules instead.
The problem is in this line:
https://github.com/hoodiehq/hoodie-client/blob/master/lib/init.js#L72
The event is not called connect
but reconnect
, see https://github.com/hoodiehq/hoodie-connection-status#events
follow up for hoodiehq/hoodie#194
You can reproduce the problem on https://tracker.hood.ie/
Sign in to an account. Then on the terminal
hoodie.store.on('change', () => console.log('change'))
Now
hoodie.store.add({name: 'foo'})
You should see change
logs.
Now if you sign out on the console
hoodie.account.signOut()
and now create another document
hoodie.store.add({name: 'foo'})
there is no change
logged, but should be
Due to its offline-first nature, the Hoodie client should provide APIs to tell if connected to its back-end or not.
hoodie.checkConnection()
hoodie.isConnected()
hoodie.on('connected', handler)
hoodie.on('disconnected', handler)
I never liked the fact that the logic is not contained in a namespace like hoodie.store
& hoodie.account
, and thet .isConnected()
is a function.
I've an idea for a new API but am not yet happy with it. What we need:
disconnected
event if request to check connection failed, pass meaningful errorreconnected
event if request to check connection succeeded when it failed beforehoodie.connection
Here's what my current idea looks like
// - undefined if no status yet,
// - true last request responded ok
// - false if last request failed
hoodie.connection.ok
// returns promise, rejects with meaningful error
hoodie.connection.check({
// optional: start checking with interval. Not true interval, ignore time of pending requests.
// there can only be one interval at a time. Starting a new one clears existing.
// different intervals can be set with { connected: 30000, disconnected: 1000 }
interval: 1000,
// optional: timeout when to abort
timeout: 1000
})
// events
hoodie.connection.on('disconnected', handler)
hoodie.connection.on('reconnected', handler)
Open questions (updated Oct 24):
{connection: { check: { interval: 10000, timeout: 1000 }}}
hoodie.connection.lastCheckedAt
"reconnected"
event, which might be confusing. To avoid that, we can set a cache timeout after which the cache will be ignoredHi,
While using the something tracker app I noticed that when adding a new tracked item the new item will not show up in the couch db user table.
Only when I call hoodie.store.connect() in the console the sync is working correctly.
The same thing happens when entering a new value in the database.
It will not automatically sync and the sync needs to be triggered manually.
I would like to be able to install hoodie-client
via Bower. See the instructions for creating bower packages for reference. In my understanding, this would include:
bower.json
file.bower.json
.Step 4 could be a blocker, as there appears to be third party dependencies that are not already packaged up as Bower components.
In the current Hoodie, we don’t let the user sign out, unless all local changes have been synchronised, to avoid data loss, unless the user calls hoodie.account.signOut
with the ignoreLocalChanges
option, see http://docs.hood.ie/en/techdocs/api/client/hoodie.account.html#accountsignout
As account
and store
are now separated, I'd like to find a way to make that work without adding store
-related logic into the account
module.
For example, we could add a before:signout
event, to which we pass the options
from the signOut
call as well as a hook which we can use to delay and cancel the signout with a custom error
hoodie.on('account.signOut', function (accountProperties, options, hook) {
hook(function () {
// return a promise, or throw an error
return hoodie.store.push()
.catch(function () {
if (options.ignoreLocalChanges) return
throw new HoodieAccountLocalChangesError()
})
})
})
Maybe there is a better pattern for this use case, but that should work. In the account
module, we would
do something like
var promise = Promise.resolve()
emit('before:signout', accountProperties, options, function (hook) {
promise = promise.then(hook)
})
return promise.then(function () {
emit('signout', accountProperties)
})
npm run test:coverage
...
=============================== Coverage summary ===============================
Statements : 85.57% ( 83/97 )
Branches : 93.1% ( 27/29 )
Functions : 58.82% ( 10/17 )
Lines : 85.57% ( 83/97 )
================================================================================
Ping us in the Hoodie Chat or on Twitter if you have _any_ questions
related: #22
For the glue code between hoodie.account, hoodie.store and future plugins, we sometimes need to intercept an event, for example for hoodie.reset() or to sync all local changes before signing out, so no data gets lost.
For that I’d suggest we introduce a new hoodie.hook
API, which would look like this:
// Create a hook event
hoodie.hook('foo'/*, method*/)
// register before/after hooks. The methods can be async by returning a Promise
hoodie.hook.before('foo', asyncPreparations)
hoodie.hook.after('foo', asyncPostProcessing)
// remove pre/post hooks
hoodie.hook.remove('signin', asyncPostProcessing)
hoodie.hook.remove.before('signin', asyncPostProcessing)
hoodie.hook.remove.after('signin', asyncPostProcessing)
So for example, to sync all local changes before sign out, we would do
hoodie.hook.before('signout', function (options) {
return hoodie.store.push()
})
If hoodie.store.push
fails, then signout would fail. In the hoodie.account.signOut implementation we would wrap the DELETE /session
request
function signOut (state, options) {
var accountProperties = internals.get(state, 'account')
return state.hook('signout', options, function () {
return sendSignOutRequest(state, options)
})
}
function sendSignOutRequest (state, options) {
request({
method: 'DELETE',
url: state.url + '/session',
headers: {
authorization: 'Bearer ' + state.account.session.id
}
})
// ...
}
I was thinking about using the events API for that, but a dedicated hook API makes things more clear I think
I don’t know when and why exactly, but we dropped our 100% test coverage.
I’ve reduced coverall’s required coverage to 97% for the time being. Once fixed, we have to get it back to 100%. Setting is at https://coveralls.io/github/hoodiehq/hoodie-client/settings
See #79 for instructions how to run coverage locally
Branch | Build failing 🚨 |
---|---|
Dependency | uglify-js |
Current Version | 2.8.9 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
As uglify-js is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.
I recommend you give this issue a high priority. I’m sure you can resolve this 💪
The new version differs by 5 commits .
e9920f7
v2.8.10
7e465d4
scan RHS of dropped assignments (#1581)
aa80ee3
remove checkboxes from Issues template
80e8176
explain how to make a proper bug report (#1579)
711f88d
scan assignment value in drop_unused() (#1578)
See the full diff.
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot 🌴
✨ This is a dreamcode question ✨
hoodie.account.id
and add it to each object added by hoodie.store.add
as the .createdBy
property?Here is a suggestion: we could add a .validate
function to hoodie-client-store together with an options.validate
argument that can be passed to the constructor, like we have it in hoodie-client-account
That validate function could not only throw custom errors and prevent store.add
& store.update
, it could also alter data. For example, in our Hoodie Tracker App we only have documents with the properties amount
and note
. Instead of throwing an error if amount
is not a number, we could try to parse if a string was entered, and only if that fails, we would throw an error.
With that in place, we could alter the data by adding a .createdBy
property. We could even use that to move the .updatedAt
, .createdAt
, .deletedAt
timestamps that are currently implemented in pouchdb-hoodie-api and instead implement them with the validate function.
So dreamcode for the hoodie.store part of the Hoodie constructor would look like this:
var store = new CustomStore(dbName, {
validate: function (properties, existingObject) {
// existingObject is undefined if it’s an `add`. For `.update` and `.remove` it’s set
// to the properties of the existing object in store
// directly mutates properties before it’s saved
properties.createdBy = properties.createdBy || account.id
// optionally we could allow to return a promise for async validations
},
ajax: function () { /* ... */ }
)
Let me know what you think
When signing in, the hoodie.account.id
changes so the local store needs to be reset (and existing data needs to be cleared). For that we can use the new store.reset({name: hoodie.account.id})
method
"hoodie-client-store"
version in package.json to the latest (4.0.0
right now) and commit the change with chore(package): hoodie-client-store@^4.0.0
(or whatever is the current version) unless it’s already updatedsignin
event handler in index.js, add store.reset(options).then(store.connect)
. That resets the store, and once finished, connects the new store to the new remote of the signed in userfix: reset store on signin
If you have any questions, ping us at http://hood.ie/chat/ or https://twitter.com/hoodiehq
var url = hoodie.url
// url is something like http://example.com/hoodie
using a getter
The Constructor accepts an optional url
option, which is the base URL to a hoodie server. If it’s not set, it defaults to location.origin
.
Example 1:
// given the current URL is http://localhost:1234/foo/bar
var hoodie = new Hoodie()
hoodie.url // http://localhost:1234/hoodie
Example 2:
var hoodie = new Hoodie({
url: 'https://myhoodieserver.com'
})
hoodie.url // https://myhoodieserver.com/hoodie
This issue is reserved for participants of Welcome to Open Source, Atlanta.
If it’s still available after April 2nd, it’s all yours :)
In the testing section of this repository’s README we tell the user to clone the repository using git clone [email protected]:hoodiehq/hoodie-client.git
. But GitHub itself recommends the https://
protocol instead of the git@
which is SSH (see which remote should I use).
Replace the git clone [email protected]:hoodiehq/hoodie-client.git
with https://github.com/hoodiehq/hoodie-client.git
in the README
If this is your first, welcome 🎉 😄 Here is a great tutorial on how to send a pull request
README.md
file.docs(README): fixed git clone URL
closes #68
in the description of the pull requestPing us in the Hoodie Chat or on Twitter if you have any questions :)
I’ve published a new version with a fix: https://github.com/hoodiehq/hoodie-client-store/releases/tag/v3.0.2
When I install Hoodie, I don’t get the fix, because hoodie-client
gets build on publish, and it does not get published when a sub library gets released.
Any idea how to handle this?
to reproduce
npm run build
cat dist/hoodie.min.js | pbcopy
Open http://example.com/, open console, paste, enter
window.Hoodie
is undefined.
Doing
cat dist/hoodie.js | pbcopy
and pasting works as expected
moved to hoodiehq/camp#101
This one is tricky.
The problem is, that hoodie.store.clear()
gets called on the signout event, which calls PouchDB’s db.destroy(). After a PouchDB instance called .destroy()
, it can no longer be used, so we need to instantiate a new instance.
hoodie.store is using hoodie.account.id
as part as its name. As hoodie.acount.id
changes after signOut, we would need an entirely new instance of hoodie.store, but without loosing all the event bindings.
I’m not sure what the best way is to approach that problem
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.