RICADO Gen 4 API client for NodeJS and Browsers
- Written in modern JavaScript. Tested for NodeJS 16+ and Browsers
- Includes Typings for Typescript
- Complete support for the RICADO Gen 4 API - OpenAPI Documentation
- Perfect symmetry: JS method signatures match the Web API Docs
- All methods return a
Promise
- The Authentication Token is automatically handled on all methods
NOTE: All examples written in this README use the NodeJS (ES5) Specification.
Documentation for the latest Stable Release can be found here: ricado-group.github.io/js-api-client
npm install @ricado/api-client
The src
folder contains ESNext code.
The dist
folder contains ES6 transpiled code and is the default export for this module.
@ricado/api-client
mirrors the published API Docs. All interaction is through stateless functions in Controllers.
const api = require('@ricado/api-client');
api.initialize();
api.userAccountLogin('user@ricado.co.nz', 'abcd1234')
.then(jwt => console.log(jwt))
.catch(error => console.log(error));
api.Controllers.UserAccountController.getCurrent()
.then(userAccount => console.log("Logged in as `" + userAccount.firstName + " " + userAccount.lastName))
.catch(error => console.log(error));
Using async/await
in Node 8.x or newer:
const api = require('@ricado/api-client');
;(async function() {
var userAccount = await api.Controllers.UserAccountController.getCurrent();
console.log("Hello! I'm " + userAccount.firstName);
})();
NOTE: A Promise
will only resolve if there was no issue that needs dealing with. See Error Handling
below for examples.
Your first step will be to import the API Client module and Initialize the API before any use.
const api = require('@ricado/api-client');
api.initialize();
The api.initialize()
method can also support an existing JSON Web Token. This is useful if you are persisting the JSON Web Token in your app and would like to skip the Login (Generate a new JWT) process.
const api = require('@ricado/api-client');
let jwt = myFunctionThatGetsTheJWT();
api.initialize(jwt);
You'll need to Login (Generate a new JWT) before you can make any API Calls (except for /ping of course!)
To Login a User Account:
let email = 'name@ricado.co.nz';
let password = 'abcd1234';
api.userAccountLogin(email, password)
.then((jwt) => {
console.log("Signed In!");
// NOTE: You may wish to persist this jwt somewhere in your app for future use!
})
.catch((error) => {
console.log("Failed to Sign In!");
console.log(error);
});
To Login an API Account:
let key = 'myapikey';
let secret = 'myapisecret';
api.apiAccountLogin(key, secret)
.then((jwt) => {
console.log("Ready to go!");
// NOTE: You may wish to persist this jwt somewhere in your app for future use!
})
.catch((error) => {
console.log("Failed to Sign In!");
console.log(error);
});
If you wish to Logout (Destroy existing JWT) there's one simple method to call.
NOTE: Calling this method will Destroy the Token on the API Servers and will clear the locally stored JWT (api.JWT
)
api.logout()
.then(result => console.log("Done!"))
.catch(error => console.log(error));
The API makes use of a concept called "Token Locking" to reduce the risk of a JSON Web Token being copied and used by another party. The API will (at it's own discretion) automatically Lock
the JSON Web Token after a period of inactivity. It is then required to Unlock
the JSON Web Token before any API calls can be successfully resumed. If you make an API call without first unlocking the token, an UnauthorizedError
will be thrown with a message about the Token being Locked.
NOTE: These methods can only be used on Tokens for a User Account
. Tokens for an API Account
will never be locked.
If the User has a Pin Code set, unlock using that Pin Code
let pinCode = 12345;
api.pinCodeUnlock(pinCode)
.then(result => console.log("Unlocked!")) // Remember when the return type is `Promise<boolean>` it will always be `true`!
.catch(error => console.log(error));
If the User doesn't have a Pin Code set, unlock using a Password
let password = "abcd1234";
api.passwordUnlock(password)
.then(result => console.log("Unlocked!"))
.catch(error => console.log(error));
Lock is called without any parameters
api.lock()
.then(result => console.log("Locked!"))
.catch(error => console.log(error));
A Single Model can be retrieved by calling the stateless getOne(id)
function on a Controller. The Single Model is passed back in the Promise.then
method.
let siteId = 1;
api.Controllers.SiteController.getOne(siteId)
.then(site => console.log("Got My Site: " + site.name))
.catch(error => console.log(error));
Models can be updated by calling the stateless update(id, properties)
function on a Controller. When you Update a Single Model, the Updated version of that same Model is passed back in the Promise.then
method.
let siteId = 1;
api.Controllers.SiteController.update(siteId, {name: "My New Site Name"})
.then(site => console.log("The Name is now: " + site.name))
.catch(error => console.log(error));
Models can be deleted by calling the stateless delete(id)
function on a Controller. When you Delete a Single Model, the Promise.then
method will be called if successful, otherwise the Promise.catch
method will be called with the appropriate Error
.
let siteId = 1;
api.Controllers.SiteController.delete(siteId)
.then(result => console.log("Deleted!"))
.catch(error => console.log(error));
A Collection of Models (all) can be retrieved by calling the stateless getAll()
function on a Controller. The Model Collection is passed back in the Promise.then
method.
api.Controllers.SiteController.getAll()
.then((sites) => {
sites.forEach((site) => {
console.log("Got another Site: " + site.name);
});
})
.catch(error => console.log(error));
A new Model Object can be created by calling the stateless create(json)
function on a Controller. The newly created Model Object is passed back in the Promise.then
method.
api.Controllers.SiteController.create({name: "My Site Name", companyId: "xyz-xyz-xyz"})
.then(site => console.log("Got my new Site ID: " + site.id))
.catch(error => console.log(error));
NOTE: Refer to the API Documentation for the structures required to create each type of Model.
This API Client provides additional Error Classes that extend the built-in Error
type. All Errors will at minimum define Error.message
. You can also make use of Error.stack
in Node and on most modern browsers.
Errors:
BadRequestError
Used for Response Code 400UnauthorizedError
Used for Response Code 401ForbiddenError
Used for Response Code 403NotFoundError
Used for Response Code 404NotAllowedError
Used for Response Code 405ServerError
Used for Response Code 500NetworkError
Wraps up Errors thrown byfetch
Promise
Example:
api.Controllers.UserAccountController.deleteCurrent()
.then(result => result ? console.log("Success!") : console.log("Uh-oh!"))
.catch((error) => {
// This Error should be one of the Above Errors or a generic `Error` type.
console.log("Error Message: " + error.message);
console.log("Error Stack: " + error.stack);
});
async/await
Example:
async function deleteApiAccount(id) {
try
{
var result = await api.Controllers.ApiAccountController.delete(id);
result ? console.log("Success!") : console.log("Uh-oh!");
}
catch (error)
{
// This Error should be one of the Above Errors or a generic `Error` type.
console.log("Error Message: " + error.message);
console.log("Error Stack: " + error.stack);
}
}
Example: Retrieving a Collection of Users
api.Controllers.UserAccountController.getAll()
.then((users) => {
// The `users` variable will always be set and will at minimum be an empty Array `[]`. There isn't a need to check that users is defined and that is is in-fact an Array.
users.forEach(user => console.log("Got " + user.firstName + " " + user.lastName));
})
.catch((error) => {
/**
* `.catch(error)` will always be called if something went wrong
*
* - A network error occured
* - You might not be logged in or have a locked token
* - The server had an *issue*
*/
console.log(error);
});
Example: Attempting to Retrieve a User that doesn't exist
api.Controllers.UserAccountController.getOne('an-id-that-does-not-exist')
.then((user) => {
// You'll never make it to here as the User does not exist. If the user did exist however, you can always be confident that the `user` variable will be set and will at bare minimum be a `UserAccountModel` object.
console.log("His name is " + user.firstName + " " + user.lastName);
})
.catch((error) => {
/**
* In this example, apart from something like a `NetworkError` we would expect to see a `NotFoundError` to be passed back.
*/
console.log(error);
});
Example: Attempting to Delete a User that doesn't exist
api.Controllers.UserAccountController.delete('an-id-that-does-not-exist')
.then((result) => {
// You'll never make it to here as the User does not exist. If the user did exist however, you can always be confident that the `result` variable will be set and will always be `true` meaning `result === true` will always be the case!
})
.catch((error) => {
/**
* In this example, apart from something like a `NetworkError` we would expect to see a `NotFoundError` to be passed back.
*/
console.log(error);
});
For Node:
npm test
For Browsers:
Yet to be supported!!
Currently this code-base is mostly generated from the PHP API and then hand-edited as required. In the future, we hope this process of generation will happen automatically with the use of a local npm
script!
In the mean-time, if you wish to contribute, please either create a new branch (if you have permission) or fork this repository and submit a pull request.
- Support generating this README.md from a Template so we can inject some code examples and types automatically!