Getting started

Shapes SDK exists t to provide clear methods for requesting and storing profile data, managing the state of this data and emitting events to subscribed components, on update. It also handles all caching of data and merging of resource requests, to avoid unecessary requests;

Installing

Using npm:

$ npm install @omneo/shapes-sdk

Using yarn:

$ yarn add @omneo/shapes-sdk

Using CDN:

<script type="text/javascript" src="https://cdn.omneo.io/shapes-sdk/shapes.sdk.js"></script>

When including ShapesSDK from the CDN, the library will be attached to the window and accessible at window.ShapesSDK. When including from npm/yarn ShapesSDK can be used via ES6 import or ES5 require:

import ShapesSDK from '@omneo/shapes-sdk'
var ShapesSDK = require('@omneo/shapes-sdk')

ShapesSDK.init()

Returns a client object

When initializing the ShapesSDK, the init function requires an Omneo ID (or proxy) url url and an Omneo ID token token. The constructor also allows an optional flag to be set, to enable console logging, for debugging logging

var shapesClient = ShapesSDK.init({
    url: 'https://api.{environment}.getomneo.com/id', 
    token: '{omneo_id_token}',
    logging: true
})

Some implementations may use a proxy url, please check with your Omneo implementation partner to confirm this.

Omneo ID token must first be generated by a secure server process. If you are using an Omneo eCommerce plugin, the token will be generated on login and added to a metafield

Client Object

One initialised the shapesClient object exposes a number of methods for retrieving cached profile data, handling requests to Omneo and subscribing to state updates. All methods interact with the client data state, which follows this structure:

{
    "client_id": uuid,
    "loading": boolean,
    "profile": {
        "init": true,
        "error": false, 
        "loading": false,
        "data": {
            "id": "8e697f6b-533d-4837-8680-e7c6b3cde9f0",
            "first_name": "John",
            "last_name": "Smith",
            ...
        }
    }
}

Methods

.find()

Traverses and returns value from the shapes data state, using a path in dot . format.

Arguments

path - Dot notation path to data in state

Returns

Value from existing shapesClient state. If no value is found, null is returned.

Note

This method is not responsible with fetching new data. When shapesClient loads, it will pull all cached data and a fresh set of top level profile data. If an endpoint such as transactions is required, register this with the hydrate() method below, which will then fetch from the Omneo API.

Example

let transactions = shapesClient.find('transactions'); // Get all 
transactions
let combined_balance = shapesClient.find('balances.combined_balance_dollars') // Get first transaction by index
let loading = shapesClient.find('loading'); // Get loading state
let state = shapesClient.find(); // Get shapes state

.hydrate()

Registers that shapesClient must retrieve the given endpoint. If the data has not already been fetched, shapesClient will get this data from Omneo and merge it into the client state. Once initialized, shapesClient will then emit the relevant shapes.{endpoint}.ready event.

Arguments

  • path - Dot notation path to endpoint

Returns

true if there were no exceptions. All updates should be watched for through the .on() method

Example

shapesClient.hydrate('transactions')
shapesClient.hydrate('profile')
shapesClient.hydrate('lists')

.on()

Allows you to add handlers to a shapesClient event. You can register multiple handlers to the same event, by calling this function for each. Each time the event with event_name is triggered, all handlers for this name will be called with event data passed as an argument.

For available events, see Events

Arguments

  • event_name - Dot notation event name
  • handler - Function with single data argument, to be executed on event

Returns

The value of that event's relevant endpoint. Note that list endpoints are transformed into keyed objects for ease of state management.

Example

let handler = function(data){
    console.log(data);
};

let profile = shapesClient.on('profile.update', handler);

// console.log
// {
//     "init": true,
//     "error": false, 
//     "loading": false,
//     "data": {
//         "id": "8e697f6b-533d-4837-8680-e7c6b3cde9f0",
//         "first_name": "John",
//         "last_name": "Smith",
//         ...
//     }
// }

.off()

Allows you to remove a handler for a shapesClient event.

For available events, see Events

Arguments

  • event_name - Dot notation event name
  • handler - Function with single data argument, to be executed on event

Returns

true if event listener was unregistered correctly

Example

let handler = function(data){
    // Do something with data
};

shapesClient.off('profile.update', handler);

.dispatch()

Dispatches an action directly to the internal store to manually manage state. The internal store reducer handles a number of action types.

[resource].update

Will merge the payload into the top level resources. Special consideration is given to data so it will be merged and not overwrite the existing state. Ensure that for resources such as transactions the array of items has been converted to an object with id as key.

{
    "type": "profile.update", 
    "payload": {
        "error": false,
        "data": {
            "first_name": "John"
        }
    }
}

[resource].add

An alias of update that is used when adding new items to resource lists, such as rewards or transactions

[resource].remove

Removes a key from the {resource}.data object by specifying the key in the payload

{
    "type": "transaction.remove", 
    "payload": {
        "id": "5"
    }
}

[resource].set

Merges the payload against the whole state object. Special provisions are not made for data and anything included in the set payload will overwrite the existing state. This is especially useful if you are managing the whole state manually.

{
    "type": "lists.set", 
    "payload": {
        "init": true,
        "loading": false,
        "data": {
            "5": {...},
            "27": {...}
        }
    }
}

[resource].load

Sets the loading state of a resource. This does not merge any other payload keys. This is useful for setting loading: true before a http request etc.

{
    "type": "profile.load", 
    "payload": {
        "loading": true
    }
}

[resource].reset

Resets the resource back to the initial state of the reducer. Useful for clearing if cached data is malformed or if there has been an error.

{
    "type": "lists.reset", 
}

Arguments

Dispatch receives a single action object, with type and payload keys to update the state.

  • type - Action type, using . separator to designate the resource. eg. profile.set
  • payload - Object containing key/values to update in state. Refer to the action types for examples and accepted keys for each type

Returns

undefined

Example

shapesClient.dispatch({
    type: 'profile.update',
    payload: {
        data: {
            first_name: "John",
            last_name: "Smith",
            email: "john@example.com"
        }
    }
})

shapesClient.dispatch({
    type: 'transacitons.add',
    payload: {
        data: {
            "5":{
                id: 5,
                items: [...]
            }
        }
    }
})

shapesClient.dispatch({
    type: 'lists.remove',
    payload: {
        data: {
            id: 5
        }
    }
})

Requests

Shapes provides methods for making authenticated requests to all profile endpoints in Omneo. In addition, the shapes requests methods allow for automatic updating of top level profile objects such as transactions

Note

Currently the Request methods do not support automatic state updates of deeply nested objects, such as items within a list eg. lists.1.items.4

Methods

// GET
shapesClient.get(path, params, updateState)

// POST
shapesClient.put(path, data, updateState)

// PUT
shapesClient.post(path, data, updateState)

// DELETE
shapesClient.delete(path, false, updateState)

Arguments

  • path - Dot notation path to endpoint
  • data - Body payload for PUT and POST requests
  • params - GET parameters, used to filter and paginate browse/list requests
  • updateState - A boolean flag automatically merge request response into the state and emit update events to all subscribers.

Returns

A JavaScript Promise object. Once resolved, this method will return the value of that endpoint.

Example

shapesClient.get('profile').then(response=>{
    // Do something with profile data
})
shapesClient.post('profile', { first_name: "James" }, true).then(response=>{
 // Profile object with updated "new_name" field
})
shapesClient.put('lists.6', { id: 2, title: 'New List Item' }, true).then(() => {
  // Added new item to a list with the id of 6
})
shapesClient.delete('list.6', true).then(response => {
  // Delete entire list with id of 6
  // response.status = 204 no content
})

Events

As the shapesClient manages all state and requests internally, it exposes a number of events to keep subscribed components up to date. These events are emitted through 2 differend streams. The first is to subscribers of shapesClient.on('{event_name}') and the second is to the native browser js Event() handler.

Note: In addition to the methods below, the shapesClient also emits all events to the document as custom named events.

Event structure

Events are defined by an event type and payload. Shapes will emit general events for when the client is initialized and for any state update. It will also emit events for profile.ready and profile.update as well as ready and update events for all individual endpoints. Events will include the UUID for the shapesClient as well as a loading indicator to confirm if an update event represents a loading state for that state object.

Event types

  • shapes.ready
  • shapes.update
  • shapes.{endpoint}.ready
  • shapes.{endpoint}.load
  • shapes.{endpoint}.update

shapes.{event_type}

{
    "client_id": uuid,
    "profile":{
        "init": true,
        "error": false, 
        "loading": false,
        "data": {...}
    },
    "transactions":{
        "init": true,
        "error": false, 
        "loading": false,
        "data": {...}
    },
    ...
}

shapes.{resource}.{event_type}

{
    "init": true,
    "error": false, 
    "loading": false,
    "data": {
        "id": "8e697f6b-533d-4837-8680-e7c6b3cde9f0",
        "first_name": "John",
        "last_name": "Smith",
        ...
    }
}