UNPKG

@mochabug/adapt-web

Version:

The client library to execute automations, without effort, in a browser environment

187 lines 7.17 kB
"use strict"; 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