yggio-connect: a wrapper for yggio's REST api.
Through initial configuration, yggio-connect takes care of the boilerplate code necessary to register a service-provider, as well as wrapping all 'routes' with oauth refreshToken functionality (i.e. if an yggio api call fails due to an invalid accessToken, a single attempt at getting a replacement is made using the User's refreshToken). Additionally, some service-provider specific functionality/info is exposed.
Using yggio-connect WITHOUT service-provider functionality:
This is not recommended necessarily, but if yggio-connect is initialized with ONLY a url, then the exports.rawRoutes
IS functional, but ALL of the service-provider boilerplate will need to be implemented externally (ALL service-provider dependent yggio-connect functionality will throw errors).
const yggioConnect = require('yggio-connect');
// rules engine and the yggio rest-api have different urls that need to be supplied
const config = { url: 'yggio-url.com' };
yggioConnect.init(config);
// and the routes are exposed
const routes = yggioConnect.routes;
Note that the routes ARE exposed prior to running yggioConnect.init(config)
, but the individual routes WILL throw errors if the yggio url has not been set.
Using yggio-connect WITH service-provider functionality (recommended):
The primary purpose of yggio-connect is as a one-stop shop to get all the service-provider functionality up and going, which otherwise requires a number of steps. This does necessitate some configuration in addition to just the yggio url.
const yggioConnect = require('yggio-connect');
// rules engine and the yggio rest-api have different urls that need to be supplied
const config = {
// the url needs to be present as earlier
url: 'yggio-url.com',
// the yggio user that 'owns' the service-provider (effectively an admin user)
account: {
username: 'owner@my-service.com', // required -- customize!
password: 'password' // required -- customize!
},
// and all information specific to the service provider
provider: {
name: 'My Service', // required -- customize!
info: 'an optional description', // optional
// the redirectUris ARE required, and can be either an object or array
redirectUris: {
browser: 'my-service-url.com', // at least one entry is required
app: 'fms://login'
},
// the channel is optional. Without it however, yggio does not know how
// to publish device updates to the service-provider, which effectively
// disables all device subscription functionality.
channel: {
url: 'my-service-url.com', // required if channel config included
route: '/my-message-route'
},
logoPath: path.join(__dirname, '../asset/your-company-logo.png') // optional path to logo file
},
// finally a refresh callback function is needed
refreshCallback: async (refreshedUser) => {
// save the refreshToken for the user is generally what you want to
// do here, such as:
return User.findById(refreshedUser._id).exec()
.then(user => {
user.refreshToken = refreshedUser.refreshToken;
return user.save();
});
},
};
// initialize as before, if any part of the config looks wrong, the init will throw an error
await yggioConnect.init(config, providerSecret); // Secret should only be supplied once a provider is registered, it will be ignored otherwise
// and the wrapped routes are now exposed & should be working
const routes = yggioConnect.routes;
routes
and rawRoutes
, there is also an exports.provider
which provides some service-provider specific functionality
Apart from To subscribe to a specific device, given a user (with accessToken and refreshToken)
const subscribe = yggioConnect.provider.subscribe;
// some valid iotnode id that user has read writes to
const yggioId = 'xxx';
// and then use the
return subscribe(user, yggioId);
Once you have gotten an oauth code (through the external oauth process) for a given redirectUri, you can redeem the code in exchange for the corresponding user:
const redeemCode = yggioConnect.provider.redeemCode;
const code = 'xxx'; // the code
const redirectUri = 'xxx'; // same uri specified in the external oauth process
const user = await redeemCode(code, redirectUri);
Additionally, it is possible to inspect the service-provider account and provider objects
// these have additional info retrieved from yggio
const details = yggioConnect.provider.getProviderDetails();
const accountInfo = details.account;
const providerInfo = details.provider;
Available routes
The following routes are available:
const routes = {
// //
// First the routes that do NOT have a user as first parameter
// //
login,
register,
refreshAccessToken,
oauthCode,
// //
// And then the routes that DO have a user as first parameter
// //
// provider
setLogo,
registerProvider,
subscribe,
// iotnodes
command,
getMe,
logoutFromYggio,
getNode,
getNodes,
getAccessibleNodes,
createNode,
updateNode,
deleteNode,
// oauth
checkOAuthStatus,
// states
getRulesStates,
setRulesState,
// rules
getRule,
getRules,
executeRule,
getScenarioTemplates,
createScenario,
getRulesConditions,
updateRulesCondition,
createRulesCondition,
getRulesActions,
createRulesAction,
updateRulesAction,
deleteRulesAction,
createRule,
deleteRule,
updateRule,
addRuleTrigger,
addRuleEvent,
// Contacts
getContacts,
setContacts,
};
// a User object should have the following shape.
// only the accessToken is required.
// if refreshToken is not supplied, the refresh is never attempted.
const user = {
// an access token is required
accessToken: 'xxx',
// a refresh token is required for refresh (if desired..)
refreshToken: 'xxx',
// when using 'exports.routes', and the refreshCallback is called
// it can be nice to have an external identifier oter than the tokens
serviceId: 'xxx',
otherField: 'additional keys just get copied and returned',
};
Warning: expect breaking changes between minor versions
It is likely that some of the functionality will be changed/removed/renamed
License
yggio-api is under the MIT license. See LICENSE file.