Merge branch 'main' of github.com:jambonz/jambonz-feature-server into feature/cognigy-enhancements-alex

This commit is contained in:
akirilyuk
2022-02-03 17:04:02 +01:00
9 changed files with 85 additions and 59 deletions

View File

@@ -1,4 +1,4 @@
FROM node:17-slim FROM node:17.4-slim
WORKDIR /opt/app/ WORKDIR /opt/app/
COPY package.json ./ COPY package.json ./
RUN npm install RUN npm install

3
app.js
View File

@@ -31,6 +31,7 @@ const {
// HTTP // HTTP
const express = require('express'); const express = require('express');
const helmet = require('helmet');
const app = express(); const app = express();
Object.assign(app.locals, { Object.assign(app.locals, {
logger, logger,
@@ -73,6 +74,8 @@ srf.invite((req, res) => {
}); });
// HTTP // HTTP
app.use(helmet());
app.use(helmet.hidePoweredBy());
app.use(express.urlencoded({ extended: true })); app.use(express.urlencoded({ extended: true }));
app.use(express.json()); app.use(express.json());
app.use('/', httpRoutes); app.use('/', httpRoutes);

View File

@@ -35,6 +35,8 @@ router.post('/', async(req, res) => {
opts.headers = { opts.headers = {
...opts.headers, ...opts.headers,
'X-Jambonz-Routing': target.type,
'X-Jambonz-FS-UUID': srf.locals.fsUUID,
'X-Call-Sid': callSid, 'X-Call-Sid': callSid,
'X-Account-Sid': req.body.account_sid 'X-Account-Sid': req.body.account_sid
}; };

View File

@@ -264,6 +264,12 @@ class CallSession extends Emitter {
region: credential.region region: credential.region
}; };
} }
else if ('wellsaid' === vendor) {
return {
speech_credential_sid: credential.speech_credential_sid,
api_key: credential.api_key
};
}
} }
else { else {
writeAlerts({ writeAlerts({

View File

@@ -179,6 +179,7 @@ class TaskDial extends Task {
this._killOutdials(); this._killOutdials();
if (this.sd) { if (this.sd) {
this.sd.kill(); this.sd.kill();
this.sd.removeAllListeners();
this.sd = null; this.sd = null;
} }
if (this.callSid) sessionTracker.remove(this.callSid); if (this.callSid) sessionTracker.remove(this.callSid);

View File

@@ -62,7 +62,9 @@ class Task extends Emitter {
kill(cs) { kill(cs) {
if (this.cs && !this.cs.isConfirmCallSession) this.logger.debug(`${this.name} is being killed`); if (this.cs && !this.cs.isConfirmCallSession) this.logger.debug(`${this.name} is being killed`);
this._killInProgress = true; this._killInProgress = true;
// no-op
/* remove reference to parent task or else entangled parent-child tasks will not be gc'ed */
setImmediate(() => this.parentTask = null);
} }
/** /**

View File

@@ -36,6 +36,10 @@ const speechMapper = (cred) => {
obj.api_key = o.api_key; obj.api_key = o.api_key;
obj.region = o.region; obj.region = o.region;
} }
else if ('wellsaid' === obj.vendor) {
const o = JSON.parse(decrypt(credential));
obj.api_key = o.api_key;
}
return obj; return obj;
}; };
@@ -53,6 +57,7 @@ module.exports = (logger, srf) => {
const haveGoogle = speech.find((s) => s.vendor === 'google'); const haveGoogle = speech.find((s) => s.vendor === 'google');
const haveAws = speech.find((s) => s.vendor === 'aws'); const haveAws = speech.find((s) => s.vendor === 'aws');
const haveMicrosoft = speech.find((s) => s.vendor === 'microsoft'); const haveMicrosoft = speech.find((s) => s.vendor === 'microsoft');
const haveWellsaid = speech.find((s) => s.vendor === 'wellsaid');
if (!haveGoogle || !haveAws || !haveMicrosoft) { if (!haveGoogle || !haveAws || !haveMicrosoft) {
const [r3] = await pp.query(sqlSpeechCredentialsForSP, account_sid); const [r3] = await pp.query(sqlSpeechCredentialsForSP, account_sid);
if (r3.length) { if (r3.length) {
@@ -68,6 +73,10 @@ module.exports = (logger, srf) => {
const ms = r3.find((s) => s.vendor === 'microsoft'); const ms = r3.find((s) => s.vendor === 'microsoft');
if (ms) speech.push(speechMapper(ms)); if (ms) speech.push(speechMapper(ms));
} }
if (!haveWellsaid) {
const wellsaid = r3.find((s) => s.vendor === 'wellsaid');
if (wellsaid) speech.push(speechMapper(wellsaid));
}
} }
} }

108
package-lock.json generated
View File

@@ -1,29 +1,30 @@
{ {
"name": "jambonz-feature-server", "name": "jambonz-feature-server",
"version": "v0.7.1", "version": "v0.7.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "jambonz-feature-server", "name": "jambonz-feature-server",
"version": "v0.7.1", "version": "v0.7.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@cognigy/socket-client": "^4.5.5", "@cognigy/socket-client": "^4.5.5",
"@jambonz/db-helpers": "^0.6.16", "@jambonz/db-helpers": "^0.6.16",
"@jambonz/http-health-check": "^0.0.1", "@jambonz/http-health-check": "^0.0.1",
"@jambonz/mw-registrar": "^0.2.1", "@jambonz/mw-registrar": "^0.2.1",
"@jambonz/realtimedb-helpers": "^0.4.17", "@jambonz/realtimedb-helpers": "^0.4.19",
"@jambonz/stats-collector": "^0.1.6", "@jambonz/stats-collector": "^0.1.6",
"@jambonz/time-series": "^0.1.5", "@jambonz/time-series": "^0.1.6",
"aws-sdk": "^2.1060.0", "aws-sdk": "^2.1060.0",
"bent": "^7.3.12", "bent": "^7.3.12",
"cidr-matcher": "^2.1.1", "cidr-matcher": "^2.1.1",
"debug": "^4.3.2", "debug": "^4.3.2",
"deepcopy": "^2.1.0", "deepcopy": "^2.1.0",
"drachtio-fsmrf": "^2.0.13", "drachtio-fsmrf": "^2.0.13",
"drachtio-srf": "^4.4.55", "drachtio-srf": "^4.4.61",
"express": "^4.17.1", "express": "^4.17.1",
"helmet": "^5.0.2",
"ip": "^1.1.5", "ip": "^1.1.5",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"moment": "^2.29.1", "moment": "^2.29.1",
@@ -547,13 +548,14 @@
} }
}, },
"node_modules/@jambonz/realtimedb-helpers": { "node_modules/@jambonz/realtimedb-helpers": {
"version": "0.4.17", "version": "0.4.19",
"resolved": "https://registry.npmjs.org/@jambonz/realtimedb-helpers/-/realtimedb-helpers-0.4.17.tgz", "resolved": "https://registry.npmjs.org/@jambonz/realtimedb-helpers/-/realtimedb-helpers-0.4.19.tgz",
"integrity": "sha512-ERE+VLAmbZJ4DFIHXS689xr3EDVPWvpLxx69kSb/Z+QAZtbbv7a2E7XmJ6/QxF25VgKxNHOg949qYCFoWxb2RQ==", "integrity": "sha512-wEc7OXogQ5SZ9mgLNxviBNY0WvUKGGztyDzze3oi44edsZp0vNneVHUmdZuDzuDvUMBqsvCa0fvri8LGaxovlw==",
"dependencies": { "dependencies": {
"@google-cloud/text-to-speech": "^3.4.0", "@google-cloud/text-to-speech": "^3.4.0",
"@jambonz/promisify-redis": "^0.0.6", "@jambonz/promisify-redis": "^0.0.6",
"aws-sdk": "^2.1060.0", "aws-sdk": "^2.1060.0",
"bent": "^7.3.12",
"debug": "^4.3.3", "debug": "^4.3.3",
"microsoft-cognitiveservices-speech-sdk": "^1.19.0", "microsoft-cognitiveservices-speech-sdk": "^1.19.0",
"redis": "^3.1.2" "redis": "^3.1.2"
@@ -569,9 +571,9 @@
} }
}, },
"node_modules/@jambonz/time-series": { "node_modules/@jambonz/time-series": {
"version": "0.1.5", "version": "0.1.6",
"resolved": "https://registry.npmjs.org/@jambonz/time-series/-/time-series-0.1.5.tgz", "resolved": "https://registry.npmjs.org/@jambonz/time-series/-/time-series-0.1.6.tgz",
"integrity": "sha512-JDkAshqq9VRdIY7S/Edz9iIyKNoyCoUMfn0IUVyUG4Hf53fmhYRCnFnDTdMFAs6Y4amE39m3968nrZRr+lVIqQ==", "integrity": "sha512-EFO1ZFUazHLCzDYkAbpke0IfmPRogLkGg+KGWwz3SGpnuiltfohQ3TsJ5KG8Gp9mXqdpkyAioWSdaJxGDquthQ==",
"dependencies": { "dependencies": {
"debug": "^4.3.1", "debug": "^4.3.1",
"influx": "^5.8.0" "influx": "^5.8.0"
@@ -1604,9 +1606,9 @@
} }
}, },
"node_modules/drachtio-sip": { "node_modules/drachtio-sip": {
"version": "0.6.2", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/drachtio-sip/-/drachtio-sip-0.6.2.tgz", "resolved": "https://registry.npmjs.org/drachtio-sip/-/drachtio-sip-0.6.3.tgz",
"integrity": "sha512-BkiRZq3Yq2WVSGY3M7Hv4yX4dIW/o0/4xNMcm26IxT71YIRy07UtbQUHaMI3P2HfPu5zK6RoQW2MHrxPXtz6ZQ==", "integrity": "sha512-sQQ2JdRQ58z+WbkxORlWKZCeinu499tugfsdh7jRBWX6SO4odDevT5JL+42dMlwrL83CZUL6w2Xjgu0uaABoMQ==",
"dependencies": { "dependencies": {
"debug": "^4.3.1", "debug": "^4.3.1",
"eslint-plugin-promise": "^5.1.0", "eslint-plugin-promise": "^5.1.0",
@@ -1614,9 +1616,9 @@
} }
}, },
"node_modules/drachtio-sip/node_modules/eslint-plugin-promise": { "node_modules/drachtio-sip/node_modules/eslint-plugin-promise": {
"version": "5.1.1", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.1.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz",
"integrity": "sha512-XgdcdyNzHfmlQyweOPTxmc7pIsS6dE4MvwhXWMQ2Dxs1XAL2GJDilUsjWen6TWik0aSI+zD/PqocZBblcm9rdA==", "integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==",
"engines": { "engines": {
"node": "^10.12.0 || >=12.0.0" "node": "^10.12.0 || >=12.0.0"
}, },
@@ -1625,15 +1627,15 @@
} }
}, },
"node_modules/drachtio-srf": { "node_modules/drachtio-srf": {
"version": "4.4.59", "version": "4.4.61",
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.59.tgz", "resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.61.tgz",
"integrity": "sha512-hrW9bZ8TZR9JQ3pqI+nyrI1eAzEOwHuvm1lNL1fbmZmRddKJzYdylkgVoyURs/OlT/nANy/M43GrQjcGP4psPw==", "integrity": "sha512-HZwKTAR6V7dc84BV50h5xAopkQ1k8wUy04JXDmq2/O+uryANFwaklICidg1oJkIrnYUPWQn/1IfZnqGSv9O2Sw==",
"dependencies": { "dependencies": {
"async": "^1.4.2", "async": "^1.4.2",
"debug": "^3.2.7", "debug": "^3.2.7",
"delegates": "^0.1.0", "delegates": "^0.1.0",
"deprecate": "^1.1.1", "deprecate": "^1.1.1",
"drachtio-sip": "^0.6.2", "drachtio-sip": "^0.6.3",
"node-noop": "0.0.1", "node-noop": "0.0.1",
"only": "0.0.2", "only": "0.0.2",
"sdp-transform": "^2.14.1", "sdp-transform": "^2.14.1",
@@ -1641,7 +1643,7 @@
"sip-methods": "^0.3.0", "sip-methods": "^0.3.0",
"sip-status": "^0.1.0", "sip-status": "^0.1.0",
"utils-merge": "1.0.0", "utils-merge": "1.0.0",
"uuid": "^3.4.0" "uuid": "^8.3.2"
}, },
"engines": { "engines": {
"node": ">= 6.9.3" "node": ">= 6.9.3"
@@ -1660,15 +1662,6 @@
"ms": "^2.1.1" "ms": "^2.1.1"
} }
}, },
"node_modules/drachtio-srf/node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/duplexify": { "node_modules/duplexify": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz",
@@ -2720,6 +2713,14 @@
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.2.1.tgz", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.2.1.tgz",
"integrity": "sha1-B8tKXfJa3Z6Cbrxn3Mn9idsn2Eo=" "integrity": "sha1-B8tKXfJa3Z6Cbrxn3Mn9idsn2Eo="
}, },
"node_modules/helmet": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-5.0.2.tgz",
"integrity": "sha512-QWlwUZZ8BtlvwYVTSDTBChGf8EOcQ2LkGMnQJxSzD1mUu8CCjXJZq/BXP8eWw4kikRnzlhtYo3lCk0ucmYA3Vg==",
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/hot-shots": { "node_modules/hot-shots": {
"version": "8.5.2", "version": "8.5.2",
"resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-8.5.2.tgz", "resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-8.5.2.tgz",
@@ -5886,13 +5887,14 @@
} }
}, },
"@jambonz/realtimedb-helpers": { "@jambonz/realtimedb-helpers": {
"version": "0.4.17", "version": "0.4.19",
"resolved": "https://registry.npmjs.org/@jambonz/realtimedb-helpers/-/realtimedb-helpers-0.4.17.tgz", "resolved": "https://registry.npmjs.org/@jambonz/realtimedb-helpers/-/realtimedb-helpers-0.4.19.tgz",
"integrity": "sha512-ERE+VLAmbZJ4DFIHXS689xr3EDVPWvpLxx69kSb/Z+QAZtbbv7a2E7XmJ6/QxF25VgKxNHOg949qYCFoWxb2RQ==", "integrity": "sha512-wEc7OXogQ5SZ9mgLNxviBNY0WvUKGGztyDzze3oi44edsZp0vNneVHUmdZuDzuDvUMBqsvCa0fvri8LGaxovlw==",
"requires": { "requires": {
"@google-cloud/text-to-speech": "^3.4.0", "@google-cloud/text-to-speech": "^3.4.0",
"@jambonz/promisify-redis": "^0.0.6", "@jambonz/promisify-redis": "^0.0.6",
"aws-sdk": "^2.1060.0", "aws-sdk": "^2.1060.0",
"bent": "^7.3.12",
"debug": "^4.3.3", "debug": "^4.3.3",
"microsoft-cognitiveservices-speech-sdk": "^1.19.0", "microsoft-cognitiveservices-speech-sdk": "^1.19.0",
"redis": "^3.1.2" "redis": "^3.1.2"
@@ -5908,9 +5910,9 @@
} }
}, },
"@jambonz/time-series": { "@jambonz/time-series": {
"version": "0.1.5", "version": "0.1.6",
"resolved": "https://registry.npmjs.org/@jambonz/time-series/-/time-series-0.1.5.tgz", "resolved": "https://registry.npmjs.org/@jambonz/time-series/-/time-series-0.1.6.tgz",
"integrity": "sha512-JDkAshqq9VRdIY7S/Edz9iIyKNoyCoUMfn0IUVyUG4Hf53fmhYRCnFnDTdMFAs6Y4amE39m3968nrZRr+lVIqQ==", "integrity": "sha512-EFO1ZFUazHLCzDYkAbpke0IfmPRogLkGg+KGWwz3SGpnuiltfohQ3TsJ5KG8Gp9mXqdpkyAioWSdaJxGDquthQ==",
"requires": { "requires": {
"debug": "^4.3.1", "debug": "^4.3.1",
"influx": "^5.8.0" "influx": "^5.8.0"
@@ -6755,9 +6757,9 @@
} }
}, },
"drachtio-sip": { "drachtio-sip": {
"version": "0.6.2", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/drachtio-sip/-/drachtio-sip-0.6.2.tgz", "resolved": "https://registry.npmjs.org/drachtio-sip/-/drachtio-sip-0.6.3.tgz",
"integrity": "sha512-BkiRZq3Yq2WVSGY3M7Hv4yX4dIW/o0/4xNMcm26IxT71YIRy07UtbQUHaMI3P2HfPu5zK6RoQW2MHrxPXtz6ZQ==", "integrity": "sha512-sQQ2JdRQ58z+WbkxORlWKZCeinu499tugfsdh7jRBWX6SO4odDevT5JL+42dMlwrL83CZUL6w2Xjgu0uaABoMQ==",
"requires": { "requires": {
"debug": "^4.3.1", "debug": "^4.3.1",
"eslint-plugin-promise": "^5.1.0", "eslint-plugin-promise": "^5.1.0",
@@ -6765,23 +6767,23 @@
}, },
"dependencies": { "dependencies": {
"eslint-plugin-promise": { "eslint-plugin-promise": {
"version": "5.1.1", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.1.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz",
"integrity": "sha512-XgdcdyNzHfmlQyweOPTxmc7pIsS6dE4MvwhXWMQ2Dxs1XAL2GJDilUsjWen6TWik0aSI+zD/PqocZBblcm9rdA==", "integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==",
"requires": {} "requires": {}
} }
} }
}, },
"drachtio-srf": { "drachtio-srf": {
"version": "4.4.59", "version": "4.4.61",
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.59.tgz", "resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.61.tgz",
"integrity": "sha512-hrW9bZ8TZR9JQ3pqI+nyrI1eAzEOwHuvm1lNL1fbmZmRddKJzYdylkgVoyURs/OlT/nANy/M43GrQjcGP4psPw==", "integrity": "sha512-HZwKTAR6V7dc84BV50h5xAopkQ1k8wUy04JXDmq2/O+uryANFwaklICidg1oJkIrnYUPWQn/1IfZnqGSv9O2Sw==",
"requires": { "requires": {
"async": "^1.4.2", "async": "^1.4.2",
"debug": "^3.2.7", "debug": "^3.2.7",
"delegates": "^0.1.0", "delegates": "^0.1.0",
"deprecate": "^1.1.1", "deprecate": "^1.1.1",
"drachtio-sip": "^0.6.2", "drachtio-sip": "^0.6.3",
"node-noop": "0.0.1", "node-noop": "0.0.1",
"only": "0.0.2", "only": "0.0.2",
"sdp-transform": "^2.14.1", "sdp-transform": "^2.14.1",
@@ -6789,7 +6791,7 @@
"sip-methods": "^0.3.0", "sip-methods": "^0.3.0",
"sip-status": "^0.1.0", "sip-status": "^0.1.0",
"utils-merge": "1.0.0", "utils-merge": "1.0.0",
"uuid": "^3.4.0" "uuid": "^8.3.2"
}, },
"dependencies": { "dependencies": {
"async": { "async": {
@@ -6804,11 +6806,6 @@
"requires": { "requires": {
"ms": "^2.1.1" "ms": "^2.1.1"
} }
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
} }
} }
}, },
@@ -7637,6 +7634,11 @@
} }
} }
}, },
"helmet": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-5.0.2.tgz",
"integrity": "sha512-QWlwUZZ8BtlvwYVTSDTBChGf8EOcQ2LkGMnQJxSzD1mUu8CCjXJZq/BXP8eWw4kikRnzlhtYo3lCk0ucmYA3Vg=="
},
"hot-shots": { "hot-shots": {
"version": "8.5.2", "version": "8.5.2",
"resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-8.5.2.tgz", "resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-8.5.2.tgz",

View File

@@ -1,6 +1,6 @@
{ {
"name": "jambonz-feature-server", "name": "jambonz-feature-server",
"version": "v0.7.1", "version": "v0.7.2",
"main": "app.js", "main": "app.js",
"engines": { "engines": {
"node": ">= 10.16.0" "node": ">= 10.16.0"
@@ -31,17 +31,18 @@
"@jambonz/db-helpers": "^0.6.16", "@jambonz/db-helpers": "^0.6.16",
"@jambonz/http-health-check": "^0.0.1", "@jambonz/http-health-check": "^0.0.1",
"@jambonz/mw-registrar": "^0.2.1", "@jambonz/mw-registrar": "^0.2.1",
"@jambonz/realtimedb-helpers": "^0.4.17", "@jambonz/realtimedb-helpers": "^0.4.19",
"@jambonz/stats-collector": "^0.1.6", "@jambonz/stats-collector": "^0.1.6",
"@jambonz/time-series": "^0.1.5", "@jambonz/time-series": "^0.1.6",
"aws-sdk": "^2.1060.0", "aws-sdk": "^2.1060.0",
"bent": "^7.3.12", "bent": "^7.3.12",
"cidr-matcher": "^2.1.1", "cidr-matcher": "^2.1.1",
"debug": "^4.3.2", "debug": "^4.3.2",
"deepcopy": "^2.1.0", "deepcopy": "^2.1.0",
"drachtio-fsmrf": "^2.0.13", "drachtio-fsmrf": "^2.0.13",
"drachtio-srf": "^4.4.55", "drachtio-srf": "^4.4.61",
"express": "^4.17.1", "express": "^4.17.1",
"helmet": "^5.0.2",
"ip": "^1.1.5", "ip": "^1.1.5",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"moment": "^2.29.1", "moment": "^2.29.1",