Quickstart
This quickstart aims to present all the main features of Wakanda Client, and how they works. The API is very close to the Angular-Wakanda one, so if you already know it, you will be on a known field.
All asynchronous methods return a promise, so you'll have to be familiar with it to use Wakanda Client.
On a browser or on node, Wakanda Client is used the same. The only thing that differs is the way you include it on your projet. As it's exposed as a UMD module, you're free to use a various panel of module loader, or even this good old global variable on browser to use it.
On node for example
var WakandaClient = require('wakanda-client');
On a browser
<script src="/path/to/wakanda-client.min.js"></script>
Then, simply instantiate it. You have to pass an URI to indicate where is your Wakanda Server. On browser, you can omit this parameter, then all requests will be done on /rest/...
address, so it's on you to proxy it to your Wakanda Server.
var wakanda = new WakandaClient.WakandaClient('http://localhost:8081');
You can also import exposed classes with import
command.
import {WakandaClient} from 'wakanda-client';
let client = new WakandaClient();
On next examples, wakanda
variable will designate an instance of WakandaClient
.
Before working with dataClasses, you will need to retrieve it. A set of dataClasses is called a Catalog.
wakanda.getCatalog().then(function (ds) {
//ds (for dataStore) is our catalog, it contains all ours dataClasses. For example:
//ds.Company, ds.Employee, etc.
});
If you want only specific dataClasses, pass an array with dataClasses name to getCatalog
wakanda.getCatalog(['Company']).then(function (ds) {
//ds.Company is defined, but ds.Employee is not
});
On next examples ds
will designate a fully retrieved catalog.
To find an entity with its key, use find
method on a dataClass.
ds.Company.find(6)
.then(function (company) {
//company is an entity, with its properties and framework methods (see next parts for their documentation)
})
.catch(function () {
//company not found
});
You can also find several entities (a collection) with query
method. It takes an optional object as parameter to describe your query (order, expanding, filter, etc).
ds.Company.query({
filter: 'staffCount > :1',
params: [500],
orderBy: 'name'
})
.then(function (companyCollection) {
var firstCompany = companyCollection.entities[0];
});
There are some utility methods on collections (especially for paging), it will be described on the next parts.
save()
method on an entity will create or update it. If there is some server-side processing on the entity, it will be updated when the promise resolves.
ds.Employee.find(4).then(function (employee) {
employee.firstName = 'Jack';
employee.save().then(function () {
//Our entity is updated
});
});
To create an entity, call create()
on the right dataClass, affect values for its properties then save it.
var newCompany = ds.Company.create();
company.name = 'Nice Corp';
company.save();
You can also pass an object as parameter to affect properties at the same time.
var newCompany = ds.Company.create({
name: 'Nice Corp'
});
newCompany.save();
To delete an entity, call delete()
on it.
ds.Company.find(5).then(function (company) {
company.delete().then(function () {
//company is deleted
});
});
Wakanda allows us to manipulate seamlessly related entities. We can affect, retrieve and access related entities with no pain.
On a find or a query, we can use expand
option to eagerly retrieve a related entity or a collection.
//Expanding an entity
ds.Employee.find(4, {expand: 'employer'}).then(function (employee) {
var company = employee.employer;
//company is a fully featured entity, we can manipulate it like the others
});
//Expanding a collection
ds.Company.find({
orderBy: 'name',
expand: 'staff'
})
.then(function (companies) {
var firstCompany = companies.entities[0];
//firstCompany.staff is an employee collection
var firstEmployeeOfTheFirstCompany = firstCompany.staff.entities[0];
});
To access a related entity or collection that have not been expanded, you can to fetch it with fetch()
method. Before being fetched (or expanded), it's considered as deferred.
ds.Employee.find(4).then(function (employee) {
employee.employer; //deferred entity
employee.employer.fetch().then(function () {
//employee.employer is now fetched and can be used like any other entity
//it works the same for a collection
employee.employer.staff.fetch().then(function () {
//staff is now filled with its entities
});
});
});
We can affect a related entity as any other scalar type, with an affectation.
ds.Company.find(4).then(function (company) {
var newEmployee = ds.Employee.create({
firstName: 'Jonh',
lastName: 'Smith',
employer: company
};
//or newEmployee.employer = company; It's the same
newEmployee.save();
});
Image and files (blob) can be affected to an entity thanks to upload()
method. This method is present on every attributes of type image
or blob
. upload()
method can only be called on an already saved entity, you can't call it just after a create()
, because the entity has to exist on the server-side.
Considering the following HTML file:
<input type="file" id="fileInput" />
ds.Employee.find(12).then(function (employee) {
var fileInput = document.getElementById('fileInput');
var file = fileInput.files[0];
employee.profilePicture.upload(file).then(function () {
//file is uploaded and entity is updated
});
});
image
and blob
attributes are represented by an object, with the upload()
method, and a uri
property. This property carries the actual URI of the file, if there is one.
ds.Employee.find(12).then(function (employee) {
//employee.profilePicture.uri
});
To delete the current file affected to a image
or blob
attribute, you can call the delete()
method on the property.
ds.Employee.find(12).then(function (employee) {
employee.profilePicture.delete().then(function () {
//The file has been deleted, and detached from the entity
});
});
There are several helpers on collection to make paging or infinite loading an easy task:
-
nextPage()
: get the next page of the collection -
prevPage()
: get the previous page of the collection -
more()
: load a new page and append it to the current collection
Difference between more
and nextPage
is that more will add the retrieved entities to the current entities
array, where nextPage
will replace the actual entities with the retrieved ones.
All three methods return a promise and change the collection they are called on.
//Next page
ds.Company.query({pageSize: 10}).then(function (collection) {
//When we want to next 10 entities
collection.nextPage().then(function () {
//collection.entities has now the 10 nexts
});
});
//More
ds.Company.query({pageSize: 10}).then(function (collection) {
//When we want 10 entities more (infinite loading you say?)
collection.more().then(function () {
//collection.entities has now the 20 entities
});
});
Obviously, mixing nextPage
and more
will not result on something funny, you don't want to do that.
On Wakanda, you can define methods on the model designer. It can be attached on DataClass, Entity or Collection.
You can directly call theses methods on the object you manipulate with Wakanda Client (excepting collection methods, that will be implemented soon).
//On an entity
ds.Company.find(3).then(function (company) {
company.myEntityMethod().then(function (result) {
//result will contain what have been return by the method (if any)
});
});
//On a dataClass
ds.Company.myDataClassMethod().then(function (result) {
});
If the method defined on the server returns an entity or a collection, Wakanda Client will automatically consider the returned value as an entity or a collection.
ds.Company.methodThatReturnsAnEntity().then(function (result) {
//result is an entity, we can manipulate that like any other entity
result.foo = 'bar';
result.save();
});
Wakanda-Clients allows you to use directory methods to authenticate.
All those methods are accessible with the directory
property of a WakandaClient
instance.
To log in, use login()
method.
wakanda.directory.login('username', 'password')
.then(function () {
//User is logged in
})
.catch(function (e) {
//Login failed. Maybe bad credentials?
});
You can set a duration in seconds as third parameter.
wakanda.directory.login('username', 'password', 86400) //session will be available for 24 hours
To logout, simply use logout()
method.
wakanda.directory.logout()
.then(function () {
//logout with success
});
To get the current user, use currentUser()
method.
wakanda.directory.currentUser()
.then(function (user) {
//user.userName, user.fullName, user.ID
});
To check if the current user belongs to a specific group, use currentUserBelongsTo()
method.
wakanda.directory.currentUserBelongsTo('Admin')
.then(function (result) {
console.log('You are ' + (result ? '' : 'not ') + 'an admin');
});