@reshuffle/monday-redis-service
Version:
Reshuffle service for mirroring Monday to Redis
824 lines • 42 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
exports.__esModule = true;
exports.createAndInitializeMondayRedisService = exports.MondayRedisService = void 0;
var reshuffle_base_connector_1 = require("reshuffle-base-connector");
var Cipher_1 = require("./Cipher");
var MONDAY_SYNC_TIMER_MS = parseInt(process.env.MONDAY_SYNC_TIMER_MS || '5000', 10);
var UNDEFINED_NULL_PLACEHOLDER = 'UNDEFINED_OR_NULL';
var MondayRedisService = /** @class */ (function (_super) {
__extends(MondayRedisService, _super);
function MondayRedisService(app, options, id) {
var _this = _super.call(this, app, options, id) || this;
_this.encryptedColumns = {};
_this.destageIntervalID = null;
_this.mondaySyncIntervalID = null;
_this.boardName = MondayRedisService.validateBoardName(options.boardName);
_this.keyBase = "MondayBoard/" + encodeURIComponent(_this.boardName);
_this.namesKey = _this.keyBase + "/names";
_this.changesKey = _this.keyBase + "/changes";
if (typeof options.monday !== 'object' ||
options.monday.constructor.name !== 'MondayConnector') {
throw new Error("Not a monday connector: " + options.monday);
}
_this.monday = options.monday;
if (typeof options.redis !== 'object' ||
options.redis.constructor.name !== 'RedisConnector') {
throw new Error("Not a redis connector: " + options.redis);
}
_this.redis = options.redis;
if (options.encryptionKey !== undefined &&
options.encryptedColumnList !== undefined) {
if (!Array.isArray(options.encryptedColumnList)) {
throw new Error("Invalid column list: " + options.encryptedColumnList);
}
for (var _i = 0, _a = options.encryptedColumnList; _i < _a.length; _i++) {
var title = _a[_i];
if (typeof title !== 'string' || title.trim().length === 0) {
throw new Error("Invalid column list: " + options.encryptedColumnList);
}
_this.encryptedColumns[title] = true;
}
_this.cipher = new Cipher_1.Cipher(options.encryptionKey);
}
_this.resetDestageInterval();
_this.resetMondaySync();
return _this;
}
MondayRedisService.prototype.resetDestageInterval = function () {
var _this = this;
if (this.destageIntervalID) {
clearInterval(this.destageIntervalID);
}
this.destageIntervalID = setInterval(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.destageChanges()];
case 1: return [2 /*return*/, _a.sent()];
}
}); }); }, MONDAY_SYNC_TIMER_MS);
};
MondayRedisService.prototype.resetMondaySync = function () {
var _this = this;
if (this.mondaySyncIntervalID) {
clearInterval(this.mondaySyncIntervalID);
}
this.mondaySyncIntervalID = setInterval(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.syncBoardItemAdditionDeletion()];
case 1: return [2 /*return*/, _a.sent()];
}
}); }); }, MONDAY_SYNC_TIMER_MS * 5);
};
MondayRedisService.prototype.getChangeKey = function (itemId, title) {
return itemId + ":" + encodeURIComponent(title);
};
MondayRedisService.prototype.syncBoardItemAdditionDeletion = function () {
return __awaiter(this, void 0, void 0, function () {
var mondayItemIds_1, redisItemIds_1, createdItems, deletedItems, _i, deletedItems_1, deletedItemId, existInMonday, _a, createdItems_1, createdItemId, exist, res, mondayItem;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!this.boardId) return [3 /*break*/, 12];
return [4 /*yield*/, this.monday.getBoardItemIds(this.boardId)];
case 1:
mondayItemIds_1 = _b.sent();
return [4 /*yield*/, this.getBoardItemIds()];
case 2:
redisItemIds_1 = _b.sent();
createdItems = mondayItemIds_1.filter(function (id) { return !redisItemIds_1.includes(id); });
deletedItems = redisItemIds_1.filter(function (id) { return !mondayItemIds_1.includes(id); });
_i = 0, deletedItems_1 = deletedItems;
_b.label = 3;
case 3:
if (!(_i < deletedItems_1.length)) return [3 /*break*/, 6];
deletedItemId = deletedItems_1[_i];
existInMonday = mondayItemIds_1.includes(deletedItemId);
if (!!existInMonday) return [3 /*break*/, 5];
this.app
.getLogger()
.info("Item " + deletedItemId + " removed from board " + this.boardName + ", syncing Redis cache");
return [4 /*yield*/, this.deleteItemInRedis(deletedItemId)];
case 4:
_b.sent();
_b.label = 5;
case 5:
_i++;
return [3 /*break*/, 3];
case 6:
_a = 0, createdItems_1 = createdItems;
_b.label = 7;
case 7:
if (!(_a < createdItems_1.length)) return [3 /*break*/, 12];
createdItemId = createdItems_1[_a];
return [4 /*yield*/, this.redis.hexists(this.keyForItem(createdItemId), 'id')];
case 8:
exist = _b.sent();
if (!!exist) return [3 /*break*/, 11];
this.app
.getLogger()
.info("New item " + createdItemId + " detected in board " + this.boardName + ", syncing Redis cache");
return [4 /*yield*/, this.monday.getItem(parseInt(createdItemId, 10))];
case 9:
res = _b.sent();
mondayItem = res && res.items && res.items.length && res.items[0];
if (!mondayItem) return [3 /*break*/, 11];
return [4 /*yield*/, this.createItemInRedis(__assign({ id: createdItemId }, mondayItem))];
case 10:
_b.sent();
_b.label = 11;
case 11:
_a++;
return [3 /*break*/, 7];
case 12: return [2 /*return*/];
}
});
});
};
MondayRedisService.prototype.destageChanges = function (skipChangeKey) {
return __awaiter(this, void 0, void 0, function () {
var changes;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.redis.getset(this.changesKey, '')];
case 1:
changes = _a.sent();
if (!changes) return [3 /*break*/, 3];
return [4 /*yield*/, Promise.all(changes
.split(' ')
.slice(1)
.sort()
.filter(function (e, i, a) { return i === a.indexOf(e); }) // unique
.filter(function (e) { return e !== skipChangeKey; }) // Skip skipChangeKey
.map(function (change) {
var _a = change.split(':'), itemId = _a[0], title = _a[1];
return _this.destageOneChange(itemId, decodeURIComponent(title));
}))];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
};
MondayRedisService.prototype.destageOneChange = function (itemId, title) {
return __awaiter(this, void 0, void 0, function () {
var serial, value, _a, _b, _c, _d;
var _e;
return __generator(this, function (_f) {
switch (_f.label) {
case 0: return [4 /*yield*/, this.redis.hget(this.keyForItem(itemId), title)];
case 1:
serial = _f.sent();
value = this.deserialize(serial, title);
if (!(title === 'name')) return [3 /*break*/, 4];
_b = (_a = this.monday).updateItemName;
return [4 /*yield*/, this.getBoardId()];
case 2: return [4 /*yield*/, _b.apply(_a, [_f.sent(), itemId, value])];
case 3:
_f.sent();
return [3 /*break*/, 7];
case 4:
_d = (_c = this.monday).updateColumnValues;
return [4 /*yield*/, this.getBoardId()];
case 5: return [4 /*yield*/, _d.apply(_c, [_f.sent(), itemId, (_e = {},
_e[title] = function () { return value; },
_e)])];
case 6:
_f.sent();
_f.label = 7;
case 7: return [2 /*return*/];
}
});
});
};
// Helpers ////////////////////////////////////////////////////////
MondayRedisService.prototype.keyForItem = function (itemId) {
// If the schema changes, you'll new to review the getBoardItemIds implementation
return this.keyBase + "/item/" + (itemId || '*');
};
MondayRedisService.prototype.getBoardItemIds = function () {
return __awaiter(this, void 0, void 0, function () {
var keys;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.redis.keys(this.keyForItem())];
case 1:
keys = _a.sent();
return [2 /*return*/, keys.map(function (key) { return key.substr(key.lastIndexOf('/') + 1); })];
}
});
});
};
MondayRedisService.prototype.serialize = function (value, title) {
if (value === null || value === undefined) {
return UNDEFINED_NULL_PLACEHOLDER;
}
var json = JSON.stringify(value);
return this.cipher && this.encryptedColumns[title]
? this.cipher.encrypt(json)
: json;
};
MondayRedisService.prototype.deserialize = function (str, title) {
if (!str || str === UNDEFINED_NULL_PLACEHOLDER) {
return undefined;
}
var json = this.cipher && this.encryptedColumns[title]
? this.cipher.decrypt(str)
: str;
return JSON.parse(json);
};
MondayRedisService.prototype.getMondayBoardItems = function () {
return __awaiter(this, void 0, void 0, function () {
var board, _a, _b, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
_b = (_a = this.monday).getBoardItems;
return [4 /*yield*/, this.getBoardId()];
case 1: return [4 /*yield*/, _b.apply(_a, [_e.sent()])];
case 2:
board = _e.sent();
if (!(!board || board.name !== this.boardName)) return [3 /*break*/, 5];
this.boardId = undefined;
_d = (_c = this.monday).getBoardItems;
return [4 /*yield*/, this.getBoardId()];
case 3: return [4 /*yield*/, _d.apply(_c, [_e.sent()])];
case 4:
board = _e.sent();
_e.label = 5;
case 5:
if (!board || board.name !== this.boardName) {
throw new Error("Unable to read Monday board: " + this.boardName);
}
return [2 /*return*/, board.items];
}
});
});
};
MondayRedisService.prototype.createItemInRedis = function (item) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Promise.all(__spreadArrays(Object.keys(item).map(function (title) {
return _this.redis.hset(_this.keyForItem(item.id), title, _this.serialize(item[title], title));
}), [
this.redis.hset(this.namesKey, item.name, item.id),
]))];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
MondayRedisService.prototype.deleteItemInRedis = function (itemId) {
return __awaiter(this, void 0, void 0, function () {
var item;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getBoardItemById(itemId)];
case 1:
item = _a.sent();
if (!item) return [3 /*break*/, 3];
return [4 /*yield*/, Promise.all([
this.redis.del(this.keyForItem(item.id)),
this.redis.hdel(this.namesKey, item.name),
])];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
};
MondayRedisService.prototype.updateColumnValue = function (itemId, title, update) {
return __awaiter(this, void 0, void 0, function () {
var change;
return __generator(this, function (_a) {
change = this.getChangeKey(itemId, title);
return [2 /*return*/, Promise.all([
update,
this.redis.append(this.changesKey, ' ' + change),
])];
});
});
};
// Initialize the Redis mirror for this board.
MondayRedisService.prototype.initialize = function () {
return __awaiter(this, void 0, void 0, function () {
var initialized, items, _a;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
this.app.getLogger().info("Initializing " + this.boardName + " board");
return [4 /*yield*/, this.redis.setnx(this.changesKey, '')];
case 1:
initialized = _b.sent();
if (!(initialized === 1)) return [3 /*break*/, 4];
this.app.getLogger().info("Populating Redis mirror for " + this.boardName);
return [4 /*yield*/, this.getMondayBoardItems()];
case 2:
items = _b.sent();
return [4 /*yield*/, Promise.all(Object.values(items).map(function (item) { return _this.createItemInRedis(item); }))];
case 3:
_b.sent();
_b.label = 4;
case 4:
_a = this;
return [4 /*yield*/, this.getBoardId()];
case 5:
_a.boardId = _b.sent();
this.monday.on({
type: 'ChangeColumnValue',
boardId: this.boardId
}, function (event) { return __awaiter(_this, void 0, void 0, function () {
var boardId, itemId, columnTitle, columnType, value, userId, newValue, _a, res, mondayItem;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
boardId = event.boardId, itemId = event.itemId, columnTitle = event.columnTitle, columnType = event.columnType, value = event.value, userId = event.userId;
if (this.configOptions.apiUserIdsToIgnoreOnNewEvent &&
this.configOptions.apiUserIdsToIgnoreOnNewEvent.includes(userId)) {
this.app
.getLogger()
.info("Monday event received - skip changes from user: " + userId + " (listed in configOptions.apiUserIdsToIgnoreOnNewEvent)");
return [2 /*return*/];
}
_a = columnType;
switch (_a) {
case 'location': return [3 /*break*/, 1];
case 'color': return [3 /*break*/, 3];
case 'board-relation': return [3 /*break*/, 4];
case 'text': return [3 /*break*/, 5];
case 'numeric': return [3 /*break*/, 5];
case 'dropdown': return [3 /*break*/, 6];
}
return [3 /*break*/, 7];
case 1: return [4 /*yield*/, this.monday.getItem(parseInt(itemId, 10))];
case 2:
res = _b.sent();
mondayItem = res && res.items && res.items.length && res.items[0];
newValue = mondayItem === null || mondayItem === void 0 ? void 0 : mondayItem.Location;
return [3 /*break*/, 8];
case 3:
newValue = value.label;
return [3 /*break*/, 8];
case 4:
newValue = { linkedPulseIds: value.linkedPulseIds };
return [3 /*break*/, 8];
case 5:
newValue = value ? value.value : value;
return [3 /*break*/, 8];
case 6:
newValue = value ? value.chosenValues : value;
return [3 /*break*/, 8];
case 7:
newValue = value;
_b.label = 8;
case 8:
if (!(this.boardId === parseInt(boardId, 10))) return [3 /*break*/, 11];
this.app
.getLogger()
.info("Monday event received - Update Redis cache with " + JSON.stringify(newValue) + " for itemId " + itemId + " (columnTitle: " + columnTitle + ")");
return [4 /*yield*/, this.redis.hset(this.keyForItem(itemId), columnTitle, this.serialize(newValue, columnTitle))];
case 9:
_b.sent();
this.resetMondaySync();
return [4 /*yield*/, this.destageChanges(this.getChangeKey(itemId, columnTitle))];
case 10:
_b.sent();
_b.label = 11;
case 11: return [2 /*return*/];
}
});
}); });
this.monday.on({
type: 'UpdateName',
boardId: this.boardId
}, function (event) { return __awaiter(_this, void 0, void 0, function () {
var boardId, itemId, previousValue, value, userId;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
boardId = event.boardId, itemId = event.itemId, previousValue = event.previousValue, value = event.value, userId = event.userId;
if (this.configOptions.apiUserIdsToIgnoreOnNewEvent &&
this.configOptions.apiUserIdsToIgnoreOnNewEvent.includes(userId)) {
this.app
.getLogger()
.info("Monday event received - skip changes from user: " + userId + " (listed in configOptions.apiUserIdsToIgnoreOnNewEvent)");
return [2 /*return*/];
}
if (!(this.boardId === parseInt(boardId, 10) &&
typeof value.name === 'string')) return [3 /*break*/, 2];
this.app
.getLogger()
.info("Monday event received - Update item name in Redis cache (itemId: " + itemId + ", previousName: " + previousValue.name + ", itemName: " + value.name + ")");
return [4 /*yield*/, this.setItemName(itemId, value.name)];
case 1:
_a.sent();
_a.label = 2;
case 2: return [2 /*return*/];
}
});
}); });
this.monday.on({
type: 'CreateItem',
boardId: this.boardId
}, function (event) { return __awaiter(_this, void 0, void 0, function () {
var boardId, itemId, itemName, userId, response;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
boardId = event.boardId, itemId = event.itemId, itemName = event.itemName, userId = event.userId;
if (this.configOptions.apiUserIdsToIgnoreOnNewEvent &&
this.configOptions.apiUserIdsToIgnoreOnNewEvent.includes(userId)) {
this.app
.getLogger()
.info("Monday event received - skip changes from user: " + userId + " (listed in configOptions.apiUserIdsToIgnoreOnNewEvent)");
return [2 /*return*/];
}
if (!(this.boardId === parseInt(boardId, 10))) return [3 /*break*/, 3];
this.app
.getLogger()
.info("Monday event received - Create new item in Redis cache (itemId: " + itemId + ", itemName: " + itemName + ")");
return [4 /*yield*/, this.monday.getItem(parseInt(itemId, 10))];
case 1:
response = _a.sent();
if (!(response && response.items && response.items[0])) return [3 /*break*/, 3];
this.resetMondaySync();
return [4 /*yield*/, this.createItemInRedis(__assign({ id: itemId }, response.items[0]))];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/];
}
});
}); });
return [2 /*return*/, this];
}
});
});
};
// Create a new item in Monday and the Redis mirror.
//
// @param name item name
// @param columnValues values by column titles
//
// @return item object
//
MondayRedisService.prototype.createItem = function (name, columnValues) {
return __awaiter(this, void 0, void 0, function () {
var boardId, columnUpdaters, _loop_1, _i, _a, _b, title, value, itemId, item;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, this.getBoardId()];
case 1:
boardId = _c.sent();
columnUpdaters = {};
_loop_1 = function (title, value) {
columnUpdaters[title] = function () { return value; };
};
for (_i = 0, _a = Object.entries(columnValues); _i < _a.length; _i++) {
_b = _a[_i], title = _b[0], value = _b[1];
_loop_1(title, value);
}
return [4 /*yield*/, this.monday.createItem(boardId, name, columnUpdaters)];
case 2:
itemId = _c.sent();
item = __assign({ id: itemId, name: name }, columnValues);
return [4 /*yield*/, this.createItemInRedis(item)];
case 3:
_c.sent();
return [2 /*return*/, item];
}
});
});
};
// Get the id of this board.
//
// @return board id
//
MondayRedisService.prototype.getBoardId = function () {
return __awaiter(this, void 0, void 0, function () {
var BoardIdInRedis, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!!this.boardId) return [3 /*break*/, 6];
return [4 /*yield*/, this.redis.get("boards/" + this.boardName)];
case 1:
BoardIdInRedis = _b.sent();
if (!BoardIdInRedis) return [3 /*break*/, 2];
this.boardId = parseInt(BoardIdInRedis, 10);
return [3 /*break*/, 5];
case 2:
_a = this;
return [4 /*yield*/, this.monday.getBoardIdByName(this.boardName)];
case 3:
_a.boardId = _b.sent();
if (!this.boardId) return [3 /*break*/, 5];
return [4 /*yield*/, this.redis.set("boards/" + this.boardName, this.boardId)];
case 4:
_b.sent();
_b.label = 5;
case 5:
if (!this.boardId) {
throw new Error("Monday board not found: " + this.boardName);
}
_b.label = 6;
case 6: return [2 /*return*/, this.boardId];
}
});
});
};
// Get all items.
//
//
// @return an array of objects with the item's id, name and column
// value (undefined if not found)
//
MondayRedisService.prototype.getBoardItems = function () {
return __awaiter(this, void 0, void 0, function () {
var ids, items, _i, ids_1, id, item;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getBoardItemIds()];
case 1:
ids = _a.sent();
items = [];
if (!ids) return [3 /*break*/, 5];
_i = 0, ids_1 = ids;
_a.label = 2;
case 2:
if (!(_i < ids_1.length)) return [3 /*break*/, 5];
id = ids_1[_i];
return [4 /*yield*/, this.getBoardItemById(id)];
case 3:
item = _a.sent();
item && items.push(item);
_a.label = 4;
case 4:
_i++;
return [3 /*break*/, 2];
case 5: return [2 /*return*/, items];
}
});
});
};
// Get an item with the specified id from this board.
//
// @param itemId item id
//
// @return an object with the item's id, name and column
// value (undefined if not found)
//
MondayRedisService.prototype.getBoardItemById = function (itemId) {
return __awaiter(this, void 0, void 0, function () {
var raw, item, _i, _a, title;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
MondayRedisService.validateId(itemId);
return [4 /*yield*/, this.redis.hgetall(this.keyForItem(itemId))];
case 1:
raw = _b.sent();
if (raw) {
item = {};
for (_i = 0, _a = Object.keys(raw); _i < _a.length; _i++) {
title = _a[_i];
item[title] = this.deserialize(raw[title], title);
}
return [2 /*return*/, item];
}
return [2 /*return*/];
}
});
});
};
// Get an item with the specified name from this board.
//
// @param name item name
//
// @return an object with the item's id, name and column
// value (undefined if not found)
//
MondayRedisService.prototype.getBoardItemByName = function (name) {
return __awaiter(this, void 0, void 0, function () {
var id;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
MondayRedisService.validateBoardName(name);
return [4 /*yield*/, this.redis.hget(this.namesKey, name)];
case 1:
id = _a.sent();
return [2 /*return*/, id && this.getBoardItemById(id)];
}
});
});
};
// Set a new value for one column of a specific item.
//
// The new value is atomically written to the Redis mirror, and will
// eventually be synchronized back to Monday. This assures updates
// are atomic and reduces load on Monday, as multiple updates to the
// same column are consolidated before Monday is updated.
//
// The new value is encrypted if necessary before caching.
//
// @param itemId id of the Monday item to be updated
// @param title title of the Monday column to be updated
// @param value new value
//
MondayRedisService.prototype.setColumnValue = function (itemId, title,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
value) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.updateColumnValue(itemId, title, this.redis.hset(this.keyForItem(itemId), title, this.serialize(value, title)))];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
MondayRedisService.prototype.setItemName = function (itemId, name) {
return __awaiter(this, void 0, void 0, function () {
var item;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getBoardItemById(itemId)];
case 1:
item = _a.sent();
return [4 /*yield*/, this.setColumnValue(itemId, 'name', name)];
case 2:
_a.sent();
if (!item) return [3 /*break*/, 4];
return [4 /*yield*/, this.redis.hdel(this.namesKey, item.name)];
case 3:
_a.sent();
_a.label = 4;
case 4: return [4 /*yield*/, this.redis.hset(this.namesKey, name, itemId)];
case 5:
_a.sent();
return [2 /*return*/];
}
});
});
};
// Increase (or decrease) the value for one column of a specific
// item. The column must have a numeric value and must not be
// encrypted.
//
// The new value is atomically written to the Redis mirror, and will
// eventually be synchronized back to Monday. This assures updates
// are atomic and reduces load on Monday, as multiple updates to the
// same column are consolidated before Monday is updated.
//
// @param itemId id of the Monday item to be updated
// @param title title of the Monday column to be updated
// @param incr numeric increment (negative to decrement)
//
MondayRedisService.prototype.incrColumnValue = function (itemId, title, incr) {
if (incr === void 0) { incr = 1; }
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.updateColumnValue(itemId, title, this.redis.hincrby(this.keyForItem(itemId), title, incr))];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
// Static /////////////////////////////////////////////////////////
// Validate an item id and throw an error otherwise.
//
// @param itemId item id
//
// @return same item id
//
MondayRedisService.validateId = function (itemId) {
if (typeof itemId !== 'string' || !/^\d{9,10}$/.test(itemId)) {
throw new Error("Invalid item id: " + itemId);
}
return itemId;
};
// Validate an item name and throw an error otherwise.
//
// @param name item name
//
// @return same item name
//
MondayRedisService.validateBoardName = function (name) {
if (typeof name !== 'string' || name.trim().length === 0) {
throw new Error("Invalid name: " + name);
}
return name;
};
return MondayRedisService;
}(reshuffle_base_connector_1.BaseConnector));
exports.MondayRedisService = MondayRedisService;
// Create a new service.
//
// @param boardName name of board
// @param monday pre-configured Reshuffle Monday connector
// @param redis pre-configured Reshuffle Redis connector
// @param encryptionKey optional key for encrypting data in Redis (if
// not specified data is mirrored in the clear)
// @param encryptedColumnList optional list of columns to be encrypted
//
// @return new board accessor
//
function createAndInitializeMondayRedisService(app, boardName, monday, redis, encryptionKey, encryptedColumnList, apiUserIdsToIgnoreOnNewEvent) {
return __awaiter(this, void 0, void 0, function () {
var mrs;
return __generator(this, function (_a) {
mrs = new MondayRedisService(app, {
boardName: boardName,
monday: monday,
redis: redis,
encryptionKey: encryptionKey,
encryptedColumnList: encryptedColumnList,
apiUserIdsToIgnoreOnNewEvent: apiUserIdsToIgnoreOnNewEvent
});
return [2 /*return*/, mrs.initialize()];
});
});
}
exports.createAndInitializeMondayRedisService = createAndInitializeMondayRedisService;
//# sourceMappingURL=index.js.map