lemon-core
Version:
Lemon Serverless Micro-Service Platform
168 lines • 7.59 kB
JavaScript
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
;