UNPKG

@buildable/events

Version:

Custom Events for Buildable

197 lines (196 loc) 8.66 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const axios_1 = __importDefault(require("axios")); const utils_1 = require("../utils"); const errorsMap = { '401': 'You are not authorized to make this request.', emit: 'There was an error trying to emit this event', default: 'An error has occurred' }; const baseURL = process.env.BLD_EVENTS_BASE_URL || 'https://events.buildable.dev'; const emitPath = "/emit"; const SEPERATOR = "---"; function createClient(secret) { if (!secret) { throw new Error('A valid Buildable secret is required'); } let listeners = {}; const getListenerId = ({ eventName, txKey }) => { return eventName + SEPERATOR + txKey; }; const runTransactions = async ({ eventName, txKey, since = Date.now(), sleepTime = 3000, platform, label }) => { var _a, _b, _c, _d, _e, _f; try { const listener = listeners[getListenerId({ eventName, txKey })]; if (!listener) { return; //deregistered } const { handler } = listener; let events = []; let page = 1; let hasMorePages = true; while (hasMorePages) { try { const { data: { rows, totalPages } } = await (0, axios_1.default)({ method: "post", url: baseURL + "/query", headers: { "X-BUILDABLE-SECRET": secret }, data: { eventName, txKey, platform, label, since, txState: "does-not-exist", page, pageSize: 10 } }); if (totalPages > page) { page++; } else { hasMorePages = false; } events = rows; } catch (e) { hasMorePages = false; console.error("Error fetching events for ", { eventName, txKey }, { data: (_a = e === null || e === void 0 ? void 0 : e.response) === null || _a === void 0 ? void 0 : _a.data, status: (_b = e === null || e === void 0 ? void 0 : e.response) === null || _b === void 0 ? void 0 : _b.status }); } for (const event of events) { const { headers, query, payload, key, eventName } = event; try { await (0, axios_1.default)({ method: "post", url: baseURL + "/init", headers: { "X-BUILDABLE-SECRET": secret }, data: { key, txKey, } }); } catch (e) { console.error(`Error initializing transaction for event: ${eventName}, with key: ${key} and txKey: ${txKey}`, { data: (_c = e === null || e === void 0 ? void 0 : e.response) === null || _c === void 0 ? void 0 : _c.data, status: (_d = e === null || e === void 0 ? void 0 : e.response) === null || _d === void 0 ? void 0 : _d.status }); continue; } let output; let error; try { output = await handler({ headers, query, payload, event }); } catch (e) { error = e; } if (error) { await (0, axios_1.default)({ method: "post", url: baseURL + "/transact", headers: { "X-BUILDABLE-SECRET": secret }, data: { key, txKey, output: (0, utils_1.stringify)(error), state: "failed" } }); } else { await (0, axios_1.default)({ method: "post", url: baseURL + "/transact", headers: { "X-BUILDABLE-SECRET": secret }, data: { key, txKey, output: (0, utils_1.stringify)(output), state: "finished" } }); } } } } catch (e) { console.error("Error occurred in query interval", (e === null || e === void 0 ? void 0 : e.response) ? { data: (_e = e === null || e === void 0 ? void 0 : e.response) === null || _e === void 0 ? void 0 : _e.data, status: (_f = e === null || e === void 0 ? void 0 : e.response) === null || _f === void 0 ? void 0 : _f.status } : e); } await (0, utils_1.sleep)(sleepTime); const listener = listeners[getListenerId({ eventName, txKey })]; if (listener && listener.interval) { listener.interval.then(() => runTransactions({ eventName, txKey, since, sleepTime, platform, label })); // doesn't affect stack size } }; return { emit: async (event, payload = {}) => { var _a, _b, _c; if (!event) { throw Error('Need to provide an `event name`'); } try { const data = { event, payload }; const options = { headers: { 'X-Buildable-Secret': secret } }; const res = await axios_1.default.post(baseURL + emitPath, data, options); // todo: check actual response data return !!(res === null || res === void 0 ? void 0 : res.data); } catch (ex) { const resCode = (_b = (_a = ex === null || ex === void 0 ? void 0 : ex.response) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : 'emit'; const msg = (_c = errorsMap[resCode]) !== null && _c !== void 0 ? _c : errorsMap.default; throw Error(msg); } }, on: (eventName, handler, options = {}) => { const txKey = options.txKey || `js-sdk.${eventName}`; const id = getListenerId({ eventName, txKey }); if (listeners[id]) { throw new Error(`Listener already exists with eventName: ${eventName}, txKey: ${txKey}`); } listeners[id] = { eventName, handler, txKey, options, id }; listeners[id].interval = runTransactions({ eventName, txKey, since: options.since, platform: options.platform, label: options.label }); return { eventName, handler, txKey, options, id }; }, deregister: ({ eventName, txKey }) => { const removeKeys = Object.keys(listeners).filter(id => { const [_eventName, _txKey] = id.split(SEPERATOR); if (eventName && txKey) { return _eventName === eventName && _txKey === txKey; } if (eventName) { return _eventName === eventName; } if (txKey) { return _txKey === txKey; } return false; }); for (const key of removeKeys) { if (listeners[key]) { delete listeners[key]; } } }, deregisterAll: () => { listeners = {}; } }; } module.exports = { createClient, baseURL };