Account client API for the browser
hoodie-client-account
is a JavaScript front-end client for
the Account JSON API.
It persists session information in localStorage and provides
front-end friendly APIs for things like creating a user account,
confirming, resetting a password, changing profile information,
or closing the account.
There is also an admin-specific account client
// Account loaded via <script> or require('hoodie-client-account')
var account = new Account('https://example.com/account/api')
if (account.isSignedIn()) {
renderWelcome(account)
}
account.on('signout', redirectToHome)
- Constructor
- account.id
- account.username
- account.validate
- account.isSignedIn
- account.hasInvalidSession
- account.signUp
- account.signIn
- account.signOut
- account.destroy
- account.get
- account.fetch
- account.update
- account.profile.get
- account.profile.fetch
- account.profile.update
- account.request
- account.on
- account.one
- account.off
- Events
- Requests
new Account(options)
Argument | Type | Description | Required |
---|---|---|---|
options.url |
String | Path or full URL to root location of the account JSON API | Yes |
options.id |
String | The initial account id can be passed. Useful for apps that can be used locally without an account. | Defaults to random id |
options.cacheKey |
String | Name of localStorage key where to persist the session state. | Defaults to \account |
options.validate |
Function | Optional function to validate account before sending sign up / sign in / update requests | No |
Returns account
API.
Example
new Account({
url: '/api',
id: 'user123',
cacheKey: 'myapp.session',
validate: function (options) {
if (options.username.length < 3) {
throw new Error('Username must have at least 3 characters')
}
}
})
Read-only. Returns the account id. If accessed for the first time, a new id gets generated and persisted in localStorage.
Read-only. Returns the username if signed in, otherwise undefined
.
Calls the function passed into the Constructor.
Returns a Promise that resolves to true
by default
account.validate(options)
Argument | Type | Required |
---|---|---|
options.username |
String | No |
options.password |
String | No |
options.profile |
Object | No |
Resolves with an argument.
Rejects with any errors thrown by the function originally passed into the Constructor.
Example
var account = new Account({
url: '/api',
cacheKey: 'app.session',
validate: function (options) {
if (options.password.length < 8) {
throw new Error('password should contain at least 8 characters')
}
}
})
account.validate({
username: 'DocsChicken',
password: 'secret'
})
.then(function () {
console.log('Successfully validated!')
})
.catch(function (error) {
console.log(error) // should be an error about the password being too short
})
Returns true
if user is currently signed in, otherwise false
.
account.isSignedIn()
Checks account.session.invalid
property.
Returns true
if user has invalid session, otherwise undefined
.
account.hasInvalidSession()
Creates a new user account on the Hoodie server. Does not sign in the user automatically, account.signIn must be called separately.
account.signUp(accountProperties)
Argument | Type | Required |
---|---|---|
accountProperties.username |
String | Yes |
accountProperties.password |
String | Yes |
Resolves with accountProperties
:
{
"id": "account123",
"username": "pat",
"createdAt": "2016-01-01T00:00.000Z",
"updatedAt": "2016-01-01T00:00.000Z"
}
Rejects with:
InvalidError |
Username must be set |
---|---|
SessionError |
Must sign out first |
ConflictError |
Username <username> already exists |
ConnectionError |
Could not connect to server |
Example
account.signUp({
username: 'pat',
password: 'secret'
}).then(function (accountProperties) {
alert('Account created for ' + accountProperties.username)
}).catch(function (error) {
alert(error)
})
🐕 Implement account.signUp with profile: {...} option: #11
Creates a user session
account.signIn(options)
Argument | Type | Description | Required |
---|---|---|---|
options.username |
String | - | Yes |
options.password |
String | - | Yes |
Resolves with accountProperties
:
{
"id": "account123",
"username": "pat",
"createdAt": "2016-01-01T00:00.000Z",
"updatedAt": "2016-01-02T00:00.000Z",
"profile": {
"fullname": "Dr. Pat Hook"
}
}
Rejects with:
UnconfirmedError |
Account has not been confirmed yet |
---|---|
UnauthorizedError |
Invalid Credentials |
Error |
A custom error set on the account object, e.g. the account could be blocked due to missing payments |
ConnectionError |
Could not connect to server |
Example
account.signIn({
username: 'pat',
password: 'secret'
}).then(function (sessionProperties) {
alert('Ohaj, ' + sessionProperties.account.username)
}).catch(function (error) {
alert(error)
})
Deletes the user’s session
account.signOut()
Resolves with sessionProperties
like account.signin,
but without the session id:
{
"account": {
"id": "account123",
"username": "pat",
"createdAt": "2016-01-01T00:00.000Z",
"updatedAt": "2016-01-02T00:00.000Z",
"profile": {
"fullname": "Dr. Pat Hook"
}
}
}
Rejects with:
Error |
A custom error thrown in a before:signout hook |
---|
Example
account.signOut().then(function (sessionProperties) {
alert('Bye, ' + sessionProperties.account.username)
}).catch(function (error) {
alert(error)
})
Destroys the account of the currently signed in user.
account.destroy()
Resolves with sessionProperties
like account.signin,
but without the session id:
{
"account": {
"id": "account123",
"username": "pat",
"createdAt": "2016-01-01T00:00.000Z",
"updatedAt": "2016-01-02T00:00.000Z",
"profile": {
"fullname": "Dr. Pat Hook"
}
}
}
Rejects with:
Error |
A custom error thrown in a before:destroy hook |
---|---|
ConnectionError |
Could not connect to server |
Example
account.destroy().then(function (sessionProperties) {
alert('Bye, ' + sessionProperties.account.username)
}).catch(function (error) {
alert(error)
})
Returns account properties from local cache.
account.get(properties)
Argument | Type | Description | Required |
---|---|---|---|
properties |
String or Array of strings | When String, only this property gets returned. If array of strings, only passed properties get returned | No |
Returns object with account properties, or undefined
if not signed in.
Examples
var properties = account.get()
alert('You signed up at ' + properties.createdAt)
var createdAt = account.get('createdAt')
alert('You signed up at ' + createdAt)
var properties = account.get(['createdAt', 'updatedAt'])
alert('You signed up at ' + properties.createdAt)
Fetches account properties from server.
account.fetch(properties)
Argument | Type | Description | Required |
---|---|---|---|
properties |
String or Array of strings | When String, only this property gets returned. If array of strings, only passed properties get returned. Property names can have `.` separators to return nested properties. | No |
Resolves with accountProperties
:
{
"id": "account123",
"username": "pat",
"createdAt": "2016-01-01T00:00.000Z",
"updatedAt": "2016-01-02T00:00.000Z"
}
Rejects with:
UnauthenticatedError |
Session is invalid |
---|---|
ConnectionError |
Could not connect to server |
Examples
account.fetch().then(function (properties) {
alert('You signed up at ' + properties.createdAt)
})
account.fetch('createdAt').then(function (createdAt) {
alert('You signed up at ' + createdAt)
})
account.fetch(['createdAt', 'updatedAt']).then(function (properties) {
alert('You signed up at ' + properties.createdAt)
})
Update account properties on server and local cache
account.update(changedProperties)
Argument | Type | Description | Required |
---|---|---|---|
changedProperties |
Object | Object of properties & values that changed. Other properties remain unchanged. | No |
Resolves with accountProperties
:
{
"id": "account123",
"username": "pat",
"createdAt": "2016-01-01T00:00.000Z",
"updatedAt": "2016-01-01T00:00.000Z"
}
Rejects with:
UnauthenticatedError |
Session is invalid |
---|---|
InvalidError |
Custom validation error |
ConflictError |
Username <username> already exists |
ConnectionError |
Could not connect to server |
Example
account.update({username: 'treetrunks'}).then(function (properties) {
alert('You are now known as ' + properties.username)
})
account.profile.get()
Returns profile properties from local cache.
account.profile.get(properties)
Argument | Type | Description | Required |
---|---|---|---|
properties |
String or Array of strings | When String, only this property gets returned. If array of strings, only passed properties get returned. Property names can have `.` separators to return nested properties. | No |
Returns object with profile properties, or undefined
if not signed in.
Examples
var properties = account.profile.get()
alert('Hey there ' + properties.fullname)
var fullname = account.profile.get('fullname')
alert('Hey there ' + fullname)
var properties = account.profile.get(['fullname', 'address.city'])
alert('Hey there ' + properties.fullname + '. How is ' + properties.address.city + '?')
Fetches profile properties from server.
account.profile.fetch(options)
Argument | Type | Description | Required |
---|---|---|---|
properties |
String or Array of strings | When String, only this property gets returned. If array of strings, only passed properties get returned. Property names can have `.` separators to return nested properties. | No |
Resolves with profileProperties
:
{
"id": "account123-profile",
"fullname": "Dr Pat Hook",
"address": {
"city": "Berlin",
"street": "Adalberststraße 4a"
}
}
Rejects with:
UnauthenticatedError |
Session is invalid |
---|---|
ConnectionError |
Could not connect to server |
Examples
account.fetch().then(function (properties) {
alert('Hey there ' + properties.fullname)
})
account.fetch('fullname').then(function (fullname) {
alert('Hey there ' + fullname)
})
account.fetch(['fullname', 'address.city']).then(function (properties) {
alert('Hey there ' + properties.fullname + '. How is ' + properties.address.city + '?')
})
Update profile properties on server and local cache
account.profile.update(changedProperties)
Argument | Type | Description | Required |
---|---|---|---|
changedProperties |
Object | Object of properties & values that changed. Other properties remain unchanged. | No |
Resolves with profileProperties
:
{
"id": "account123-profile",
"fullname": "Dr Pat Hook",
"address": {
"city": "Berlin",
"street": "Adalberststraße 4a"
}
}
Rejects with:
UnauthenticatedError |
Session is invalid |
---|---|
InvalidError |
Custom validation error |
ConnectionError |
Could not connect to server |
Example
account.profile.update({fullname: 'Prof Pat Hook'}).then(function (properties) {
alert('Congratulations, ' + properties.fullname)
})
Sends a custom request to the server, for things like password resets, account upgrades, etc.
account.request(properties)
Argument | Type | Description | Required |
---|---|---|---|
properties.type |
String | Name of the request type, e.g. "passwordreset" | Yes |
properties |
Object | Additional properties for the request | No |
Resolves with requestProperties
:
{
"id": "request123",
"type": "passwordreset",
"contact": "pat@example.com",
"createdAt": "2016-01-01T00:00.000Z",
"updatedAt": "2016-01-01T00:00.000Z"
}
Rejects with:
ConnectionError |
Could not connect to server |
---|---|
NotFoundError |
Handler missing for "passwordreset" |
InvalidError |
Custom validation error |
Example
account.request({type: 'passwordreset', contact: 'pat@example.com'}).then(function (properties) {
alert('A password reset link was sent to ' + properties.contact)
})
account.on(event, handler)
Example
account.on('signin', function (accountProperties) {
alert('Hello there, ' + accountProperties.username)
})
Call function once at given account event.
account.one(event, handler)
Example
account.on('signin', function (accountProperties) {
alert('Hello there, ' + accountProperties.username)
})
Removes event handler that has been added before
account.off(event, handler)
Example
hoodie.off('connectionstatus:disconnected', showNotification)
Event | Description | Arguments |
---|---|---|
signup |
New user account created successfully | accountProperties with .session property |
signin |
Successfully signed in to an account | accountProperties with .session property |
signout |
Successfully signed out | accountProperties with .session property |
passwordreset |
Email with password reset token sent | |
unauthenticate |
Server responded with "unauthenticated" when checking session | |
reauthenticate |
Successfully signed in with the same username (useful when session has expired) | accountProperties with .session property |
update |
Successfully updated an account's properties | accountProperties with .session property |
Hoodie comes with a list of built-in account requests, which can be disabled, overwritten or extended in hoodie-server-account
When a request succeeds, an event with the same name as the request type gets
emitted. For example, account.request({type: 'passwordreset', contact: 'pat@example.com')
triggers a passwordreset
event, with the requestProperties
passed as argument.
passwordreset |
Request a password reset token |
---|
In Node.js
Run all tests and validate JavaScript Code Style using standard
npm test
To run only the tests
npm run test:node
Have a look at the Hoodie project's contribution guidelines. If you want to hang out you can join our Hoodie Community Chat.