diff --git a/package-lock.json b/package-lock.json
index a118566b8..ebca1057e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -95,6 +95,7 @@
"@types/node": "^8.10.61",
"@types/supertest": "^6.0.2",
"babel-jest": "^29.7.0",
+ "baseline-browser-mapping": "^2.10.29",
"eslint": "^8.47.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-base": "^15.0.0",
@@ -1577,6 +1578,7 @@
"node_modules/@babel/core": {
"version": "7.28.5",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@@ -4548,6 +4550,7 @@
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz",
"integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"cluster-key-slot": "1.1.2",
"generic-pool": "3.9.0",
@@ -5700,6 +5703,7 @@
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz",
"integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/node": "*",
"form-data": "^4.0.4"
@@ -5871,6 +5875,7 @@
"version": "8.15.0",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -5900,6 +5905,7 @@
"node_modules/ajv": {
"version": "6.12.6",
"license": "MIT",
+ "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -6887,10 +6893,15 @@
}
},
"node_modules/baseline-browser-mapping": {
- "version": "2.8.25",
+ "version": "2.10.29",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz",
+ "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==",
"license": "Apache-2.0",
"bin": {
- "baseline-browser-mapping": "dist/cli.js"
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
}
},
"node_modules/basic-ftp": {
@@ -7128,6 +7139,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.19",
"caniuse-lite": "^1.0.30001751",
@@ -8168,6 +8180,7 @@
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/runtime": "^7.21.0"
},
@@ -8368,7 +8381,8 @@
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1581282.tgz",
"integrity": "sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ==",
"dev": true,
- "license": "BSD-3-Clause"
+ "license": "BSD-3-Clause",
+ "peer": true
},
"node_modules/dezalgo": {
"version": "1.0.4",
@@ -9031,6 +9045,7 @@
"integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -9208,6 +9223,7 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -9265,6 +9281,7 @@
"integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"aria-query": "^5.3.2",
"array-includes": "^3.1.8",
@@ -9295,6 +9312,7 @@
"integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"array-includes": "^3.1.8",
"array.prototype.findlast": "^1.2.5",
@@ -9328,6 +9346,7 @@
"integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=10"
},
@@ -19792,6 +19811,7 @@
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
"integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=10.0.0"
},
diff --git a/package.json b/package.json
index c488c5e5d..991e548ab 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
"@types/node": "^8.10.61",
"@types/supertest": "^6.0.2",
"babel-jest": "^29.7.0",
+ "baseline-browser-mapping": "^2.10.29",
"eslint": "^8.47.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-base": "^15.0.0",
diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js
index eef1dd74f..6472be314 100644
--- a/src/controllers/userProfileController.js
+++ b/src/controllers/userProfileController.js
@@ -2089,6 +2089,8 @@ const createControllerMethods = function (UserProfile, Project, cache) {
if (userIdx !== -1) {
const userData = allUserData[userIdx];
userData.isActive = user.isActive;
+ userData.reactivationDate = null;
+ userData.endDate = null;
allUserData.splice(userIdx, 1, userData);
cache.setCache('allusers', JSON.stringify(allUserData));
}
diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js
index 8146116f1..d76d554bb 100644
--- a/src/helpers/userHelper.js
+++ b/src/helpers/userHelper.js
@@ -39,6 +39,7 @@ const Timer = require('../models/timer');
const DEFAULT_CC_EMAILS = ['onecommunityglobal@gmail.com', 'jae@onecommunityglobal.org'];
const DEFAULT_BCC_EMAILS = ['onecommunityhospitality@gmail.com'];
const DEFAULT_REPLY_TO = ['jae@onecommunityglobal.org'];
+const { COMPANY_TZ } = require('../constants/company');
const delay = (ms) =>
new Promise((resolve) => {
@@ -2260,7 +2261,7 @@ const userHelper = function () {
const lastDay = moment(person.endDate).format('YYYY-MM-DD');
logger.logInfo(`User with id: ${user._id}'s final Day is set at ${moment().format()}.`);
person.teams.map(async (teamId) => {
- const managementEmails = await userHelper.getTeamManagementEmail(teamId);
+ const managementEmails = await getTeamManagementEmail(teamId);
if (Array.isArray(managementEmails) && managementEmails.length > 0) {
managementEmails.forEach((management) => {
recipients.push(management.email);
@@ -2297,7 +2298,7 @@ const userHelper = function () {
const lastDay = moment(person.endDate).format('YYYY-MM-DD');
logger.logInfo(`User with id: ${user._id} was de-activated at ${moment().format()}.`);
person.teams.map(async (teamId) => {
- const managementEmails = await userHelper.getTeamManagementEmail(teamId);
+ const managementEmails = await getTeamManagementEmail(teamId);
if (Array.isArray(managementEmails) && managementEmails.length > 0) {
managementEmails.forEach((management) => {
recipients.push(management.email);
@@ -2628,12 +2629,316 @@ const userHelper = function () {
}
};
+ const sendUserPausedEmail = ({ firstName, lastName, email, reactivationDate, recipients }) => {
+ const returnDate = moment(reactivationDate)
+ .tz(COMPANY_TZ)
+ .add(1, 'day') // adding a day to make it clear they return on the day of reactivation
+ .format('M-D-YYYY');
+ const subject = `IMPORTANT: ${firstName} ${lastName} has been PAUSED in the Highest Good Network`;
+
+ const emailBody = `
+
Management,
+
+ Please note that ${firstName} ${lastName} has been PAUSED in the Highest Good Network.
+
+
+ Please confirm all work has been wrapped up until they return on
+ ${returnDate}.
+
+ With Gratitude,
One Community
+ `;
+
+ emailSender(recipients, subject, emailBody, null, email);
+ };
+
+ const sendUserSeparatedEmail = ({ firstName, lastName, email, recipients, endDate }) => {
+ const formattedFinalDay = moment(endDate).tz(COMPANY_TZ).format('M-D-YYYY');
+ const subject = `IMPORTANT: ${firstName} ${lastName} has been deactivated in the Highest Good Network`;
+
+ const emailBody = `
+ Management,
+
+ Please note that ${firstName} ${lastName} has been DEACTIVATED and made inactive in the Highest Good Network from ${formattedFinalDay} onwards.
+
+
+ Please confirm all work has been wrapped up and nothing further is required.
+
+ With Gratitude,
One Community
+ `;
+
+ emailSender(recipients, subject, emailBody, null, email);
+ };
+
+ const sendUserActivatedEmail = ({ firstName, lastName, email, recipients }) => {
+ const subject = `IMPORTANT: ${firstName} ${lastName} has been activated in the Highest Good Network`;
+
+ const emailBody = `
+ Management,
+
+ ${firstName} ${lastName} has been activated in the Highest Good Network.
+
+ Email: ${email}
+ With Gratitude,
One Community
+ `;
+
+ emailSender(recipients, subject, emailBody, null, email);
+ };
+
+ const sendUserScheduledSeparationEmail = ({
+ firstName,
+ lastName,
+ email,
+ endDate,
+ recipients,
+ }) => {
+ const formattedFinalDay = endDate ? moment(endDate).tz(COMPANY_TZ).format('M-D-YYYY') : 'N/A';
+ const subject = `IMPORTANT: ${firstName} ${lastName} has a FINAL DAY scheduled in the Highest Good Network`;
+
+ const emailBody = `
+ Management,
+
+ Please note that ${firstName} ${lastName} has a FINAL DAY scheduled in the Highest Good Network.
+
+
+ The final day is set for ${formattedFinalDay}, and they have until the end of this day to continue logging hours.
+
+
+ Please begin wrapping up any remaining work as they will be deactivated the following day.
+
+ With Gratitude,
One Community
+ `;
+
+ emailSender(recipients, subject, emailBody, null, email);
+ };
+
+ const sendUserResumedEmail = ({ firstName, lastName, email, recipients, pausedOn }) => {
+ const formattedPausedOn = pausedOn
+ ? moment(pausedOn).tz(COMPANY_TZ).format('M-D-YYYY')
+ : 'an earlier date';
+ const subject = `IMPORTANT: ${firstName} ${lastName} has been RESUMED in the Highest Good Network`;
+
+ const emailBody = `
+ Management,
+
+ Please note that ${firstName} ${lastName}, who was previously PAUSED in the Highest Good Network on
+ ${formattedPausedOn}, has now been RESUMED and is active again.
+
+
+ ${firstName} ${lastName} will remain active until they are deactivated, paused again,
+ or a final day is scheduled.
+
+ With Gratitude,
One Community
+ `;
+
+ emailSender(recipients, subject, emailBody, null, email);
+ };
+
+ const sendUserReactivatedAfterSeparation = ({
+ firstName,
+ lastName,
+ email,
+ recipients,
+ previousEndDate,
+ }) => {
+ const formattedPreviousEndDate = moment(previousEndDate).tz(COMPANY_TZ).format('M-D-YYYY');
+ const subject = `IMPORTANT: ${firstName} ${lastName} has been REACTIVATED in the Highest Good Network`;
+
+ const emailBody = `
+ Management,
+
+ Please note that ${firstName} ${lastName}, who was previously DEACTIVATED from the Highest Good Network on
+ ${formattedPreviousEndDate}, has now been REACTIVATED.
+
+
+ ${firstName} ${lastName} is currently active and will remain so until they are deactivated,
+ paused, or a final day is scheduled.
+
+ With Gratitude,
One Community
+ `;
+
+ emailSender(recipients, subject, emailBody, null, email);
+ };
+
+ const sendUserCancelledSeparationEmail = ({
+ firstName,
+ lastName,
+ email,
+ recipients,
+ previousEndDate,
+ }) => {
+ const formattedPreviousEndDate = moment(previousEndDate).tz(COMPANY_TZ).format('M-D-YYYY');
+ const subject = `IMPORTANT: Final Day has been CANCELLED for ${firstName} ${lastName}`;
+
+ const emailBody = `
+ Management,
+
+ Please note that the previously scheduled FINAL DAY for ${firstName} ${lastName}
+ in the Highest Good Network as ${formattedPreviousEndDate} has now been REMOVED.
+
+
+ ${firstName} ${lastName} is currently active and will remain so until they are
+ deactivated, paused, or a new final day is scheduled.
+
+ With Gratitude,
One Community
+ `;
+
+ emailSender(recipients, subject, emailBody, null, email);
+ };
+
+ async function finalizeUserEndDates() {
+ const now = moment.tz(COMPANY_TZ);
+
+ // 1) Only users who are scheduled for separation (still active)
+ const users = await userProfile.find({
+ isActive: true,
+ endDate: { $ne: null },
+ inactiveReason: InactiveReason.SCHEDULED_SEPARATION,
+ // Safety: should not be a paused user
+ reactivationDate: { $in: [null, undefined] },
+ });
+
+ console.log('Found', users.length, 'scheduled-separation users to process.');
+
+ for (const user of users) {
+ const scheduledEndMoment = moment(user.endDate).tz(COMPANY_TZ).endOf('day');
+ const recipients = await getEmailRecipientsForStatusChange(user._id);
+
+ // 2) 3-week email logic (trigger window starts at start of day, 3 weeks before endDate)
+ if (
+ !user.finalEmailThreeWeeksSent &&
+ now.isSameOrAfter(
+ moment(scheduledEndMoment)
+ .subtract(WEEKS_BEFORE_END_DATE_FOR_EMAIL, 'weeks')
+ .startOf('day'),
+ ) &&
+ now.isBefore(scheduledEndMoment) // only while still pending
+ ) {
+ await sendThreeWeekFinalDayEmail({
+ email: user.email,
+ firstName: user.firstName,
+ lastName: user.lastName,
+ endDate: user.endDate, // IMPORTANT: email references scheduled endDate
+ recipients,
+ });
+
+ user.finalEmailThreeWeeksSent = true;
+ await user.save();
+ }
+
+ // 3) If endDate hasn't passed yet, skip finalization
+ if (now.isBefore(scheduledEndMoment)) continue;
+
+ // 4) Finalize separation
+ if (user.deactivatedAt) continue; // safety check
+
+ user.deactivatedAt = now.toDate();
+ user.isActive = false;
+ user.inactiveReason = InactiveReason.SEPARATED;
+ user.endDate = resolveEffectiveEndDate(user).toDate();
+ sendUserSeparatedEmail({
+ firstName: user.firstName,
+ lastName: user.lastName,
+ email: user.email,
+ recipients,
+ endDate: user.endDate,
+ });
+ await user.save();
+ }
+ }
+
+ function resolveEffectiveEndDate(user) {
+ // 1) endDate + lastActivityAt → earlier of the two
+ if (user?.endDate && user?.lastActivityAt) {
+ return moment.min(
+ moment(user.endDate).tz(COMPANY_TZ),
+ moment(user.lastActivityAt).tz(COMPANY_TZ),
+ );
+ }
+
+ // 2) no lastActivityAt → use createdDate (normalized to COMPANY_TZ)
+ if (!user?.lastActivityAt && user?.createdDate) {
+ return moment.tz(user.createdDate, 'YYYY-MM-DD', COMPANY_TZ).startOf('day');
+ }
+
+ // 3) only endDate present
+ if (user?.endDate) {
+ return moment(user.endDate).tz(COMPANY_TZ);
+ }
+
+ // 4) only lastActivityAt present
+ if (user?.lastActivityAt) {
+ return moment(user.lastActivityAt).tz(COMPANY_TZ);
+ }
+
+ // 5) fallback → now
+ return moment().tz(COMPANY_TZ);
+ }
+
+ const sendThreeWeekFinalDayEmail = async ({
+ email,
+ firstName,
+ lastName,
+ endDate,
+ recipients,
+ }) => {
+ const subject = `IMPORTANT: Upcoming final day for ${firstName} ${lastName} in the Highest Good Network`;
+
+ const formattedEndDate = moment(endDate).tz(COMPANY_TZ).format('M-D-YYYY');
+
+ const emailBody = `
+ Management,
+
+
+ Please note that the final day for ${firstName} ${lastName}
+ in the Highest Good Network is set for ${formattedEndDate}.
+
+
+
+ This is a reminder sent approximately three weeks in advance.
+ Please begin wrapping up any remaining work and transitions with this individual.
+
+
+
+ Please note that they will be actively able to log hours until the end of their final day.
+
+
+ With gratitude,
One Community
+ `;
+ try {
+ await emailSender(recipients, subject, emailBody, null, email, email);
+ } catch (err) {
+ logger.logException(err, 'Failed to send 3-week final day email');
+ }
+ };
+
+ const getEmailRecipientsForStatusChange = async (userId) => {
+ const emailReceivers = await userProfile.find(
+ { isActive: true, role: { $in: ['Owner'] } },
+ '_id isActive role email',
+ );
+ const recipients = emailReceivers.map((receiver) => receiver.email);
+
+ try {
+ const findUser = await userProfile.findById(userId, 'teams');
+ findUser.teams.map(async (teamId) => {
+ const managementEmails = await getTeamManagementEmail(teamId);
+ if (Array.isArray(managementEmails) && managementEmails.length > 0) {
+ managementEmails.forEach((management) => {
+ recipients.push(management.email);
+ });
+ }
+ });
+ } catch (err) {
+ logger.logException(err, 'Unexpected error in finding menagement team');
+ }
+ return recipients;
+ };
+
return {
changeBadgeCount,
getUserName,
getTeamMembers,
checkTeamCodeMismatch,
- getTeamManagementEmail,
validateProfilePic,
assignBlueSquareForTimeNotMet,
applyMissedHourForCoreTeam,
@@ -2650,6 +2955,16 @@ const userHelper = function () {
deleteExpiredTokens,
deleteOldTimeOffRequests,
getProfileImagesFromWebsite,
+ sendUserPausedEmail,
+ sendUserSeparatedEmail,
+ sendUserActivatedEmail,
+ sendUserScheduledSeparationEmail,
+ sendUserResumedEmail,
+ sendUserReactivatedAfterSeparation,
+ sendUserCancelledSeparationEmail,
+ finalizeUserEndDates,
+ getEmailRecipientsForStatusChange,
+ getTeamManagementEmail,
};
};
diff --git a/yarn.lock b/yarn.lock
index 38883a2df..52cd4dc14 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1770,6 +1770,13 @@
resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+"@emnapi/runtime@^1.7.0":
+ version "1.8.1"
+ resolved "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz"
+ integrity sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==
+ dependencies:
+ tslib "^2.4.0"
+
"@eslint-community/eslint-utils@^4.2.0":
version "4.9.0"
dependencies:
@@ -1856,6 +1863,143 @@
"@img/colour@^1.0.0":
version "1.0.0"
+"@img/sharp-darwin-arm64@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz"
+ integrity sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==
+ optionalDependencies:
+ "@img/sharp-libvips-darwin-arm64" "1.2.4"
+
+"@img/sharp-darwin-x64@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz"
+ integrity sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==
+ optionalDependencies:
+ "@img/sharp-libvips-darwin-x64" "1.2.4"
+
+"@img/sharp-libvips-darwin-arm64@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz"
+ integrity sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==
+
+"@img/sharp-libvips-darwin-x64@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz"
+ integrity sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==
+
+"@img/sharp-libvips-linux-arm@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz"
+ integrity sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==
+
+"@img/sharp-libvips-linux-arm64@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz"
+ integrity sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==
+
+"@img/sharp-libvips-linux-ppc64@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz"
+ integrity sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==
+
+"@img/sharp-libvips-linux-riscv64@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz"
+ integrity sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==
+
+"@img/sharp-libvips-linux-s390x@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz"
+ integrity sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==
+
+"@img/sharp-libvips-linux-x64@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz"
+ integrity sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==
+
+"@img/sharp-libvips-linuxmusl-arm64@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz"
+ integrity sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==
+
+"@img/sharp-libvips-linuxmusl-x64@1.2.4":
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz"
+ integrity sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==
+
+"@img/sharp-linux-arm@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz"
+ integrity sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==
+ optionalDependencies:
+ "@img/sharp-libvips-linux-arm" "1.2.4"
+
+"@img/sharp-linux-arm64@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz"
+ integrity sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==
+ optionalDependencies:
+ "@img/sharp-libvips-linux-arm64" "1.2.4"
+
+"@img/sharp-linux-ppc64@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz"
+ integrity sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==
+ optionalDependencies:
+ "@img/sharp-libvips-linux-ppc64" "1.2.4"
+
+"@img/sharp-linux-riscv64@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz"
+ integrity sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==
+ optionalDependencies:
+ "@img/sharp-libvips-linux-riscv64" "1.2.4"
+
+"@img/sharp-linux-s390x@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz"
+ integrity sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==
+ optionalDependencies:
+ "@img/sharp-libvips-linux-s390x" "1.2.4"
+
+"@img/sharp-linux-x64@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz"
+ integrity sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==
+ optionalDependencies:
+ "@img/sharp-libvips-linux-x64" "1.2.4"
+
+"@img/sharp-linuxmusl-arm64@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz"
+ integrity sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==
+ optionalDependencies:
+ "@img/sharp-libvips-linuxmusl-arm64" "1.2.4"
+
+"@img/sharp-linuxmusl-x64@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz"
+ integrity sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==
+ optionalDependencies:
+ "@img/sharp-libvips-linuxmusl-x64" "1.2.4"
+
+"@img/sharp-wasm32@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz"
+ integrity sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==
+ dependencies:
+ "@emnapi/runtime" "^1.7.0"
+
+"@img/sharp-win32-arm64@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz"
+ integrity sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==
+
+"@img/sharp-win32-ia32@0.34.5":
+ version "0.34.5"
+ resolved "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz"
+ integrity sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==
+
"@img/sharp-win32-x64@0.34.5":
version "0.34.5"
resolved "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz"
@@ -3705,8 +3849,10 @@ base64id@~2.0.0, base64id@2.0.0:
resolved "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz"
integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==
-baseline-browser-mapping@^2.8.19:
- version "2.8.25"
+baseline-browser-mapping@^2.10.29, baseline-browser-mapping@^2.8.19:
+ version "2.10.29"
+ resolved "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz"
+ integrity sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==
basic-ftp@^5.0.2:
version "5.2.2"
@@ -5832,6 +5978,16 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+fsevents@^2.3.2, fsevents@~2.3.2:
+ version "2.3.3"
+ resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz"
+ integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
+
+fsevents@2.3.2:
+ version "2.3.2"
+ resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
@@ -10217,7 +10373,7 @@ teex@^1.0.1:
dependencies:
streamx "^2.12.5"
-telesignsdk@^3.0.3:
+telesignsdk@^3.0.4:
version "3.0.4"
resolved "https://registry.npmjs.org/telesignsdk/-/telesignsdk-3.0.4.tgz"
integrity sha512-aBcC7BqRSjGTs4EZkYOcIMSJhLOxHYDfX/Qi5NVW6McAmbJim9V6baw9VHXd2Br+2POCJB6Ww0sV7zwchDTbYA==
@@ -10350,7 +10506,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz"
integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==
-twilio@^5.5.2:
+twilio@^5.10.2:
version "5.10.4"
dependencies:
axios "^1.12.0"