@mochabug/adapt-web
Version:
The client library to execute automations, without effort, in a browser environment
187 lines • 7.17 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MqttClient = exports.RestClientError = void 0;
exports.startSession = startSession;
exports.inheritSession = inheritSession;
exports.getSession = getSession;
exports.readOutput = readOutput;
exports.readUrls = readUrls;
exports.stopSession = stopSession;
const protobuf_1 = require("@bufbuild/protobuf");
const wkt_1 = require("@bufbuild/protobuf/wkt");
const mqtt_1 = __importDefault(require("mqtt"));
const automations_pb_js_1 = require("./genproto/mochabugapis/adapt/automations/v1/automations_pb.js");
const mqttUrl = "wss://adapt-dev.mochabugapis.com/mqtt";
const baseUrl = "https://adapt-dev.mochabugapis.com/v1/automations";
async function startSession(req, token) {
const headers = new Headers({
"Content-Type": "application/json",
"Response-Type": "application/json",
});
if (token) {
headers.set("Authorization", `Bearer ${token}`);
}
const response = await fetch(`${baseUrl}/${req.automation.organization}/${req.automation.group}/${req.automation.automation}/start`, {
method: "POST",
body: JSON.stringify(req),
headers,
});
if (!response.ok) {
throw new RestClientError(response);
}
return await response.json();
}
async function inheritSession(automation, sessionToken) {
const response = await fetch(`${baseUrl}/${automation.organization}/${automation.group}/${automation.automation}/session/inherit`, {
method: "POST",
body: JSON.stringify(automation),
headers: {
"Content-Type": "application/json",
"Response-Type": "application/json",
Authorization: `Bearer ${sessionToken}`,
},
});
if (!response.ok) {
throw new RestClientError(response);
}
return await response.json();
}
async function getSession(automation, sessionToken) {
const response = await fetch(`${baseUrl}/${automation.organization}/${automation.group}/${automation.automation}/session/status`, {
method: "GET",
headers: {
"Response-Type": "application/json",
Authorization: `Bearer ${sessionToken}`,
},
});
if (!response.ok) {
throw new RestClientError(response);
}
return await response.json();
}
async function readOutput(automation, sessionToken) {
const response = await fetch(`${baseUrl}/${automation.organization}/${automation.group}/${automation.automation}/session/output`, {
method: "GET",
headers: {
"Response-Type": "application/json",
Authorization: `Bearer ${sessionToken}`,
},
});
if (!response.ok) {
throw new RestClientError(response);
}
return await response.json();
}
async function readUrls(automation, sessionToken) {
const response = await fetch(`${baseUrl}/${automation.organization}/${automation.group}/${automation.automation}/session/urls`, {
method: "GET",
headers: {
"Response-Type": "application/json",
Authorization: `Bearer ${sessionToken}`,
},
});
if (!response.ok) {
throw new RestClientError(response);
}
return await response.json();
}
async function stopSession(automation, sessionToken) {
const response = await fetch(`${baseUrl}/${automation.organization}/${automation.group}/${automation.automation}/session/stop`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${sessionToken}`,
},
});
if (!response.ok) {
throw new RestClientError(response);
}
}
class RestClientError extends Error {
constructor(response) {
super(`HTTP Error: ${response.status} ${response.statusText}`);
this.name = "RestClientError";
this.status = response.status;
this.statusText = response.statusText;
this.response = response;
}
}
exports.RestClientError = RestClientError;
class MqttClient {
constructor(clientId) {
this.mqttClient = null;
this.clientId = clientId;
this.subscribe = this.subscribe.bind(this);
this.unsubscribe = this.unsubscribe.bind(this);
}
async subscribe(opts) {
this.unsubscribe();
this.mqttClient = await mqtt_1.default.connectAsync(mqttUrl, {
transformWsUrl: (url, options) => {
options.password = opts.sessionToken;
return url;
},
clientId: this.clientId,
password: opts.sessionToken,
username: this.clientId,
clean: false,
keepalive: 20,
protocolVersion: 5,
});
this.mqttClient.on("error", (err) => {
console.error("MQTT error", err);
});
this.mqttClient.on("message", (topic, _, packet) => {
if (!(packet.payload instanceof Uint8Array)) {
throw new Error("Payload is not a Uint8Array. The wireformat must be binary");
}
if (topic.endsWith("session")) {
opts.onSession?.((0, protobuf_1.toJson)(automations_pb_js_1.SessionSchema, (0, protobuf_1.fromBinary)(automations_pb_js_1.SessionSchema, packet.payload)));
}
else if (topic.endsWith("url")) {
opts.onUrl?.((0, protobuf_1.toJson)(automations_pb_js_1.UrlSchema, (0, protobuf_1.fromBinary)(automations_pb_js_1.UrlSchema, packet.payload)));
}
else if (topic.endsWith("output")) {
const output = (0, protobuf_1.fromBinary)(automations_pb_js_1.OutputSchema, packet.payload);
opts.onOutput?.({
vertex: output.vertex,
data: Object.fromEntries(Object.entries(output.data).map(([k, v]) => [
k,
(0, protobuf_1.toJson)(wkt_1.ValueSchema, v),
])),
created: (0, wkt_1.timestampDate)(output.created),
});
}
else {
console.error("Unknown topic", topic);
}
});
const baseTopic = `org/${opts.automation.organization}/ag/${opts.automation.group}/aut/${opts.automation.automation}/session/${opts.session}`;
const options = {
qos: 1,
nl: true,
rh: 0,
rap: false,
};
const subs = [];
if (opts.onSession) {
subs.push(this.mqttClient.subscribeAsync(`${baseTopic}/session`, options));
}
if (opts.onUrl) {
subs.push(this.mqttClient.subscribeAsync(`${baseTopic}/url`, options));
}
if (opts.onOutput) {
subs.push(this.mqttClient.subscribeAsync(`${baseTopic}/output`, options));
}
await Promise.all(subs);
}
async unsubscribe() {
if (this.mqttClient) {
await this.mqttClient.endAsync(true);
}
}
}
exports.MqttClient = MqttClient;
//# sourceMappingURL=index.js.map