diff --git a/config/default.js b/config/default.js index 69c64cc..c6ab49b 100644 --- a/config/default.js +++ b/config/default.js @@ -48,5 +48,8 @@ module.exports = { API_CONTEXT_PATH: process.env.API_CONTEXT_PATH || '/v5/email', PAYLOAD_SENDGRID_TEMPLATE_KEY: process.env.PAYLOAD_SENDGRID_TEMPLATE_KEY || 'sendgrid_template_id', - + //Tracing information + APM_OTLP_TRACE_EXPORTER_URL: process.env.APM_OTLP_TRACE_EXPORTER_URL || '', + APM_SERVICE_NAME: process.env.APM_SERVICE_NAME || 'tc-email-service', + APM_TRACER_NAME: process.env.APM_TRACER_NAME || 'tc-email-service', }; diff --git a/connect/connectEmailServer.js b/connect/connectEmailServer.js index a3c2a37..3e8dbf2 100644 --- a/connect/connectEmailServer.js +++ b/connect/connectEmailServer.js @@ -6,6 +6,7 @@ const config = require('config'); const emailServer = require('../index'); const service = require('./service'); const logger = require('../src/common/logger'); +const { functionWrapper } = require('../src/common/wrapper'); // set configuration for the server, see ../config/default.js for available config parameters // setConfig should be called before initDatabase and start functions @@ -17,20 +18,23 @@ emailServer.setConfig({ LOG_LEVEL: config.LOG_LEVEL }); // the topic is topic name, // the message is JSON event message, const handler = async (topic, message) => { - let templateId = config.TEMPLATE_MAP[topic]; - templateId = _.get(message, config.PAYLOAD_SENDGRID_TEMPLATE_KEY, templateId); - if (!templateId) { - return { success: false, error: `Template not found for topic ${topic}` }; - } - - try { - await service.sendEmail(templateId, message) - return { success: true }; - } catch (err) { - logger.error("Error occurred in sendgrid api calling:", err); - return { success: false, error: err }; - } + (await functionWrapper(async () => { + let templateId = config.TEMPLATE_MAP[topic]; + templateId = _.get(message, config.PAYLOAD_SENDGRID_TEMPLATE_KEY, templateId); + if (!templateId) { + return { success: false, error: `Template not found for topic ${topic}` }; + } + + try { + await service.sendEmail(templateId, message) + return { success: true }; + } catch (err) { + logger.error("Error occurred in sendgrid api calling:", err); + return { success: false, error: err }; + } + + }, 'emailHandler'))(topic, message); }; // init all events diff --git a/connect/service.js b/connect/service.js index 805a80d..7db9021 100644 --- a/connect/service.js +++ b/connect/service.js @@ -10,55 +10,57 @@ const logger = require('../src/common/logger'); sgMail.setApiKey(config.SENDGRID_API_KEY); const sendEmail = async (templateId, message) => { // send email + (await functionWrapper(async () => { - let msg = {} - const from = message.from ? message.from : config.EMAIL_FROM; - const replyTo = message.replyTo ? message.replyTo : config.EMAIL_FROM; - const substitutions = message.data; - const categories = message.categories ? message.categories : []; - const to = message.recipients; - const cc = message.cc ? message.cc : []; - const bcc = message.bcc ? message.bcc : []; - const sendAt = message.sendAt ? message.sendAt : undefined; - const personalizations = message.personalizations ? message.personalizations : undefined - const attachments = message.attachments ? message.attachments : []; + let msg = {} + const from = message.from ? message.from : config.EMAIL_FROM; + const replyTo = message.replyTo ? message.replyTo : config.EMAIL_FROM; + const substitutions = message.data; + const categories = message.categories ? message.categories : []; + const to = message.recipients; + const cc = message.cc ? message.cc : []; + const bcc = message.bcc ? message.bcc : []; + const sendAt = message.sendAt ? message.sendAt : undefined; + const personalizations = message.personalizations ? message.personalizations : undefined + const attachments = message.attachments ? message.attachments : []; - if (message.version && message.version == "v3") { - msg = { - to, - templateId, - dynamicTemplateData: substitutions, - personalizations, - from, - replyTo, - categories, - cc, - bcc, - attachments, - sendAt - }; - } else { - msg = { - to, - templateId, - substitutions, - substitutionWrappers: ['{{', '}}'], - from, - replyTo, - categories, - cc, - bcc, - }; - } - logger.info(`Sending email with templateId: ${templateId} and message: ${JSON.stringify(msg)}`); - try { - const result = await sgMail.send(msg) - logger.info(`Email sent successfully with result: ${JSON.stringify(result)}`); - return result - } catch (err) { - logger.error(`Error occurred in sendgrid api calling: ${err}`); - throw err - } + if (message.version && message.version == "v3") { + msg = { + to, + templateId, + dynamicTemplateData: substitutions, + personalizations, + from, + replyTo, + categories, + cc, + bcc, + attachments, + sendAt + }; + } else { + msg = { + to, + templateId, + substitutions, + substitutionWrappers: ['{{', '}}'], + from, + replyTo, + categories, + cc, + bcc, + }; + } + logger.info(`Sending email with templateId: ${templateId} and message: ${JSON.stringify(msg)}`); + try { + const result = await sgMail.send(msg) + logger.info(`Email sent successfully with result: ${JSON.stringify(result)}`); + return result + } catch (err) { + logger.error(`Error occurred in sendgrid api calling: ${err}`); + throw err + } + }, 'sendgridSendEmail'))(templateId, message); } module.exports = { sendEmail, diff --git a/package-lock.json b/package-lock.json index 154ca5f..5fca655 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,6 +53,18 @@ } } }, + "@grpc/proto-loader": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.11.3", + "yargs": "^16.2.0" + } + }, "@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -138,11 +150,281 @@ "fastq": "^1.6.0" } }, + "@opentelemetry/api": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.2.0.tgz", + "integrity": "sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g==" + }, + "@opentelemetry/api-metrics": { + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-metrics/-/api-metrics-0.29.2.tgz", + "integrity": "sha512-yRdF5beqKuEdsPNoO7ijWCQ9HcyN0Tlgicf8RS6gzGOI54d6Hj7yKquJ6+X9XV+CSRbRWJYb+lOsXyso7uyX2g==", + "requires": { + "@opentelemetry/api": "^1.0.0" + } + }, + "@opentelemetry/core": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.3.1.tgz", + "integrity": "sha512-k7lOC86N7WIyUZsUuSKZfFIrUtINtlauMGQsC1r7jNmcr0vVJGqK1ROBvt7WWMxLbpMnt1q2pXJO8tKu0b9auA==", + "requires": { + "@opentelemetry/semantic-conventions": "1.3.1" + }, + "dependencies": { + "@opentelemetry/semantic-conventions": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.3.1.tgz", + "integrity": "sha512-wU5J8rUoo32oSef/rFpOT1HIjLjAv3qIDHkw1QIhODV3OpAVHi5oVzlouozg9obUmZKtbZ0qUe/m7FP0y0yBzA==" + } + } + }, + "@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.29.2.tgz", + "integrity": "sha512-fnKOiOzfahHfyi8OekJm/HRoV9VloJ1VmDoxG5PDxdxbJirkZxokJ+mdE/UZ8Z0PSaL/yqPvBkBnaeFyhoEMng==", + "requires": { + "@grpc/proto-loader": "^0.6.9", + "@opentelemetry/core": "1.3.1", + "@opentelemetry/otlp-exporter-base": "0.29.2", + "@opentelemetry/otlp-proto-exporter-base": "0.29.2", + "@opentelemetry/otlp-transformer": "0.29.2", + "@opentelemetry/resources": "1.3.1", + "@opentelemetry/sdk-trace-base": "1.3.1", + "protobufjs": "^6.9.0" + }, + "dependencies": { + "@opentelemetry/resources": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.3.1.tgz", + "integrity": "sha512-X8bl3X0YjlsHWy0Iv0KUETtZuRUznX4yr1iScKCtfy8AoRfZFc2xxWKMDJ0TrqYwSapgeg4YwpmRzUKmmnrbeA==", + "requires": { + "@opentelemetry/core": "1.3.1", + "@opentelemetry/semantic-conventions": "1.3.1" + } + }, + "@opentelemetry/sdk-trace-base": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.3.1.tgz", + "integrity": "sha512-Or95QZ+9QyvAiwqj+K68z8bDDuyWF50c37w17D10GV1dWzg4Ezcectsu/GB61QcBxm3Y4br0EN5F5TpIFfFliQ==", + "requires": { + "@opentelemetry/core": "1.3.1", + "@opentelemetry/resources": "1.3.1", + "@opentelemetry/semantic-conventions": "1.3.1" + } + }, + "@opentelemetry/semantic-conventions": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.3.1.tgz", + "integrity": "sha512-wU5J8rUoo32oSef/rFpOT1HIjLjAv3qIDHkw1QIhODV3OpAVHi5oVzlouozg9obUmZKtbZ0qUe/m7FP0y0yBzA==" + } + } + }, + "@opentelemetry/instrumentation": { + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.29.2.tgz", + "integrity": "sha512-LXx5V0ONNATQFCE8C5uqnxWSm4rcXLssdLHdXjtGdxRmURqj/JO8jYefqXCD0LzsqEQ6yxOx2GZ0dgXvhBVdTw==", + "requires": { + "@opentelemetry/api-metrics": "0.29.2", + "require-in-the-middle": "^5.0.3", + "semver": "^7.3.2", + "shimmer": "^1.2.1" + } + }, + "@opentelemetry/instrumentation-winston": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.29.0.tgz", + "integrity": "sha512-z48oitpODk5BkJXp4OlRLAQf5JLH0jcSmHvqhlgB9tHddNG+xQWa1Xb0kyBX4i4r0jGFR7cvImIb53wrEavUBA==", + "requires": { + "@opentelemetry/instrumentation": "^0.29.2" + } + }, + "@opentelemetry/otlp-exporter-base": { + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.29.2.tgz", + "integrity": "sha512-tTK+v2ER9Rv7YQXLrCvZpPdNdvZx8TGdZtlK7TKnzpyMRBIf7lqV1Jl0VaHFml+cgVJcGtow/ER6k5uJ5W4kUQ==", + "requires": { + "@opentelemetry/core": "1.3.1" + } + }, + "@opentelemetry/otlp-proto-exporter-base": { + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-proto-exporter-base/-/otlp-proto-exporter-base-0.29.2.tgz", + "integrity": "sha512-a46z6yMUzVKrPMbKZLWyO5z+9x1ja7zyS3dlZ1vQLB9fymdsubZsqpCetyh3uSpmfGtHweTie8z0MgR6MMsmiA==", + "requires": { + "@grpc/proto-loader": "^0.6.9", + "@opentelemetry/core": "1.3.1", + "@opentelemetry/otlp-exporter-base": "0.29.2", + "protobufjs": "^6.9.0" + } + }, + "@opentelemetry/otlp-transformer": { + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.29.2.tgz", + "integrity": "sha512-Y6dJj+rhRGynxhLlgEJkdkXuLHdFG8igcSBv6oy3m3GHSSvZkyNV34dVjtZJ586mUXsbFuAf6uqjzteobewO1g==", + "requires": { + "@opentelemetry/api-metrics": "0.29.2", + "@opentelemetry/core": "1.3.1", + "@opentelemetry/resources": "1.3.1", + "@opentelemetry/sdk-metrics-base": "0.29.2", + "@opentelemetry/sdk-trace-base": "1.3.1" + }, + "dependencies": { + "@opentelemetry/resources": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.3.1.tgz", + "integrity": "sha512-X8bl3X0YjlsHWy0Iv0KUETtZuRUznX4yr1iScKCtfy8AoRfZFc2xxWKMDJ0TrqYwSapgeg4YwpmRzUKmmnrbeA==", + "requires": { + "@opentelemetry/core": "1.3.1", + "@opentelemetry/semantic-conventions": "1.3.1" + } + }, + "@opentelemetry/sdk-trace-base": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.3.1.tgz", + "integrity": "sha512-Or95QZ+9QyvAiwqj+K68z8bDDuyWF50c37w17D10GV1dWzg4Ezcectsu/GB61QcBxm3Y4br0EN5F5TpIFfFliQ==", + "requires": { + "@opentelemetry/core": "1.3.1", + "@opentelemetry/resources": "1.3.1", + "@opentelemetry/semantic-conventions": "1.3.1" + } + }, + "@opentelemetry/semantic-conventions": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.3.1.tgz", + "integrity": "sha512-wU5J8rUoo32oSef/rFpOT1HIjLjAv3qIDHkw1QIhODV3OpAVHi5oVzlouozg9obUmZKtbZ0qUe/m7FP0y0yBzA==" + } + } + }, + "@opentelemetry/resources": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.7.0.tgz", + "integrity": "sha512-u1M0yZotkjyKx8dj+46Sg5thwtOTBmtRieNXqdCRiWUp6SfFiIP0bI+1XK3LhuXqXkBXA1awJZaTqKduNMStRg==", + "requires": { + "@opentelemetry/core": "1.7.0", + "@opentelemetry/semantic-conventions": "1.7.0" + }, + "dependencies": { + "@opentelemetry/core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.7.0.tgz", + "integrity": "sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ==", + "requires": { + "@opentelemetry/semantic-conventions": "1.7.0" + } + } + } + }, + "@opentelemetry/sdk-metrics-base": { + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics-base/-/sdk-metrics-base-0.29.2.tgz", + "integrity": "sha512-7hhhZ/6YRRgAXOUTeCsbe6SIk3wZAdAHnEwGGp7aiVH5AOyioHyHInw4EHtowlD6dbLxUWURjh6k+Geht2zbxg==", + "requires": { + "@opentelemetry/api-metrics": "0.29.2", + "@opentelemetry/core": "1.3.1", + "@opentelemetry/resources": "1.3.1", + "lodash.merge": "4.6.2" + }, + "dependencies": { + "@opentelemetry/resources": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.3.1.tgz", + "integrity": "sha512-X8bl3X0YjlsHWy0Iv0KUETtZuRUznX4yr1iScKCtfy8AoRfZFc2xxWKMDJ0TrqYwSapgeg4YwpmRzUKmmnrbeA==", + "requires": { + "@opentelemetry/core": "1.3.1", + "@opentelemetry/semantic-conventions": "1.3.1" + } + }, + "@opentelemetry/semantic-conventions": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.3.1.tgz", + "integrity": "sha512-wU5J8rUoo32oSef/rFpOT1HIjLjAv3qIDHkw1QIhODV3OpAVHi5oVzlouozg9obUmZKtbZ0qUe/m7FP0y0yBzA==" + } + } + }, + "@opentelemetry/sdk-trace-base": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz", + "integrity": "sha512-Iz84C+FVOskmauh9FNnj4+VrA+hG5o+tkMzXuoesvSfunVSioXib0syVFeNXwOm4+M5GdWCuW632LVjqEXStIg==", + "requires": { + "@opentelemetry/core": "1.7.0", + "@opentelemetry/resources": "1.7.0", + "@opentelemetry/semantic-conventions": "1.7.0" + }, + "dependencies": { + "@opentelemetry/core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.7.0.tgz", + "integrity": "sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ==", + "requires": { + "@opentelemetry/semantic-conventions": "1.7.0" + } + } + } + }, + "@opentelemetry/semantic-conventions": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz", + "integrity": "sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA==" + }, "@panva/asn1.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, "@sendgrid/client": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-7.7.0.tgz", @@ -279,6 +561,11 @@ "@types/node": "*" } }, + "@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, "@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", @@ -388,14 +675,12 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" }, @@ -404,7 +689,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -412,8 +696,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" } } }, @@ -503,6 +786,29 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "aws-sdk": { + "version": "2.395.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.395.0.tgz", + "integrity": "sha512-ldTTjctniZT4E2lq2z3D8Y2u+vpkp+laoEnDkXgjKXTKbiJ0QEtfWsUdx/IQ7awCt8stoxyqZK47DJOxIbRNoA==", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.8", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -543,6 +849,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -600,6 +911,16 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha512-DNK4ruAqtyHaN8Zne7PkBTO+dD1Lr0YfTduMqlIyjvQIoztBkUxrvL+hKeLW8NXFKHOq/2upkxuoS9znQ9bW9A==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -714,7 +1035,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -911,6 +1231,11 @@ "type-detect": "^4.0.0" } }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==" + }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -998,6 +1323,40 @@ "nan": "^2.14.0" } }, + "dynamoose": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/dynamoose/-/dynamoose-1.11.1.tgz", + "integrity": "sha512-73T0GOeSh2FQDdK5V+cN9yowFU4uVt2OsOvknCB4Xdb+nSL/hBaecPY/meJaWZApVx73Hl1DcBSCGp/VWMvfRA==", + "requires": { + "@types/node": "11.11.0", + "aws-sdk": "2.395.0", + "debug": "4.1.1", + "deep-equal": "1.0.1", + "hooks": "0.3.2", + "object-path": "0.11.4", + "q": "1.5.1" + }, + "dependencies": { + "@types/node": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.0.tgz", + "integrity": "sha512-D5Rt+HXgEywr3RQJcGlZUCTCx1qVbCZpVk3/tOOA6spLNZdGm8BU+zRgdRYDoF1pO3RuXLxADzMrF903JlQXqg==" + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1023,8 +1382,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "enabled": { "version": "2.0.0", @@ -1090,8 +1448,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-html": { "version": "1.0.3", @@ -1352,6 +1709,11 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==" + }, "express": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", @@ -1640,8 +2002,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-func-name": { "version": "2.0.0", @@ -1669,6 +2030,11 @@ } } }, + "get-parameter-names": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/get-parameter-names/-/get-parameter-names-0.3.0.tgz", + "integrity": "sha512-KkR1dX7U1TynXFkqveVE/XoRn9qRAsM2q4Eu2WsGTFzoaSdnNQEfxbcK+LMv8DcFoQQT9BFjNL+bf9ZyTLkWpg==" + }, "get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -1756,7 +2122,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -1806,6 +2171,16 @@ "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==" }, + "hoek": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==" + }, + "hooks": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/hooks/-/hooks-0.3.2.tgz", + "integrity": "sha512-TqeFzUf12rSzcbm5lUls81jimUC8TmXZ4ANPxxeeMou09hrjBcHYhAQ0WgyN5YqNCXOzz7L6xVNl/+ctFuSeOw==" + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -1885,6 +2260,11 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha512-/aoyv2Nt7mGLnCAWzE0C1WH9Xd8ZsqR0f4Pjwxputi1JNm01+InyAYQotF4N+ulEIjbEsJo22NOHr+U/XEZ1Pw==" + }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -1985,7 +2365,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dev": true, "requires": { "has": "^1.0.3" } @@ -2008,8 +2387,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { "version": "4.0.3", @@ -2118,6 +2496,19 @@ "call-bind": "^1.0.2" } }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "isemail": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", + "requires": { + "punycode": "2.x.x" + } + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2129,6 +2520,11 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==" + }, "joi": { "version": "17.6.1", "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.1.tgz", @@ -2321,6 +2717,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -2359,8 +2760,7 @@ "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "lodash.once": { "version": "4.1.1", @@ -2396,6 +2796,11 @@ } } }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "long-timeout": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", @@ -2618,6 +3023,11 @@ } } }, + "module-details-from-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + }, "moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", @@ -2712,6 +3122,11 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, + "object-path": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", + "integrity": "sha512-ICbQN+aw/eAASDtaC7+SJXSAruz7fvvNjxMFfS3mTdvZaaiuuw81XXYu+9CSJeUVrS3YpRhTr862YGywMQUOWg==" + }, "object.assign": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", @@ -2841,8 +3256,7 @@ "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { "version": "0.1.7", @@ -2960,6 +3374,26 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2989,6 +3423,11 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" + }, "qs": { "version": "6.10.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", @@ -2997,6 +3436,11 @@ "side-channel": "^1.0.4" } }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==" + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3149,14 +3593,37 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "require-in-the-middle": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz", + "integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==", + "requires": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, "requires": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -3219,6 +3686,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" + }, "semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -3352,6 +3824,11 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -3416,7 +3893,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3457,7 +3933,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -3524,8 +3999,7 @@ "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "tc-core-library-js": { "version": "2.4.1", @@ -3620,6 +4094,37 @@ } } }, + "tc-framework": { + "version": "github:topcoder-platform/tc-framework#6d76273ca8619b2a6f0b605a97a49080befda123", + "from": "github:topcoder-platform/tc-framework#develop", + "requires": { + "@opentelemetry/api": "^1.1.0", + "@opentelemetry/exporter-trace-otlp-proto": "^0.29.2", + "@opentelemetry/instrumentation": "^0.29.2", + "@opentelemetry/instrumentation-winston": "^0.29.0", + "@opentelemetry/resources": "^1.3.1", + "@opentelemetry/sdk-trace-base": "^1.3.1", + "@opentelemetry/semantic-conventions": "^1.3.1", + "config": "^3.3.7", + "dynamoose": "^1.11.1", + "get-parameter-names": "^0.3.0", + "joi": "^14.0.0", + "lodash": "^4.17.21", + "winston": "^3.8.0" + }, + "dependencies": { + "joi": { + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-14.3.1.tgz", + "integrity": "sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==", + "requires": { + "hoek": "6.x.x", + "isemail": "3.x.x", + "topo": "3.x.x" + } + } + } + }, "text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -3645,6 +4150,14 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, + "topo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", + "integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==", + "requires": { + "hoek": "6.x.x" + } + }, "toposort-class": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", @@ -3762,6 +4275,22 @@ } } }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + } + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -3871,7 +4400,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3883,6 +4411,20 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -3891,8 +4433,7 @@ "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "yallist": { "version": "2.1.2", @@ -3903,7 +4444,6 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -3917,8 +4457,7 @@ "yargs-parser": { "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==" }, "yargs-unparser": { "version": "2.0.0", diff --git a/package.json b/package.json index ad60fce..c9f3947 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "sequelize": "^6.23.1", "superagent": "^8.0.0", "tc-core-library-js": "^2.4.1", + "tc-framework": "topcoder-platform/tc-framework.git#develop", "winston": "^3.8.1" } } diff --git a/src/common/logger.js b/src/common/logger.js index 770ebc0..8d9c359 100644 --- a/src/common/logger.js +++ b/src/common/logger.js @@ -1,152 +1,7 @@ /** - * This module contains the winston logger configuration. + * Configure the logger. */ -const _ = require('lodash'); -const Joi = require('joi'); -const winston = require('winston'); -const util = require('util'); -const config = require('config'); - -const transports = []; - -transports.push(new (winston.transports.Console)({ level: config.LOG_LEVEL })); - -if (config.DISABLE_LOGGING == 'false') { - transports.push(new (winston.transports.File)({ - filename: 'log.txt', - timestamp: true, - json: true, - })); -} - -const logger = winston.createLogger({ transports }); - -/** - * Log error details with signature - * @param err the error - * @param signature the signature - */ -logger.logFullError = function (err, signature) { // eslint-disable-line - if (!err) { - return; - } - if (signature) { - logger.error(signature); - } - const args = Array.prototype.slice.call(arguments); - args.shift(); - logger.error.apply(logger, args); - logger.error(util.inspect(err)); - if (!err.logged) { - logger.error(err.stack); - } - err.logged = true; -}; - -/** - * Sanitize object. - * @param {Object} obj the object - * @returns {Object} the new object with removed properties - * @private - */ -function _sanitizeObject(obj) { - try { - return JSON.parse(JSON.stringify(obj, (name, value) => { - if (_.isArray(value) && value.length > 30) { - return 'Array(' + value.length + ')'; - } - return value; - })); - } catch (e) { - return obj; - } -} - -/** - * Convert array with arguments to object - * @param {Array} params the name of parameters - * @param {Array} arr the array with values - * @private - */ -function _combineObject(params, arr) { - const ret = {}; - _.each(arr, (arg, i) => { - ret[params[i]] = arg; - }); - return ret; -} - -/** - * Decorate all functions of a service and log debug information if DEBUG is enabled - * @param {Object} service the service - */ -logger.decorateWithLogging = function (service) { - if (config.LOG_LEVEL !== 'debug') { - return; - } - _.each(service, (method, name) => { - //TODO: figure out a way to get params from method - const params = method.params || []; - service[name] = function* () { - logger.debug('ENTER ' + name); - logger.debug('input arguments'); - const args = Array.prototype.slice.call(arguments); - logger.debug(util.inspect(_sanitizeObject(_combineObject(params, args)))); - try { - const result = yield* method.apply(this, arguments); - logger.debug('EXIT ' + name); - logger.debug('output arguments'); - if (result !== null && result !== undefined) { - logger.debug('output arguments'); - logger.debug(util.inspect(_sanitizeObject(result))); - } - return result; - } catch (e) { - logger.logFullError(e, name); - throw e; - } - }; - }); -}; - -/** - * Decorate all functions of a service and validate input values - * and replace input arguments with sanitized result form Joi - * Service method must have a `schema` property with Joi schema - * @param {Object} service the service - */ -logger.decorateWithValidators = function (service) { - _.each(service, (method, name) => { - if (!method.schema) { - return; - } - //TODO: figure out a way to get params from method - const params = method.params || []; - service[name] = function* () { - const args = Array.prototype.slice.call(arguments); - const value = _combineObject(params, args); - const normalized = Joi.attempt(value, method.schema); - const newArgs = []; - // Joi will normalize values - // for example string number '1' to 1 - // if schema type is number - _.each(params, (param) => { - newArgs.push(normalized[param]); - }); - return yield method.apply(this, newArgs); - }; - service[name].params = params; - }); -}; - -/** - * Apply logger and validation decorators - * @param {Object} service the service to wrap - */ -logger.buildService = function (service) { - logger.decorateWithValidators(service); - logger.decorateWithLogging(service); -}; - -module.exports = logger; +const config = require('config') +const logger = require('tc-framework').logger(config) +module.exports = logger diff --git a/src/common/wrapper.js b/src/common/wrapper.js new file mode 100644 index 0000000..6eaa6d6 --- /dev/null +++ b/src/common/wrapper.js @@ -0,0 +1,20 @@ +const logger = require('../common/logger') + +function functionWrapper (fn, fnName) { + return async function () { + const span = await logger.startSpan(fnName ?? fn.name) + try { + const result = await fn.apply(this, arguments) + await logger.endSpan(span) + return result + } catch (e) { + await logger.endSpanWithError(span, e) + throw e + } + } +} + +module.exports = { + functionWrapper +} +logger.buildService(module.exports) diff --git a/src/init.js b/src/init.js index 11e41c9..666ddf5 100644 --- a/src/init.js +++ b/src/init.js @@ -7,6 +7,7 @@ const _ = require('lodash'); const { Kafka } = require('kafkajs') const logger = require('./common/logger'); const models = require('./models'); +const { functionWrapper } = require('./common/wrapper'); /** @@ -39,65 +40,75 @@ async function configureKafkaConsumer(handlers) { async function dataHandler(consumer, handlers) { - await consumer.run({ - eachMessage: async (data) => { - const topic = data.topic - const msg = data.message - const partition = data.partition - //If there is no message, return - if (!msg) return - const message = msg.value.toString('utf8') - logger.info(`Handle Kafka event message; Topic: ${topic}; Partition: ${partition}; Message: ${message}.`); - // ignore configured Kafka topic prefix - let topicName = topic; - // find handler - const handler = handlers[topicName]; - if (!handler) { - logger.info(`No handler configured for topic: ${topicName}`); - // return null to ignore this message - return null; - } - const emailModel = await models.loadEmailModule() - const busPayload = JSON.parse(message); - const messageJSON = busPayload.payload; - try { - const emailInfo = { - status: 'PENDING', - topicName, - data: JSON.stringify(messageJSON), - recipients: JSON.stringify(messageJSON.recipients), + + (await functionWrapper(async () => { + + + await consumer.run({ + eachMessage: async (data) => { + const topic = data.topic + const msg = data.message + const partition = data.partition + //If there is no message, return + if (!msg) return + const message = msg.value.toString('utf8') + logger.info(`Handle Kafka event message; Topic: ${topic}; Partition: ${partition}; Message: ${message}.`); + // ignore configured Kafka topic prefix + let topicName = topic; + // find handler + const handler = handlers[topicName]; + if (!handler) { + logger.info(`No handler configured for topic: ${topicName}`); + // return null to ignore this message + return null; } + const emailModel = await models.loadEmailModule() + const busPayload = JSON.parse(message); + const messageJSON = busPayload.payload; + try { + const emailInfo = { + status: 'PENDING', + topicName, + data: JSON.stringify(messageJSON), + recipients: JSON.stringify(messageJSON.recipients), + } - await emailModel.create(emailInfo) - const result = await handler(topicName, messageJSON); - - logger.info('info', 'Email sent', { - sender: 'Connect', - to_address: messageJSON.recipients.join(','), - from_address: config.EMAIL_FROM, - status: result.success ? 'Message accepted' : 'Message rejected', - error: result.error ? result.error.toString() : 'No error message', - }); - const emailTries = {} - if (result.success) { - emailTries[topicName] = 0; - emailModel.status = 'SUCCESS'; - await emailModel.save(); - } else { - // emailTries[topicName] += 1; //temporary disabling this feature - if (result.error) { - logger.error('error', 'Send email error details', result.error); + await emailModel.create(emailInfo) + const result = await handler(topicName, messageJSON); + + logger.info('info', 'Email sent', { + sender: 'Connect', + to_address: messageJSON.recipients.join(','), + from_address: config.EMAIL_FROM, + status: result.success ? 'Message accepted' : 'Message rejected', + error: result.error ? result.error.toString() : 'No error message', + }); + const emailTries = {} + if (result.success) { + emailTries[topicName] = 0; + emailModel.status = 'SUCCESS'; + await emailModel.save(); + } else { + // emailTries[topicName] += 1; //temporary disabling this feature + if (result.error) { + logger.error('error', 'Send email error details', result.error); + } } + } catch (e) { + logger.error(e) } - } catch (e) { - logger.error(e) - } - }, - }) + }, + }) + + + + }, 'dataHandler'))(consumer, handlers); + + const errorTypes = ['unhandledRejection', 'uncaughtException'] const signalTraps = ['SIGTERM', 'SIGINT', 'SIGUSR2'] @@ -125,6 +136,8 @@ async function dataHandler(consumer, handlers) { }) }) + + }