
happner-client
The client for happner-2 and happner cluster services.
npm install happner-client
Usage
Create client instance.
var HappnerClient = require('happner-client');
var client = new HappnerClient({
requestTimeout: 10 * 1000,
responseTimeout: 20 * 1000,
logger: null
});
Connect
var optionalInfo = {
}
client.connect(
{
host: 'localhost',
port: 55000
},
{
protocol: 'https',
username: '_ADMIN',
password: 'happn',
allowSelfSignedCerts: true,
info: {}
}
).then(...).catch(...);
client.connect(null, {username: '_ADMIN', password: 'happn'}, function (e) {
})
Create and connect
the simpler way: (v12.6 onwards)
const client = await HappnerClient.create({
host: 'localhost',
port: 55000,
username: '_ADMIN',
password: 'xxx'
});
Login with token and logout
it is possible to connect with another clients token, the call to .logout() will invalidate your connection token, and disconnect all clients that have used it to login with:
const connectionOptions = {
host: 'localhost',
port: 55000,
username: '_ADMIN',
};
const client = await HappnerClient.create({ ...connectionOptions, password: 'xxx' });
let token = client.dataClient().session.token;
let otherClient = await HappnerClient.create({ ...connectionOptions, token });
test.expect(otherClient.dataClient().status).to.be(1);
await client.logout();
await test.delay(2e3);
test.expect(otherClient.dataClient().status).to.be(2);
Events
client.on('connected', function () {
});
client.on('reconnected', function () {
});
client.on('disconnected', function () {
});
client.on('reconnecting', function () {
});
client.on('error', function (e) {
});
Construct your API
var kitchenModel = {
fridge: {
version: '^1.0.0',
methods: {
getTemperature: {
params: [
{name: 'shelves', type: 'array'}
]
}
}
}
};
var kitchen = client.construct(kitchenModel);
Use API functions
kitchen.exchange.fridge.getTemperature(['top', 'middle'], function (e, temps) {});
kitchen.exchange.fridge.getTemperature(['top', 'middle'])
.then(function (temps) {})
.catch(function (e) {})
Listen to API events
kitchen.event.fridge.on('/eventName', function (data) {});
Discover component methods
NB: this will only work if you connect before you construct
const client = new HappnerClient({ discoverMethods: true });
var model = {
component1: {
version: '^1.0.0'
},
component2: {
version: '^1.0.0'
}
};
await client.connect(null, {
username: '_ADMIN',
password: 'xxx'
});
const createdApi = createdClient.construct(model);
await createdApi.component1.discoveredMethod();
Access happn data points directly, via the dataClient
var dataClient = client.dataClient();
dataClient.on('/test/point', function(data){
}).then(...);
dataClient.set('/test/point', {my: 'data'}).then(...)
dataClient.get('/test/point').then(...)
dataClient.remove('/test/point').then(...)
see this test for a full demonstration
Browser usage
Assuming served from happner-2 packaged /api/client
script
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/api/client"></script>
</head>
<body>
<script>
var client = new Happner.HappnerClient({
requestTimeout: 10 * 1000,
responseTimeout: 20 * 1000
});
var model = {
'component': {
version: '^2.0.0',
methods: {
method1: {}
}
}
};
var api = client.construct(model);
client.connect()
.then(function () {
api.event.component.on('test/event', function (data, meta) {
console.log('EVENT', meta.path);
});
})
.catch(function (error) {
console.error('connection error', error);
});
setInterval(function () {
api.exchange.component.method1()
.then(function (reply) {
console.log('REPLY', reply);
})
.catch(function (error) {
console.error('ERROR', error);
});
}, 1000);
</script>
</body>
</html>
happn-client lite
this version of the client does not require the construction of the expected API, the calls are transactional with a the same payload structure
connect, login with a token, call a method, listen to an event and finally logout
const LightClient = require('happner-client').Light;
const Happner = require('happner-2');
const DOMAIN = 'DOMAIN_NAME';
const serverInstance = await Happner.create({
domain: DOMAIN,
happn: {
secure: true,
adminPassword: 'xxx',
},
modules: {
remoteComponent: {
instance: {
remoteMethod: async (arg1, arg2, $happn) => {
$happn.emit(`remoteEvents/1`, { arg1, arg2 });
return `${arg1}/${arg2}`;
},
},
},
},
components: {
remoteComponent: {},
},
});
const connectionOptions = {
host: 'localhost',
port: 55000,
username: '_ADMIN',
domain: DOMAIN,
};
const myClient = await LightClient.create({ ...connectionOptions, password: 'xxx' });
const result = await myClient.exchange.$call({
component: 'remoteComponent',
method: 'remoteMethod',
arguments: ['arg1', 'arg2'],
});
console.log(result);
const onEventId = await myClient.event.$on(
{ component: 'remoteComponent', path: 'remoteEvents/*' },
function (eventData) {
console.log('$on:' + JSON.stringify(eventData));
}
);
await myClient.event.$off(onEventId);
await myClient.event.$offPath({ component: 'remoteComponent', path: 'remoteEvents/*' });
await myClient.event.$once(
{ component: 'remoteComponent', path: 'remoteEvents/*' },
function (eventData) {
console.log('$once:' + JSON.stringify(eventData));
}
);
await myClient.exchange.$call({
component: 'remoteComponent',
method: 'remoteMethod',
arguments: ['arg1', 'arg2'],
});
await myClient.exchange.$call({
component: 'remoteComponent',
method: 'remoteMethod',
arguments: ['arg1', 'arg2'],
});
let token = myClient.dataClient().session.token;
let myOtherClient = await LightClient.create({ ...connectionOptions, token });
console.log(`status === 1: ${myOtherClient.dataClient().status === 1}`);
await myClient.logout();
console.log(`status === 2: ${myOtherClient.dataClient().status === 2}`);
serverInstance.stop();