DTS API client
Installation
npm i --save dts-api-client
Package can be consumed in Webpack and Node.js environments.
Webpack setup
If you need to use the upload client in a Webpack application, use the following configuration:
config.resolve = {
alias: {
'aws-sdk': 'aws-sdk/dist/aws-sdk.min.js'
}
};
Ignore the packages that you don't need completely to reduce the footprint:
config.plugins = [
new webpack.IgnorePlugin(/^(aws-sdk)$/), //If you don't use the upload client
new webpack.IgnorePlugin(/^(jquery)$/), //If you don't use the legacy client
new webpack.IgnorePlugin(/^(socketcluster-client)$/), //If you don't use the socket client
];
Configuration
If you don't use some of the clients (e.g. the upload client), set the related configuration section to a false key.
Not set configuration properties will use the default configuration.
import DtsApi from 'dts-api-client';
/* Application configuration */
const application = {
"client_id": "d04ad813dac443b28a490ddca27b9178",
"security": "oauth",
"redirect_uri": "https://web.snap.menu/"
};
/* Client configuration */
const client = new DtsApi.Client({
/* All client configs and keys are optional */
//API client configuration
api: {
host: 'api.managesnap.com',
secure: true,
path: '/frontend/',
application: application //Optional, defaults to { security: 'oauth' }
},
//Alternative API configuration (with Swagger object):
/*
api: {
spec: require('./swagger.json')
},
*/
//CDN client configuration
cdn: {
host: 'cdn.snap.menu',
secure: false,
path: '/',
application: application
},
//Socket client configuration
socket: {
host: 'socket.managesnap.com',
secure: true,
path: '/snap/',
application: application
},
//Partial configuration example:
//Legacy client configuration
legacy: {
host: 'api-jwt.managesnap.com'
//See? No secure or path here
},
//Exclude client example:
//Upload client configuration
upload: false
});
/* Manager configuration */
const manager = new DtsApi.Manager([
application
])
Usage Example
class Application {
constructor(mainApplication, client, manager) {
this._mainApplication = mainApplication;
this._client = client;
this._manager = manager;
}
//An OAuth callback is received (i.e. check current URL on application launch)
oauthCallback(application, data) {
//Create new token to save
let token = {
access_token: data.access_token,
refresh_token: data.refresh_token,
expires_in: data.expires_in
};
this._saveToken(token, application);
}
//Watch for API token events
watchAuthentication() {
this._manager.tokenExpiring.add((token, application) => this._refreshToken(token, application));
this._manager.tokenExpired.add((token, application) => this._refreshToken(token, application));
}
_refreshToken(token, application) {
return this.client.api.request('oauth2', 'grantToken', {
grant_type: 'refresh_token',
client_id: application.client_id,
refresh_token: token.refresh_token
})
.then(token => {
console.log('OAuth token refreshed', token);
this._saveToken(token, application);
})
.catch(e => {
console.error('Unable to refresh an OAuth token.', e);
if (this._manager.isAccessValid(application)) {
console.warn('Falling back to an existing OAuth token.');
return Promise.resolve();
}
return Promise.reject(e);
});
}
_saveToken(token, application) {
this._client.authorize(application, token);
this._manager.saveToken(application, token);
}
//Enable WebSocket connections and listen to client events
configureWebSocket() {
this._client.socket.isEnabled = true; //Explicitly indicate when you need a WebSocket connection
console.log('WebSocket is connected:', this._client.socket.isConnected);
this._client.socket.isConnectedChanged.add(isConnected => console.log('WebSocket is connected:', isConnected));
this._client.socket.onError.add(err => console.error('WebSocket error:', err));
}
//Restore authentication on application startup
startup() {
return this._manager.applications.reduce((promise, application) => {
let token = this._manager.getToken(application); //Read active token
//Check if refresh token has not expired
if (!this._manager.isAccessValid(application)) {
//No refresh token found
if (!token || !token.refresh_token) {
return promise;
}
return promise.then(() => {
console.log(`Refreshing access for '${application.client_id}'...`);
return this.refreshAccess(application)
.then(() => console.log(`Access for '${application.client_id}' has been refreshed.`))
.catch(e => {
console.warn(`Unable to refresh access for '${application.client_id}'`, e);
return Promise.resolve();
});
});
}
// Optional: authenticate Raygun with the current API user
//
// if (application === this._mainApplication) {
// let metadata = this._manager.getTokenMetadata(token);
// Raygun.setUser(metadata.location, false, undefined, undefined, undefined, metadata.device);
// }
return promise.then(() => this._client.authorize(application, token));
}, Promise.resolve());
}
//Check if API token is valid
get isAccessValid() {
let token = this._manager.getToken(this._mainApplication);
if (!token || !token.refresh_token) {
return false;
}
return this._manager.isAccessValid(this._mainApplication);
}
//Get an OAuth authorization URL to redirect when an API token is not valid
authorize() {
return this._client.api.getAuthorizationUrl(this._mainApplication)
.then(url => window.location = url);
}
//Call API
loadLocationInfo(id) {
return this._client.api.request('asset', 'assetLocationRead', { token: id });
}
//Load data from CDN
loadData() {
return this._client.cdn.load('deployment/847429c4-bb61-40b5-b3fa-a4a50151030c/4a69171b-9b85-416f-af2e-71739ed865e2.json');
}
//Load data from CDN as a binary blob
loadBinary() {
return this._client.cdn.loadBinary('version/2b8cd287-d93c-455e-a1ef-a4b100f06550_470_410.jpg');
}
//Subscribe to a WebSocket topic
listenToTopic() {
this._client.socket.subscribe('location_847429c4-bb61-40b5-b3fa-a4a50151030c', message => {
console.log(message);
});
}
//Send a WebSocket message to a topic
publishToTopic(message) {
this._client.socket.publish('location_847429c4-bb61-40b5-b3fa-a4a50151030c', message);
}
//Send a WebSocket event
sendEvent(message) {
this._client.socket.emit('some_event', message);
}
}