UNPKG

lemon-core

Version:
168 lines 7.59 kB
"use strict"; 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 _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.TopicsService = void 0; /** * `sns-service.js` * - encrypt/decrypt service api with KMS * * * @author Ian Kim <ian@lemoncloud.io> * @date 2023-09-25 initial azure service bus topics service * * @copyright (C) lemoncloud.io 2023 - All Rights Reserved. */ /** **************************************************************************************************************** * Common Headers ** ****************************************************************************************************************/ // eslint-disable-next-line @typescript-eslint/no-unused-vars const engine_1 = require("../../engine"); // import { KeyVaultService } from '../azure' require("dotenv/config"); const NS = engine_1.$U.NS('AZTP', 'blue'); /** * use `target` as value or environment value. * environ('abc') => string 'abc' * environ('ABC') => use `env.ABC` */ const environ = (target, defEnvName, defEnvValue) => { const isUpperStr = target && /^[A-Z][A-Z0-9_]+$/.test(target); defEnvName = isUpperStr ? target : defEnvName; const val = defEnvName ? engine_1.$engine.environ(defEnvName, defEnvValue) : defEnvValue; target = isUpperStr ? '' : target; return `${target || val}`; }; /** **************************************************************************************************************** * Public Instance Exported. ** ****************************************************************************************************************/ //! main service instance. class TopicsService { constructor(arn) { /** * get name of this */ this.name = () => `service-bus-topics`; // public static $kv: KeyVaultService = new KeyVaultService(); this.instance = () => __awaiter(this, void 0, void 0, function* () { // eslint-disable-next-line @typescript-eslint/no-var-requires const { ServiceBusClient } = require('@azure/service-bus'); // const connectionString = await TopicsService.$kv.decrypt(process.env.SERVICEBUS_CONNECTION_STRING) const connectionString = process.env.SERVICEBUS_CONNECTION_STRING; const serviceBusClient = new ServiceBusClient(connectionString); return { serviceBusClient }; }); /** * hello */ this.hello = () => `az-sb-topics-service:${TopicsService.DEF_SB_TOPICS_ENDPOINT}`; /** * publish message * * @return {string | object} message-id */ this.publish = (target, subject, payload) => __awaiter(this, void 0, void 0, function* () { const endpoint = target ? target : TopicsService.DEF_SB_TOPICS_ENDPOINT; const { serviceBusClient } = yield this.instance(); try { const sender = serviceBusClient.createSender(endpoint); const params = [ { contentType: 'application/json', subject: subject, body: payload, }, ]; let batch = yield sender.createMessageBatch(); for (const param of params) { if (!batch.tryAddMessage(param)) { // Send the current batch as it is full and create a new one yield sender.sendMessages(batch); batch = yield sender.createMessageBatch(); if (!batch.tryAddMessage(param)) { throw new Error('Message too big to fit in a batch'); } } } yield sender.sendMessages(batch); yield sender.close(); yield serviceBusClient.close(); return; } catch (e) { (0, engine_1._err)(NS, '! err=', e); throw e; } }); /** * report error via SNS with subject 'error' * - default to `lemon-hello-sns` or using `env[REPORT_ERROR_ARN]` * * @param e Error instance * @param data simple text message or object to override. * @param target (optional) target SNS arn (default is `REPORT_ERROR_ARN`) */ this.reportError = (e, data, target) => __awaiter(this, void 0, void 0, function* () { if (!e) return 'N/A'; (0, engine_1._inf)(NS, `reportError(${data}, target=${target || ''})...`); (0, engine_1._err)(NS, '> error =', e); //! find out endpoint. // target = environ(target, 'REPORT_ERROR_ARN', 'lemon-hello-sns'); target = TopicsService.DEF_SB_TOPICS_ENDPOINT; const payload = this.asPayload(e, data); // _log(NS, '> payload =', $U.json(payload)); return this.publish(target, 'error', payload).catch(e => { return `ERROR - ${(e && e.message) || e}`; }); }); /** * convert Error to payload. */ this.asPayload = (e, data) => { //TODO - optimize message extractor. const $message = (e) => { const m = (e && (e.message || e.statusMessage)) || e; return typeof m == 'object' ? engine_1.$U.json(m) : `${m}`; }; //! prepare payload const e2 = e; const base = data && typeof data == 'object' ? data : {}; const message = data && typeof data == 'string' ? data : $message(e); const stack = e instanceof Error ? e.stack : undefined; const error = typeof e == 'string' ? e : e instanceof Error ? `${e.message}` : JSON.stringify(e); const errors = e2.errors || (e2.body && e2.body.errors) || undefined; const payload = Object.assign(base, { 'stack-trace': stack, message, error, errors, }); //! root of errors. const error0 = (errors && errors[0]) || undefined; if (error0) { payload.message = $message(payload.error); payload.error = error0 instanceof Error ? `${e.message}` : JSON.stringify(error0); } //! returns payload for sns error return payload; }; this._arn = arn; } } exports.TopicsService = TopicsService; /** * environ name of SNS KEY * - for self messaging. */ TopicsService.ENV_SB_TOPICS_ENDPOINT = 'MY_SNS_ENDPOINT'; TopicsService.DEF_SB_TOPICS_ENDPOINT = (_a = process.env.SERVICEBUS_TOPIC_RESOURCE) !== null && _a !== void 0 ? _a : 'topic-lemon'; //# sourceMappingURL=azure-sb-topics-service.js.map