diff --git a/package-lock.json b/package-lock.json index 04571c006..d5a2e7fdf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -95,7 +95,6 @@ "@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", @@ -3085,9 +3084,9 @@ "license": "MIT" }, "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", "license": "MIT", "optional": true, "dependencies": { @@ -6522,15 +6521,10 @@ } }, "node_modules/baseline-browser-mapping": { - "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==", + "version": "2.8.25", "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" + "baseline-browser-mapping": "dist/cli.js" } }, "node_modules/basic-ftp": { diff --git a/package.json b/package.json index 34751423a..c7c84088b 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "@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/constants/toolUtilization.js b/src/constants/toolUtilization.js new file mode 100644 index 000000000..f56298be2 --- /dev/null +++ b/src/constants/toolUtilization.js @@ -0,0 +1,88 @@ +const UTILIZATION_THRESHOLDS = { + UNDER_UTILIZED_MAX: 55, + NORMAL_MAX: 85, +}; + +const UTILIZATION_LABELS = { + UNDER: 'Under-utilized', + NORMAL: 'Normal', + OVER: 'Over-utilized', +}; + +const TRAFFIC_LIGHT = { + GREEN: 'green', + YELLOW: 'yellow', + RED: 'red', +}; + +const FORECAST_MODES = { + HISTORICAL: 'historical', + FORECAST_30: 'forecast30', + FORECAST_FULL: 'forecastFull', +}; + +const VALID_FORECAST_MODES = Object.values(FORECAST_MODES); + +const REPORT_FORMATS = ['pdf', 'csv']; + +const MAINTENANCE_TRIGGER_THRESHOLD = 85; + +const MINIMUM_WEEKS_FOR_REGRESSION = 3; + +const FORECAST_DEFAULT_DAYS = 30; + +const HOURS_PER_DAY = 24; +const DAYS_PER_WEEK = 7; +const MS_PER_HOUR = 3600000; + +const DEGRADED_CONDITIONS = ['Worn', 'Needs Repair', 'Needs Replacing']; +const NON_OPERATIONAL_STATUSES = ['Under Maintenance', 'Out of Service']; + +const CONFIDENCE_THRESHOLDS = { + HIGH: 0.7, + MEDIUM: 0.4, +}; + +const ENSEMBLE_WEIGHTS = { + HIGH_R2: { regression: 0.6, ema: 0.4 }, + MEDIUM_R2: { regression: 0.4, ema: 0.6 }, + LOW_R2: { regression: 0.2, ema: 0.8 }, +}; + +const EMA_SMOOTHING_BASE = 2; + +const ROUNDING_PRECISION = 10; +const PDF_MOVE_DOWN_HALF = 0.5; + +const PDF_STYLES = { + FONT_SIZE_TITLE: 24, + FONT_SIZE_METADATA: 10, + FONT_SIZE_SECTION_HEADER: 16, + FONT_SIZE_BODY: 11, + FONT_SIZE_DETAIL: 10, + PAGE_BREAK_THRESHOLD: 700, + PAGE_MARGIN: 50, +}; + +module.exports = { + UTILIZATION_THRESHOLDS, + UTILIZATION_LABELS, + TRAFFIC_LIGHT, + FORECAST_MODES, + VALID_FORECAST_MODES, + REPORT_FORMATS, + MAINTENANCE_TRIGGER_THRESHOLD, + MINIMUM_WEEKS_FOR_REGRESSION, + FORECAST_DEFAULT_DAYS, + HOURS_PER_DAY, + DAYS_PER_WEEK, + MS_PER_HOUR, + DEGRADED_CONDITIONS, + NON_OPERATIONAL_STATUSES, + CONFIDENCE_THRESHOLDS, + ENSEMBLE_WEIGHTS, + EMA_SMOOTHING_BASE, + ROUNDING_PRECISION, + PDF_MOVE_DOWN_HALF, + PDF_STYLES, +}; diff --git a/src/controllers/bmdashboard/__tests__/bmNewLessonController.test.js b/src/controllers/bmdashboard/__tests__/bmNewLessonController.test.js index 0ce794a59..617ca927d 100644 --- a/src/controllers/bmdashboard/__tests__/bmNewLessonController.test.js +++ b/src/controllers/bmdashboard/__tests__/bmNewLessonController.test.js @@ -1,5 +1,4 @@ const bmNewLessonController = require('../bmNewLessonController'); -const logger = require('../../../startup/logger'); // Mock dependencies const mockBuildingNewLesson = { @@ -12,7 +11,6 @@ const mockBuildingNewLesson = { updateMany: jest.fn(), deleteMany: jest.fn(), getAllTags: jest.fn(), - aggregate: jest.fn(), }; const mockBuildingProject = { @@ -49,7 +47,6 @@ describe('bmNewLessonController', () => { mockReq = { body: {}, params: {}, - query: {}, }; mockRes = { @@ -401,296 +398,6 @@ describe('bmNewLessonController', () => { }); }); - describe('getLessonsLearnt', () => { - const VALID_PROJECT_ID = '507f1f77bcf86cd799439011'; - const mockProjectObjId = { toString: () => VALID_PROJECT_ID }; - - const defaultLessonsInRange = [ - { project: 'Project A', projectId: mockProjectObjId, lessonsCount: 5 }, - ]; - const defaultThisMonth = [{ _id: mockProjectObjId, thisMonthCount: 3 }]; - const defaultLastMonth = [{ _id: mockProjectObjId, lastMonthCount: 2 }]; - - beforeEach(() => { - mockBuildingNewLesson.aggregate - .mockResolvedValueOnce(defaultLessonsInRange) - .mockResolvedValueOnce(defaultThisMonth) - .mockResolvedValueOnce(defaultLastMonth); - }); - - // --- Validation: Issue 1 (invalid projectId) --- - it('should return 400 for an invalid projectId', async () => { - mockReq.query = { projectId: 'not-a-valid-objectid' }; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.status).toHaveBeenCalledWith(400); - expect(mockRes.json).toHaveBeenCalledWith({ error: 'Invalid projectId' }); - expect(mockBuildingNewLesson.aggregate).not.toHaveBeenCalled(); - }); - - it('should not reject projectId=ALL and proceed normally', async () => { - mockReq.query = { projectId: 'ALL' }; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.status).toHaveBeenCalledWith(200); - expect(mockBuildingNewLesson.aggregate).toHaveBeenCalledTimes(3); - }); - - it('should not apply a relatedProject filter when projectId=ALL', async () => { - mockReq.query = { projectId: 'ALL' }; - - await controller.getLessonsLearnt(mockReq, mockRes); - - const firstMatchStage = mockBuildingNewLesson.aggregate.mock.calls[0][0][0].$match; - expect(firstMatchStage.relatedProject).toBeUndefined(); - }); - - // --- Validation: Issue 3 (invalid dates) --- - it('should return 400 for an invalid startDate', async () => { - mockReq.query = { startDate: 'not-a-date' }; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.status).toHaveBeenCalledWith(400); - expect(mockRes.json).toHaveBeenCalledWith({ error: 'Invalid startDate' }); - expect(mockBuildingNewLesson.aggregate).not.toHaveBeenCalled(); - }); - - it('should return 400 for an invalid endDate', async () => { - mockReq.query = { endDate: 'not-a-date' }; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.status).toHaveBeenCalledWith(400); - expect(mockRes.json).toHaveBeenCalledWith({ error: 'Invalid endDate' }); - expect(mockBuildingNewLesson.aggregate).not.toHaveBeenCalled(); - }); - - // --- Happy path: no params --- - it('should return 200 with lessons grouped by project when no params given', async () => { - mockReq.query = {}; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockBuildingNewLesson.aggregate).toHaveBeenCalledTimes(3); - expect(mockRes.status).toHaveBeenCalledWith(200); - expect(mockRes.json).toHaveBeenCalledWith({ - data: [ - { - project: 'Project A', - projectId: mockProjectObjId, - lessonsCount: 5, - changePercentage: '+50.0%', - }, - ], - }); - }); - - it('should return empty data array when no lessons exist', async () => { - mockBuildingNewLesson.aggregate.mockReset(); - mockBuildingNewLesson.aggregate - .mockResolvedValueOnce([]) - .mockResolvedValueOnce([]) - .mockResolvedValueOnce([]); - mockReq.query = {}; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.status).toHaveBeenCalledWith(200); - expect(mockRes.json).toHaveBeenCalledWith({ data: [] }); - }); - - // --- Filter construction: valid projectId --- - it('should apply relatedProject filter when a valid projectId is given', async () => { - mockReq.query = { projectId: VALID_PROJECT_ID }; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.status).toHaveBeenCalledWith(200); - const firstMatchStage = mockBuildingNewLesson.aggregate.mock.calls[0][0][0].$match; - expect(firstMatchStage.relatedProject).toBeDefined(); - }); - - // --- Filter construction: date range --- - it('should apply $gte and $lte date filters when startDate and endDate are given', async () => { - mockReq.query = { startDate: '2024-01-01', endDate: '2024-12-31' }; - - await controller.getLessonsLearnt(mockReq, mockRes); - - const firstMatchStage = mockBuildingNewLesson.aggregate.mock.calls[0][0][0].$match; - expect(firstMatchStage.date.$gte).toEqual(new Date('2024-01-01')); - expect(firstMatchStage.date.$lte).toEqual(new Date('2024-12-31')); - }); - - it('should apply only $gte when only startDate is given', async () => { - mockReq.query = { startDate: '2024-01-01' }; - - await controller.getLessonsLearnt(mockReq, mockRes); - - const firstMatchStage = mockBuildingNewLesson.aggregate.mock.calls[0][0][0].$match; - expect(firstMatchStage.date.$gte).toEqual(new Date('2024-01-01')); - expect(firstMatchStage.date.$lte).toBeUndefined(); - }); - - it('should apply only $lte when only endDate is given', async () => { - mockReq.query = { endDate: '2024-12-31' }; - - await controller.getLessonsLearnt(mockReq, mockRes); - - const firstMatchStage = mockBuildingNewLesson.aggregate.mock.calls[0][0][0].$match; - expect(firstMatchStage.date.$lte).toEqual(new Date('2024-12-31')); - expect(firstMatchStage.date.$gte).toBeUndefined(); - }); - - it('should not apply a date filter when neither startDate nor endDate is given', async () => { - mockReq.query = {}; - - await controller.getLessonsLearnt(mockReq, mockRes); - - const firstMatchStage = mockBuildingNewLesson.aggregate.mock.calls[0][0][0].$match; - expect(firstMatchStage.date).toBeUndefined(); - }); - - // --- changePercentage calculation --- - it('should return +100% when lastMonth is 0 and thisMonth is positive', async () => { - mockBuildingNewLesson.aggregate.mockReset(); - mockBuildingNewLesson.aggregate - .mockResolvedValueOnce([ - { project: 'Project A', projectId: mockProjectObjId, lessonsCount: 3 }, - ]) - .mockResolvedValueOnce([{ _id: mockProjectObjId, thisMonthCount: 3 }]) - .mockResolvedValueOnce([]); - mockReq.query = {}; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.json).toHaveBeenCalledWith({ - data: [expect.objectContaining({ changePercentage: '+100%' })], - }); - }); - - it('should return 0% when both lastMonth and thisMonth are 0', async () => { - mockBuildingNewLesson.aggregate.mockReset(); - mockBuildingNewLesson.aggregate - .mockResolvedValueOnce([ - { project: 'Project A', projectId: mockProjectObjId, lessonsCount: 5 }, - ]) - .mockResolvedValueOnce([]) - .mockResolvedValueOnce([]); - mockReq.query = {}; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.json).toHaveBeenCalledWith({ - data: [expect.objectContaining({ changePercentage: '0%' })], - }); - }); - - it('should return a positive percentage when thisMonth exceeds lastMonth', async () => { - mockBuildingNewLesson.aggregate.mockReset(); - mockBuildingNewLesson.aggregate - .mockResolvedValueOnce([ - { project: 'Project A', projectId: mockProjectObjId, lessonsCount: 6 }, - ]) - .mockResolvedValueOnce([{ _id: mockProjectObjId, thisMonthCount: 6 }]) - .mockResolvedValueOnce([{ _id: mockProjectObjId, lastMonthCount: 4 }]); - mockReq.query = {}; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.json).toHaveBeenCalledWith({ - data: [expect.objectContaining({ changePercentage: '+50.0%' })], - }); - }); - - it('should return a negative percentage when thisMonth is less than lastMonth', async () => { - mockBuildingNewLesson.aggregate.mockReset(); - mockBuildingNewLesson.aggregate - .mockResolvedValueOnce([ - { project: 'Project A', projectId: mockProjectObjId, lessonsCount: 2 }, - ]) - .mockResolvedValueOnce([{ _id: mockProjectObjId, thisMonthCount: 2 }]) - .mockResolvedValueOnce([{ _id: mockProjectObjId, lastMonthCount: 4 }]); - mockReq.query = {}; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.json).toHaveBeenCalledWith({ - data: [expect.objectContaining({ changePercentage: '-50.0%' })], - }); - }); - - it('should return +0.0% when thisMonth equals lastMonth (no change)', async () => { - mockBuildingNewLesson.aggregate.mockReset(); - mockBuildingNewLesson.aggregate - .mockResolvedValueOnce([ - { project: 'Project A', projectId: mockProjectObjId, lessonsCount: 4 }, - ]) - .mockResolvedValueOnce([{ _id: mockProjectObjId, thisMonthCount: 4 }]) - .mockResolvedValueOnce([{ _id: mockProjectObjId, lastMonthCount: 4 }]); - mockReq.query = {}; - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.json).toHaveBeenCalledWith({ - data: [expect.objectContaining({ changePercentage: '+0.0%' })], - }); - }); - - it('should correctly compute changePercentage independently for multiple projects', async () => { - const projectObjId2 = { toString: () => '507f1f77bcf86cd799439012' }; - mockBuildingNewLesson.aggregate.mockReset(); - mockBuildingNewLesson.aggregate - .mockResolvedValueOnce([ - { project: 'Project A', projectId: mockProjectObjId, lessonsCount: 6 }, - { project: 'Project B', projectId: projectObjId2, lessonsCount: 2 }, - ]) - .mockResolvedValueOnce([ - { _id: mockProjectObjId, thisMonthCount: 6 }, - { _id: projectObjId2, thisMonthCount: 1 }, - ]) - .mockResolvedValueOnce([ - { _id: mockProjectObjId, lastMonthCount: 4 }, - { _id: projectObjId2, lastMonthCount: 2 }, - ]); - mockReq.query = {}; - - await controller.getLessonsLearnt(mockReq, mockRes); - - const responseData = mockRes.json.mock.calls[0][0].data; - expect(responseData).toHaveLength(2); - expect(responseData[0]).toMatchObject({ project: 'Project A', changePercentage: '+50.0%' }); - expect(responseData[1]).toMatchObject({ project: 'Project B', changePercentage: '-50.0%' }); - }); - - // --- Error path: Issue 4 (logger) --- - it('should return 500 and call logger.logException when aggregate throws', async () => { - const dbError = new Error('Database error'); - mockBuildingNewLesson.aggregate.mockReset(); - mockBuildingNewLesson.aggregate.mockRejectedValue(dbError); - mockReq.query = { projectId: VALID_PROJECT_ID }; - - // The controller captures `logger` at module-load time (top-level require), so - // jest.mock factory cannot intercept it. jest.spyOn mutates the shared cached - // module object that the controller already holds a reference to. - const logExceptionSpy = jest - .spyOn(logger, 'logException') - .mockReturnValue('mock-tracking-id'); - - await controller.getLessonsLearnt(mockReq, mockRes); - - expect(mockRes.status).toHaveBeenCalledWith(500); - expect(mockRes.json).toHaveBeenCalledWith({ error: 'Internal Server Error' }); - expect(logExceptionSpy).toHaveBeenCalledWith(dbError, 'getLessonsLearnt', { - query: { projectId: VALID_PROJECT_ID }, - }); - - logExceptionSpy.mockRestore(); - }); - }); - describe('getLessonTags', () => { it('should return unique sorted tags', async () => { const mockLessons = [ diff --git a/src/controllers/bmdashboard/__tests__/toolUtilizationController.test.js b/src/controllers/bmdashboard/__tests__/toolUtilizationController.test.js new file mode 100644 index 000000000..a7cd2a44f --- /dev/null +++ b/src/controllers/bmdashboard/__tests__/toolUtilizationController.test.js @@ -0,0 +1,307 @@ +jest.mock('../../../helpers/toolUtilizationHelpers'); +jest.mock('../../../helpers/toolUtilizationReportHelpers'); +jest.mock('../../../startup/logger', () => ({ logException: jest.fn() })); + +const { + computeUtilizationData, + buildUtilizationResponse, + generateRecommendations, + generateMaintenanceAlerts, + generateResourceBalancingSuggestions, + buildInsightsSummary, + buildReportPayload, +} = require('../../../helpers/toolUtilizationHelpers'); +const { + generatePDFReport, + generateCSVReport, +} = require('../../../helpers/toolUtilizationReportHelpers'); +const toolUtilizationController = require('../toolUtilizationController'); + +// ─── Shared setup ─── +const mockBuildingTool = {}; +const controller = toolUtilizationController(mockBuildingTool); + +const makeReq = (query = {}) => ({ query }); +const makeRes = () => ({ + status: jest.fn().mockReturnThis(), + json: jest.fn(), + setHeader: jest.fn(), + send: jest.fn(), + headersSent: false, +}); + +const mockRangeStart = new Date('2026-01-01'); +const mockRangeEnd = new Date('2026-01-31'); +const mockUtilizationData = [ + { + name: 'Drill', + utilizationRate: 75, + downtime: 180, + classification: { label: 'Normal', trafficLight: 'green' }, + toolCount: 1, + toolGroupDetails: { tools: [], purchaseStatuses: [], conditions: [], currentUsages: [] }, + }, +]; +const mockReportPayload = { + utilizationData: mockUtilizationData, + alerts: [], + balancing: [], + recommendations: [], + summary: {}, + metadata: {}, +}; + +beforeEach(() => { + jest.clearAllMocks(); + computeUtilizationData.mockResolvedValue({ + utilizationData: mockUtilizationData, + rangeStart: mockRangeStart, + rangeEnd: mockRangeEnd, + }); + buildUtilizationResponse.mockResolvedValue(mockUtilizationData); + generateRecommendations.mockReturnValue([]); + generateMaintenanceAlerts.mockReturnValue([]); + generateResourceBalancingSuggestions.mockReturnValue([]); + buildInsightsSummary.mockReturnValue({ + totalToolTypes: 1, + underUtilized: 0, + normal: 1, + overUtilized: 0, + averageUtilization: 75, + }); + buildReportPayload.mockReturnValue(mockReportPayload); +}); + +// ─── getUtilization ─── +describe('getUtilization', () => { + it('returns 200 with utilization data when no mode is specified', async () => { + const req = makeReq({}); + const res = makeRes(); + + await controller.getUtilization(req, res); + + expect(computeUtilizationData).toHaveBeenCalledWith(mockBuildingTool, { + tool: undefined, + project: undefined, + startDate: undefined, + endDate: undefined, + }); + expect(buildUtilizationResponse).toHaveBeenCalledWith( + expect.objectContaining({ selectedMode: 'historical' }), + ); + expect(res.status).toHaveBeenCalledWith(200); + expect(res.json).toHaveBeenCalledWith(mockUtilizationData); + }); + + it('passes forecast30 mode to buildUtilizationResponse', async () => { + const req = makeReq({ mode: 'forecast30' }); + const res = makeRes(); + + await controller.getUtilization(req, res); + + expect(buildUtilizationResponse).toHaveBeenCalledWith( + expect.objectContaining({ selectedMode: 'forecast30' }), + ); + expect(res.status).toHaveBeenCalledWith(200); + }); + + it('returns 400 when mode is invalid', async () => { + const req = makeReq({ mode: 'badMode' }); + const res = makeRes(); + + await controller.getUtilization(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ error: expect.stringContaining('Invalid mode') }), + ); + }); + + it('returns 400 when startDate is after endDate', async () => { + const req = makeReq({ startDate: '2026-01-31', endDate: '2026-01-01' }); + const res = makeRes(); + + await controller.getUtilization(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ error: expect.stringContaining('startDate') }), + ); + expect(computeUtilizationData).not.toHaveBeenCalled(); + }); + + it('returns 500 when computeUtilizationData throws', async () => { + computeUtilizationData.mockRejectedValue(new Error('DB failure')); + const req = makeReq({}); + const res = makeRes(); + + await controller.getUtilization(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ error: expect.stringContaining('DB failure') }), + ); + }); + + it('returns 500 when buildUtilizationResponse throws', async () => { + buildUtilizationResponse.mockRejectedValue(new Error('Response build failed')); + const req = makeReq({}); + const res = makeRes(); + + await controller.getUtilization(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + }); +}); + +// ─── getInsights ─── +describe('getInsights', () => { + it('returns 200 with all insight sections', async () => { + const recommendations = [{ toolName: 'Drill', action: 'Plan maintenance.' }]; + const alerts = [{ toolName: 'Drill', alertType: 'overuse', message: 'High.', urgency: 'high' }]; + const balancing = [{ suggestion: 'Redistribute.', fromTool: 'Drill', toTool: 'Shovel' }]; + const summary = { + totalToolTypes: 1, + underUtilized: 0, + normal: 0, + overUtilized: 1, + averageUtilization: 90, + }; + + generateRecommendations.mockReturnValue(recommendations); + generateMaintenanceAlerts.mockReturnValue(alerts); + generateResourceBalancingSuggestions.mockReturnValue(balancing); + buildInsightsSummary.mockReturnValue(summary); + + const req = makeReq({}); + const res = makeRes(); + + await controller.getInsights(req, res); + + expect(res.status).toHaveBeenCalledWith(200); + expect(res.json).toHaveBeenCalledWith({ + recommendations, + maintenanceAlerts: alerts, + resourceBalancing: balancing, + summary, + }); + }); + + it('calls all insight helpers with utilizationData from computeUtilizationData', async () => { + const req = makeReq({}); + const res = makeRes(); + + await controller.getInsights(req, res); + + expect(generateRecommendations).toHaveBeenCalledWith(mockUtilizationData); + expect(generateMaintenanceAlerts).toHaveBeenCalledWith(mockUtilizationData); + expect(generateResourceBalancingSuggestions).toHaveBeenCalledWith(mockUtilizationData); + expect(buildInsightsSummary).toHaveBeenCalledWith(mockUtilizationData); + }); + + it('returns 400 when startDate is after endDate', async () => { + const req = makeReq({ startDate: '2026-01-31', endDate: '2026-01-01' }); + const res = makeRes(); + + await controller.getInsights(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ error: expect.stringContaining('startDate') }), + ); + expect(computeUtilizationData).not.toHaveBeenCalled(); + }); + + it('returns 500 when computeUtilizationData throws', async () => { + computeUtilizationData.mockRejectedValue(new Error('DB error')); + const req = makeReq({}); + const res = makeRes(); + + await controller.getInsights(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ error: expect.stringContaining('DB error') }), + ); + }); +}); + +// ─── exportReport ─── +describe('exportReport', () => { + it('returns 400 when format param is missing', async () => { + const req = makeReq({}); + const res = makeRes(); + + await controller.exportReport(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ error: expect.stringContaining('Invalid format') }), + ); + }); + + it('returns 400 when format is not pdf or csv', async () => { + const req = makeReq({ format: 'xlsx' }); + const res = makeRes(); + + await controller.exportReport(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + }); + + it('returns 400 when startDate is after endDate', async () => { + const req = makeReq({ format: 'csv', startDate: '2026-01-31', endDate: '2026-01-01' }); + const res = makeRes(); + + await controller.exportReport(req, res); + + expect(res.status).toHaveBeenCalledWith(400); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ error: expect.stringContaining('startDate') }), + ); + expect(computeUtilizationData).not.toHaveBeenCalled(); + }); + + it('calls generateCSVReport for csv format', async () => { + const req = makeReq({ format: 'csv' }); + const res = makeRes(); + + await controller.exportReport(req, res); + + expect(generateCSVReport).toHaveBeenCalledWith(res, mockReportPayload); + expect(generatePDFReport).not.toHaveBeenCalled(); + }); + + it('calls generatePDFReport for pdf format', async () => { + const req = makeReq({ format: 'pdf' }); + const res = makeRes(); + + await controller.exportReport(req, res); + + expect(generatePDFReport).toHaveBeenCalledWith(res, mockReportPayload); + expect(generateCSVReport).not.toHaveBeenCalled(); + }); + + it('returns 500 when error occurs and headers are not yet sent', async () => { + computeUtilizationData.mockRejectedValue(new Error('Export failed')); + const req = makeReq({ format: 'csv' }); + const res = { ...makeRes(), headersSent: false }; + + await controller.exportReport(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ error: expect.stringContaining('Export failed') }), + ); + }); + + it('does not send error response when headers are already sent', async () => { + computeUtilizationData.mockRejectedValue(new Error('Stream error')); + const req = makeReq({ format: 'csv' }); + const res = { ...makeRes(), headersSent: true }; + + await controller.exportReport(req, res); + + expect(res.status).not.toHaveBeenCalled(); + }); +}); diff --git a/src/controllers/bmdashboard/bmNewLessonController.js b/src/controllers/bmdashboard/bmNewLessonController.js index bb304481a..6704805f1 100644 --- a/src/controllers/bmdashboard/bmNewLessonController.js +++ b/src/controllers/bmdashboard/bmNewLessonController.js @@ -1,29 +1,6 @@ /* eslint-disable no-unused-vars */ const mongoose = require('mongoose'); -const logger = require('../../startup/logger'); -/** Builds a MongoDB filter fragment for projectId. Returns {} for 'ALL' or absent value. */ -const buildProjectIdFilter = (projectId) => { - if (!projectId || projectId === 'ALL') return {}; - return { relatedProject: new mongoose.Types.ObjectId(projectId) }; -}; - -/** Returns month-over-month change as a signed percentage string (e.g. '+50.0%', '-25.0%'). */ -const calculateChangePercentage = (thisMonth, lastMonth) => { - if (lastMonth === 0 && thisMonth > 0) return '+100%'; - if (lastMonth > 0) { - const change = ((thisMonth - lastMonth) / lastMonth) * 100; - return `${change >= 0 ? '+' : ''}${change.toFixed(1)}%`; - } - return '0%'; -}; - -// Named constants for end-of-day time components used in month boundary Date construction -const END_HOUR = 23; -const END_MINUTE = 59; -const END_SECOND = 59; - -// eslint-disable-next-line max-lines-per-function const bmNewLessonController = function (BuildingNewLesson) { const buildingProject = require('../../models/bmdashboard/buildingProject'); const Like = require('../../models/bmdashboard/buldingLessonLike'); @@ -58,7 +35,7 @@ const bmNewLessonController = function (BuildingNewLesson) { res.json(lesson); } catch (error) { - logger.logException(error, 'bmGetSingleLesson', { lessonId }); + console.error(`Error fetching lesson with ID ${lessonId}:`, error); res.status(500).json({ error: 'Internal Server Error' }); } }; @@ -98,7 +75,7 @@ const bmNewLessonController = function (BuildingNewLesson) { res.json(updatedLesson); } catch (error) { - logger.logException(error, 'bmEditSingleLesson', { lessonId }); + console.error(`Error updating lesson with ID ${req.params.lessonId}:`, error); res.status(500).json({ error: 'Internal Server Error' }); } }; @@ -130,7 +107,7 @@ const bmNewLessonController = function (BuildingNewLesson) { res.json({ message: 'Lesson deleted successfully', deletedLesson }); } catch (error) { - logger.logException(error, 'bmDeleteSingleLesson', { lessonId }); + console.error(`Error removing lesson with ID ${lessonId}:`, error); res.status(500).json({ error: 'Internal Server Error' }); } }; @@ -159,7 +136,7 @@ const bmNewLessonController = function (BuildingNewLesson) { const tags = await BuildingNewLesson.getAllTags(); return res.status(201).json(tags); } catch (error) { - logger.logException(error, 'addNewTag', { tag: req.body.tag }); + console.error('Tag creation error:', error); return res.status(500).json({ error: 'Error adding new tag', details: error.message, @@ -187,7 +164,7 @@ const bmNewLessonController = function (BuildingNewLesson) { const remainingTags = await BuildingNewLesson.getAllTags(); return res.status(200).json(remainingTags); } catch (error) { - logger.logException(error, 'deleteTag', { tag: req.params.tag }); + console.error('Delete tag error:', error); return res.status(500).json({ error: 'Error deleting tag', details: error.message, @@ -224,7 +201,7 @@ const bmNewLessonController = function (BuildingNewLesson) { return res.status(200).json({ status: 'success', message: 'Lesson liked successfully' }); } catch (error) { - logger.logException(error, 'likeLesson', { lessonId, userId }); + console.error('Error liking/unliking lesson:', error); return res.status(500).json({ status: 'error', message: 'Error liking/unliking lesson' }); } }; @@ -242,26 +219,25 @@ const bmNewLessonController = function (BuildingNewLesson) { try { const { projectId, startDate, endDate } = req.query; - if (projectId && projectId !== 'ALL' && !mongoose.Types.ObjectId.isValid(projectId)) { - return res.status(400).json({ error: 'Invalid projectId' }); + const filter = {}; + if (projectId && projectId !== 'ALL') { + filter.relatedProject = new mongoose.Types.ObjectId(projectId); } - if (startDate && Number.isNaN(Date.parse(startDate))) { - return res.status(400).json({ error: 'Invalid startDate' }); - } - if (endDate && Number.isNaN(Date.parse(endDate))) { - return res.status(400).json({ error: 'Invalid endDate' }); - } - - const filter = { ...buildProjectIdFilter(projectId) }; if (startDate || endDate) { filter.date = {}; if (startDate) filter.date.$gte = new Date(startDate); if (endDate) filter.date.$lte = new Date(endDate); } + // Current Period const lessonsInRange = await BuildingNewLesson.aggregate([ { $match: filter }, - { $group: { _id: '$relatedProject', lessonsCount: { $sum: 1 } } }, + { + $group: { + _id: '$relatedProject', + lessonsCount: { $sum: 1 }, + }, + }, { $lookup: { from: 'buildingProjects', @@ -280,57 +256,92 @@ const bmNewLessonController = function (BuildingNewLesson) { }, ]); - const now = endDate ? new Date(endDate) : new Date(); - const year = now.getFullYear(); - const month = now.getMonth(); - const projectFilter = buildProjectIdFilter(projectId); + // This Month + let now = new Date(); + if (endDate) { + now = new Date(endDate); + } + const thisMonthStart = new Date(now.getFullYear(), now.getMonth(), 1); + const thisMonthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59); + + const thisMonthFilter = { + ...(projectId && + projectId !== 'ALL' && + mongoose.Types.ObjectId.isValid(projectId) && { + relatedProject: new mongoose.Types.ObjectId(String(projectId)), + }), + date: { $gte: thisMonthStart, $lte: thisMonthEnd }, + }; const thisMonthLessons = await BuildingNewLesson.aggregate([ + { $match: thisMonthFilter }, { - $match: { - ...projectFilter, - date: { - $gte: new Date(year, month, 1), - $lte: new Date(year, month + 1, 0, END_HOUR, END_MINUTE, END_SECOND), - }, + $group: { + _id: '$relatedProject', + thisMonthCount: { $sum: 1 }, }, }, - { $group: { _id: '$relatedProject', thisMonthCount: { $sum: 1 } } }, ]); + // Last Month + const lastMonthStart = new Date(now.getFullYear(), now.getMonth() - 1, 1); + const lastMonthEnd = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59); + + const lastMonthFilter = { + ...(projectId && + projectId !== 'ALL' && + mongoose.Types.ObjectId.isValid(projectId) && { + relatedProject: new mongoose.Types.ObjectId(String(projectId)), + }), + date: { $gte: lastMonthStart, $lte: lastMonthEnd }, + }; + const lastMonthLessons = await BuildingNewLesson.aggregate([ + { $match: lastMonthFilter }, { - $match: { - ...projectFilter, - date: { - $gte: new Date(year, month - 1, 1), - $lte: new Date(year, month, 0, END_HOUR, END_MINUTE, END_SECOND), - }, + $group: { + _id: '$relatedProject', + lastMonthCount: { $sum: 1 }, }, }, - { $group: { _id: '$relatedProject', lastMonthCount: { $sum: 1 } } }, ]); - const thisMonthMap = Object.fromEntries( - thisMonthLessons.map((e) => [e._id.toString(), e.thisMonthCount]), - ); - const lastMonthMap = Object.fromEntries( - lastMonthLessons.map((e) => [e._id.toString(), e.lastMonthCount]), - ); + // Mapping this month and last month counts + const thisMonthMap = {}; + thisMonthLessons.forEach((entry) => { + thisMonthMap[entry._id.toString()] = entry.thisMonthCount; + }); + const lastMonthMap = {}; + lastMonthLessons.forEach((entry) => { + lastMonthMap[entry._id.toString()] = entry.lastMonthCount; + }); + // console.log(lastMonthMap, thisMonthMap) + + // Build final result const result = lessonsInRange.map((entry) => { - const id = entry.projectId.toString(); + const projectIdStr = entry.projectId.toString(); + const thisMonth = thisMonthMap[projectIdStr] || 0; + const lastMonth = lastMonthMap[projectIdStr] || 0; + let changePercentage = '0%'; + if (lastMonth === 0 && thisMonth > 0) { + changePercentage = '+100%'; + } else if (lastMonth > 0) { + const change = ((thisMonth - lastMonth) / lastMonth) * 100; + changePercentage = `${change >= 0 ? '+' : ''}${change.toFixed(1)}%`; + } + return { project: entry.project, projectId: entry.projectId, lessonsCount: entry.lessonsCount, - changePercentage: calculateChangePercentage(thisMonthMap[id] || 0, lastMonthMap[id] || 0), + changePercentage, }; }); res.status(200).json({ data: result }); } catch (err) { - logger.logException(err, 'getLessonsLearnt', { query: req.query }); + console.error('Error fetching lessons learnt:', err); res.status(500).json({ error: 'Internal Server Error' }); } }; diff --git a/src/controllers/bmdashboard/toolUtilizationController.js b/src/controllers/bmdashboard/toolUtilizationController.js index 93dea939e..6378632d5 100644 --- a/src/controllers/bmdashboard/toolUtilizationController.js +++ b/src/controllers/bmdashboard/toolUtilizationController.js @@ -1,174 +1,126 @@ -const mongoose = require('mongoose'); - -const toolUtilizationController = (BuildingTool) => { - // Shared helper: compute utilization data for a given set of tools and date range - const computeUtilizationForRange = (tools, rangeStart, rangeEnd) => { - const totalHours = (rangeEnd - rangeStart) / (1000 * 60 * 60); - - // Group tools by itemType - const toolGroups = {}; - tools.forEach((toolItem) => { - if (!toolItem.itemType) return; - const toolName = toolItem.itemType.name || 'Unknown Tool'; - const toolTypeId = toolItem.itemType._id.toString(); - if (!toolGroups[toolTypeId]) { - toolGroups[toolTypeId] = { name: toolName, tools: [] }; - } - toolGroups[toolTypeId].tools.push(toolItem); - }); - - // Calculate utilization per tool group - const utilizationData = Object.values(toolGroups).map((group) => { - let totalCheckedOutHours = 0; - let totalDowntimeHours = 0; - let toolCount = 0; - - group.tools.forEach((toolItem) => { - toolCount += 1; +const logger = require('../../startup/logger'); +const { + FORECAST_MODES, + VALID_FORECAST_MODES, + REPORT_FORMATS, +} = require('../../constants/toolUtilization'); +const { + computeUtilizationData, + buildUtilizationResponse, + generateRecommendations, + generateMaintenanceAlerts, + generateResourceBalancingSuggestions, + buildInsightsSummary, + buildReportPayload, +} = require('../../helpers/toolUtilizationHelpers'); +const { + generatePDFReport, + generateCSVReport, +} = require('../../helpers/toolUtilizationReportHelpers'); + +const toolUtilizationController = function (BuildingTool) { + const getUtilization = async (req, res) => { + try { + const { tool, project, startDate, endDate, mode } = req.query; + const selectedMode = mode || FORECAST_MODES.HISTORICAL; - const relevantLogs = (toolItem.logRecord || []).filter((log) => { - const logDate = new Date(log.date); - return logDate >= rangeStart && logDate <= rangeEnd; + if (mode && !VALID_FORECAST_MODES.includes(selectedMode)) { + return res.status(400).json({ + error: `Invalid mode. Must be one of: ${VALID_FORECAST_MODES.join(', ')}`, }); + } - relevantLogs.sort((a, b) => new Date(a.date) - new Date(b.date)); - - let checkedOutTime = 0; - let lastCheckOut = null; - - relevantLogs.forEach((log) => { - if (log.type === 'Check Out') { - lastCheckOut = new Date(log.date); - } else if (log.type === 'Check In' && lastCheckOut) { - const checkInTime = new Date(log.date); - const hoursCheckedOut = (checkInTime - lastCheckOut) / (1000 * 60 * 60); - checkedOutTime += Math.max(0, hoursCheckedOut); - lastCheckOut = null; - } - }); + if (startDate && endDate && new Date(startDate) > new Date(endDate)) { + return res.status(400).json({ error: 'startDate cannot be after endDate.' }); + } - if (lastCheckOut) { - const hoursCheckedOut = (rangeEnd - lastCheckOut) / (1000 * 60 * 60); - checkedOutTime += Math.max(0, hoursCheckedOut); - } - - if (relevantLogs.length === 0 && toolItem.logRecord && toolItem.logRecord.length > 0) { - const sortedAllLogs = [...toolItem.logRecord].sort( - (a, b) => new Date(b.date) - new Date(a.date), - ); - const lastLog = sortedAllLogs[0]; - if (lastLog && lastLog.type === 'Check Out') { - const lastCheckOutDate = new Date(lastLog.date); - if (lastCheckOutDate < rangeStart) { - checkedOutTime = totalHours; - } - } - } - - totalCheckedOutHours += checkedOutTime; + const { utilizationData, rangeStart, rangeEnd } = await computeUtilizationData(BuildingTool, { + tool, + project, + startDate, + endDate, }); - totalDowntimeHours = totalHours * toolCount - totalCheckedOutHours; + const responseData = await buildUtilizationResponse({ + utilizationData, + rangeStart, + rangeEnd, + selectedMode, + project, + }); - const totalPossibleHours = totalHours * toolCount; - const utilizationRate = - totalPossibleHours > 0 ? Math.round((totalCheckedOutHours / totalPossibleHours) * 100) : 0; + return res.status(200).json(responseData); + } catch (err) { + logger.logException(err, 'toolUtilizationController.getUtilization'); + return res.status(500).json({ error: `Server error: ${err.message}` }); + } + }; - return { - name: group.name, - utilizationRate, - downtime: Math.round(totalDowntimeHours * 10) / 10, - count: toolCount, - }; - }); + const getInsights = async (req, res) => { + try { + const { startDate, endDate } = req.query; + if (startDate && endDate && new Date(startDate) > new Date(endDate)) { + return res.status(400).json({ error: 'startDate cannot be after endDate.' }); + } - utilizationData.sort((a, b) => b.utilizationRate - a.utilizationRate); - return utilizationData; - }; + const { utilizationData } = await computeUtilizationData(BuildingTool, req.query); - // Split a date range into N weekly buckets - const buildWeeklyBuckets = (rangeStart, rangeEnd, numWeeks = 4) => { - const buckets = []; - for (let i = 0; i < numWeeks; i += 1) { - const bucketStart = new Date(rangeEnd); - bucketStart.setDate(rangeEnd.getDate() - (numWeeks - i) * 7); - const bucketEnd = new Date(rangeEnd); - bucketEnd.setDate(rangeEnd.getDate() - (numWeeks - i - 1) * 7); - const label = `Week of ${bucketStart.toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - })}`; - buckets.push({ label, start: bucketStart, end: bucketEnd }); + return res.status(200).json({ + recommendations: generateRecommendations(utilizationData), + maintenanceAlerts: generateMaintenanceAlerts(utilizationData), + resourceBalancing: generateResourceBalancingSuggestions(utilizationData), + summary: buildInsightsSummary(utilizationData), + }); + } catch (err) { + logger.logException(err, 'toolUtilizationController.getInsights'); + return res.status(500).json({ error: `Server error: ${err.message}` }); } - return buckets; }; - const getUtilization = async (req, res) => { + const exportReport = async (req, res) => { try { - const { tool, project, startDate, endDate, groupBy } = req.query; - - // Build filter for tools - const toolFilter = {}; + const { format, startDate, endDate } = req.query; - if (tool && tool !== 'ALL') { - if (mongoose.Types.ObjectId.isValid(tool)) { - toolFilter.itemType = mongoose.Types.ObjectId(tool); - } + if (startDate && endDate && new Date(startDate) > new Date(endDate)) { + return res.status(400).json({ error: 'startDate cannot be after endDate.' }); } - if (project && project !== 'ALL') { - if (mongoose.Types.ObjectId.isValid(project)) { - toolFilter.project = mongoose.Types.ObjectId(project); - } - } - - // Fetch all matching tools once - const tools = await BuildingTool.find({ - ...toolFilter, - __t: 'tool_item', - }) - .populate('itemType', 'name') - .populate('project', 'name') - .lean(); - - // Resolve date range - const defaultEnd = new Date(); - const defaultStart = new Date(); - defaultStart.setDate(defaultStart.getDate() - 30); - - const rangeStart = startDate ? new Date(startDate) : defaultStart; - const rangeEnd = endDate ? new Date(endDate) : defaultEnd; - - // --- groupBy=week: return weekly bucketed avg utilization --- - if (groupBy === 'week') { - const buckets = buildWeeklyBuckets(rangeStart, rangeEnd, 4); - - const weeklyData = buckets.map(({ label, start, end }) => { - const utilizationData = computeUtilizationForRange(tools, start, end); - const avgUtilization = - utilizationData.length > 0 - ? Math.round( - (utilizationData.reduce((sum, t) => sum + t.utilizationRate, 0) / - utilizationData.length) * - 10, - ) / 10 - : 0; - return { week: label, avgUtilization }; + if (!format || !REPORT_FORMATS.includes(format)) { + return res.status(400).json({ + error: `Invalid format. Must be one of: ${REPORT_FORMATS.join(', ')}`, }); - - return res.status(200).json(weeklyData); } - // --- Default: return per-tool utilization --- - const utilizationData = computeUtilizationForRange(tools, rangeStart, rangeEnd); - return res.status(200).json(utilizationData); + const { utilizationData, rangeStart, rangeEnd } = await computeUtilizationData( + BuildingTool, + req.query, + ); + const reportPayload = buildReportPayload( + utilizationData, + rangeStart, + rangeEnd, + req.query.project, + ); + + if (format === 'pdf') { + generatePDFReport(res, reportPayload); + } else { + generateCSVReport(res, reportPayload); + } } catch (err) { - console.error('Error calculating tool utilization:', err); - res.status(500).json({ error: `Server error: ${err.message}` }); + logger.logException(err, 'toolUtilizationController.exportReport'); + if (!res.headersSent) { + return res.status(500).json({ error: `Server error: ${err.message}` }); + } } + return undefined; }; - return { getUtilization }; + return { + getUtilization, + getInsights, + exportReport, + }; }; module.exports = toolUtilizationController; diff --git a/src/controllers/studentTaskController.js b/src/controllers/studentTaskController.js index f4e3803ac..d23ecc3d7 100644 --- a/src/controllers/studentTaskController.js +++ b/src/controllers/studentTaskController.js @@ -366,78 +366,10 @@ const studentTaskController = function () { } }; - /** - * POST /student/tasks/:taskId/log-hours - * Increments loggedHours for a task, capped at suggestedTotalHours. - * Returns updated loggedHours and a canMarkDone eligibility flag. - */ - const logHours = async (req, res) => { - try { - const { taskId } = req.params; - const studentId = req.body.requestor?.requestorId; - - if (!taskId || !mongoose.Types.ObjectId.isValid(taskId)) { - return res.status(400).json({ error: 'Invalid Task ID' }); - } - if (!studentId || !mongoose.Types.ObjectId.isValid(studentId)) { - return res.status(400).json({ error: 'Invalid Student ID' }); - } - - const hours = Number(req.body.hours); - if (!Number.isFinite(hours) || hours <= 0) { - return res.status(400).json({ error: 'hours must be a positive number' }); - } - - const task = await EducationTask.findOne({ - _id: mongoose.Types.ObjectId(taskId), - studentId: mongoose.Types.ObjectId(studentId), - }); - - if (!task) { - return res.status(404).json({ error: 'Task not found or does not belong to you' }); - } - - if (task.status === 'completed' || task.status === 'graded') { - return res.status(400).json({ error: 'Cannot log hours for a completed task' }); - } - - const cap = task.suggestedTotalHours > 0 ? task.suggestedTotalHours : Infinity; - const newLoggedHours = Math.min(task.loggedHours + hours, cap); - - const newStatus = - task.status === 'assigned' && newLoggedHours > 0 ? 'in_progress' : task.status; - - const updated = await EducationTask.findOneAndUpdate( - { _id: mongoose.Types.ObjectId(taskId) }, - { $set: { loggedHours: newLoggedHours, status: newStatus } }, - { new: true, runValidators: false }, - ); - - if (!updated) { - return res.status(404).json({ error: 'Task not found during update' }); - } - - const canMarkDone = - updated.suggestedTotalHours > 0 && updated.loggedHours >= updated.suggestedTotalHours; - - return res.status(200).json({ - message: 'Hours logged successfully', - loggedHours: updated.loggedHours, - suggestedTotalHours: updated.suggestedTotalHours, - status: updated.status, - canMarkDone, - }); - } catch (error) { - console.error('Error logging hours:', error); - return res.status(500).json({ error: 'Internal server error' }); - } - }; - return { getStudentTasks, updateTaskProgress, uploadFile, - logHours, }; }; diff --git a/src/controllers/studentTaskController.spec.js b/src/controllers/studentTaskController.spec.js deleted file mode 100644 index d6ca7408b..000000000 --- a/src/controllers/studentTaskController.spec.js +++ /dev/null @@ -1,166 +0,0 @@ -const EducationTask = require('../models/educationTask'); -const { mockReq, mockRes } = require('../test'); -const studentTaskController = require('./studentTaskController'); - -const VALID_TASK_ID = '507f1f77bcf86cd799439011'; -const VALID_STUDENT_ID = '65cf6c3706d8ac105827bb2e'; - -// Shared helpers to reduce repetition -const makeTask = (overrides = {}) => ({ - status: 'assigned', - loggedHours: 0, - suggestedTotalHours: 5, - ...overrides, -}); - -const makeUpdated = (overrides = {}) => ({ - loggedHours: 1, - suggestedTotalHours: 5, - status: 'in_progress', - ...overrides, -}); - -const spyFindOne = (result) => jest.spyOn(EducationTask, 'findOne').mockResolvedValueOnce(result); -const spyFindOneAndUpdate = (result) => - jest.spyOn(EducationTask, 'findOneAndUpdate').mockResolvedValueOnce(result); - -describe('studentTaskController - logHours', () => { - let logHours; - - beforeEach(() => { - logHours = studentTaskController().logHours; - mockReq.params.taskId = VALID_TASK_ID; - mockReq.body.requestor = { requestorId: VALID_STUDENT_ID }; - mockReq.body.hours = 1; - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('Input validation', () => { - test.each([ - ['taskId is missing', { params: { taskId: '' } }, 400, { error: 'Invalid Task ID' }], - [ - 'taskId is not a valid ObjectId', - { params: { taskId: 'bad-id' } }, - 400, - { error: 'Invalid Task ID' }, - ], - [ - 'studentId is missing', - { body: { requestor: {}, hours: 1 } }, - 400, - { error: 'Invalid Student ID' }, - ], - [ - 'studentId is not a valid ObjectId', - { body: { requestor: { requestorId: 'bad' }, hours: 1 } }, - 400, - { error: 'Invalid Student ID' }, - ], - [ - 'hours is zero', - { body: { requestor: { requestorId: VALID_STUDENT_ID }, hours: 0 } }, - 400, - { error: 'hours must be a positive number' }, - ], - [ - 'hours is negative', - { body: { requestor: { requestorId: VALID_STUDENT_ID }, hours: -1 } }, - 400, - { error: 'hours must be a positive number' }, - ], - [ - 'hours is not a number', - { body: { requestor: { requestorId: VALID_STUDENT_ID }, hours: 'abc' } }, - 400, - { error: 'hours must be a positive number' }, - ], - ])('Returns %i when %s', async (_, reqOverrides, expectedStatus, expectedBody) => { - Object.assign(mockReq, reqOverrides); - if (reqOverrides.params) Object.assign(mockReq.params, reqOverrides.params); - await logHours(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(expectedStatus); - expect(mockRes.json).toHaveBeenCalledWith(expectedBody); - }); - }); - - describe('Database interactions', () => { - test('Returns 404 if task is not found', async () => { - spyFindOne(null); - await logHours(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(404); - expect(mockRes.json).toHaveBeenCalledWith({ - error: 'Task not found or does not belong to you', - }); - }); - - test.each([ - ['completed', makeTask({ status: 'completed', loggedHours: 3 })], - ['graded', makeTask({ status: 'graded', loggedHours: 5 })], - ])('Returns 400 if task status is %s', async (_, task) => { - spyFindOne(task); - await logHours(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(400); - expect(mockRes.json).toHaveBeenCalledWith({ error: 'Cannot log hours for a completed task' }); - }); - - test('Returns 200 and transitions assigned -> in_progress on first log', async () => { - spyFindOne(makeTask()); - spyFindOneAndUpdate(makeUpdated()); - await logHours(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(200); - expect(mockRes.json).toHaveBeenCalledWith({ - message: 'Hours logged successfully', - loggedHours: 1, - suggestedTotalHours: 5, - status: 'in_progress', - canMarkDone: false, - }); - }); - - test('Returns 200 and caps loggedHours at suggestedTotalHours', async () => { - mockReq.body.hours = 3; - spyFindOne(makeTask({ status: 'in_progress', loggedHours: 4 })); - spyFindOneAndUpdate(makeUpdated({ loggedHours: 5 })); - await logHours(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(200); - expect(mockRes.json).toHaveBeenCalledWith({ - message: 'Hours logged successfully', - loggedHours: 5, - suggestedTotalHours: 5, - status: 'in_progress', - canMarkDone: true, - }); - expect(EducationTask.findOneAndUpdate).toHaveBeenCalledWith( - expect.any(Object), - { $set: { loggedHours: 5, status: 'in_progress' } }, - { new: true, runValidators: false }, - ); - }); - - test('Returns 404 if findOneAndUpdate returns null', async () => { - spyFindOne(makeTask()); - spyFindOneAndUpdate(null); - await logHours(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(404); - expect(mockRes.json).toHaveBeenCalledWith({ error: 'Task not found during update' }); - }); - - test('Returns 200 with canMarkDone false when suggestedTotalHours is 0', async () => { - spyFindOne(makeTask({ suggestedTotalHours: 0 })); - spyFindOneAndUpdate(makeUpdated({ suggestedTotalHours: 0 })); - await logHours(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(200); - expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({ canMarkDone: false })); - }); - - test('Returns 500 if findOne throws an error', async () => { - spyFindOne(Promise.reject(new Error('DB error'))); - await logHours(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(500); - expect(mockRes.json).toHaveBeenCalledWith({ error: 'Internal server error' }); - }); - }); -}); diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js index 6db0d6f36..16b1ba46f 100644 --- a/src/controllers/userProfileController.js +++ b/src/controllers/userProfileController.js @@ -2089,8 +2089,6 @@ 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/__tests__/toolUtilizationHelpers.test.js b/src/helpers/__tests__/toolUtilizationHelpers.test.js new file mode 100644 index 000000000..dc7baa86d --- /dev/null +++ b/src/helpers/__tests__/toolUtilizationHelpers.test.js @@ -0,0 +1,872 @@ +jest.mock('mongoose', () => ({ + Types: { + ObjectId: Object.assign( + jest.fn((id) => id), + { + isValid: jest.fn(), + }, + ), + }, +})); + +jest.mock('regression', () => ({ linear: jest.fn() })); + +jest.mock('../../models/bmdashboard/projectRiskProfile', () => ({ findOne: jest.fn() })); + +const mockCache = { hasCache: jest.fn(), getCache: jest.fn(), setCache: jest.fn() }; +jest.mock('../../utilities/nodeCache', () => jest.fn(() => mockCache)); + +const mongoose = require('mongoose'); +const regression = require('regression'); +const ProjectRiskProfile = require('../../models/bmdashboard/projectRiskProfile'); +const cache = require('../../utilities/nodeCache')(); +const { + classifyUtilization, + calculateCheckedOutHours, + buildToolFilter, + parseDateRange, + groupToolsByType, + calculateGroupUtilization, + buildCacheKey, + computeUtilizationData, + bucketUtilizationByWeek, + forecastUtilization, + generateMaintenanceAlerts, + generateResourceBalancingSuggestions, + generateRecommendations, + stripInternalDetails, + buildInsightsSummary, + determineForecastDays, + buildUtilizationResponse, + buildReportPayload, +} = require('../toolUtilizationHelpers'); + +// ─── Shared fixtures ─── +const makeLog = (type, dateStr) => ({ type, date: new Date(dateStr) }); + +const JAN1 = new Date('2026-01-01T00:00:00Z'); +const JAN31 = new Date('2026-01-31T23:59:59Z'); +const JAN_HOURS = (JAN31 - JAN1) / 3600000; + +const makeToolItem = (logRecord = [], extra = {}) => ({ + logRecord, + itemType: { _id: { toString: () => 'type1' }, name: 'Power Drill' }, + purchaseStatus: 'Purchased', + condition: 'Good', + currentUsage: 'Available', + ...extra, +}); + +const makeUtilizationItem = ( + name, + rate, + purchaseStatuses = [], + conditions = [], + currentUsages = [], +) => ({ + name, + utilizationRate: rate, + downtime: 100, + classification: classifyUtilization(rate), + toolCount: purchaseStatuses.length || 2, + totalCheckedOutHours: rate * 0.72, + totalPossibleHours: 720, + toolGroupDetails: { + tools: purchaseStatuses.map(() => ({})), + purchaseStatuses, + conditions, + currentUsages, + }, +}); + +const makeMockBuildingTool = (tools = []) => { + const lean = jest.fn().mockResolvedValue(tools); + const chain = { populate: jest.fn(), lean }; + chain.populate.mockReturnValue(chain); + return { BuildingTool: { find: jest.fn().mockReturnValue(chain) }, lean }; +}; + +beforeEach(() => { + jest.clearAllMocks(); + mongoose.Types.ObjectId.isValid.mockReturnValue(true); + cache.hasCache.mockReturnValue(false); + regression.linear.mockReturnValue({ + r2: 0.8, + predict: jest.fn().mockImplementation((i) => [i, 60]), + }); +}); + +// ─── classifyUtilization ─── +describe('classifyUtilization', () => { + it('returns Under-utilized and yellow for rate 0', () => { + expect(classifyUtilization(0)).toEqual({ label: 'Under-utilized', trafficLight: 'yellow' }); + }); + + it('returns Under-utilized and yellow for rate 54', () => { + expect(classifyUtilization(54)).toEqual({ label: 'Under-utilized', trafficLight: 'yellow' }); + }); + + it('returns Normal and green for rate 55', () => { + expect(classifyUtilization(55)).toEqual({ label: 'Normal', trafficLight: 'green' }); + }); + + it('returns Normal and green for rate 85', () => { + expect(classifyUtilization(85)).toEqual({ label: 'Normal', trafficLight: 'green' }); + }); + + it('returns Over-utilized and red for rate 86', () => { + expect(classifyUtilization(86)).toEqual({ label: 'Over-utilized', trafficLight: 'red' }); + }); + + it('returns Over-utilized and red for rate 100', () => { + expect(classifyUtilization(100)).toEqual({ label: 'Over-utilized', trafficLight: 'red' }); + }); +}); + +// ─── calculateCheckedOutHours ─── +describe('calculateCheckedOutHours', () => { + it('returns 0 when logRecord is undefined', () => { + expect(calculateCheckedOutHours({ logRecord: undefined }, JAN1, JAN31)).toBe(0); + }); + + it('returns 0 when no logs fall within period and only a prior checkin exists', () => { + const toolWithCheckin = makeToolItem([makeLog('Check In', '2025-12-15T00:00:00Z')]); + expect(calculateCheckedOutHours(toolWithCheckin, JAN1, JAN31)).toBe(0); + }); + + it('returns full period hours when no logs in period and last prior log is Check Out', () => { + const tool = makeToolItem([makeLog('Check Out', '2025-12-15T00:00:00Z')]); + const result = calculateCheckedOutHours(tool, JAN1, JAN31); + expect(result).toBeCloseTo(JAN_HOURS, 0); + }); + + it('returns 0 when no logs in period and last prior log is Check In', () => { + const tool = makeToolItem([ + makeLog('Check Out', '2025-12-01T00:00:00Z'), + makeLog('Check In', '2025-12-15T00:00:00Z'), + ]); + expect(calculateCheckedOutHours(tool, JAN1, JAN31)).toBe(0); + }); + + it('returns hours between Check Out and Check In within period', () => { + const checkOut = new Date('2026-01-05T08:00:00Z'); + const checkIn = new Date('2026-01-05T12:00:00Z'); + const tool = makeToolItem([makeLog('Check Out', checkOut), makeLog('Check In', checkIn)]); + expect(calculateCheckedOutHours(tool, JAN1, JAN31)).toBeCloseTo(4, 5); + }); + + it('counts time to period end when Check Out has no matching Check In', () => { + const checkOut = new Date('2026-01-31T20:00:00Z'); + const tool = makeToolItem([makeLog('Check Out', checkOut)]); + const expected = (JAN31 - checkOut) / 3600000; + expect(calculateCheckedOutHours(tool, JAN1, JAN31)).toBeCloseTo(expected, 5); + }); + + it('ignores orphan Check In with no preceding Check Out', () => { + const tool = makeToolItem([makeLog('Check In', '2026-01-10T10:00:00Z')]); + expect(calculateCheckedOutHours(tool, JAN1, JAN31)).toBe(0); + }); + + it('accumulates multiple checkout/checkin pairs', () => { + const logs = [ + makeLog('Check Out', '2026-01-05T08:00:00Z'), + makeLog('Check In', '2026-01-05T10:00:00Z'), // 2 hours + makeLog('Check Out', '2026-01-10T06:00:00Z'), + makeLog('Check In', '2026-01-10T10:00:00Z'), // 4 hours + ]; + const tool = makeToolItem(logs); + expect(calculateCheckedOutHours(tool, JAN1, JAN31)).toBeCloseTo(6, 5); + }); +}); + +// ─── buildToolFilter ─── +describe('buildToolFilter', () => { + it('returns only __t filter when no params', () => { + expect(buildToolFilter({})).toEqual({ __t: 'tool_item' }); + }); + + it('ignores tool when tool is ALL', () => { + expect(buildToolFilter({ tool: 'ALL' })).toEqual({ __t: 'tool_item' }); + }); + + it('ignores tool when ObjectId is invalid', () => { + mongoose.Types.ObjectId.isValid.mockReturnValue(false); + expect(buildToolFilter({ tool: 'invalid-id' })).toEqual({ __t: 'tool_item' }); + }); + + it('adds itemType when tool is a valid ObjectId', () => { + const result = buildToolFilter({ tool: 'abc123' }); + expect(result.__t).toBe('tool_item'); + expect(result.itemType).toBeDefined(); + }); + + it('ignores project when project is ALL', () => { + expect(buildToolFilter({ project: 'ALL' })).toEqual({ __t: 'tool_item' }); + }); + + it('adds both itemType and project when both are valid ObjectIds', () => { + const result = buildToolFilter({ tool: 'tool1', project: 'proj1' }); + expect(result.itemType).toBeDefined(); + expect(result.project).toBeDefined(); + }); +}); + +// ─── parseDateRange ─── +describe('parseDateRange', () => { + it('defaults to last 30 days when no dates provided', () => { + const before = Date.now(); + const { rangeEnd, totalHours } = parseDateRange(undefined, undefined); + const after = Date.now(); + expect(rangeEnd.getTime()).toBeGreaterThanOrEqual(before); + expect(rangeEnd.getTime()).toBeLessThanOrEqual(after); + // 30 calendar days ≈ 719–721 hours depending on DST transitions + expect(totalHours).toBeGreaterThanOrEqual(29 * 24); + expect(totalHours).toBeLessThanOrEqual(31 * 24); + }); + + it('uses provided startDate', () => { + const { rangeStart } = parseDateRange('2026-01-01', undefined); + expect(rangeStart.toISOString().startsWith('2026-01-01')).toBe(true); + }); + + it('uses provided endDate', () => { + const { rangeEnd } = parseDateRange(undefined, '2026-02-01'); + expect(rangeEnd.toISOString().startsWith('2026-02-01')).toBe(true); + }); + + it('computes totalHours correctly when both dates provided', () => { + const { totalHours } = parseDateRange('2026-01-01T00:00:00Z', '2026-01-02T00:00:00Z'); + expect(totalHours).toBeCloseTo(24, 5); + }); +}); + +// ─── groupToolsByType ─── +describe('groupToolsByType', () => { + it('returns empty object for empty tools array', () => { + expect(groupToolsByType([])).toEqual({}); + }); + + it('skips tools without itemType', () => { + const tool = { logRecord: [] }; // no itemType + expect(groupToolsByType([tool])).toEqual({}); + }); + + it('groups multiple tools of the same type under one key', () => { + const tool1 = makeToolItem(); + const tool2 = makeToolItem(); + const groups = groupToolsByType([tool1, tool2]); + expect(Object.keys(groups)).toHaveLength(1); + expect(groups.type1.tools).toHaveLength(2); + }); + + it('creates separate groups for different types', () => { + const tool1 = makeToolItem([], { + itemType: { _id: { toString: () => 'typeA' }, name: 'Drill' }, + }); + const tool2 = makeToolItem([], { + itemType: { _id: { toString: () => 'typeB' }, name: 'Hammer' }, + }); + const groups = groupToolsByType([tool1, tool2]); + expect(Object.keys(groups)).toHaveLength(2); + }); +}); + +// ─── calculateGroupUtilization ─── +describe('calculateGroupUtilization', () => { + it('returns utilizationRate of 0 when totalHours is 0', () => { + const group = { name: 'Drill', tools: [makeToolItem()] }; + const result = calculateGroupUtilization(group, JAN1, JAN1, 0); + expect(result.utilizationRate).toBe(0); + }); + + it('computes correct utilization rate and downtime for normal case', () => { + const checkOut = new Date('2026-01-15T00:00:00Z'); + const checkIn = new Date('2026-01-16T00:00:00Z'); // 24 hours checked out + const tool = makeToolItem([makeLog('Check Out', checkOut), makeLog('Check In', checkIn)]); + const result = calculateGroupUtilization( + { name: 'Drill', tools: [tool] }, + JAN1, + JAN31, + JAN_HOURS, + ); + expect(result.utilizationRate).toBeGreaterThan(0); + expect(result.downtime).toBeGreaterThanOrEqual(0); + expect(result.classification).toBeDefined(); + }); + + it('collects purchaseStatuses, conditions, and currentUsages from tools', () => { + const tool1 = makeToolItem([], { + purchaseStatus: 'Purchased', + condition: 'Worn', + currentUsage: 'Under Maintenance', + }); + const tool2 = makeToolItem([], { + purchaseStatus: 'Rental', + condition: 'Good', + currentUsage: 'Available', + }); + const result = calculateGroupUtilization( + { name: 'Drill', tools: [tool1, tool2] }, + JAN1, + JAN31, + JAN_HOURS, + ); + expect(result.toolGroupDetails.purchaseStatuses).toEqual(['Purchased', 'Rental']); + expect(result.toolGroupDetails.conditions).toEqual(['Worn', 'Good']); + expect(result.toolGroupDetails.currentUsages).toEqual(['Under Maintenance', 'Available']); + }); + + it('includes toolCount and totalCheckedOutHours in result', () => { + const group = { name: 'Drill', tools: [makeToolItem(), makeToolItem()] }; + const result = calculateGroupUtilization(group, JAN1, JAN31, JAN_HOURS); + expect(result.toolCount).toBe(2); + expect(result.totalCheckedOutHours).toBeGreaterThanOrEqual(0); + expect(result.totalPossibleHours).toBeCloseTo(JAN_HOURS * 2, 0); + }); +}); + +// ─── buildCacheKey ─── +describe('buildCacheKey', () => { + it('builds full key from all params', () => { + expect( + buildCacheKey({ tool: 't1', project: 'p1', startDate: '2026-01-01', endDate: '2026-01-31' }), + ).toBe('toolUtil:t1:p1:2026-01-01:2026-01-31'); + }); + + it('uses ALL and default when params are absent', () => { + expect(buildCacheKey({})).toBe('toolUtil:ALL:ALL:default:default'); + }); + + it('fills in defaults for missing params only', () => { + expect(buildCacheKey({ tool: 'myTool' })).toBe('toolUtil:myTool:ALL:default:default'); + }); +}); + +// ─── computeUtilizationData ─── +describe('computeUtilizationData', () => { + it('returns cached result without querying DB when cache hits', async () => { + const cached = { + utilizationData: [], + rangeStart: JAN1, + rangeEnd: JAN31, + totalHours: JAN_HOURS, + }; + cache.hasCache.mockReturnValue(true); + cache.getCache.mockReturnValue(cached); + + const { BuildingTool } = makeMockBuildingTool([]); + const result = await computeUtilizationData(BuildingTool, {}); + + expect(result).toBe(cached); + expect(BuildingTool.find).not.toHaveBeenCalled(); + }); + + it('queries DB and caches result on cache miss', async () => { + const tool = makeToolItem([], { itemType: { _id: { toString: () => 'id1' }, name: 'Drill' } }); + const { BuildingTool } = makeMockBuildingTool([tool]); + + const result = await computeUtilizationData(BuildingTool, {}); + + expect(BuildingTool.find).toHaveBeenCalled(); + expect(cache.setCache).toHaveBeenCalled(); + expect(result.utilizationData).toHaveLength(1); + }); + + it('returns empty utilizationData when no tools found', async () => { + const { BuildingTool } = makeMockBuildingTool([]); + const result = await computeUtilizationData(BuildingTool, {}); + expect(result.utilizationData).toHaveLength(0); + }); + + it('sorts utilizationData by utilizationRate descending', async () => { + const now = new Date(); + const thirtyDaysAgo = new Date(now.getTime() - 29 * 24 * 3600000); + const highUseTool = makeToolItem( + [makeLog('Check Out', thirtyDaysAgo), makeLog('Check In', now)], + { itemType: { _id: { toString: () => 'highId' }, name: 'Hammer' } }, + ); + const lowUseTool = makeToolItem([], { + itemType: { _id: { toString: () => 'lowId' }, name: 'Shovel' }, + }); + const { BuildingTool } = makeMockBuildingTool([lowUseTool, highUseTool]); + + const result = await computeUtilizationData(BuildingTool, {}); + + expect(result.utilizationData[0].utilizationRate).toBeGreaterThanOrEqual( + result.utilizationData[1].utilizationRate, + ); + }); +}); + +// ─── bucketUtilizationByWeek ─── +describe('bucketUtilizationByWeek', () => { + const toolGroup = { tools: [makeToolItem()] }; + + it('returns 1 bucket when range is less than one week', () => { + const start = new Date('2026-01-01T00:00:00Z'); + const end = new Date('2026-01-03T00:00:00Z'); // 2 days + const buckets = bucketUtilizationByWeek(toolGroup, start, end); + expect(buckets).toHaveLength(1); + }); + + it('returns 2 buckets for a 14-day range', () => { + const start = new Date('2026-01-01T00:00:00Z'); + const end = new Date('2026-01-15T00:00:00Z'); + const buckets = bucketUtilizationByWeek(toolGroup, start, end); + expect(buckets).toHaveLength(2); + }); + + it('returns 5 buckets for a 30-day range', () => { + const start = new Date('2026-01-01T00:00:00Z'); + const end = new Date('2026-01-31T00:00:00Z'); + const buckets = bucketUtilizationByWeek(toolGroup, start, end); + expect(buckets).toHaveLength(5); + }); + + it('each bucket has weekIndex, weekStart, weekEnd, and utilizationRate', () => { + const start = new Date('2026-01-01T00:00:00Z'); + const end = new Date('2026-01-15T00:00:00Z'); + const buckets = bucketUtilizationByWeek(toolGroup, start, end); + buckets.forEach((bucket, i) => { + expect(bucket.weekIndex).toBe(i); + expect(bucket.weekStart).toBeInstanceOf(Date); + expect(bucket.weekEnd).toBeInstanceOf(Date); + expect(typeof bucket.utilizationRate).toBe('number'); + }); + }); +}); + +// ─── forecastUtilization ─── +describe('forecastUtilization', () => { + const makeWeeklyBuckets = (count, rate = 50) => + Array.from({ length: count }, (_, i) => ({ + weekIndex: i, + weekStart: new Date(Date.now() - (count - i) * 7 * 24 * 3600000), + weekEnd: new Date(Date.now() - (count - i - 1) * 7 * 24 * 3600000), + utilizationRate: rate, + })); + + it('returns predictedRate 0 and method average for empty buckets', () => { + const result = forecastUtilization([], 30); + expect(result.predictedRate).toBe(0); + expect(result.method).toBe('average'); + expect(result.confidence).toBe('low'); + }); + + it('uses average method when fewer than 3 buckets', () => { + const result = forecastUtilization(makeWeeklyBuckets(2, 60), 30); + expect(result.method).toBe('average'); + expect(result.predictedRate).toBe(60); + expect(result.confidence).toBe('low'); + }); + + it('uses average when exactly 1 bucket', () => { + const result = forecastUtilization(makeWeeklyBuckets(1, 40), 30); + expect(result.method).toBe('average'); + expect(result.predictedRate).toBe(40); + }); + + it('uses ensemble method with high confidence for r2 >= 0.7', () => { + regression.linear.mockReturnValue({ r2: 0.8, predict: jest.fn().mockReturnValue([0, 65]) }); + const result = forecastUtilization(makeWeeklyBuckets(4, 60), 30); + expect(result.method).toBe('ensemble'); + expect(result.confidence).toBe('high'); + }); + + it('uses ensemble with medium confidence for r2 between 0.4 and 0.7', () => { + regression.linear.mockReturnValue({ r2: 0.5, predict: jest.fn().mockReturnValue([0, 55]) }); + const result = forecastUtilization(makeWeeklyBuckets(4, 50), 30); + expect(result.method).toBe('ensemble'); + expect(result.confidence).toBe('medium'); + }); + + it('uses ensemble with low confidence for r2 below 0.4', () => { + regression.linear.mockReturnValue({ r2: 0.2, predict: jest.fn().mockReturnValue([0, 50]) }); + const result = forecastUtilization(makeWeeklyBuckets(4, 50), 30); + expect(result.confidence).toBe('low'); + }); + + it('clamps blended prediction to 0 when regression predicts very low', () => { + regression.linear.mockReturnValue({ r2: 0.9, predict: jest.fn().mockReturnValue([0, -100]) }); + const result = forecastUtilization(makeWeeklyBuckets(4, 0), 30); + result.weeklyPredictions.forEach((w) => { + expect(w.predictedRate).toBeGreaterThanOrEqual(0); + }); + }); + + it('clamps blended prediction to 100 when regression predicts very high', () => { + regression.linear.mockReturnValue({ r2: 0.9, predict: jest.fn().mockReturnValue([0, 200]) }); + const result = forecastUtilization(makeWeeklyBuckets(4, 100), 30); + result.weeklyPredictions.forEach((w) => { + expect(w.predictedRate).toBeLessThanOrEqual(100); + }); + }); + + it('returns ISO forecastEndDate and predictedClassification', () => { + const result = forecastUtilization(makeWeeklyBuckets(2, 50), 30); + expect(() => new Date(result.forecastEndDate)).not.toThrow(); + expect(result.predictedClassification).toHaveProperty('label'); + expect(result.predictedClassification).toHaveProperty('trafficLight'); + }); +}); + +// ─── generateMaintenanceAlerts ─── +describe('generateMaintenanceAlerts', () => { + it('returns no alerts for a normal tool', () => { + const data = [makeUtilizationItem('Drill', 70, ['Purchased'], ['Good'], ['Available'])]; + expect(generateMaintenanceAlerts(data)).toHaveLength(0); + }); + + it('generates overuse alert when rate exceeds 85', () => { + const data = [makeUtilizationItem('Drill', 90, ['Purchased'], ['Good'], ['Available'])]; + const alerts = generateMaintenanceAlerts(data); + const overuseAlert = alerts.find((a) => a.alertType === 'overuse'); + expect(overuseAlert).toBeDefined(); + expect(overuseAlert.urgency).toBe('high'); + expect(overuseAlert.message).toContain('90%'); + }); + + it('generates condition alert for degraded tool condition', () => { + const data = [makeUtilizationItem('Drill', 70, [], ['Worn'], [])]; + const alerts = generateMaintenanceAlerts(data); + expect(alerts.find((a) => a.alertType === 'condition')).toBeDefined(); + }); + + it('deduplicates condition alerts for same condition appearing twice', () => { + const data = [makeUtilizationItem('Drill', 70, [], ['Worn', 'Worn'], [])]; + const conditionAlerts = generateMaintenanceAlerts(data).filter( + (a) => a.alertType === 'condition', + ); + expect(conditionAlerts).toHaveLength(1); + }); + + it('does not generate condition alert for Good condition', () => { + const data = [makeUtilizationItem('Drill', 70, [], ['Good'], [])]; + expect(generateMaintenanceAlerts(data).filter((a) => a.alertType === 'condition')).toHaveLength( + 0, + ); + }); + + it('generates non_operational alert when tool is Under Maintenance', () => { + const data = [makeUtilizationItem('Drill', 70, [], [], ['Under Maintenance'])]; + const alerts = generateMaintenanceAlerts(data); + const nonOpAlert = alerts.find((a) => a.alertType === 'non_operational'); + expect(nonOpAlert).toBeDefined(); + expect(nonOpAlert.urgency).toBe('medium'); + expect(nonOpAlert.message).toContain('1 unit(s)'); + }); + + it('counts multiple non-operational units in single alert per status', () => { + const data = [ + makeUtilizationItem('Drill', 70, [], [], ['Under Maintenance', 'Under Maintenance']), + ]; + const nonOpAlerts = generateMaintenanceAlerts(data).filter( + (a) => a.alertType === 'non_operational', + ); + expect(nonOpAlerts).toHaveLength(1); + expect(nonOpAlerts[0].message).toContain('2 unit(s)'); + }); +}); + +// ─── generateResourceBalancingSuggestions ─── +describe('generateResourceBalancingSuggestions', () => { + it('returns no suggestions for all-normal tools', () => { + const data = [makeUtilizationItem('Drill', 70), makeUtilizationItem('Hammer', 65)]; + expect(generateResourceBalancingSuggestions(data)).toHaveLength(0); + }); + + it('suggests redistribution when over and under-utilized tools coexist', () => { + const data = [makeUtilizationItem('Drill', 90), makeUtilizationItem('Wheelbarrow', 30)]; + const suggestions = generateResourceBalancingSuggestions(data); + expect(suggestions.find((s) => s.suggestion.includes('redistributing'))).toBeDefined(); + }); + + it('pairs over-utilized with the least-used under-utilized tool', () => { + const data = [ + makeUtilizationItem('Drill', 90), + makeUtilizationItem('Shovel', 40), + makeUtilizationItem('Wheelbarrow', 20), + ]; + const suggestions = generateResourceBalancingSuggestions(data); + const redist = suggestions.find((s) => s.suggestion.includes('redistributing')); + expect(redist.toTool).toBe('Wheelbarrow'); + }); + + it('suggests purchasing when over-utilized tool is mostly rented', () => { + const data = [makeUtilizationItem('Drill', 90, ['Rental', 'Rental', 'Purchased'])]; + const suggestions = generateResourceBalancingSuggestions(data); + expect(suggestions.find((s) => s.suggestion.includes('purchasing additional'))).toBeDefined(); + }); + + it('suggests renting when under-utilized tool is mostly owned', () => { + const data = [makeUtilizationItem('Shovel', 30, ['Purchased', 'Purchased', 'Rental'])]; + const suggestions = generateResourceBalancingSuggestions(data); + expect(suggestions.find((s) => s.suggestion.includes('renting instead'))).toBeDefined(); + }); + + it('no redistribution suggestion when over-utilized has no under-utilized counterpart', () => { + const data = [makeUtilizationItem('Drill', 90, ['Purchased', 'Purchased'])]; + const suggestions = generateResourceBalancingSuggestions(data); + expect(suggestions.find((s) => s.suggestion.includes('redistributing'))).toBeUndefined(); + }); +}); + +// ─── generateRecommendations ─── +describe('generateRecommendations', () => { + it('recommends review for under-utilized tool', () => { + const result = generateRecommendations([makeUtilizationItem('Shovel', 30)]); + expect(result[0].action).toContain('Potentially removable'); + expect(result[0].toolName).toBe('Shovel'); + expect(result[0].trafficLight).toBe('yellow'); + }); + + it('recommends no action for normal tool', () => { + const result = generateRecommendations([makeUtilizationItem('Drill', 70)]); + expect(result[0].action).toContain('Normal operation'); + expect(result[0].trafficLight).toBe('green'); + }); + + it('recommends maintenance planning for over-utilized tool', () => { + const result = generateRecommendations([makeUtilizationItem('Crane', 90)]); + expect(result[0].action).toContain('Requires maintenance scheduling'); + expect(result[0].trafficLight).toBe('red'); + }); +}); + +// ─── stripInternalDetails ─── +describe('stripInternalDetails', () => { + it('removes toolGroupDetails from item', () => { + const item = { name: 'Drill', utilizationRate: 75, toolGroupDetails: { tools: [] } }; + const result = stripInternalDetails(item); + expect(result.toolGroupDetails).toBeUndefined(); + }); + + it('preserves all other public fields', () => { + const item = { + name: 'Drill', + utilizationRate: 75, + downtime: 100, + classification: { label: 'Normal', trafficLight: 'green' }, + toolCount: 2, + toolGroupDetails: { tools: [] }, + }; + const result = stripInternalDetails(item); + expect(result.name).toBe('Drill'); + expect(result.utilizationRate).toBe(75); + expect(result.downtime).toBe(100); + expect(result.classification).toBeDefined(); + expect(result.toolCount).toBe(2); + }); +}); + +// ─── buildInsightsSummary ─── +describe('buildInsightsSummary', () => { + it('returns all zeros for empty array', () => { + const result = buildInsightsSummary([]); + expect(result).toEqual({ + totalToolTypes: 0, + underUtilized: 0, + normal: 0, + overUtilized: 0, + averageUtilization: 0, + }); + }); + + it('counts all as normal when all tools are normal', () => { + const data = [makeUtilizationItem('A', 60), makeUtilizationItem('B', 75)]; + const result = buildInsightsSummary(data); + expect(result.normal).toBe(2); + expect(result.underUtilized).toBe(0); + expect(result.overUtilized).toBe(0); + }); + + it('correctly counts mixed utilization categories', () => { + const data = [ + makeUtilizationItem('A', 30), // under + makeUtilizationItem('B', 70), // normal + makeUtilizationItem('C', 90), // over + ]; + const result = buildInsightsSummary(data); + expect(result.underUtilized).toBe(1); + expect(result.normal).toBe(1); + expect(result.overUtilized).toBe(1); + expect(result.totalToolTypes).toBe(3); + }); + + it('computes averageUtilization as rounded mean', () => { + const data = [makeUtilizationItem('A', 60), makeUtilizationItem('B', 80)]; + const result = buildInsightsSummary(data); + expect(result.averageUtilization).toBe(70); + }); +}); + +// ─── determineForecastDays ─── +describe('determineForecastDays', () => { + it('returns 30 days with no warning for forecast30 mode', async () => { + const result = await determineForecastDays('forecast30', 'anyId'); + expect(result.forecastDays).toBe(30); + expect(result.warning).toBeNull(); + }); + + it('returns 30 days with warning when no projectId for forecastFull', async () => { + const result = await determineForecastDays('forecastFull', undefined); + expect(result.forecastDays).toBe(30); + expect(result.warning).toContain('No specific project'); + }); + + it('returns 30 days with warning when projectId is ALL', async () => { + const result = await determineForecastDays('forecastFull', 'ALL'); + expect(result.forecastDays).toBe(30); + expect(result.warning).toBeTruthy(); + }); + + it('returns 30 days with warning when no risk profile found', async () => { + ProjectRiskProfile.findOne.mockReturnValue({ lean: jest.fn().mockResolvedValue(null) }); + const result = await determineForecastDays('forecastFull', 'validProjectId'); + expect(result.forecastDays).toBe(30); + expect(result.warning).toContain('No project schedule'); + }); + + it('returns 30 days with warning when risk profile has no endDate', async () => { + ProjectRiskProfile.findOne.mockReturnValue({ + lean: jest.fn().mockResolvedValue({ projectId: 'p1' }), + }); + const result = await determineForecastDays('forecastFull', 'validProjectId'); + expect(result.forecastDays).toBe(30); + expect(result.warning).toBeTruthy(); + }); + + it('returns calculated days when risk profile has a future endDate', async () => { + const futureDate = new Date(Date.now() + 60 * 24 * 3600000); + ProjectRiskProfile.findOne.mockReturnValue({ + lean: jest.fn().mockResolvedValue({ endDate: futureDate }), + }); + const result = await determineForecastDays('forecastFull', 'validProjectId'); + expect(result.forecastDays).toBeGreaterThan(50); + expect(result.warning).toBeNull(); + }); + + it('enforces minimum of 7 days when endDate is very soon', async () => { + const nearDate = new Date(Date.now() + 2 * 24 * 3600000); + ProjectRiskProfile.findOne.mockReturnValue({ + lean: jest.fn().mockResolvedValue({ endDate: nearDate }), + }); + const result = await determineForecastDays('forecastFull', 'validProjectId'); + expect(result.forecastDays).toBe(7); + }); +}); + +// ─── buildUtilizationResponse ─── +describe('buildUtilizationResponse', () => { + const rangeStart = new Date('2026-01-01T00:00:00Z'); + const rangeEnd = new Date('2026-01-22T00:00:00Z'); // 21 days → 3 weekly buckets + + const makeItem = (name, rate) => ({ + ...makeUtilizationItem(name, rate), + toolGroupDetails: { + tools: [makeToolItem()], + purchaseStatuses: [], + conditions: [], + currentUsages: [], + }, + }); + + it('sets forecast to null in historical mode', async () => { + const data = [makeItem('Drill', 70)]; + const result = await buildUtilizationResponse({ + utilizationData: data, + rangeStart, + rangeEnd, + selectedMode: 'historical', + project: null, + }); + expect(result[0].forecast).toBeNull(); + expect(result[0].toolGroupDetails).toBeUndefined(); + }); + + it('attaches forecast object in forecast30 mode', async () => { + const data = [makeItem('Drill', 70)]; + const result = await buildUtilizationResponse({ + utilizationData: data, + rangeStart, + rangeEnd, + selectedMode: 'forecast30', + project: null, + }); + expect(result[0].forecast).not.toBeNull(); + expect(result[0].forecast).toHaveProperty('predictedRate'); + expect(result[0].forecast).toHaveProperty('weeklyPredictions'); + }); + + it('adds warning to all items when no project selected in forecastFull', async () => { + const data = [makeItem('Drill', 70), makeItem('Hammer', 50)]; + const result = await buildUtilizationResponse({ + utilizationData: data, + rangeStart, + rangeEnd, + selectedMode: 'forecastFull', + project: null, + }); + expect(result[0].warning).toBeTruthy(); + expect(result[1].warning).toBeTruthy(); + }); + + it('does not add warning when valid project has a risk profile', async () => { + const futureDate = new Date(Date.now() + 60 * 24 * 3600000); + ProjectRiskProfile.findOne.mockReturnValue({ + lean: jest.fn().mockResolvedValue({ endDate: futureDate }), + }); + const data = [makeItem('Drill', 70)]; + const result = await buildUtilizationResponse({ + utilizationData: data, + rangeStart, + rangeEnd, + selectedMode: 'forecastFull', + project: 'validProjectId', + }); + expect(result[0].warning).toBeUndefined(); + }); + + it('strips toolGroupDetails from all response items', async () => { + const data = [makeItem('Drill', 70)]; + const result = await buildUtilizationResponse({ + utilizationData: data, + rangeStart, + rangeEnd, + selectedMode: 'historical', + project: null, + }); + expect(result[0].toolGroupDetails).toBeUndefined(); + }); +}); + +// ─── buildReportPayload ─── +describe('buildReportPayload', () => { + const rangeStart = new Date('2026-01-01T00:00:00Z'); + const rangeEnd = new Date('2026-01-31T00:00:00Z'); + + it('returns object with all required keys', () => { + const data = [makeUtilizationItem('Drill', 70)]; + const result = buildReportPayload(data, rangeStart, rangeEnd, 'proj1'); + expect(result).toHaveProperty('utilizationData'); + expect(result).toHaveProperty('alerts'); + expect(result).toHaveProperty('balancing'); + expect(result).toHaveProperty('recommendations'); + expect(result).toHaveProperty('summary'); + expect(result).toHaveProperty('metadata'); + }); + + it('builds metadata with correct dateRange and projectFilter', () => { + const data = [makeUtilizationItem('Drill', 70)]; + const result = buildReportPayload(data, rangeStart, rangeEnd, 'myProject'); + expect(result.metadata.dateRange).toContain(rangeStart.toISOString()); + expect(result.metadata.dateRange).toContain(rangeEnd.toISOString()); + expect(result.metadata.projectFilter).toBe('myProject'); + }); + + it('defaults projectFilter to ALL when project is not provided', () => { + const data = []; + const result = buildReportPayload(data, rangeStart, rangeEnd, undefined); + expect(result.metadata.projectFilter).toBe('ALL'); + }); +}); diff --git a/src/helpers/__tests__/toolUtilizationReportHelpers.test.js b/src/helpers/__tests__/toolUtilizationReportHelpers.test.js new file mode 100644 index 000000000..644473d2c --- /dev/null +++ b/src/helpers/__tests__/toolUtilizationReportHelpers.test.js @@ -0,0 +1,181 @@ +jest.mock('pdfkit', () => jest.fn()); +jest.mock('json2csv', () => ({ Parser: jest.fn() })); + +const PDFDocument = require('pdfkit'); +const { Parser } = require('json2csv'); +const { generatePDFReport, generateCSVReport } = require('../toolUtilizationReportHelpers'); + +// ─── Shared fixtures ─── +const makeReportData = (overrides = {}) => ({ + utilizationData: [ + { + name: 'Drill', + utilizationRate: 90, + downtime: 72, + classification: { label: 'Over-utilized', trafficLight: 'red' }, + toolCount: 2, + }, + { + name: 'Wheelbarrow', + utilizationRate: 30, + downtime: 504, + classification: { label: 'Under-utilized', trafficLight: 'yellow' }, + toolCount: 1, + }, + ], + alerts: [{ toolName: 'Drill', urgency: 'high', message: 'High utilization at 90%.' }], + balancing: [ + { + suggestion: 'Redistribute.', + rationale: 'Drill at 90%.', + fromTool: 'Drill', + toTool: 'Wheelbarrow', + }, + ], + recommendations: [ + { toolName: 'Drill', action: 'Schedule maintenance.' }, + { toolName: 'Wheelbarrow', action: 'Review necessity.' }, + ], + summary: { + totalToolTypes: 2, + underUtilized: 1, + normal: 0, + overUtilized: 1, + averageUtilization: 60, + }, + metadata: { + generatedDate: '3/20/2026', + dateRange: '2026-01-01 to 2026-01-31', + projectFilter: 'ALL', + }, + ...overrides, +}); + +// ─── generatePDFReport ─── +describe('generatePDFReport', () => { + let mockDoc; + let mockRes; + + beforeEach(() => { + jest.clearAllMocks(); + mockDoc = { + fontSize: jest.fn().mockReturnThis(), + font: jest.fn().mockReturnThis(), + text: jest.fn().mockReturnThis(), + moveDown: jest.fn().mockReturnThis(), + addPage: jest.fn().mockReturnThis(), + fillColor: jest.fn().mockReturnThis(), + pipe: jest.fn(), + end: jest.fn(), + y: 100, + }; + PDFDocument.mockImplementation(() => mockDoc); + + mockRes = { + setHeader: jest.fn(), + pipe: jest.fn(), + }; + }); + + it('sets Content-Type header to application/pdf', () => { + generatePDFReport(mockRes, makeReportData()); + expect(mockRes.setHeader).toHaveBeenCalledWith('Content-Type', 'application/pdf'); + }); + + it('sets Content-Disposition header with pdf filename', () => { + generatePDFReport(mockRes, makeReportData()); + const [, disposition] = mockRes.setHeader.mock.calls.find(([h]) => h === 'Content-Disposition'); + expect(disposition).toMatch(/attachment; filename="tool-utilization-report-\d+\.pdf"/); + }); + + it('pipes document to response', () => { + generatePDFReport(mockRes, makeReportData()); + expect(mockDoc.pipe).toHaveBeenCalledWith(mockRes); + }); + + it('calls doc.end() to finalize PDF', () => { + generatePDFReport(mockRes, makeReportData()); + expect(mockDoc.end).toHaveBeenCalled(); + }); + + it('skips empty sections when alerts, balancing, and recommendations are empty', () => { + const emptyData = makeReportData({ alerts: [], balancing: [], recommendations: [] }); + const moveDownCallsBefore = mockDoc.moveDown.mock.calls.length; + generatePDFReport(mockRes, emptyData); + // writePDFSection returns early for empty arrays, so fewer moveDown calls + // At minimum doc.end() is called meaning the function completed + expect(mockDoc.end).toHaveBeenCalled(); + expect(mockDoc.moveDown.mock.calls.length).toBeLessThanOrEqual(moveDownCallsBefore + 10); + }); + + it('calls addPage when doc.y exceeds page break threshold', () => { + mockDoc.y = 750; // above PAGE_BREAK_THRESHOLD (700) + generatePDFReport(mockRes, makeReportData()); + expect(mockDoc.addPage).toHaveBeenCalled(); + }); +}); + +// ─── generateCSVReport ─── +describe('generateCSVReport', () => { + let mockRes; + let mockParseInstance; + + beforeEach(() => { + jest.clearAllMocks(); + mockParseInstance = { parse: jest.fn().mockReturnValue('Tool Name,Rate\nDrill,90') }; + Parser.mockImplementation(() => mockParseInstance); + + mockRes = { + setHeader: jest.fn(), + send: jest.fn(), + }; + }); + + it('sets Content-Type header to text/csv', () => { + generateCSVReport(mockRes, makeReportData()); + expect(mockRes.setHeader).toHaveBeenCalledWith('Content-Type', 'text/csv; charset=utf-8'); + }); + + it('sets Content-Disposition header with csv filename', () => { + generateCSVReport(mockRes, makeReportData()); + const [, disposition] = mockRes.setHeader.mock.calls.find(([h]) => h === 'Content-Disposition'); + expect(disposition).toMatch(/attachment; filename="tool-utilization-report-\d+\.csv"/); + }); + + it('sends response with UTF-8 BOM prefix', () => { + generateCSVReport(mockRes, makeReportData()); + const sent = mockRes.send.mock.calls[0][0]; + expect(sent.startsWith('\ufeff')).toBe(true); + }); + + it('sets maintenanceAlert to None when no alerts for a tool', () => { + const data = makeReportData({ alerts: [] }); + generateCSVReport(mockRes, data); + const rowsPassed = mockParseInstance.parse.mock.calls[0][0]; + rowsPassed.forEach((row) => { + expect(row.maintenanceAlert).toBe('None'); + }); + }); + + it('concatenates multiple alerts for the same tool with semicolons', () => { + const data = makeReportData({ + alerts: [ + { toolName: 'Drill', message: 'High usage.' }, + { toolName: 'Drill', message: 'Condition worn.' }, + ], + }); + generateCSVReport(mockRes, data); + const rowsPassed = mockParseInstance.parse.mock.calls[0][0]; + const drillRow = rowsPassed.find((r) => r.name === 'Drill'); + expect(drillRow.maintenanceAlert).toBe('High usage.; Condition worn.'); + }); + + it('sets recommendation to None when no recommendation exists for a tool', () => { + const data = makeReportData({ recommendations: [] }); + generateCSVReport(mockRes, data); + const rowsPassed = mockParseInstance.parse.mock.calls[0][0]; + rowsPassed.forEach((row) => { + expect(row.recommendation).toBe('None'); + }); + }); +}); diff --git a/src/helpers/toolUtilizationHelpers.js b/src/helpers/toolUtilizationHelpers.js new file mode 100644 index 000000000..bac7f9f09 --- /dev/null +++ b/src/helpers/toolUtilizationHelpers.js @@ -0,0 +1,564 @@ +const mongoose = require('mongoose'); +const regression = require('regression'); +const ProjectRiskProfile = require('../models/bmdashboard/projectRiskProfile'); +const cache = require('../utilities/nodeCache')(); +const { + UTILIZATION_THRESHOLDS, + UTILIZATION_LABELS, + TRAFFIC_LIGHT, + FORECAST_MODES, + MAINTENANCE_TRIGGER_THRESHOLD, + MINIMUM_WEEKS_FOR_REGRESSION, + FORECAST_DEFAULT_DAYS, + HOURS_PER_DAY, + DAYS_PER_WEEK, + MS_PER_HOUR, + DEGRADED_CONDITIONS, + NON_OPERATIONAL_STATUSES, + CONFIDENCE_THRESHOLDS, + ENSEMBLE_WEIGHTS, + EMA_SMOOTHING_BASE, + ROUNDING_PRECISION, +} = require('../constants/toolUtilization'); + +// ─── classifyUtilization ─── +const classifyUtilization = (rate) => { + if (rate < UTILIZATION_THRESHOLDS.UNDER_UTILIZED_MAX) { + return { label: UTILIZATION_LABELS.UNDER, trafficLight: TRAFFIC_LIGHT.YELLOW }; + } + if (rate <= UTILIZATION_THRESHOLDS.NORMAL_MAX) { + return { label: UTILIZATION_LABELS.NORMAL, trafficLight: TRAFFIC_LIGHT.GREEN }; + } + return { label: UTILIZATION_LABELS.OVER, trafficLight: TRAFFIC_LIGHT.RED }; +}; + +// ─── calculateCheckedOutHours ─── +const calculateCheckedOutHours = (toolItem, periodStart, periodEnd) => { + const periodHours = (periodEnd - periodStart) / MS_PER_HOUR; + const relevantLogs = (toolItem.logRecord || []).filter((log) => { + const logDate = new Date(log.date); + return logDate >= periodStart && logDate <= periodEnd; + }); + + relevantLogs.sort((a, b) => new Date(a.date) - new Date(b.date)); + + let checkedOutTime = 0; + let lastCheckOut = null; + + relevantLogs.forEach((log) => { + if (log.type === 'Check Out') { + lastCheckOut = new Date(log.date); + } else if (log.type === 'Check In' && lastCheckOut) { + const hoursOut = (new Date(log.date) - lastCheckOut) / MS_PER_HOUR; + checkedOutTime += Math.max(0, hoursOut); + lastCheckOut = null; + } + }); + + if (lastCheckOut) { + checkedOutTime += Math.max(0, (periodEnd - lastCheckOut) / MS_PER_HOUR); + } + + if (relevantLogs.length === 0 && toolItem.logRecord && toolItem.logRecord.length > 0) { + const sortedAllLogs = [...toolItem.logRecord].sort( + (a, b) => new Date(b.date) - new Date(a.date), + ); + const lastLog = sortedAllLogs[0]; + if (lastLog?.type === 'Check Out' && new Date(lastLog.date) < periodStart) { + checkedOutTime = periodHours; + } + } + + return checkedOutTime; +}; + +// ─── buildToolFilter ─── +const buildToolFilter = (query) => { + const filter = { __t: 'tool_item' }; + if (query.tool && query.tool !== 'ALL' && mongoose.Types.ObjectId.isValid(query.tool)) { + filter.itemType = mongoose.Types.ObjectId(query.tool); + } + if (query.project && query.project !== 'ALL' && mongoose.Types.ObjectId.isValid(query.project)) { + filter.project = mongoose.Types.ObjectId(query.project); + } + return filter; +}; + +// ─── parseDateRange ─── +const parseDateRange = (startDate, endDate) => { + const rangeEnd = endDate ? new Date(endDate) : new Date(); + const defaultStart = new Date(); + defaultStart.setDate(defaultStart.getDate() - FORECAST_DEFAULT_DAYS); + const rangeStart = startDate ? new Date(startDate) : defaultStart; + const totalHours = (rangeEnd - rangeStart) / MS_PER_HOUR; + return { rangeStart, rangeEnd, totalHours }; +}; + +// ─── groupToolsByType ─── +const groupToolsByType = (tools) => { + const toolGroups = {}; + tools.forEach((toolItem) => { + if (!toolItem.itemType) return; + const toolTypeId = toolItem.itemType._id.toString(); + if (!toolGroups[toolTypeId]) { + toolGroups[toolTypeId] = { + name: toolItem.itemType.name || 'Unknown Tool', + tools: [], + }; + } + toolGroups[toolTypeId].tools.push(toolItem); + }); + return toolGroups; +}; + +// ─── calculateGroupUtilization ─── +const calculateGroupUtilization = (group, rangeStart, rangeEnd, totalHours) => { + let totalCheckedOut = 0; + const purchaseStatuses = []; + const conditions = []; + const currentUsages = []; + + group.tools.forEach((toolItem) => { + totalCheckedOut += calculateCheckedOutHours(toolItem, rangeStart, rangeEnd); + if (toolItem.purchaseStatus) purchaseStatuses.push(toolItem.purchaseStatus); + if (toolItem.condition) conditions.push(toolItem.condition); + if (toolItem.currentUsage) currentUsages.push(toolItem.currentUsage); + }); + + const toolCount = group.tools.length; + const totalPossibleHours = totalHours * toolCount; + const utilizationRate = + totalPossibleHours > 0 ? Math.round((totalCheckedOut / totalPossibleHours) * 100) : 0; + const downtime = + Math.round((totalPossibleHours - totalCheckedOut) * ROUNDING_PRECISION) / ROUNDING_PRECISION; + + return { + name: group.name, + utilizationRate, + downtime, + classification: classifyUtilization(utilizationRate), + toolCount, + totalCheckedOutHours: Math.round(totalCheckedOut * ROUNDING_PRECISION) / ROUNDING_PRECISION, + totalPossibleHours: Math.round(totalPossibleHours * ROUNDING_PRECISION) / ROUNDING_PRECISION, + toolGroupDetails: { + tools: group.tools, + purchaseStatuses, + conditions, + currentUsages, + }, + }; +}; + +// ─── buildCacheKey ─── +const buildCacheKey = (query) => + `toolUtil:${query.tool || 'ALL'}:${query.project || 'ALL'}:${query.startDate || 'default'}:${query.endDate || 'default'}`; + +// ─── computeUtilizationData ─── +const computeUtilizationData = async (BuildingTool, query) => { + const cacheKey = buildCacheKey(query); + if (cache.hasCache(cacheKey)) { + return cache.getCache(cacheKey); + } + + const filter = buildToolFilter(query); + const tools = await BuildingTool.find(filter) + .populate('itemType', 'name') + .populate('project', 'name') + .lean(); + + const { rangeStart, rangeEnd, totalHours } = parseDateRange(query.startDate, query.endDate); + const toolGroups = groupToolsByType(tools); + const utilizationData = Object.values(toolGroups) + .map((group) => calculateGroupUtilization(group, rangeStart, rangeEnd, totalHours)) + .sort((a, b) => b.utilizationRate - a.utilizationRate); + + const result = { toolGroups, utilizationData, rangeStart, rangeEnd, totalHours }; + cache.setCache(cacheKey, result); + return result; +}; + +// ─── bucketUtilizationByWeek ─── +const bucketUtilizationByWeek = (toolGroup, rangeStart, rangeEnd) => { + const rangeDuration = rangeEnd.getTime() - rangeStart.getTime(); + const weekMs = DAYS_PER_WEEK * HOURS_PER_DAY * MS_PER_HOUR; + const numWeeks = Math.max(1, Math.ceil(rangeDuration / weekMs)); + const buckets = []; + + for (let i = 0; i < numWeeks; i += 1) { + const weekStart = new Date(rangeStart.getTime() + i * weekMs); + const weekEnd = new Date(Math.min(weekStart.getTime() + weekMs, rangeEnd.getTime())); + const weekHours = (weekEnd - weekStart) / MS_PER_HOUR; + + let weekCheckedOut = 0; + toolGroup.tools.forEach((toolItem) => { + weekCheckedOut += calculateCheckedOutHours(toolItem, weekStart, weekEnd); + }); + + const weekTotalPossible = weekHours * toolGroup.tools.length; + const weekRate = + weekTotalPossible > 0 ? Math.round((weekCheckedOut / weekTotalPossible) * 100) : 0; + + buckets.push({ weekIndex: i, weekStart, weekEnd, utilizationRate: weekRate }); + } + + return buckets; +}; + +// ─── computeEnsemblePredictions (internal helper for forecastUtilization) ─── +const computeEnsemblePredictions = (weeklyBuckets, forecastWeeks, weekMs, existingWeeks) => { + const data = weeklyBuckets.map((b, i) => [i, b.utilizationRate]); + const result = regression.linear(data); + const r2 = result.r2 || 0; + + let emaValue = weeklyBuckets[0].utilizationRate; + const alpha = EMA_SMOOTHING_BASE / (existingWeeks + 1); + for (let i = 1; i < existingWeeks; i += 1) { + emaValue = alpha * weeklyBuckets[i].utilizationRate + (1 - alpha) * emaValue; + } + + let weights; + let confidence = 'low'; + if (r2 >= CONFIDENCE_THRESHOLDS.HIGH) { + weights = ENSEMBLE_WEIGHTS.HIGH_R2; + confidence = 'high'; + } else if (r2 >= CONFIDENCE_THRESHOLDS.MEDIUM) { + weights = ENSEMBLE_WEIGHTS.MEDIUM_R2; + confidence = 'medium'; + } else { + weights = ENSEMBLE_WEIGHTS.LOW_R2; + } + + const weeklyPredictions = []; + for (let j = 0; j < forecastWeeks; j += 1) { + const futureIndex = existingWeeks + j; + const regressionPred = result.predict(futureIndex)[1]; + const blended = weights.regression * regressionPred + weights.ema * emaValue; + const clamped = Math.min(100, Math.max(0, Math.round(blended))); + + const weekStart = new Date(Date.now() + j * weekMs); + const weekEnd = new Date(weekStart.getTime() + weekMs); + weeklyPredictions.push({ + weekStart: weekStart.toISOString(), + weekEnd: weekEnd.toISOString(), + predictedRate: clamped, + }); + } + + return { weeklyPredictions, confidence }; +}; + +// ─── forecastUtilization (ensemble: regression + EMA) ─── +const forecastUtilization = (weeklyBuckets, forecastDays) => { + const weekMs = DAYS_PER_WEEK * HOURS_PER_DAY * MS_PER_HOUR; + const forecastWeeks = Math.max(1, Math.ceil(forecastDays / DAYS_PER_WEEK)); + const existingWeeks = weeklyBuckets.length; + let weeklyPredictions; + let confidence = 'low'; + let method = 'average'; + + if (existingWeeks < MINIMUM_WEEKS_FOR_REGRESSION) { + const avgRate = + existingWeeks > 0 + ? Math.round(weeklyBuckets.reduce((sum, b) => sum + b.utilizationRate, 0) / existingWeeks) + : 0; + + weeklyPredictions = []; + for (let j = 0; j < forecastWeeks; j += 1) { + const weekStart = new Date(Date.now() + j * weekMs); + const weekEnd = new Date(weekStart.getTime() + weekMs); + weeklyPredictions.push({ + weekStart: weekStart.toISOString(), + weekEnd: weekEnd.toISOString(), + predictedRate: avgRate, + }); + } + } else { + const ensemble = computeEnsemblePredictions( + weeklyBuckets, + forecastWeeks, + weekMs, + existingWeeks, + ); + weeklyPredictions = ensemble.weeklyPredictions; + confidence = ensemble.confidence; + method = 'ensemble'; + } + + const predictedRate = + weeklyPredictions.length > 0 + ? Math.round( + weeklyPredictions.reduce((sum, w) => sum + w.predictedRate, 0) / weeklyPredictions.length, + ) + : 0; + + const forecastEndDate = new Date( + Date.now() + forecastDays * HOURS_PER_DAY * MS_PER_HOUR, + ).toISOString(); + + return { + predictedRate, + confidence, + forecastEndDate, + weeklyPredictions, + predictedClassification: classifyUtilization(predictedRate), + method, + }; +}; + +// ─── generateMaintenanceAlerts ─── +const generateMaintenanceAlerts = (utilizationData) => { + const alerts = []; + + utilizationData.forEach((item) => { + const { toolGroupDetails } = item; + + if (item.utilizationRate > MAINTENANCE_TRIGGER_THRESHOLD) { + alerts.push({ + toolName: item.name, + alertType: 'overuse', + message: `High utilization at ${item.utilizationRate}%. Schedule preventive maintenance.`, + urgency: 'high', + }); + } + + const degradedSet = new Set(); + toolGroupDetails.conditions.forEach((condition) => { + if (DEGRADED_CONDITIONS.includes(condition) && !degradedSet.has(condition)) { + degradedSet.add(condition); + alerts.push({ + toolName: item.name, + alertType: 'condition', + message: `Tool condition is ${condition}. Immediate maintenance recommended.`, + urgency: 'high', + }); + } + }); + + const nonOpCounts = {}; + toolGroupDetails.currentUsages.forEach((usage) => { + if (NON_OPERATIONAL_STATUSES.includes(usage)) { + nonOpCounts[usage] = (nonOpCounts[usage] || 0) + 1; + } + }); + Object.entries(nonOpCounts).forEach(([status, count]) => { + alerts.push({ + toolName: item.name, + alertType: 'non_operational', + message: `${count} unit(s) currently ${status}. Effective fleet capacity reduced.`, + urgency: 'medium', + }); + }); + }); + + return alerts; +}; + +// ─── generateResourceBalancingSuggestions ─── +const generateResourceBalancingSuggestions = (utilizationData) => { + const suggestions = []; + const overUtilized = utilizationData.filter( + (d) => d.utilizationRate > UTILIZATION_THRESHOLDS.NORMAL_MAX, + ); + const underUtilized = utilizationData.filter( + (d) => d.utilizationRate < UTILIZATION_THRESHOLDS.UNDER_UTILIZED_MAX, + ); + + const sortedUnder = [...underUtilized].sort((a, b) => a.utilizationRate - b.utilizationRate); + + overUtilized.forEach((overTool) => { + if (sortedUnder.length > 0) { + const leastUsed = sortedUnder[0]; + suggestions.push({ + suggestion: 'Consider redistributing workload.', + fromTool: overTool.name, + toTool: leastUsed.name, + rationale: `${overTool.name} is at ${overTool.utilizationRate}% while ${leastUsed.name} is at ${leastUsed.utilizationRate}%.`, + }); + } + + const rentalCount = overTool.toolGroupDetails.purchaseStatuses.filter( + (s) => s === 'Rental', + ).length; + if (rentalCount > overTool.toolCount / 2) { + suggestions.push({ + suggestion: 'Consider purchasing additional units to reduce rental dependency.', + fromTool: overTool.name, + toTool: null, + rationale: `${overTool.name} is over-utilized at ${overTool.utilizationRate}% and predominantly rented.`, + }); + } + }); + + underUtilized.forEach((underTool) => { + const purchasedCount = underTool.toolGroupDetails.purchaseStatuses.filter( + (s) => s === 'Purchased', + ).length; + if (purchasedCount > underTool.toolCount / 2) { + suggestions.push({ + suggestion: 'Consider renting instead of owning, or reassign to other projects.', + fromTool: underTool.name, + toTool: null, + rationale: `${underTool.name} is under-utilized at ${underTool.utilizationRate}% and predominantly owned.`, + }); + } + }); + + return suggestions; +}; + +// ─── generateRecommendations ─── +const generateRecommendations = (utilizationData) => + utilizationData.map((item) => { + let action; + if (item.classification.label === UTILIZATION_LABELS.UNDER) { + action = 'Potentially removable or rentable instead of owned. Review necessity.'; + } else if (item.classification.label === UTILIZATION_LABELS.OVER) { + action = 'Requires maintenance scheduling, backup inventory, or purchase planning.'; + } else { + action = 'Normal operation. No action required.'; + } + + return { + toolName: item.name, + utilizationRate: item.utilizationRate, + label: item.classification.label, + trafficLight: item.classification.trafficLight, + action, + }; + }); + +// ─── stripInternalDetails ─── +const stripInternalDetails = (item) => { + const publicFields = Object.fromEntries( + Object.entries(item).filter(([key]) => key !== 'toolGroupDetails') + ); + return publicFields; +}; + +// ─── buildInsightsSummary ─── +const buildInsightsSummary = (utilizationData) => { + const totalToolTypes = utilizationData.length; + const underCount = utilizationData.filter( + (d) => d.classification.label === UTILIZATION_LABELS.UNDER, + ).length; + const overCount = utilizationData.filter( + (d) => d.classification.label === UTILIZATION_LABELS.OVER, + ).length; + const normalCount = totalToolTypes - underCount - overCount; + const averageUtilization = + totalToolTypes > 0 + ? Math.round(utilizationData.reduce((s, d) => s + d.utilizationRate, 0) / totalToolTypes) + : 0; + + return { + totalToolTypes, + underUtilized: underCount, + normal: normalCount, + overUtilized: overCount, + averageUtilization, + }; +}; + +// ─── determineForecastDays ─── +const determineForecastDays = async (mode, projectId) => { + if (mode === FORECAST_MODES.FORECAST_30) { + return { forecastDays: FORECAST_DEFAULT_DAYS, warning: null }; + } + + if (!projectId || projectId === 'ALL') { + return { + forecastDays: FORECAST_DEFAULT_DAYS, + warning: 'No specific project selected. Defaulting to 30-day forecast.', + }; + } + + const riskProfile = await ProjectRiskProfile.findOne({ + projectId: mongoose.Types.ObjectId(projectId), + }).lean(); + + if (!riskProfile?.endDate) { + return { + forecastDays: FORECAST_DEFAULT_DAYS, + warning: 'No project schedule found. Defaulting to 30-day forecast.', + }; + } + + const daysToEnd = Math.ceil( + (new Date(riskProfile.endDate) - Date.now()) / (HOURS_PER_DAY * MS_PER_HOUR), + ); + return { + forecastDays: Math.max(DAYS_PER_WEEK, daysToEnd), + warning: null, + }; +}; + +// ─── buildUtilizationResponse ─── +const buildUtilizationResponse = async ({ + utilizationData, + rangeStart, + rangeEnd, + selectedMode, + project, +}) => { + let warning = null; + + const responseData = await Promise.all( + utilizationData.map(async (item) => { + const publicItem = stripInternalDetails(item); + publicItem.forecast = null; + + if (selectedMode !== FORECAST_MODES.HISTORICAL) { + const { forecastDays, warning: fw } = await determineForecastDays(selectedMode, project); + if (fw) warning = fw; + + const weeklyBuckets = bucketUtilizationByWeek(item.toolGroupDetails, rangeStart, rangeEnd); + publicItem.forecast = forecastUtilization(weeklyBuckets, forecastDays); + } + + return publicItem; + }), + ); + + if (warning) { + responseData.forEach((item) => { + item.warning = warning; + }); + } + + return responseData; +}; + +// ─── buildReportPayload ─── +const buildReportPayload = (utilizationData, rangeStart, rangeEnd, project) => ({ + utilizationData, + alerts: generateMaintenanceAlerts(utilizationData), + balancing: generateResourceBalancingSuggestions(utilizationData), + recommendations: generateRecommendations(utilizationData), + summary: buildInsightsSummary(utilizationData), + metadata: { + generatedDate: new Date().toLocaleString(), + dateRange: `${rangeStart.toISOString()} to ${rangeEnd.toISOString()}`, + projectFilter: project || 'ALL', + }, +}); + +module.exports = { + classifyUtilization, + calculateCheckedOutHours, + buildToolFilter, + parseDateRange, + groupToolsByType, + calculateGroupUtilization, + buildCacheKey, + computeUtilizationData, + bucketUtilizationByWeek, + forecastUtilization, + generateMaintenanceAlerts, + generateResourceBalancingSuggestions, + generateRecommendations, + stripInternalDetails, + buildInsightsSummary, + determineForecastDays, + buildUtilizationResponse, + buildReportPayload, +}; diff --git a/src/helpers/toolUtilizationReportHelpers.js b/src/helpers/toolUtilizationReportHelpers.js new file mode 100644 index 000000000..d4c85a0f0 --- /dev/null +++ b/src/helpers/toolUtilizationReportHelpers.js @@ -0,0 +1,143 @@ +const PDFDocument = require('pdfkit'); +const { Parser } = require('json2csv'); +const { PDF_STYLES, PDF_MOVE_DOWN_HALF } = require('../constants/toolUtilization'); + +// ─── writePDFSection (internal helper) ─── +const writePDFSection = (doc, title, items, formatLine) => { + if (items.length === 0) return; + doc.moveDown(); + doc.fontSize(PDF_STYLES.FONT_SIZE_SECTION_HEADER).font('Helvetica-Bold').text(title); + doc.moveDown(PDF_MOVE_DOWN_HALF); + items.forEach((item, idx) => { + if (doc.y > PDF_STYLES.PAGE_BREAK_THRESHOLD) doc.addPage(); + doc.fontSize(PDF_STYLES.FONT_SIZE_DETAIL).font('Helvetica'); + doc.text(formatLine(item, idx)); + }); +}; + +// ─── generatePDFReport ─── +const generatePDFReport = (res, reportData) => { + const { utilizationData, alerts, balancing, recommendations, summary, metadata } = reportData; + const doc = new PDFDocument({ + margin: PDF_STYLES.PAGE_MARGIN, + bufferPages: true, + compress: true, + }); + const filename = `tool-utilization-report-${Date.now()}.pdf`; + + res.setHeader('Content-Type', 'application/pdf'); + res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); + res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); + doc.pipe(res); + + doc + .fontSize(PDF_STYLES.FONT_SIZE_TITLE) + .font('Helvetica-Bold') + .text('Tool Utilization & Procurement/Operations Report', { align: 'center' }); + doc.moveDown(); + + doc.fontSize(PDF_STYLES.FONT_SIZE_METADATA).font('Helvetica').fillColor('#666666'); + doc.text(`Generated: ${metadata.generatedDate}`); + doc.text(`Date Range: ${metadata.dateRange}`); + doc.text(`Project Filter: ${metadata.projectFilter}`); + doc.moveDown(); + doc.fillColor('#000000'); + + doc.fontSize(PDF_STYLES.FONT_SIZE_SECTION_HEADER).font('Helvetica-Bold').text('Summary'); + doc.fontSize(PDF_STYLES.FONT_SIZE_BODY).font('Helvetica'); + doc.text(`Total Tool Types: ${summary.totalToolTypes}`); + doc.text(`Average Utilization: ${summary.averageUtilization}%`); + doc.text( + `Under-utilized: ${summary.underUtilized} | Normal: ${summary.normal} | Over-utilized: ${summary.overUtilized}`, + ); + doc.moveDown(); + + doc + .fontSize(PDF_STYLES.FONT_SIZE_SECTION_HEADER) + .font('Helvetica-Bold') + .text('Utilization Details'); + doc.moveDown(PDF_MOVE_DOWN_HALF); + utilizationData.forEach((item) => { + if (doc.y > PDF_STYLES.PAGE_BREAK_THRESHOLD) doc.addPage(); + doc.fontSize(PDF_STYLES.FONT_SIZE_BODY).font('Helvetica-Bold'); + doc.text(`${item.name} — ${item.utilizationRate}% (${item.classification.label})`); + doc.fontSize(PDF_STYLES.FONT_SIZE_DETAIL).font('Helvetica'); + doc.text(` Downtime: ${item.downtime} hrs | Tool Count: ${item.toolCount}`); + doc.moveDown(PDF_MOVE_DOWN_HALF); + }); + + writePDFSection( + doc, + 'Maintenance Alerts', + alerts, + (alert) => `\u2022 [${alert.urgency.toUpperCase()}] ${alert.toolName}: ${alert.message}`, + ); + + writePDFSection( + doc, + 'Resource Balancing Suggestions', + balancing, + (item, idx) => `${idx + 1}. ${item.suggestion} ${item.rationale}`, + ); + + writePDFSection( + doc, + 'Recommendations', + recommendations, + (rec) => `\u2022 ${rec.toolName}: ${rec.action}`, + ); + + doc.end(); +}; + +// ─── generateCSVReport ─── +const generateCSVReport = (res, reportData) => { + const { utilizationData, alerts, recommendations } = reportData; + const filename = `tool-utilization-report-${Date.now()}.csv`; + + res.setHeader('Content-Type', 'text/csv; charset=utf-8'); + res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); + res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); + + const alertsByTool = {}; + alerts.forEach((alert) => { + if (!alertsByTool[alert.toolName]) alertsByTool[alert.toolName] = []; + alertsByTool[alert.toolName].push(alert.message); + }); + + const recByTool = {}; + recommendations.forEach((rec) => { + recByTool[rec.toolName] = rec.action; + }); + + const rows = utilizationData.map((item) => ({ + name: item.name, + utilizationRate: item.utilizationRate, + downtime: item.downtime, + classificationLabel: item.classification.label, + trafficLight: item.classification.trafficLight, + toolCount: item.toolCount, + maintenanceAlert: (alertsByTool[item.name] || []).join('; ') || 'None', + recommendation: recByTool[item.name] || 'None', + })); + + const fields = [ + { label: 'Tool Name', value: 'name' }, + { label: 'Utilization Rate (%)', value: 'utilizationRate' }, + { label: 'Downtime (hours)', value: 'downtime' }, + { label: 'Classification', value: 'classificationLabel' }, + { label: 'Traffic Light', value: 'trafficLight' }, + { label: 'Tool Count', value: 'toolCount' }, + { label: 'Maintenance Alert', value: 'maintenanceAlert' }, + { label: 'Recommendation', value: 'recommendation' }, + ]; + + const parser = new Parser({ fields }); + const csv = parser.parse(rows); + res.send(`\ufeff${csv}`); +}; + +module.exports = { + generatePDFReport, + generateCSVReport, +}; diff --git a/src/helpers/userHelper.js b/src/helpers/userHelper.js index e2ab0df4b..4fa26c802 100644 --- a/src/helpers/userHelper.js +++ b/src/helpers/userHelper.js @@ -39,7 +39,6 @@ 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 +2259,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 getTeamManagementEmail(teamId); + const managementEmails = await userHelper.getTeamManagementEmail(teamId); if (Array.isArray(managementEmails) && managementEmails.length > 0) { managementEmails.forEach((management) => { recipients.push(management.email); @@ -2297,7 +2296,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 getTeamManagementEmail(teamId); + const managementEmails = await userHelper.getTeamManagementEmail(teamId); if (Array.isArray(managementEmails) && managementEmails.length > 0) { managementEmails.forEach((management) => { recipients.push(management.email); @@ -2628,316 +2627,12 @@ 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, @@ -2954,16 +2649,6 @@ const userHelper = function () { deleteExpiredTokens, deleteOldTimeOffRequests, getProfileImagesFromWebsite, - sendUserPausedEmail, - sendUserSeparatedEmail, - sendUserActivatedEmail, - sendUserScheduledSeparationEmail, - sendUserResumedEmail, - sendUserReactivatedAfterSeparation, - sendUserCancelledSeparationEmail, - finalizeUserEndDates, - getEmailRecipientsForStatusChange, - getTeamManagementEmail, }; }; diff --git a/src/routes/bmdashboard/toolUtilizationRouter.js b/src/routes/bmdashboard/toolUtilizationRouter.js index b981c3e57..9a4026c82 100644 --- a/src/routes/bmdashboard/toolUtilizationRouter.js +++ b/src/routes/bmdashboard/toolUtilizationRouter.js @@ -7,6 +7,8 @@ const routes = function (BuildingTool) { ); toolUtilizationRouter.route('/tools/utilization').get(controller.getUtilization); + toolUtilizationRouter.route('/tools/utilization/insights').get(controller.getInsights); + toolUtilizationRouter.route('/tools/utilization/export').get(controller.exportReport); return toolUtilizationRouter; }; diff --git a/src/routes/studentTaskRouter.js b/src/routes/studentTaskRouter.js index 26bcfc144..0a2290e5a 100644 --- a/src/routes/studentTaskRouter.js +++ b/src/routes/studentTaskRouter.js @@ -7,8 +7,6 @@ const routes = function () { studentTaskRouter.route('/student/tasks').get(controller.getStudentTasks); - studentTaskRouter.route('/student/tasks/:taskId/log-hours').post(controller.logHours); - studentTaskRouter.route('/student/tasks/:taskId/progress').put(controller.updateTaskProgress); studentTaskRouter diff --git a/src/startup/cors.js b/src/startup/cors.js index 61ac21c23..16199d719 100644 --- a/src/startup/cors.js +++ b/src/startup/cors.js @@ -25,7 +25,7 @@ module.exports = function (app) { }, credentials: true, methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], - allowedHeaders: ['Content-Type', 'Authorization', 'Cache-Control', 'Pragma'], + allowedHeaders: ['Content-Type', 'Authorization'], }), ); }; diff --git a/src/startup/middleware.js b/src/startup/middleware.js index d6f14cee4..c9c1b29a4 100644 --- a/src/startup/middleware.js +++ b/src/startup/middleware.js @@ -133,15 +133,15 @@ module.exports = function (app) { try { payload = jwt.verify(authToken, config.JWT_SECRET); - } catch (error) { + } catch { res.status(401).send('Invalid token'); return; } if ( !payload || - !payload.expiryTimestamp || - !payload.userid || - !payload.role || + !payload?.expiryTimestamp || + !payload?.userid || + !payload?.role || moment().isAfter(payload.expiryTimestamp) ) { res.status(401).send('Unauthorized request'); diff --git a/yarn.lock b/yarn.lock index deb3f7562..e809952ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13,17 +13,15 @@ tslib "^2.8.1" "@apimatic/axios-client-adapter@^0.3.4": - version "0.3.21" - resolved "https://registry.yarnpkg.com/@apimatic/axios-client-adapter/-/axios-client-adapter-0.3.21.tgz#94fa288fffefc6cade844216f6a701def1f74a63" - integrity sha512-pr/XvAvH9FjbpwM+B7vHQxM7alocOX1kLNtSpXKW3yxTYxksF3ydnUuQ85rRbCoNpyfMOIjnRBCNUBzX5p2Hnw== + version "0.3.20" dependencies: - "@apimatic/convert-to-stream" "^0.1.9" + "@apimatic/convert-to-stream" "^0.1.8" "@apimatic/core-interfaces" "^0.2.14" "@apimatic/file-wrapper" "^0.3.9" "@apimatic/http-headers" "^0.3.8" "@apimatic/http-query" "^0.3.9" "@apimatic/json-bigint" "^1.2.0" - "@apimatic/proxy" "^0.1.4" + "@apimatic/proxy" "^0.1.3" axios "^1.8.4" detect-browser "^5.3.0" detect-node "^2.1.0" @@ -32,10 +30,8 @@ tiny-warning "^1.0.3" tslib "^2.8.1" -"@apimatic/convert-to-stream@^0.1.9": - version "0.1.9" - resolved "https://registry.yarnpkg.com/@apimatic/convert-to-stream/-/convert-to-stream-0.1.9.tgz#4a46a66330d69e8ea5c3bff99739063bcdad90b8" - integrity sha512-C9NEKnDZoTRBRVeUGXVyAEmy6P5o+8oLwEckTKj0iBlExJLEXNt14nf4wxfzRO1KR8j5Bw8S6yStKCrQzcVERA== +"@apimatic/convert-to-stream@^0.1.8": + version "0.1.8" dependencies: tslib "2.8.1" @@ -49,11 +45,9 @@ tslib "^2.8.1" "@apimatic/core@^0.10.14": - version "0.10.29" - resolved "https://registry.yarnpkg.com/@apimatic/core/-/core-0.10.29.tgz#df4399643be47f38a3c8f81fe4bc2f99ac56ed0e" - integrity sha512-QhORiq0QbjlDMrw8ZZsAeG2DzE6QgGz5ukD5w2MOWE/3iIWnUDEROjmc2SfhyiGsE3GoEJ8cyhMMdjlOioP6ww== + version "0.10.28" dependencies: - "@apimatic/convert-to-stream" "^0.1.9" + "@apimatic/convert-to-stream" "^0.1.8" "@apimatic/core-interfaces" "^0.2.14" "@apimatic/file-wrapper" "^0.3.9" "@apimatic/http-headers" "^0.3.8" @@ -106,10 +100,8 @@ "@apimatic/http-headers" "^0.3.8" tslib "^2.8.1" -"@apimatic/proxy@^0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@apimatic/proxy/-/proxy-0.1.4.tgz#9a5b729ac3da8edc01ca5846f14e7f29b744f8d0" - integrity sha512-Vzgfu7wcA5aEJyj2SjQ00Tb06fhBof8gDo1kSsF6sZBm4QjdFywN5AMbQwhfFOKjHqcsNmJspdeqcdymUQ77jA== +"@apimatic/proxy@^0.1.3": + version "0.1.3" dependencies: http-proxy-agent "^7.0.2" https-proxy-agent "^7.0.6" @@ -192,7 +184,14 @@ dependencies: tslib "^2.8.1" -"@atproto/syntax@^0.5.0", "@atproto/syntax@^0.5.4": +"@atproto/syntax@^0.5.0": + version "0.5.4" + resolved "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.5.4.tgz" + integrity sha512-9XJOpMAgsGFxMEIp8nJ8AIWv+krrY1xQMj+wULbbXhQztQV+9aZ0TbG9Jtn3Op2or8Kr6OqyWR4ga9Z189kKDw== + dependencies: + tslib "^2.8.1" + +"@atproto/syntax@^0.5.4": version "0.5.4" resolved "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.5.4.tgz" integrity sha512-9XJOpMAgsGFxMEIp8nJ8AIWv+krrY1xQMj+wULbbXhQztQV+9aZ0TbG9Jtn3Op2or8Kr6OqyWR4ga9Z189kKDw== @@ -250,7 +249,7 @@ "@smithy/util-utf8" "^2.0.0" tslib "^2.6.2" -"@aws-crypto/sha256-js@5.2.0", "@aws-crypto/sha256-js@^5.2.0": +"@aws-crypto/sha256-js@^5.2.0", "@aws-crypto/sha256-js@5.2.0": version "5.2.0" resolved "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz" integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA== @@ -266,7 +265,7 @@ dependencies: tslib "^2.6.2" -"@aws-crypto/util@5.2.0", "@aws-crypto/util@^5.2.0": +"@aws-crypto/util@^5.2.0", "@aws-crypto/util@5.2.0": version "5.2.0" resolved "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz" integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ== @@ -720,7 +719,7 @@ "@smithy/types" "^4.11.0" tslib "^2.6.2" -"@aws-sdk/types@3.956.0", "@aws-sdk/types@^3.222.0": +"@aws-sdk/types@^3.222.0", "@aws-sdk/types@3.956.0": version "3.956.0" resolved "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz" integrity sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug== @@ -804,7 +803,7 @@ "@azure/core-util" "^1.13.0" tslib "^2.6.2" -"@azure/core-client@^1.9.3": +"@azure/core-client@^1.10.0", "@azure/core-client@^1.9.3": version "1.10.1" resolved "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz" integrity sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w== @@ -818,11 +817,11 @@ tslib "^2.6.2" "@azure/core-http-compat@^2.2.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@azure/core-http-compat/-/core-http-compat-2.4.0.tgz#28322f317eb46d625d7d18bb0eb02c2654f5de1b" - integrity sha512-f1P96IB399YiN2ARYHP7EpZi3Bf3wH4SN2lGzrw7JVwm7bbsVYtf2iKSBwTywD2P62NOPZGHFSZi+6jjb75JuA== + version "2.3.1" dependencies: "@azure/abort-controller" "^2.1.2" + "@azure/core-client" "^1.10.0" + "@azure/core-rest-pipeline" "^1.22.0" "@azure/core-lro@^2.2.0": version "2.7.2" @@ -842,16 +841,14 @@ tslib "^2.6.2" "@azure/core-rest-pipeline@^1.19.1", "@azure/core-rest-pipeline@^1.22.0": - version "1.23.0" - resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.23.0.tgz#35f16e1c180ca9545c260ac124b751be1da9c08c" - integrity sha512-Evs1INHo+jUjwHi1T6SG6Ua/LHOQBCLuKEEE6efIpt4ZOoNonaT1kP32GoOcdNDbfqsD2445CPri3MubBy5DEQ== + version "1.22.2" dependencies: "@azure/abort-controller" "^2.1.2" "@azure/core-auth" "^1.10.0" "@azure/core-tracing" "^1.3.0" "@azure/core-util" "^1.13.0" "@azure/logger" "^1.3.0" - "@typespec/ts-http-runtime" "^0.3.4" + "@typespec/ts-http-runtime" "^0.3.0" tslib "^2.6.2" "@azure/core-tracing@^1.2.0", "@azure/core-tracing@^1.3.0": @@ -871,11 +868,9 @@ tslib "^2.6.2" "@azure/core-xml@^1.4.5": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@azure/core-xml/-/core-xml-1.5.1.tgz#5528aef8e561ee97c605d0080b8803a21d2be783" - integrity sha512-xcNRHqCoSp4AunOALEae6A8f3qATb83gSrm31Iqb01OzblvC3/W/bfXozcq78EzIdzZzuH1bZ2NvRR0TdX709w== + version "1.5.0" dependencies: - fast-xml-parser "^5.5.9" + fast-xml-parser "^5.0.7" tslib "^2.8.1" "@azure/logger@^1.0.0", "@azure/logger@^1.1.4", "@azure/logger@^1.3.0": @@ -887,9 +882,7 @@ tslib "^2.6.2" "@azure/storage-blob@^12.26.0": - version "12.31.0" - resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.31.0.tgz#97b09be2bf6ab59739b862edd8124798362ce720" - integrity sha512-DBgNv10aCSxopt92DkTDD0o9xScXeBqPKGmR50FPZQaEcH4JLQ+GEOGEDv19V5BMkB7kxr+m4h6il/cCDPvmHg== + version "12.29.1" dependencies: "@azure/abort-controller" "^2.1.2" "@azure/core-auth" "^1.9.0" @@ -902,14 +895,12 @@ "@azure/core-util" "^1.11.0" "@azure/core-xml" "^1.4.5" "@azure/logger" "^1.1.4" - "@azure/storage-common" "^12.3.0" + "@azure/storage-common" "^12.1.1" events "^3.0.0" tslib "^2.8.1" -"@azure/storage-common@^12.3.0": - version "12.3.0" - resolved "https://registry.yarnpkg.com/@azure/storage-common/-/storage-common-12.3.0.tgz#5bf257383836e67a426c91d7e9678479afe802a9" - integrity sha512-/OFHhy86aG5Pe8dP5tsp+BuJ25JOAl9yaMU3WZbkeoiFMHFtJ7tu5ili7qEdBXNW9G5lDB19trwyI6V49F/8iQ== +"@azure/storage-common@^12.1.1": + version "12.1.1" dependencies: "@azure/abort-controller" "^2.1.2" "@azure/core-auth" "^1.9.0" @@ -922,9 +913,7 @@ tslib "^2.8.1" "@babel/cli@^7.15.4": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.28.6.tgz#1da8eb79f92cbe75542b853b3b1db683c5ea406a" - integrity sha512-6EUNcuBbNkj08Oj4gAZ+BUU8yLCgKzgVX4gaTh09Ya2C8ICM4P+G30g4m3akRxSYAp3A/gnWchrNst7px4/nUQ== + version "7.28.3" dependencies: "@jridgewell/trace-mapping" "^0.3.28" commander "^6.2.0" @@ -937,34 +926,28 @@ "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" chokidar "^3.6.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c" - integrity sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-validator-identifier" "^7.28.5" + "@babel/helper-validator-identifier" "^7.27.1" js-tokens "^4.0.0" picocolors "^1.1.1" -"@babel/compat-data@^7.28.6", "@babel/compat-data@^7.29.3": - version "7.29.3" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.29.3.tgz#e3f5347f0589596c91d227ccb6a541d37fb1307b" - integrity sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg== - -"@babel/core@^7.10.2", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.29.0.tgz#5286ad785df7f79d656e88ce86e650d16ca5f322" - integrity sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA== - dependencies: - "@babel/code-frame" "^7.29.0" - "@babel/generator" "^7.29.0" - "@babel/helper-compilation-targets" "^7.28.6" - "@babel/helper-module-transforms" "^7.28.6" - "@babel/helpers" "^7.28.6" - "@babel/parser" "^7.29.0" - "@babel/template" "^7.28.6" - "@babel/traverse" "^7.29.0" - "@babel/types" "^7.29.0" +"@babel/compat-data@^7.27.2", "@babel/compat-data@^7.27.7", "@babel/compat-data@^7.28.5": + version "7.28.5" + +"@babel/core@^7.0.0", "@babel/core@^7.0.0 || ^8.0.0-0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.10.2", "@babel/core@^7.11.0", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.13.0", "@babel/core@^7.23.9", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.8.0": + version "7.28.5" + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-module-transforms" "^7.28.3" + "@babel/helpers" "^7.28.4" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.5" + "@babel/types" "^7.28.5" "@jridgewell/remapping" "^2.3.5" convert-source-map "^2.0.0" debug "^4.1.0" @@ -973,21 +956,17 @@ semver "^6.3.1" "@babel/eslint-parser@^7.15.0": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.28.6.tgz#6a294a4add732ebe7ded8a8d2792dd03dd81dc3f" - integrity sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA== + version "7.28.5" dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/generator@^7.29.0", "@babel/generator@^7.7.2": - version "7.29.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.29.1.tgz#d09876290111abbb00ef962a7b83a5307fba0d50" - integrity sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw== +"@babel/generator@^7.28.5", "@babel/generator@^7.7.2": + version "7.28.5" dependencies: - "@babel/parser" "^7.29.0" - "@babel/types" "^7.29.0" + "@babel/parser" "^7.28.5" + "@babel/types" "^7.28.5" "@jridgewell/gen-mapping" "^0.3.12" "@jridgewell/trace-mapping" "^0.3.28" jsesc "^3.0.2" @@ -999,31 +978,27 @@ dependencies: "@babel/types" "^7.27.3" -"@babel/helper-compilation-targets@^7.27.1", "@babel/helper-compilation-targets@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" - integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== +"@babel/helper-compilation-targets@^7.27.1", "@babel/helper-compilation-targets@^7.27.2": + version "7.27.2" dependencies: - "@babel/compat-data" "^7.28.6" + "@babel/compat-data" "^7.27.2" "@babel/helper-validator-option" "^7.27.1" browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.28.6": - version "7.29.3" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.3.tgz#67328947d956f06fc7b48def269bf0489155fd42" - integrity sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA== +"@babel/helper-create-class-features-plugin@^7.27.1", "@babel/helper-create-class-features-plugin@^7.28.3": + version "7.28.5" dependencies: "@babel/helper-annotate-as-pure" "^7.27.3" "@babel/helper-member-expression-to-functions" "^7.28.5" "@babel/helper-optimise-call-expression" "^7.27.1" - "@babel/helper-replace-supers" "^7.28.6" + "@babel/helper-replace-supers" "^7.27.1" "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" - "@babel/traverse" "^7.29.0" + "@babel/traverse" "^7.28.5" semver "^6.3.1" -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.27.1", "@babel/helper-create-regexp-features-plugin@^7.28.5": +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.27.1": version "7.28.5" resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz" integrity sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw== @@ -1032,23 +1007,21 @@ regexpu-core "^6.3.1" semver "^6.3.1" -"@babel/helper-define-polyfill-provider@^0.6.5", "@babel/helper-define-polyfill-provider@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz#cf1e4462b613f2b54c41e6ff758d5dfcaa2c85d1" - integrity sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA== +"@babel/helper-define-polyfill-provider@^0.6.5": + version "0.6.5" dependencies: - "@babel/helper-compilation-targets" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" - debug "^4.4.3" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" + debug "^4.4.1" lodash.debounce "^4.0.8" - resolve "^1.22.11" + resolve "^1.22.10" "@babel/helper-globals@^7.28.0": version "7.28.0" resolved "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz" integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== -"@babel/helper-member-expression-to-functions@^7.28.5": +"@babel/helper-member-expression-to-functions@^7.27.1", "@babel/helper-member-expression-to-functions@^7.28.5": version "7.28.5" resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz" integrity sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg== @@ -1056,22 +1029,18 @@ "@babel/traverse" "^7.28.5" "@babel/types" "^7.28.5" -"@babel/helper-module-imports@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" - integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== +"@babel/helper-module-imports@^7.27.1": + version "7.27.1" dependencies: - "@babel/traverse" "^7.28.6" - "@babel/types" "^7.28.6" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-module-transforms@^7.27.1", "@babel/helper-module-transforms@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" - integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== +"@babel/helper-module-transforms@^7.27.1", "@babel/helper-module-transforms@^7.28.3": + version "7.28.3" dependencies: - "@babel/helper-module-imports" "^7.28.6" - "@babel/helper-validator-identifier" "^7.28.5" - "@babel/traverse" "^7.28.6" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.28.3" "@babel/helper-optimise-call-expression@^7.27.1": version "7.27.1" @@ -1080,10 +1049,8 @@ dependencies: "@babel/types" "^7.27.1" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.28.6", "@babel/helper-plugin-utils@^7.8.0": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz#6f13ea251b68c8532e985fd532f28741a8af9ac8" - integrity sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.0": + version "7.27.1" "@babel/helper-remap-async-to-generator@^7.27.1": version "7.27.1" @@ -1094,14 +1061,12 @@ "@babel/helper-wrap-function" "^7.27.1" "@babel/traverse" "^7.27.1" -"@babel/helper-replace-supers@^7.27.1", "@babel/helper-replace-supers@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz#94aa9a1d7423a00aead3f204f78834ce7d53fe44" - integrity sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg== +"@babel/helper-replace-supers@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-member-expression-to-functions" "^7.28.5" + "@babel/helper-member-expression-to-functions" "^7.27.1" "@babel/helper-optimise-call-expression" "^7.27.1" - "@babel/traverse" "^7.28.6" + "@babel/traverse" "^7.27.1" "@babel/helper-skip-transparent-expression-wrappers@^7.27.1": version "7.27.1" @@ -1116,7 +1081,7 @@ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz" integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== -"@babel/helper-validator-identifier@^7.28.5": +"@babel/helper-validator-identifier@^7.27.1", "@babel/helper-validator-identifier@^7.28.5": version "7.28.5" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz" integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== @@ -1127,40 +1092,32 @@ integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== "@babel/helper-wrap-function@^7.27.1": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz#4e349ff9222dab69a93a019cc296cdd8442e279a" - integrity sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ== + version "7.28.3" dependencies: - "@babel/template" "^7.28.6" - "@babel/traverse" "^7.28.6" - "@babel/types" "^7.28.6" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.3" + "@babel/types" "^7.28.2" -"@babel/helpers@^7.28.6": - version "7.29.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.29.2.tgz#9cfbccb02b8e229892c0b07038052cc1a8709c49" - integrity sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw== +"@babel/helpers@^7.28.4": + version "7.28.4" dependencies: - "@babel/template" "^7.28.6" - "@babel/types" "^7.29.0" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.4" "@babel/node@^7.14.9": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.29.0.tgz#278d903d17bf80d361ed6ac9552125eebd5eab5f" - integrity sha512-9UeU8F3rx2lOZXneEW2HTnTYdA8+fXP0kr54tk7d0fPomWNlZ6WJ2H9lunr5dSvr8FNY0CDnop3Km6jZ5NAUsQ== + version "7.28.0" dependencies: - "@babel/register" "^7.28.6" + "@babel/register" "^7.27.1" commander "^6.2.0" - core-js "^3.48.0" + core-js "^3.30.2" node-environment-flags "^1.0.5" regenerator-runtime "^0.14.0" v8flags "^3.1.1" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.28.6", "@babel/parser@^7.29.0": - version "7.29.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.3.tgz#116f70a77958307fceac27747573032f8a62f88e" - integrity sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.27.2", "@babel/parser@^7.28.5": + version "7.28.5" dependencies: - "@babel/types" "^7.29.0" + "@babel/types" "^7.28.5" "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.28.5": version "7.28.5" @@ -1184,14 +1141,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@^7.29.3": - version "7.29.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz#2e14f9335803d892ccb67ef487e23cf9726156fe" - integrity sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg== - dependencies: - "@babel/helper-plugin-utils" "^7.28.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.27.1": version "7.27.1" resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz" @@ -1201,13 +1150,11 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" "@babel/plugin-transform-optional-chaining" "^7.27.1" -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz#0e8289cec28baaf05d54fd08d81ae3676065f69f" - integrity sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.28.3": + version "7.28.3" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" - "@babel/traverse" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.28.3" "@babel/plugin-proposal-logical-assignment-operators@^7.20.7": version "7.20.7" @@ -1250,19 +1197,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-import-assertions@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz#ae9bc1923a6ba527b70104dd2191b0cd872c8507" - integrity sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw== +"@babel/plugin-syntax-import-assertions@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-syntax-import-attributes@^7.24.7", "@babel/plugin-syntax-import-attributes@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz#b71d5914665f60124e133696f17cd7669062c503" - integrity sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw== +"@babel/plugin-syntax-import-attributes@^7.24.7", "@babel/plugin-syntax-import-attributes@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" @@ -1279,11 +1222,9 @@ "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz#f8ca28bbd84883b5fea0e447c635b81ba73997ee" - integrity sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w== + version "7.27.1" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" @@ -1342,11 +1283,9 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz#c7b2ddf1d0a811145b1de800d1abd146af92e3a2" - integrity sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A== + version "7.27.1" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" @@ -1363,22 +1302,18 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-async-generator-functions@^7.29.0": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz#63ed829820298f0bf143d5a4a68fb8c06ffd742f" - integrity sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w== +"@babel/plugin-transform-async-generator-functions@^7.28.0": + version "7.28.0" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/helper-remap-async-to-generator" "^7.27.1" - "@babel/traverse" "^7.29.0" + "@babel/traverse" "^7.28.0" -"@babel/plugin-transform-async-to-generator@^7.10.1", "@babel/plugin-transform-async-to-generator@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz#bd97b42237b2d1bc90d74bcb486c39be5b4d7e77" - integrity sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g== +"@babel/plugin-transform-async-to-generator@^7.10.1", "@babel/plugin-transform-async-to-generator@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-module-imports" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/helper-remap-async-to-generator" "^7.27.1" "@babel/plugin-transform-block-scoped-functions@^7.27.1": @@ -1388,50 +1323,40 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-block-scoping@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz#e1ef5633448c24e76346125c2534eeb359699a99" - integrity sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw== +"@babel/plugin-transform-block-scoping@^7.28.5": + version "7.28.5" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-class-properties@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz#d274a4478b6e782d9ea987fda09bdb6d28d66b72" - integrity sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw== +"@babel/plugin-transform-class-properties@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-create-class-features-plugin" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-class-static-block@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz#1257491e8259c6d125ac4d9a6f39f9d2bf3dba70" - integrity sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ== +"@babel/plugin-transform-class-static-block@^7.28.3": + version "7.28.3" dependencies: - "@babel/helper-create-class-features-plugin" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-create-class-features-plugin" "^7.28.3" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-classes@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz#8f6fb79ba3703978e701ce2a97e373aae7dda4b7" - integrity sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q== +"@babel/plugin-transform-classes@^7.28.4": + version "7.28.4" dependencies: "@babel/helper-annotate-as-pure" "^7.27.3" - "@babel/helper-compilation-targets" "^7.28.6" + "@babel/helper-compilation-targets" "^7.27.2" "@babel/helper-globals" "^7.28.0" - "@babel/helper-plugin-utils" "^7.28.6" - "@babel/helper-replace-supers" "^7.28.6" - "@babel/traverse" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/traverse" "^7.28.4" -"@babel/plugin-transform-computed-properties@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz#936824fc71c26cb5c433485776d79c8e7b0202d2" - integrity sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ== +"@babel/plugin-transform-computed-properties@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" - "@babel/template" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/template" "^7.27.1" -"@babel/plugin-transform-destructuring@^7.28.5": +"@babel/plugin-transform-destructuring@^7.28.0", "@babel/plugin-transform-destructuring@^7.28.5": version "7.28.5" resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz" integrity sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw== @@ -1439,13 +1364,11 @@ "@babel/helper-plugin-utils" "^7.27.1" "@babel/traverse" "^7.28.5" -"@babel/plugin-transform-dotall-regex@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz#def31ed84e0fb6e25c71e53c124e7b76a4ab8e61" - integrity sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg== +"@babel/plugin-transform-dotall-regex@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.28.5" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-duplicate-keys@^7.27.1": version "7.27.1" @@ -1454,13 +1377,11 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.29.0": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz#8014b8a6cfd0e7b92762724443bf0d2400f26df1" - integrity sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw== +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.28.5" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-dynamic-import@^7.27.1": version "7.27.1" @@ -1469,20 +1390,16 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-explicit-resource-management@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz#dd6788f982c8b77e86779d1d029591e39d9d8be7" - integrity sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg== +"@babel/plugin-transform-explicit-resource-management@^7.28.0": + version "7.28.0" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" - "@babel/plugin-transform-destructuring" "^7.28.5" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-transform-destructuring" "^7.28.0" -"@babel/plugin-transform-exponentiation-operator@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz#5e477eb7eafaf2ab5537a04aaafcf37e2d7f1091" - integrity sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw== +"@babel/plugin-transform-exponentiation-operator@^7.28.5": + version "7.28.5" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-export-namespace-from@^7.27.1": version "7.27.1" @@ -1508,12 +1425,10 @@ "@babel/helper-plugin-utils" "^7.27.1" "@babel/traverse" "^7.27.1" -"@babel/plugin-transform-json-strings@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz#4c8c15b2dc49e285d110a4cf3dac52fd2dfc3038" - integrity sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw== +"@babel/plugin-transform-json-strings@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-literals@^7.27.1": version "7.27.1" @@ -1522,12 +1437,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-logical-assignment-operators@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz#53028a3d77e33c50ef30a8fce5ca17065936e605" - integrity sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A== +"@babel/plugin-transform-logical-assignment-operators@^7.28.5": + version "7.28.5" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-member-expression-literals@^7.27.1": version "7.27.1" @@ -1544,23 +1457,19 @@ "@babel/helper-module-transforms" "^7.27.1" "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-modules-commonjs@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz#c0232e0dfe66a734cc4ad0d5e75fc3321b6fdef1" - integrity sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA== +"@babel/plugin-transform-modules-commonjs@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-module-transforms" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-modules-systemjs@^7.29.4": - version "7.29.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz#f621105da99919c15cf4bde6fcc7346ef95e7b20" - integrity sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w== +"@babel/plugin-transform-modules-systemjs@^7.28.5": + version "7.28.5" dependencies: - "@babel/helper-module-transforms" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-module-transforms" "^7.28.3" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/helper-validator-identifier" "^7.28.5" - "@babel/traverse" "^7.29.0" + "@babel/traverse" "^7.28.5" "@babel/plugin-transform-modules-umd@^7.27.1": version "7.27.1" @@ -1570,13 +1479,11 @@ "@babel/helper-module-transforms" "^7.27.1" "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-named-capturing-groups-regex@^7.29.0": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz#a26cd51e09c4718588fc4cce1c5d1c0152102d6a" - integrity sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ== +"@babel/plugin-transform-named-capturing-groups-regex@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.28.5" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-new-target@^7.27.1": version "7.27.1" @@ -1585,30 +1492,24 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-nullish-coalescing-operator@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz#9bc62096e90ab7a887f3ca9c469f6adec5679757" - integrity sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg== +"@babel/plugin-transform-nullish-coalescing-operator@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-numeric-separator@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz#1310b0292762e7a4a335df5f580c3320ee7d9e9f" - integrity sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w== +"@babel/plugin-transform-numeric-separator@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-object-rest-spread@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz#fdd4bc2d72480db6ca42aed5c051f148d7b067f7" - integrity sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA== +"@babel/plugin-transform-object-rest-spread@^7.28.4": + version "7.28.4" dependencies: - "@babel/helper-compilation-targets" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" - "@babel/plugin-transform-destructuring" "^7.28.5" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-transform-destructuring" "^7.28.0" "@babel/plugin-transform-parameters" "^7.27.7" - "@babel/traverse" "^7.28.6" + "@babel/traverse" "^7.28.4" "@babel/plugin-transform-object-super@^7.27.1": version "7.27.1" @@ -1618,19 +1519,15 @@ "@babel/helper-plugin-utils" "^7.27.1" "@babel/helper-replace-supers" "^7.27.1" -"@babel/plugin-transform-optional-catch-binding@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz#75107be14c78385978201a49c86414a150a20b4c" - integrity sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ== +"@babel/plugin-transform-optional-catch-binding@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-optional-chaining@^7.27.1", "@babel/plugin-transform-optional-chaining@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz#926cf150bd421fc8362753e911b4a1b1ce4356cd" - integrity sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w== +"@babel/plugin-transform-optional-chaining@^7.27.1", "@babel/plugin-transform-optional-chaining@^7.28.5": + version "7.28.5" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" "@babel/plugin-transform-parameters@^7.27.7": @@ -1640,22 +1537,18 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-private-methods@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz#c76fbfef3b86c775db7f7c106fff544610bdb411" - integrity sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg== +"@babel/plugin-transform-private-methods@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-create-class-features-plugin" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-private-property-in-object@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz#4fafef1e13129d79f1d75ac180c52aafefdb2811" - integrity sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA== +"@babel/plugin-transform-private-property-in-object@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-annotate-as-pure" "^7.27.3" - "@babel/helper-create-class-features-plugin" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-property-literals@^7.27.1": version "7.27.1" @@ -1664,20 +1557,16 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-regenerator@^7.29.0": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz#dec237cec1b93330876d6da9992c4abd42c9d18b" - integrity sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog== +"@babel/plugin-transform-regenerator@^7.28.4": + version "7.28.4" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-regexp-modifiers@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz#7ef0163bd8b4a610481b2509c58cf217f065290b" - integrity sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg== +"@babel/plugin-transform-regexp-modifiers@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.28.5" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-reserved-words@^7.27.1": version "7.27.1" @@ -1687,12 +1576,10 @@ "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-runtime@^7.10.1": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.0.tgz#a5fded13cc656700804bfd6e5ebd7fffd5266803" - integrity sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w== + version "7.28.5" dependencies: - "@babel/helper-module-imports" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" babel-plugin-polyfill-corejs2 "^0.4.14" babel-plugin-polyfill-corejs3 "^0.13.0" babel-plugin-polyfill-regenerator "^0.6.5" @@ -1705,12 +1592,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-spread@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz#40a2b423f6db7b70f043ad027a58bcb44a9757b6" - integrity sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA== +"@babel/plugin-transform-spread@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" "@babel/plugin-transform-sticky-regex@^7.27.1": @@ -1741,13 +1626,11 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-unicode-property-regex@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz#63a7a6c21a0e75dae9b1861454111ea5caa22821" - integrity sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A== +"@babel/plugin-transform-unicode-property-regex@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.28.5" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-unicode-regex@^7.27.1": version "7.27.1" @@ -1757,89 +1640,84 @@ "@babel/helper-create-regexp-features-plugin" "^7.27.1" "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-transform-unicode-sets-regex@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz#924912914e5df9fe615ec472f88ff4788ce04d4e" - integrity sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q== +"@babel/plugin-transform-unicode-sets-regex@^7.27.1": + version "7.27.1" dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.28.5" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/preset-env@^7.10.2": - version "7.29.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.29.5.tgz#c48b7ed94582c8b685e21b8b42de8633ec289268" - integrity sha512-/69t2aEzGKHD76DyLbHysF/QH2LJOB8iFnYO37unDTKBTubzcMRv0f3H5EiN1Q6ajOd/eB7dAInF0qdFVS06kA== + version "7.28.5" dependencies: - "@babel/compat-data" "^7.29.3" - "@babel/helper-compilation-targets" "^7.28.6" - "@babel/helper-plugin-utils" "^7.28.6" + "@babel/compat-data" "^7.28.5" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/helper-validator-option" "^7.27.1" "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.28.5" "@babel/plugin-bugfix-safari-class-field-initializer-scope" "^7.27.1" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.27.1" - "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array" "^7.29.3" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.27.1" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.28.6" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.28.3" "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-import-assertions" "^7.28.6" - "@babel/plugin-syntax-import-attributes" "^7.28.6" + "@babel/plugin-syntax-import-assertions" "^7.27.1" + "@babel/plugin-syntax-import-attributes" "^7.27.1" "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" "@babel/plugin-transform-arrow-functions" "^7.27.1" - "@babel/plugin-transform-async-generator-functions" "^7.29.0" - "@babel/plugin-transform-async-to-generator" "^7.28.6" + "@babel/plugin-transform-async-generator-functions" "^7.28.0" + "@babel/plugin-transform-async-to-generator" "^7.27.1" "@babel/plugin-transform-block-scoped-functions" "^7.27.1" - "@babel/plugin-transform-block-scoping" "^7.28.6" - "@babel/plugin-transform-class-properties" "^7.28.6" - "@babel/plugin-transform-class-static-block" "^7.28.6" - "@babel/plugin-transform-classes" "^7.28.6" - "@babel/plugin-transform-computed-properties" "^7.28.6" + "@babel/plugin-transform-block-scoping" "^7.28.5" + "@babel/plugin-transform-class-properties" "^7.27.1" + "@babel/plugin-transform-class-static-block" "^7.28.3" + "@babel/plugin-transform-classes" "^7.28.4" + "@babel/plugin-transform-computed-properties" "^7.27.1" "@babel/plugin-transform-destructuring" "^7.28.5" - "@babel/plugin-transform-dotall-regex" "^7.28.6" + "@babel/plugin-transform-dotall-regex" "^7.27.1" "@babel/plugin-transform-duplicate-keys" "^7.27.1" - "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.29.0" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.27.1" "@babel/plugin-transform-dynamic-import" "^7.27.1" - "@babel/plugin-transform-explicit-resource-management" "^7.28.6" - "@babel/plugin-transform-exponentiation-operator" "^7.28.6" + "@babel/plugin-transform-explicit-resource-management" "^7.28.0" + "@babel/plugin-transform-exponentiation-operator" "^7.28.5" "@babel/plugin-transform-export-namespace-from" "^7.27.1" "@babel/plugin-transform-for-of" "^7.27.1" "@babel/plugin-transform-function-name" "^7.27.1" - "@babel/plugin-transform-json-strings" "^7.28.6" + "@babel/plugin-transform-json-strings" "^7.27.1" "@babel/plugin-transform-literals" "^7.27.1" - "@babel/plugin-transform-logical-assignment-operators" "^7.28.6" + "@babel/plugin-transform-logical-assignment-operators" "^7.28.5" "@babel/plugin-transform-member-expression-literals" "^7.27.1" "@babel/plugin-transform-modules-amd" "^7.27.1" - "@babel/plugin-transform-modules-commonjs" "^7.28.6" - "@babel/plugin-transform-modules-systemjs" "^7.29.4" + "@babel/plugin-transform-modules-commonjs" "^7.27.1" + "@babel/plugin-transform-modules-systemjs" "^7.28.5" "@babel/plugin-transform-modules-umd" "^7.27.1" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.29.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.27.1" "@babel/plugin-transform-new-target" "^7.27.1" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.28.6" - "@babel/plugin-transform-numeric-separator" "^7.28.6" - "@babel/plugin-transform-object-rest-spread" "^7.28.6" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.27.1" + "@babel/plugin-transform-numeric-separator" "^7.27.1" + "@babel/plugin-transform-object-rest-spread" "^7.28.4" "@babel/plugin-transform-object-super" "^7.27.1" - "@babel/plugin-transform-optional-catch-binding" "^7.28.6" - "@babel/plugin-transform-optional-chaining" "^7.28.6" + "@babel/plugin-transform-optional-catch-binding" "^7.27.1" + "@babel/plugin-transform-optional-chaining" "^7.28.5" "@babel/plugin-transform-parameters" "^7.27.7" - "@babel/plugin-transform-private-methods" "^7.28.6" - "@babel/plugin-transform-private-property-in-object" "^7.28.6" + "@babel/plugin-transform-private-methods" "^7.27.1" + "@babel/plugin-transform-private-property-in-object" "^7.27.1" "@babel/plugin-transform-property-literals" "^7.27.1" - "@babel/plugin-transform-regenerator" "^7.29.0" - "@babel/plugin-transform-regexp-modifiers" "^7.28.6" + "@babel/plugin-transform-regenerator" "^7.28.4" + "@babel/plugin-transform-regexp-modifiers" "^7.27.1" "@babel/plugin-transform-reserved-words" "^7.27.1" "@babel/plugin-transform-shorthand-properties" "^7.27.1" - "@babel/plugin-transform-spread" "^7.28.6" + "@babel/plugin-transform-spread" "^7.27.1" "@babel/plugin-transform-sticky-regex" "^7.27.1" "@babel/plugin-transform-template-literals" "^7.27.1" "@babel/plugin-transform-typeof-symbol" "^7.27.1" "@babel/plugin-transform-unicode-escapes" "^7.27.1" - "@babel/plugin-transform-unicode-property-regex" "^7.28.6" + "@babel/plugin-transform-unicode-property-regex" "^7.27.1" "@babel/plugin-transform-unicode-regex" "^7.27.1" - "@babel/plugin-transform-unicode-sets-regex" "^7.28.6" + "@babel/plugin-transform-unicode-sets-regex" "^7.27.1" "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.15" - babel-plugin-polyfill-corejs3 "^0.14.0" - babel-plugin-polyfill-regenerator "^0.6.6" - core-js-compat "^3.48.0" + babel-plugin-polyfill-corejs2 "^0.4.14" + babel-plugin-polyfill-corejs3 "^0.13.0" + babel-plugin-polyfill-regenerator "^0.6.5" + core-js-compat "^3.43.0" semver "^6.3.1" "@babel/preset-modules@0.1.6-no-external-plugins": @@ -1851,10 +1729,8 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/register@^7.28.6": - version "7.29.3" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.29.3.tgz#726233ed488d52bb67aa8fd0dc5cdf19d10a2584" - integrity sha512-F6C1KpIdoImKQfsD6HSxZ+mS4YY/2Q+JsqrmTC5ApVkTR2rG+nnbpjhWwzA5bDNu8mJjB3AryqDaWFLd4gCbJQ== +"@babel/register@^7.27.1": + version "7.28.3" dependencies: clone-deep "^4.0.1" find-cache-dir "^2.0.0" @@ -1863,36 +1739,28 @@ source-map-support "^0.5.16" "@babel/runtime@^7.10.2", "@babel/runtime@^7.21.0": - version "7.29.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.2.tgz#9a6e2d05f4b6692e1801cd4fb176ad823930ed5e" - integrity sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g== - -"@babel/template@^7.28.6", "@babel/template@^7.3.3": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" - integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== - dependencies: - "@babel/code-frame" "^7.28.6" - "@babel/parser" "^7.28.6" - "@babel/types" "^7.28.6" - -"@babel/traverse@^7.27.1", "@babel/traverse@^7.28.5", "@babel/traverse@^7.28.6", "@babel/traverse@^7.29.0": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.29.0.tgz#f323d05001440253eead3c9c858adbe00b90310a" - integrity sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA== - dependencies: - "@babel/code-frame" "^7.29.0" - "@babel/generator" "^7.29.0" + version "7.28.4" + +"@babel/template@^7.27.1", "@babel/template@^7.27.2", "@babel/template@^7.3.3": + version "7.27.2" + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + +"@babel/traverse@^7.27.1", "@babel/traverse@^7.28.0", "@babel/traverse@^7.28.3", "@babel/traverse@^7.28.4", "@babel/traverse@^7.28.5": + version "7.28.5" + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" "@babel/helper-globals" "^7.28.0" - "@babel/parser" "^7.29.0" - "@babel/template" "^7.28.6" - "@babel/types" "^7.29.0" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.5" debug "^4.3.1" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.2", "@babel/types@^7.28.5", "@babel/types@^7.28.6", "@babel/types@^7.29.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.0.tgz#9f5b1e838c446e72cf3cd4b918152b8c605e37c7" - integrity sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.2", "@babel/types@^7.28.4", "@babel/types@^7.28.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.28.5" dependencies: "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.28.5" @@ -1910,9 +1778,7 @@ tslib "^2.4.0" "@eslint-community/eslint-utils@^4.2.0": - version "4.9.1" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" - integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== + version "4.9.0" dependencies: eslint-visitor-keys "^3.4.3" @@ -1995,9 +1861,7 @@ integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@img/colour@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@img/colour/-/colour-1.1.0.tgz#b0c2c2fa661adf75effd6b4964497cd80010bb9d" - integrity sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ== + version "1.0.0" "@img/sharp-darwin-arm64@0.34.5": version "0.34.5" @@ -2023,16 +1887,16 @@ 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-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-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" @@ -2063,13 +1927,6 @@ 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-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-arm@0.34.5": version "0.34.5" resolved "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz" @@ -2077,6 +1934,13 @@ 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" @@ -2153,9 +2017,7 @@ resolve-from "^5.0.0" "@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.6.tgz#8dc9afa2ac1506cb1a58f89940f1c124446c8df3" - integrity sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw== + version "0.1.3" "@jest/console@^29.7.0": version "29.7.0" @@ -2423,11 +2285,6 @@ resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz" integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== -"@nodable/entities@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@nodable/entities/-/entities-2.1.0.tgz#f543e5c6446720d4cf9e498a83019dd159973bc2" - integrity sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -2497,10 +2354,10 @@ resolved "https://registry.npmjs.org/@paypal/paypalhttp/-/paypalhttp-1.0.1.tgz" integrity sha512-DC7AHxTT7drF6dUi3YaFdPVuT15sIkpD5H2eHmdtFgxM4UanS1o1ZDfMhR9mpxd8o+X6pz2r+EZVRRq+n1cssQ== -"@puppeteer/browsers@2.13.2": - version "2.13.2" - resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.13.2.tgz#dcc8e7a4545d9680a8a72c53f132e80afc582284" - integrity sha512-5EUZSUIc37H6aIXyWO0Z4y8NlF8NnjgmqeQgOGiswAU7pY0HOo16ho4+alIWmSfdZnjqBRawMsP3I5YqLSn6kw== +"@puppeteer/browsers@2.13.0": + version "2.13.0" + resolved "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.13.0.tgz" + integrity sha512-46BZJYJjc/WwmKjsvDFykHtXrtomsCIrwYQPOP7VfMJoZY2bsDF9oROBABR3paDjDcmkUye1Pb1BqdcdiipaWA== dependencies: debug "^4.4.3" extract-zip "^2.0.1" @@ -2515,7 +2372,7 @@ resolved "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz" integrity sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg== -"@redis/client@1.6.1": +"@redis/client@^1.0.0", "@redis/client@1.6.1": version "1.6.1" resolved "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz" integrity sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw== @@ -2566,7 +2423,7 @@ "@sentry/types" "7.120.4" "@sentry/utils" "7.120.4" -"@sentry/integrations@7.120.4", "@sentry/integrations@^7.110.0": +"@sentry/integrations@^7.110.0", "@sentry/integrations@7.120.4": version "7.120.4" resolved "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.120.4.tgz" integrity sha512-kkBTLk053XlhDCg7OkBQTIMF4puqFibeRO3E3YiVc4PGLnocXMaVpOSCkMqAc1k1kZ09UgGi8DxfQhnFEjUkpA== @@ -2600,9 +2457,7 @@ "@sentry/types" "7.120.4" "@sinclair/typebox@^0.27.8": - version "0.27.10" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.10.tgz#beefe675f1853f73676aecc915b2bd2ac98c4fc6" - integrity sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA== + version "0.27.8" "@sinonjs/commons@^3.0.0": version "3.0.1" @@ -3228,9 +3083,7 @@ "@types/node" "*" "@types/express-serve-static-core@^4.17.33": - version "4.19.8" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz#99b960322a4d576b239a640ab52ef191989b036f" - integrity sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA== + version "4.19.7" dependencies: "@types/node" "*" "@types/qs" "*" @@ -3309,7 +3162,7 @@ "@types/bson" "*" "@types/node" "*" -"@types/node-fetch@^2.6.12": +"@types/node-fetch@^2.5.7", "@types/node-fetch@^2.6.12": version "2.6.13" resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz" integrity sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw== @@ -3323,16 +3176,12 @@ integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== "@types/node@>=10.0.0": - version "25.7.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-25.7.0.tgz#7498f82e90dbdce7c34b75aaaa256c498a0ebe6c" - integrity sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg== + version "24.10.0" dependencies: - undici-types "~7.21.0" + undici-types "~7.16.0" "@types/qs@*": - version "6.15.1" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.15.1.tgz#8606884272c63f0db96986bd3548650d8a9388bf" - integrity sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw== + version "6.14.0" "@types/range-parser@*": version "1.2.7" @@ -3391,29 +3240,18 @@ resolved "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz" integrity sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA== -"@types/ws@^8.5.12": - version "8.18.1" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9" - integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg== - dependencies: - "@types/node" "*" - "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz" integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== "@types/yargs@^15.0.0": - version "15.0.20" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.20.tgz#6d00a124c9f757427d4ca3cbc87daea778053c68" - integrity sha512-KIkX+/GgfFitlASYCGoSF+T4XRXhOubJLhkLVtSfsRTe9jWMmuM2g28zQ41BtPTG7TRBb2xHW+LCNVE9QR/vsg== + version "15.0.19" dependencies: "@types/yargs-parser" "*" "@types/yargs@^17.0.8": - version "17.0.35" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.35.tgz#07013e46aa4d7d7d50a49e15604c1c5340d4eb24" - integrity sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg== + version "17.0.34" dependencies: "@types/yargs-parser" "*" @@ -3424,10 +3262,8 @@ dependencies: "@types/node" "*" -"@typespec/ts-http-runtime@^0.3.0", "@typespec/ts-http-runtime@^0.3.4": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.5.tgz#ccc9b35464aa8da90982d00553d49a5c591d95f3" - integrity sha512-yURCknZhvywvQItHMMmFSo+fq5arCUIyz/CVk7jD89MSai7dkaX8ufjCWp3NttLojoTVbcE72ri+be/TnEbMHw== +"@typespec/ts-http-runtime@^0.3.0": + version "0.3.2" dependencies: http-proxy-agent "^7.0.0" https-proxy-agent "^7.0.0" @@ -3475,10 +3311,13 @@ acorn@^5.5.0: resolved "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz" integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== -acorn@^8.9.0: - version "8.16.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" - integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.9.0: + version "8.15.0" + +agent-base@^7.1.0, agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== agent-base@6: version "6.0.2" @@ -3487,11 +3326,6 @@ agent-base@6: dependencies: debug "4" -agent-base@^7.1.0, agent-base@^7.1.2: - version "7.1.4" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz" - integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== - ajv-keywords@^1.0.0: version "1.5.1" resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz" @@ -3505,10 +3339,8 @@ ajv@^4.7.0: co "^4.6.0" json-stable-stringify "^1.0.1" -ajv@^6.12.3, ajv@^6.12.4: - version "6.15.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.15.0.tgz#07e982c74626167aa7a2495c53817892d7139492" - integrity sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw== +ajv@^6.12.3, ajv@^6.12.4, ajv@>=4.10.0: + version "6.12.6" dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -3528,9 +3360,7 @@ ansi-escapes@^4.2.1: type-fest "^0.21.3" ansi-escapes@^7.0.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.3.0.tgz#5395bb74b2150a4a1d6e3c2565f4aeca78d28627" - integrity sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg== + version "7.2.0" dependencies: environment "^1.0.0" @@ -3556,10 +3386,8 @@ ansi-regex@^5.0.0, ansi-regex@^5.0.1: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-regex@^6.2.2: +ansi-regex@^6.0.1: version "6.2.2" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" - integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== ansi-styles@^2.2.1: version "2.2.1" @@ -3578,7 +3406,7 @@ ansi-styles@^5.0.0: resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.2.1, ansi-styles@^6.2.3: +ansi-styles@^6.2.1: version "6.2.3" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz" integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== @@ -3700,10 +3528,8 @@ array.prototype.flatmap@^1.3.2, array.prototype.flatmap@^1.3.3: es-abstract "^1.23.5" es-shim-unscopables "^1.0.2" -array.prototype.reduce@^1.0.8: +array.prototype.reduce@^1.0.6: version "1.0.8" - resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.8.tgz#42f97f5078daedca687d4463fd3c05cbfd83da57" - integrity sha512-DwuEqgXFBwbmZSRqt3BpQigWNUoqw9Ml2dTWdF3B2zQlQX4OeUE0zyuzX0fX0IbTvjdkZbcBTU3idgpO78qkTw== dependencies: call-bind "^1.0.8" call-bound "^1.0.4" @@ -3755,7 +3581,7 @@ asn1@~0.2.3: dependencies: safer-buffer "~2.1.0" -assert-plus@1.0.0, assert-plus@^1.0.0: +assert-plus@^1.0.0, assert-plus@1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== @@ -3840,19 +3666,14 @@ aws4@^1.8.0: integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== axe-core@^4.10.0: - version "4.11.4" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.11.4.tgz#5b535e381ff1e61ffdd615e5483d16186d3b46a5" - integrity sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA== + version "4.11.0" -axios@^1.13.5, axios@^1.16.1, axios@^1.8.4: - version "1.16.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.16.1.tgz#517e29291d19d6e8cf919ff264f4fe157261ba12" - integrity sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A== +axios@^1.12.0, axios@^1.7.7, axios@^1.8.4: + version "1.13.2" dependencies: - follow-redirects "^1.16.0" - form-data "^4.0.5" - https-proxy-agent "^5.0.1" - proxy-from-env "^2.1.0" + follow-redirects "^1.15.6" + form-data "^4.0.4" + proxy-from-env "^1.1.0" axobject-query@^4.1.0: version "4.1.0" @@ -3907,10 +3728,8 @@ babel-plugin-jest-hoist@^29.6.3: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-module-resolver@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.3.tgz#13f03cf29048ad7e0239e6a1c4dcc669d199f394" - integrity sha512-h8h6H71ZvdLJZxZrYkaeR30BojTaV7O9GfqacY14SNj5CNB8ocL9tydNzTC0JrnNN7vY3eJhwCmkDj7tuEUaqQ== +"babel-plugin-module-resolver@^3.0.0 || ^4.0.0 || ^5.0.0", babel-plugin-module-resolver@^5.0.0: + version "5.0.2" dependencies: find-babel-config "^2.1.1" glob "^9.3.3" @@ -3918,13 +3737,11 @@ babel-plugin-module-resolver@^5.0.0: reselect "^4.1.7" resolve "^1.22.8" -babel-plugin-polyfill-corejs2@^0.4.14, babel-plugin-polyfill-corejs2@^0.4.15: - version "0.4.17" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz#198f970f1c99a856b466d1187e88ce30bd199d91" - integrity sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w== +babel-plugin-polyfill-corejs2@^0.4.14: + version "0.4.14" dependencies: - "@babel/compat-data" "^7.28.6" - "@babel/helper-define-polyfill-provider" "^0.6.8" + "@babel/compat-data" "^7.27.7" + "@babel/helper-define-polyfill-provider" "^0.6.5" semver "^6.3.1" babel-plugin-polyfill-corejs3@^0.13.0: @@ -3935,20 +3752,10 @@ babel-plugin-polyfill-corejs3@^0.13.0: "@babel/helper-define-polyfill-provider" "^0.6.5" core-js-compat "^3.43.0" -babel-plugin-polyfill-corejs3@^0.14.0: - version "0.14.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz#6ac08d2f312affb70c4c69c0fbba4cb417ee5587" - integrity sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.8" - core-js-compat "^3.48.0" - -babel-plugin-polyfill-regenerator@^0.6.5, babel-plugin-polyfill-regenerator@^0.6.6: - version "0.6.8" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz#8a6bfd5dd54239362b3d06ce47ac52b2d95d7721" - integrity sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg== +babel-plugin-polyfill-regenerator@^0.6.5: + version "0.6.5" dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.8" + "@babel/helper-define-polyfill-provider" "^0.6.5" babel-preset-current-node-syntax@^1.0.0: version "1.2.0" @@ -3984,12 +3791,7 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -balanced-match@^4.0.2: - version "4.0.4" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-4.0.4.tgz#bfb10662feed8196a2c62e7c68e17720c274179a" - integrity sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA== - -bare-events@^2.5.4, bare-events@^2.7.0: +bare-events@*, bare-events@^2.5.4, bare-events@^2.7.0: version "2.8.2" resolved "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz" integrity sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ== @@ -4032,24 +3834,24 @@ bare-url@^2.2.2: dependencies: bare-path "^3.0.0" -base64-js@0.0.8: - version "0.0.8" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz" - integrity sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw== - base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64id@2.0.0, base64id@~2.0.0: +base64-js@0.0.8: + version "0.0.8" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz" + integrity sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw== + +base64id@~2.0.0, base64id@2.0.0: version "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.10.12, baseline-browser-mapping@^2.10.29: +baseline-browser-mapping@^2.10.29, baseline-browser-mapping@^2.8.19: version "2.10.29" - resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz#47bdc13027af28d341f367a4f35a07ce872e27b4" + 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: @@ -4135,27 +3937,16 @@ bowser@^2.11.0: integrity sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw== brace-expansion@^1.1.7: - version "1.1.14" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.14.tgz#d9de602370d91347cd9ddad1224d4fd701eb348b" - integrity sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g== + version "1.1.12" dependencies: balanced-match "^1.0.0" concat-map "0.0.1" brace-expansion@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.0.tgz#4f41a41190216ee36067ec381526fe9539c4f0ae" - integrity sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== + version "2.0.2" dependencies: balanced-match "^1.0.0" -brace-expansion@^5.0.5: - version "5.0.6" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-5.0.6.tgz#ec68fe0a641a29d8711579caf641d05bae1f2285" - integrity sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g== - dependencies: - balanced-match "^4.0.2" - braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" @@ -4170,16 +3961,14 @@ brotli@^1.3.2: dependencies: base64-js "^1.1.2" -browserslist@^4.24.0, browserslist@^4.28.1: - version "4.28.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.2.tgz#f50b65362ef48974ca9f50b3680566d786b811d2" - integrity sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg== +browserslist@^4.24.0, browserslist@^4.26.3, "browserslist@>= 4.21.0": + version "4.27.0" dependencies: - baseline-browser-mapping "^2.10.12" - caniuse-lite "^1.0.30001782" - electron-to-chromium "^1.5.328" - node-releases "^2.0.36" - update-browserslist-db "^1.2.3" + baseline-browser-mapping "^2.8.19" + caniuse-lite "^1.0.30001751" + electron-to-chromium "^1.5.238" + node-releases "^2.0.26" + update-browserslist-db "^1.1.4" bser@2.1.1: version "2.1.1" @@ -4189,9 +3978,7 @@ bser@2.1.1: node-int64 "^0.4.0" bson@*: - version "7.2.0" - resolved "https://registry.yarnpkg.com/bson/-/bson-7.2.0.tgz#1a496a42d9ff130b9f3ab8efd465459c758c747f" - integrity sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ== + version "7.0.0" bson@^1.1.4: version "1.1.6" @@ -4213,6 +4000,14 @@ buffer-from@^1.0.0: resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + buffer@4.9.2: version "4.9.2" resolved "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz" @@ -4222,14 +4017,6 @@ buffer@4.9.2: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - bufferstreams@^1.1.1: version "1.1.3" resolved "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.1.3.tgz" @@ -4244,12 +4031,12 @@ busboy@^1.6.0: dependencies: streamsearch "^1.1.0" -bytes@3.1.2, bytes@~3.1.2: +bytes@~3.1.2, bytes@3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== @@ -4257,14 +4044,12 @@ call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: es-errors "^1.3.0" function-bind "^1.1.2" -call-bind@^1.0.7, call-bind@^1.0.8, call-bind@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.9.tgz#39a644700c80bc7d0ca9102fc6d1d43b2fd7eee7" - integrity sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ== +call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" dependencies: - call-bind-apply-helpers "^1.0.2" - es-define-property "^1.0.1" - get-intrinsic "^1.3.0" + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" set-function-length "^1.2.2" call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: @@ -4297,37 +4082,41 @@ camelcase@^5.3.1: resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.1.0, camelcase@^6.2.0: +camelcase@^6.1.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +camelcase@^6.2.0: version "6.3.0" resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001782: - version "1.0.30001792" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz#ca8bb9be244835a335e2018272ce7223691873c5" - integrity sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw== +caniuse-lite@^1.0.30001751: + version "1.0.30001754" card-validator@^10.0.2: - version "10.0.4" - resolved "https://registry.yarnpkg.com/card-validator/-/card-validator-10.0.4.tgz#7396c5df930fb0e0287a18190eaf24a65419e18a" - integrity sha512-1Q/tDCSvM5iL3psPo6j8KF/VoI63WA7Y4Zthy1E7l/H4Iul2e2X+1S0vp33n3OMRjLgGU2+gLaK2NsGtwArJkQ== + version "10.0.3" dependencies: - credit-card-type "^10.1.0" + credit-card-type "^10.0.2" caseless@~0.12.0: version "0.12.0" resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -"chalk@4.1 - 4.1.2", chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== +chalk@^1.0.0: + version "1.1.3" + resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.1.1: version "1.1.3" resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== @@ -4338,11 +4127,30 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -change-case@^5.4.4: - version "5.4.4" - resolved "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz" - integrity sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w== - +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^4.0.0, "chalk@4.1 - 4.1.2": + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +change-case@^5.4.4: + version "5.4.4" + resolved "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz" + integrity sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w== + char-regex@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" @@ -4423,12 +4231,10 @@ cli-cursor@^5.0.0: restore-cursor "^5.0.0" cli-truncate@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-5.2.0.tgz#c8e72aaca8339c773d128c36e0a17c6315b694eb" - integrity sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw== + version "5.1.1" dependencies: - slice-ansi "^8.0.0" - string-width "^8.2.0" + slice-ansi "^7.1.0" + string-width "^8.0.0" cli-width@^2.0.0: version "2.2.1" @@ -4458,11 +4264,6 @@ clone-stats@^0.0.1: resolved "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" integrity sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA== -clone@2.x, clone@^2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz" - integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== - clone@^1.0.0: version "1.0.4" resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" @@ -4524,10 +4325,8 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^14.0.3: - version "14.0.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.3.tgz#425d79b48f9af82fcd9e4fc1ea8af6c5ec07bbc2" - integrity sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw== +commander@^14.0.1: + version "14.0.2" commander@^6.2.0: version "6.2.1" @@ -4626,32 +4425,26 @@ cookiejar@^2.1.4: resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz" integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== -core-js-compat@^3.43.0, core-js-compat@^3.48.0: - version "3.49.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.49.0.tgz#06145447d92f4aaf258a0c44f24b47afaeaffef6" - integrity sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA== +core-js-compat@^3.43.0: + version "3.46.0" dependencies: - browserslist "^4.28.1" - -core-js@^3.48.0: - version "3.49.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.49.0.tgz#8b4d520ac034311fa21aa616f017ada0e0dbbddd" - integrity sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg== + browserslist "^4.26.3" -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== +core-js@^3.30.2: + version "3.46.0" core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + cors@^2.8.4, cors@~2.8.5: - version "2.8.6" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.6.tgz#ff5dd69bd95e547503820d29aba4f8faf8dfec96" - integrity sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw== + version "2.8.5" dependencies: object-assign "^4" vary "^1" @@ -4679,10 +4472,8 @@ create-jest@^29.7.0: jest-util "^29.7.0" prompts "^2.0.1" -credit-card-type@^10.1.0: - version "10.1.2" - resolved "https://registry.yarnpkg.com/credit-card-type/-/credit-card-type-10.1.2.tgz#7cac67d259a1260ecb242b213dc7cfb277538513" - integrity sha512-fP9vlyeYSHfKbIdE6IOR63YivTXMy0ZqyEkBhHxuAbvpltepe+zJmQ34A2Va7zJ8J7ZaB5IMAdD+1YJOmsajJA== +credit-card-type@^10.0.2: + version "10.1.0" cron-parser@^4.2.0: version "4.9.0" @@ -4692,11 +4483,9 @@ cron-parser@^4.2.0: luxon "^3.2.1" cron@^1.8.2: - version "1.8.3" - resolved "https://registry.yarnpkg.com/cron/-/cron-1.8.3.tgz#2a61d7b15848716885834ec56ac072f4b9744ebd" - integrity sha512-JYR/QZFklJCIPndBLfd/2nU1nSlCMrUdtQ2mGLXSVM/qqqEK7DOrFR0gsEiyeqs0PdWrs0ve1ggH4V7XksDwXg== + version "1.8.2" dependencies: - luxon "^1.23.x" + moment-timezone "^0.5.x" cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.6" @@ -4727,7 +4516,7 @@ css-what@2.1: resolved "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz" integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== -d@1, d@^1.0.1, d@^1.0.2: +d@^1.0.1, d@^1.0.2, d@1: version "1.0.2" resolved "https://registry.npmjs.org/d/-/d-1.0.2.tgz" integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== @@ -4784,7 +4573,7 @@ date-fns-tz@^2.0.1: resolved "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.1.tgz" integrity sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA== -date-fns@^2.30.0: +date-fns@^2.30.0, date-fns@2.x: version "2.30.0" resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz" integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== @@ -4796,43 +4585,68 @@ dateformat@^2.0.0: resolved "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz" integrity sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw== -dayjs@^1.11.7, dayjs@^1.11.9: - version "1.11.20" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.20.tgz#88d919fd639dc991415da5f4cb6f1b6650811938" - integrity sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ== +dayjs@^1.11.9: + version "1.11.19" -debug@2.6.9, debug@^2.1.1, debug@~2.6.9: +debug@^2.1.1: version "2.6.9" resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: - ms "2.0.0" + ms "^2.1.1" -debug@4, debug@^4, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.3, debug@~4.4.1: +debug@^4, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.1, debug@^4.4.3, debug@4: version "4.4.3" resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== dependencies: ms "^2.1.3" -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== +debug@~2.6.9: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: - ms "^2.1.1" + ms "2.0.0" + +debug@~4.3.1: + version "4.3.7" + dependencies: + ms "^2.1.3" + +debug@~4.3.2: + version "4.3.7" + dependencies: + ms "^2.1.3" + +debug@~4.3.4: + version "4.3.7" + dependencies: + ms "^2.1.3" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" dedent@^1.0.0: - version "1.7.2" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.7.2.tgz#34e2264ab538301e27cf7b07bf2369c19baa8dd9" - integrity sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA== + version "1.7.0" deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" @@ -4881,12 +4695,12 @@ denque@^1.4.1: resolved "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz" integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== -depd@2.0.0, depd@~2.0.0: +depd@~2.0.0, depd@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -destroy@1.2.0, destroy@~1.2.0: +destroy@~1.2.0, destroy@1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== @@ -4911,10 +4725,10 @@ detect-node@^2.1.0: resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz" integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== -devtools-protocol@0.0.1608973: - version "0.0.1608973" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1608973.tgz#56e0a2a999b06d416ee928ca06aeba95a5880515" - integrity sha512-Tpm17fxYzt+J7VrGdc1k8YdRqS3YV7se/M6KeemEqvUbq/n7At1rWVuXMxQgpWkdwSdIEKYbU//Bve+Shm4YNQ== +devtools-protocol@*, devtools-protocol@0.0.1581282: + version "0.0.1581282" + resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1581282.tgz" + integrity sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ== dezalgo@^1.0.4: version "1.0.4" @@ -4939,7 +4753,14 @@ diff-sequences@^29.6.3: resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== -doctrine@^2.0.0, doctrine@^2.1.0: +doctrine@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== @@ -4953,14 +4774,6 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-serializer@0, dom-serializer@~0.1.0: - version "0.1.1" - resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== - dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" - dom-serializer@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz" @@ -4970,7 +4783,15 @@ dom-serializer@^2.0.0: domhandler "^5.0.2" entities "^4.2.0" -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: +dom-serializer@~0.1.0, dom-serializer@0: + version "0.1.1" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz" + integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== + dependencies: + domelementtype "^1.3.0" + entities "^1.1.1" + +domelementtype@^1.3.0, domelementtype@^1.3.1, domelementtype@1: version "1.3.1" resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== @@ -4994,7 +4815,7 @@ domhandler@^5.0.2, domhandler@^5.0.3: dependencies: domelementtype "^2.3.0" -domutils@1.5.1, domutils@^1.5.1: +domutils@^1.5.1, domutils@1.5.1: version "1.5.1" resolved "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz" integrity sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw== @@ -5002,10 +4823,8 @@ domutils@1.5.1, domutils@^1.5.1: dom-serializer "0" domelementtype "1" -domutils@^3.2.2: +domutils@^3.0.1: version "3.2.2" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78" - integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== dependencies: dom-serializer "^2.0.0" domelementtype "^2.3.0" @@ -5047,7 +4866,7 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: +ecdsa-sig-formatter@^1.0.11, ecdsa-sig-formatter@1.0.11: version "1.0.11" resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz" integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== @@ -5059,10 +4878,8 @@ ee-first@1.1.1: resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.5.328: - version "1.5.354" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.354.tgz#a155a4ff0009ff225d46ea2ef7037ba48e6601fb" - integrity sha512-JaBHwWcfIdmSAfWM5l3uwjGd431j8YEMikZ+K/2nXVuBqJKyZ0f+2h4n4JY5AyNiZmnY9qQr2RU3v9DxDmHMNg== +electron-to-chromium@^1.5.238: + version "1.5.249" emittery@^0.13.1: version "0.13.1" @@ -5084,6 +4901,9 @@ emoji-regex@^9.2.2: resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +encodeurl@~1.0.2: + version "1.0.2" + encodeurl@~2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz" @@ -5102,36 +4922,28 @@ engine.io-parser@~5.2.1: integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== engine.io@~6.6.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.6.7.tgz#60efa5b5b67167cdf93d64430c40a68bae9e4f21" - integrity sha512-DgOngfDKM2EviOH3Mr9m7ks1q8roetLy/IMmYthAYzbpInMbYc/GS+fWFA3rl1gvwKVsQrVV61fo5emD1y3OJQ== + version "6.6.4" dependencies: "@types/cors" "^2.8.12" "@types/node" ">=10.0.0" - "@types/ws" "^8.5.12" accepts "~1.3.4" base64id "2.0.0" cookie "~0.7.2" cors "~2.8.5" - debug "~4.4.1" + debug "~4.3.1" engine.io-parser "~5.2.1" - ws "~8.18.3" + ws "~8.17.1" entities@^1.1.1, entities@~1.1.1: version "1.1.2" resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== -entities@^4.2.0: +entities@^4.2.0, entities@^4.4.0: version "4.5.0" resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== -entities@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-7.0.1.tgz#26e8a88889db63417dcb9a1e79a3f1bc92b5976b" - integrity sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA== - env-paths@^2.2.1: version "2.2.1" resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz" @@ -5149,10 +4961,8 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9, es-abstract@^1.24.0, es-abstract@^1.24.2: - version "1.24.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.24.2.tgz#2dbd38c180735ee983f77585140a2706a963ed9a" - integrity sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg== +es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9, es-abstract@^1.24.0: + version "1.24.0" dependencies: array-buffer-byte-length "^1.0.2" arraybuffer.prototype.slice "^1.0.4" @@ -5225,26 +5035,24 @@ es-errors@^1.3.0: integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== es-iterator-helpers@^1.2.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz#8f4ff1f3603cbd09fbdb72c747a679779a65cc7f" - integrity sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw== + version "1.2.1" dependencies: - call-bind "^1.0.9" - call-bound "^1.0.4" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" - es-abstract "^1.24.2" + es-abstract "^1.23.6" es-errors "^1.3.0" - es-set-tostringtag "^2.1.0" + es-set-tostringtag "^2.0.3" function-bind "^1.1.2" - get-intrinsic "^1.3.0" + get-intrinsic "^1.2.6" globalthis "^1.0.4" gopd "^1.2.0" has-property-descriptors "^1.0.2" has-proto "^1.2.0" has-symbols "^1.1.0" internal-slot "^1.1.0" - iterator.prototype "^1.1.5" - math-intrinsics "^1.1.0" + iterator.prototype "^1.1.4" + safe-array-concat "^1.1.3" es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: version "1.1.1" @@ -5253,7 +5061,7 @@ es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: dependencies: es-errors "^1.3.0" -es-set-tostringtag@^2.1.0: +es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz" integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== @@ -5350,7 +5158,12 @@ escape-html@~1.0.3: resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -5419,13 +5232,11 @@ eslint-import-resolver-babel-module@^5.3.2: resolve "^1.20.0" eslint-import-resolver-node@^0.3.9: - version "0.3.10" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz#84ce3005abfc300588cf23bbac1aabec1fc6e8c1" - integrity sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ== + version "0.3.9" dependencies: debug "^3.2.7" - is-core-module "^2.16.1" - resolve "^2.0.0-next.6" + is-core-module "^2.13.0" + resolve "^1.22.4" eslint-module-utils@^2.12.1: version "2.12.1" @@ -5434,7 +5245,7 @@ eslint-module-utils@^2.12.1: dependencies: debug "^3.2.7" -eslint-plugin-import@^2.28.0: +eslint-plugin-import@^2.25.2, eslint-plugin-import@^2.25.3, eslint-plugin-import@^2.28.0: version "2.32.0" resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz" integrity sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA== @@ -5459,7 +5270,7 @@ eslint-plugin-import@^2.28.0: string.prototype.trimend "^1.0.9" tsconfig-paths "^3.15.0" -eslint-plugin-jsx-a11y@^6.7.1: +eslint-plugin-jsx-a11y@^6.5.1, eslint-plugin-jsx-a11y@^6.7.1: version "6.10.2" resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz" integrity sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q== @@ -5480,12 +5291,12 @@ eslint-plugin-jsx-a11y@^6.7.1: safe-regex-test "^1.0.3" string.prototype.includes "^2.0.1" -eslint-plugin-react-hooks@^4.6.0: +eslint-plugin-react-hooks@^4.3.0, eslint-plugin-react-hooks@^4.6.0: version "4.6.2" resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz" integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== -eslint-plugin-react@^7.33.1: +eslint-plugin-react@^7.28.0, eslint-plugin-react@^7.33.1: version "7.37.5" resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz" integrity sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA== @@ -5509,14 +5320,6 @@ eslint-plugin-react@^7.33.1: string.prototype.matchall "^4.0.12" string.prototype.repeat "^1.0.0" -eslint-scope@5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - eslint-scope@^7.2.2: version "7.2.2" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz" @@ -5525,58 +5328,30 @@ eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.4.1: version "3.4.3" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^3.0.0: - version "3.19.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz" - integrity sha512-x6LJGXWCGB/4YOBhL48yeppZTo+YQUNC37N5qqCpC1b1kkNzydlQHQAtPuUSFoZSxgIadrysQoW2Hq602P+uEA== - dependencies: - babel-code-frame "^6.16.0" - chalk "^1.1.3" - concat-stream "^1.5.2" - debug "^2.1.1" - doctrine "^2.0.0" - escope "^3.6.0" - espree "^3.4.0" - esquery "^1.0.0" - estraverse "^4.2.0" - esutils "^2.0.2" - file-entry-cache "^2.0.0" - glob "^7.0.3" - globals "^9.14.0" - ignore "^3.2.0" - imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" - is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" - levn "^0.3.0" - lodash "^4.0.0" - mkdirp "^0.5.0" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.7.5" - strip-bom "^3.0.0" - strip-json-comments "~2.0.1" - table "^3.7.8" - text-table "~0.2.0" - user-home "^2.0.0" +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.47.0: +"eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.32.0 || ^8.2.0", "eslint@^7.5.0 || ^8.0.0 || ^9.0.0", eslint@^8.47.0, eslint@>=7.0.0: version "8.57.1" resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz" integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== @@ -5620,6 +5395,47 @@ eslint@^8.47.0: strip-ansi "^6.0.1" text-table "^0.2.0" +eslint@^3.0.0: + version "3.19.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz" + integrity sha512-x6LJGXWCGB/4YOBhL48yeppZTo+YQUNC37N5qqCpC1b1kkNzydlQHQAtPuUSFoZSxgIadrysQoW2Hq602P+uEA== + dependencies: + babel-code-frame "^6.16.0" + chalk "^1.1.3" + concat-stream "^1.5.2" + debug "^2.1.1" + doctrine "^2.0.0" + escope "^3.6.0" + espree "^3.4.0" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.0.3" + globals "^9.14.0" + ignore "^3.2.0" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~2.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + esniff@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz" @@ -5653,9 +5469,7 @@ esprima@^4.0.0, esprima@^4.0.1: integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.0, esquery@^1.4.2: - version "1.7.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d" - integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== + version "1.6.0" dependencies: estraverse "^5.1.0" @@ -5666,7 +5480,12 @@ esrecurse@^4.1.0, esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" -estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^4.2.0: version "4.3.0" resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== @@ -5700,9 +5519,7 @@ event-target-shim@^5.0.0: integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== eventemitter3@^5.0.1: - version "5.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.4.tgz#a86d66170433712dde814707ac52b5271ceb1feb" - integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw== + version "5.0.1" events-to-async@^2.0.2: version "2.0.2" @@ -5716,11 +5533,6 @@ events-universal@^1.0.0: dependencies: bare-events "^2.7.0" -events@1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/events/-/events-1.1.1.tgz" - integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== - events@^3.0.0, events@^3.3.0: version "3.3.0" resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" @@ -5777,12 +5589,10 @@ express-session@^1.19.0: uid-safe "~2.1.5" express-validator@^7.0.1: - version "7.3.2" - resolved "https://registry.yarnpkg.com/express-validator/-/express-validator-7.3.2.tgz#7b322847efc81f9cf76f9a42c10de29b80536e9b" - integrity sha512-ctLw1Vl6dXVH62dIQMDdTAQkrh480mkFuG6/SGXOaVlwPNukhRAe7EgJIMJ2TSAni8iwHBRp530zAZE5ZPF2IA== + version "7.3.0" dependencies: - lodash "^4.18.1" - validator "~13.15.23" + lodash "^4.17.21" + validator "~13.15.15" express-ws@^5.0.2: version "5.0.2" @@ -5791,7 +5601,7 @@ express-ws@^5.0.2: dependencies: ws "^7.4.6" -express@^4.22.1: +"express@^4.0.0 || ^5.0.0-alpha.1", express@^4.22.1: version "4.22.1" resolved "https://registry.npmjs.org/express/-/express-4.22.1.tgz" integrity sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g== @@ -5851,7 +5661,7 @@ extract-zip@^2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" -extsprintf@1.3.0, extsprintf@^1.2.0: +extsprintf@^1.2.0, extsprintf@1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== @@ -5896,13 +5706,10 @@ fast-text-encoding@^1.0.0: resolved "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz" integrity sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w== -fast-xml-builder@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz#abd2363145a7625d9789ad96da375fabe3cff28c" - integrity sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q== +fast-xml-parser@^5.0.7: + version "5.3.1" dependencies: - path-expression-matcher "^1.5.0" - xml-naming "^0.1.0" + strnum "^2.1.0" fast-xml-parser@5.2.5: version "5.2.5" @@ -5911,21 +5718,8 @@ fast-xml-parser@5.2.5: dependencies: strnum "^2.1.0" -fast-xml-parser@^5.5.9: - version "5.8.0" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.8.0.tgz#64d71f0f8d4bf23621dffd762aef7e98c1884fc1" - integrity sha512-6bIM7fsJxeo3uXv7OncQYsBAMPJ7V16Slahl/6M98C/i2q+vB1+4a0MtrvYwDFEUrwDSbAmeLDRXsOBwrL7yAg== - dependencies: - "@nodable/entities" "^2.1.0" - fast-xml-builder "^1.2.0" - path-expression-matcher "^1.5.0" - strnum "^2.3.0" - xml-naming "^0.1.0" - fastq@^1.6.0: - version "1.20.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.20.1.tgz#ca750a10dc925bc8b18839fd203e3ef4b3ced675" - integrity sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw== + version "1.19.1" dependencies: reusify "^1.0.4" @@ -5974,16 +5768,14 @@ fill-range@^7.1.1: to-regex-range "^5.0.1" finalhandler@~1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.2.tgz#1ebc2228fc7673aac4a472c310cc05b77d852b88" - integrity sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg== + version "1.3.1" dependencies: debug "2.6.9" encodeurl "~2.0.0" escape-html "~1.0.3" - on-finished "~2.4.1" + on-finished "2.4.1" parseurl "~1.3.3" - statuses "~2.0.2" + statuses "2.0.1" unpipe "~1.0.0" find-babel-config@^2.1.1: @@ -6054,14 +5846,10 @@ flat-cache@^3.0.4: rimraf "^3.0.2" flatted@^3.2.9: - version "3.4.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.2.tgz#f5c23c107f0f37de8dbdf24f13722b3b98d52726" - integrity sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA== + version "3.3.3" -follow-redirects@^1.16.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" - integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== +follow-redirects@^1.15.6: + version "1.15.11" fontkit@^2.0.4: version "2.0.4" @@ -6125,7 +5913,7 @@ forwarded@0.2.0: resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fresh@~0.5.2: +fresh@~0.5.2, fresh@0.5.2: version "0.5.2" resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== @@ -6145,16 +5933,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: - version "2.3.2" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - 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" @@ -6243,10 +6031,8 @@ get-caller-file@^2.0.5: resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-east-asian-width@^1.0.0, get-east-asian-width@^1.3.1, get-east-asian-width@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz#216900f91df11a8b2c198c3e1d93d6c035a776b9" - integrity sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA== +get-east-asian-width@^1.0.0, get-east-asian-width@^1.3.0, get-east-asian-width@^1.3.1: + version "1.4.0" get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: version "1.3.0" @@ -6575,16 +6361,6 @@ html-escaper@^2.0.0: resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -htmlparser2@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-10.1.0.tgz#fe3f2e12c73b6e462d4e10395db9c1119e4d6ae4" - integrity sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ== - dependencies: - domelementtype "^2.3.0" - domhandler "^5.0.3" - domutils "^3.2.2" - entities "^7.0.1" - htmlparser2@^3.9.1: version "3.10.1" resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz" @@ -6597,7 +6373,24 @@ htmlparser2@^3.9.1: inherits "^2.0.1" readable-stream "^3.1.1" -http-errors@~2.0.0, http-errors@~2.0.1: +htmlparser2@^8.0.0: + version "8.0.2" + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + entities "^4.4.0" + +http-errors@~2.0.0, http-errors@2.0.0: + version "2.0.0" + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@~2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz" integrity sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ== @@ -6625,9 +6418,9 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: +https-proxy-agent@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" @@ -6651,23 +6444,21 @@ husky@^9.1.7: resolved "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz" integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== -"iconv-lite@0.4.13 - 0.6.3", iconv-lite@~0.4.24: +iconv-lite@~0.4.24, "iconv-lite@0.4.13 - 0.6.3": version "0.4.24" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" -ieee754@1.1.13, ieee754@^1.1.4: +ieee754@^1.1.13: + version "1.2.1" + +ieee754@^1.1.4, ieee754@1.1.13: version "1.1.13" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz" @@ -6717,7 +6508,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: +inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4, inherits@2, inherits@2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -6755,6 +6546,11 @@ interpret@^1.0.0: resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== +ip-address@^10.0.1: + version "10.1.0" + resolved "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz" + integrity sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q== + "ip-address@5.8.9 - 5.9.4": version "5.9.4" resolved "https://registry.npmjs.org/ip-address/-/ip-address-5.9.4.tgz" @@ -6764,11 +6560,6 @@ interpret@^1.0.0: lodash "^4.17.15" sprintf-js "1.1.2" -ip-address@^10.0.1: - version "10.1.0" - resolved "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz" - integrity sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q== - ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" @@ -6834,7 +6625,7 @@ is-callable@^1.2.7: resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.16.1: +is-core-module@^2.13.0, is-core-module@^2.16.1: version "2.16.1" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz" integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== @@ -6887,7 +6678,7 @@ is-fullwidth-code-point@^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== -is-fullwidth-code-point@^5.0.0, is-fullwidth-code-point@^5.1.0: +is-fullwidth-code-point@^5.0.0: version "5.1.0" resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz" integrity sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ== @@ -7069,12 +6860,7 @@ is@^3.2.1: resolved "https://registry.npmjs.org/is/-/is-3.3.2.tgz" integrity sha512-a2xr4E3s1PjDS8ORcGgXpWx6V+liNs+O3JRD2mb9aeugD7rtkkZ0zgLdYgw0tWsKhsdiezGYptSiMlVazCBTuQ== -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== - -isarray@^1.0.0, isarray@~1.0.0: +isarray@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== @@ -7084,6 +6870,16 @@ isarray@^2.0.5: resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" @@ -7170,10 +6966,8 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -iterator.prototype@^1.1.5: +iterator.prototype@^1.1.4: version "1.1.5" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.5.tgz#12c959a29de32de0aa3bbbb801f4d777066dae39" - integrity sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g== dependencies: define-data-property "^1.1.4" es-object-atoms "^1.0.0" @@ -7401,7 +7195,7 @@ jest-resolve-dependencies@^29.7.0: jest-regex-util "^29.6.3" jest-snapshot "^29.7.0" -jest-resolve@^29.7.0: +jest-resolve@*, jest-resolve@^29.7.0: version "29.7.0" resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz" integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== @@ -7589,30 +7383,26 @@ js-tokens@^3.0.2: integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== js-yaml@^3.13.1, js-yaml@^3.5.1: - version "3.14.2" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0" - integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg== + version "3.14.1" dependencies: argparse "^1.0.7" esprima "^4.0.0" js-yaml@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" - integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== + version "4.1.0" dependencies: argparse "^2.0.1" -jsbn@1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz" - integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz" + integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== + jsesc@^3.0.2, jsesc@~3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz" @@ -7697,12 +7487,10 @@ jsonpointer@^5.0.0: resolved "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz" integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== -jsonwebtoken@^9.0.0, jsonwebtoken@^9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz#6cd57ab01e9b0ac07cb847d53d3c9b6ee31f7ae2" - integrity sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g== +jsonwebtoken@^9.0.0, jsonwebtoken@^9.0.2: + version "9.0.2" dependencies: - jws "^4.0.1" + jws "^3.2.2" lodash.includes "^4.3.0" lodash.isboolean "^3.0.3" lodash.isinteger "^4.0.4" @@ -7733,21 +7521,30 @@ jsprim@^1.2.2: object.assign "^4.1.4" object.values "^1.1.6" -jwa@^2.0.1: +jwa@^1.4.1: + version "1.4.2" + dependencies: + buffer-equal-constant-time "^1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jwa@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.1.tgz#bf8176d1ad0cd72e0f3f58338595a13e110bc804" - integrity sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg== dependencies: buffer-equal-constant-time "^1.0.1" ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" -jws@^4.0.0, jws@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.1.tgz#07edc1be8fac20e677b283ece261498bd38f0690" - integrity sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA== +jws@^3.2.2: + version "3.2.2" + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +jws@^4.0.0: + version "4.0.0" dependencies: - jwa "^2.0.1" + jwa "^2.0.0" safe-buffer "^5.0.1" kareem@2.3.2: @@ -7784,13 +7581,6 @@ language-tags@^1.0.9: dependencies: language-subtag-registry "^0.3.20" -launder@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/launder/-/launder-1.7.1.tgz#ef7155ab0c3ddec2323089c961d2e9a249aa5b0d" - integrity sha512-mU6WRz5EusL9ZZuiZ5SO4Y6C0P9PAUR9iwdb6bzj4KDihm28DiHFw+/yk9DBH4f+Pv1wuzQ4e2jV3oQ7mkIqvw== - dependencies: - dayjs "^1.11.7" - lazy@1.0.11: version "1.0.11" resolved "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz" @@ -7838,16 +7628,15 @@ lines-and-columns@^1.1.6: integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== lint-staged@^16.2.6: - version "16.4.0" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-16.4.0.tgz#a00b0e3abff59239cef6d7d9341e8f8473308e23" - integrity sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw== + version "16.2.6" dependencies: - commander "^14.0.3" + commander "^14.0.1" listr2 "^9.0.5" - picomatch "^4.0.3" + micromatch "^4.0.8" + nano-spawn "^2.0.0" + pidtree "^0.6.0" string-argv "^0.3.2" - tinyexec "^1.0.4" - yaml "^2.8.2" + yaml "^2.8.1" listr2@^9.0.5: version "9.0.5" @@ -8156,11 +7945,6 @@ lru-cache@^7.14.1: resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== -luxon@^1.23.x: - version "1.28.1" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.1.tgz#528cdf3624a54506d710290a2341aa8e6e6c61b0" - integrity sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw== - luxon@^3.2.1: version "3.7.2" resolved "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz" @@ -8260,16 +8044,16 @@ micromatch@^4.0.4: braces "^3.0.3" picomatch "^2.3.1" -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - "mime-db@>= 1.43.0 < 2": version "1.54.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz" integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" @@ -8277,7 +8061,7 @@ mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: dependencies: mime-db "1.52.0" -mime@1.6.0, mime@^1.3.4: +mime@^1.3.4, mime@1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== @@ -8297,24 +8081,13 @@ mimic-function@^5.0.0: resolved "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz" integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== -minimatch@^10.2.1: - version "10.2.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.5.tgz#bd48687a0be38ed2961399105600f832095861d1" - integrity sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg== - dependencies: - brace-expansion "^5.0.5" - minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" - integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== + version "3.1.2" dependencies: brace-expansion "^1.1.7" minimatch@^8.0.2: - version "8.0.7" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.7.tgz#954766e22da88a3e0a17ad93b58c15c9d8a579de" - integrity sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg== + version "8.0.4" dependencies: brace-expansion "^2.0.1" @@ -8329,28 +8102,38 @@ minipass@^4.2.4: integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== "minipass@^5.0.0 || ^6.0.2 || ^7.0.0": - version "7.1.3" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b" - integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A== + version "7.1.2" mitt@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz" integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== -mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.6: +mkdirp@^0.5.0: + version "0.5.6" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: minimist "^1.2.6" +mkdirp@^0.5.6: + version "0.5.6" + dependencies: + minimist "^1.2.6" + mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -moment-timezone@^0.5.35: +moment-timezone@^0.5.35, moment-timezone@^0.5.x: version "0.5.48" resolved "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz" integrity sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw== @@ -8394,7 +8177,7 @@ mongodb-memory-server@^7.6.3: mongodb-memory-server-core "7.6.3" tslib "^2.3.0" -mongodb@3.7.4, mongodb@^3.7.3: +mongodb@^3.7.3, mongodb@3.7.4: version "3.7.4" resolved "https://registry.npmjs.org/mongodb/-/mongodb-3.7.4.tgz" integrity sha512-K5q8aBqEXMwWdVNh94UQTwZ6BejVbFhh1uB6c5FKtPE9eUMZPUO3sRZdgIEcHSrAWmxzpG/FeODDKL388sqRmw== @@ -8420,7 +8203,7 @@ mongoose-validator@^2.1.0: is "^3.2.1" validator "^10.4.0" -mongoose@^5.13.23: +mongoose@*, mongoose@^5.13.23: version "5.13.23" resolved "https://registry.npmjs.org/mongoose/-/mongoose-5.13.23.tgz" integrity sha512-Q5bo1yYOcH2wbBPP4tGmcY5VKsFkQcjUDh66YjrbneAFB3vNKQwLvteRFLuLiU17rA5SDl3UMcMJLD9VS8ng2Q== @@ -8456,6 +8239,11 @@ mquery@3.2.5: safe-buffer "5.1.2" sliced "1.0.1" +ms@^2.1.1, ms@^2.1.3, ms@2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + ms@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" @@ -8466,11 +8254,6 @@ ms@2.1.2: resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1, ms@^2.1.3: - version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - multer@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz" @@ -8501,6 +8284,9 @@ mute-stream@0.0.5: resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz" integrity sha512-EbrziT4s8cWPmzr47eYVW3wimS4HsvlnV5ri1xw1aR6JQo/OrJX5rkl32K/QQHdxeabJETtfeaROGhd8W7uBgg== +nano-spawn@^2.0.0: + version "2.0.0" + nanoid@^3.3.11: version "3.3.11" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz" @@ -8511,16 +8297,16 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - negotiator@~0.6.4: version "0.6.4" resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz" integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + netmask@^2.0.2: version "2.1.1" resolved "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz" @@ -8575,16 +8361,6 @@ node-environment-flags@^1.0.5: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" -node-exports-info@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/node-exports-info/-/node-exports-info-1.6.0.tgz#1aedafb01a966059c9a5e791a94a94d93f5c2a13" - integrity sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw== - dependencies: - array.prototype.flatmap "^1.3.3" - es-errors "^1.3.0" - object.entries "^1.1.9" - semver "^6.3.1" - node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" @@ -8593,19 +8369,15 @@ node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.7.0: whatwg-url "^5.0.0" node-forge@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.4.0.tgz#1c7b7d8bdc2d078739f58287d589d903a11b2fc2" - integrity sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ== + version "1.3.1" node-int64@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.36: - version "2.0.44" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.44.tgz#212c9b983f5bb70d311dd68c27d55dd0e65d1ca7" - integrity sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ== +node-releases@^2.0.26: + version "2.0.27" node-schedule@^2.1.1: version "2.1.1" @@ -8622,14 +8394,12 @@ nodemailer@^7.0.11: integrity sha512-gnXhNRE0FNhD7wPSCGhdNh46Hs6nm+uTyg+Kq0cZukNQiYdnCsoQjodNP9BQVG9XrcK/v6/MgpAPBUFyzh9pvw== nodemon@^3.0.1: - version "3.1.14" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.14.tgz#8487ca379c515301d221ec007f27f24ecafa2b51" - integrity sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw== + version "3.1.10" dependencies: chokidar "^3.5.2" debug "^4" ignore-by-default "^1.0.1" - minimatch "^10.2.1" + minimatch "^3.1.2" pstree.remy "^1.1.8" semver "^7.5.3" simple-update-notifier "^2.0.0" @@ -8724,17 +8494,15 @@ object.fromentries@^2.0.8: es-object-atoms "^1.0.0" object.getownpropertydescriptors@^2.0.3: - version "2.1.9" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.9.tgz#bf9e7520f14d50de88dee2b9c9eca841166322dc" - integrity sha512-mt8YM6XwsTTovI+kdZdHSxoyF2DI59up034orlC9NfweclcWOt7CVascNNLp6U+bjFVCVCIh9PwS76tDM/rH8g== + version "2.1.8" dependencies: - array.prototype.reduce "^1.0.8" - call-bind "^1.0.8" + array.prototype.reduce "^1.0.6" + call-bind "^1.0.7" define-properties "^1.2.1" - es-abstract "^1.24.0" - es-object-atoms "^1.1.1" - gopd "^1.2.0" - safe-array-concat "^1.1.3" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + gopd "^1.0.1" + safe-array-concat "^1.1.2" object.groupby@^1.0.3: version "1.0.3" @@ -8755,7 +8523,7 @@ object.values@^1.1.6, object.values@^1.2.1: define-properties "^1.2.1" es-object-atoms "^1.0.0" -on-finished@~2.4.1: +on-finished@~2.4.1, on-finished@2.4.1: version "2.4.1" resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== @@ -8793,11 +8561,6 @@ onetime@^7.0.0: dependencies: mimic-function "^5.0.0" -optional-require@1.0.x: - version "1.0.3" - resolved "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz" - integrity sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA== - optional-require@^1.1.8: version "1.1.10" resolved "https://registry.npmjs.org/optional-require/-/optional-require-1.1.10.tgz" @@ -8805,6 +8568,11 @@ optional-require@^1.1.8: dependencies: require-at "^1.0.6" +optional-require@1.0.x: + version "1.0.3" + resolved "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz" + integrity sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA== + optionator@^0.8.2: version "0.8.3" resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz" @@ -8969,11 +8737,6 @@ path-exists@^4.0.0: resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-expression-matcher@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz#3b98545dc88ffebb593e2d8458d0929da9275f4a" - integrity sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ== - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" @@ -9003,9 +8766,7 @@ path-scurry@^1.6.1: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-to-regexp@~0.1.12: - version "0.1.13" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.13.tgz#9b22ec16bc3ab88d05a0c7e369869421401ab17d" - integrity sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA== + version "0.1.12" pdfkit@^0.17.2: version "0.17.2" @@ -9034,14 +8795,7 @@ picocolors@^1.1.1: integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601" - integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== - -picomatch@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589" - integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== + version "2.3.1" pidtree@^0.6.0: version "0.6.0" @@ -9065,7 +8819,14 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" -pkg-dir@^4.1.0, pkg-dir@^4.2.0: +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== @@ -9109,9 +8870,7 @@ possible-typed-array-names@^1.0.0: integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== postcss@^8.3.11: - version "8.5.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.14.tgz#a66c2d7808fadf69ebb5b84a03f8bafd76c4919c" - integrity sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg== + version "8.5.6" dependencies: nanoid "^3.3.11" picocolors "^1.1.1" @@ -9215,11 +8974,6 @@ proxy-from-env@^1.1.0: resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -proxy-from-env@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba" - integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA== - psl@^1.1.28: version "1.15.0" resolved "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz" @@ -9240,60 +8994,53 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -puppeteer-core@24.43.1: - version "24.43.1" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-24.43.1.tgz#c10a5d398b69911c324e04c85ee2b236b9ec940e" - integrity sha512-T5ScUMAsmhdNbgDR41AGESYeS6V9MSgetkSnVhhW+gXvzC42VesKCn5ld87gAZDJ6vLHL9GkRvY9WtQWSnwFbw== +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== + +puppeteer-core@24.40.0: + version "24.40.0" + resolved "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.40.0.tgz" + integrity sha512-MWL3XbUCfVgGR0gRsidzT6oKJT2QydPLhMITU6HoVWiiv4gkb6gJi3pcdAa8q4HwjBTbqISOWVP4aJiiyUJvag== dependencies: - "@puppeteer/browsers" "2.13.2" + "@puppeteer/browsers" "2.13.0" chromium-bidi "14.0.0" debug "^4.4.3" - devtools-protocol "0.0.1608973" - typed-query-selector "^2.12.2" + devtools-protocol "0.0.1581282" + typed-query-selector "^2.12.1" webdriver-bidi-protocol "0.4.1" - ws "^8.20.0" + ws "^8.19.0" -puppeteer@^24.41.0: - version "24.43.1" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-24.43.1.tgz#86cad9170ce2dec2db3b8d1d34c0c91424bbe3e3" - integrity sha512-/FSOViCrqRdb1HDocpsM9Z1giA71gTQPUt3SpHGVRALKAy/rJr1fLFYZW9F23qPxqVxTHQnbh/5B5opJST3kAw== +puppeteer@^24.40.0: + version "24.40.0" + resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-24.40.0.tgz" + integrity sha512-IxQbDq93XHVVLWHrAkFP7F7iHvb9o0mgfsSIMlhHb+JM+JjM1V4v4MNSQfcRWJopx9dsNOr9adYv0U5fm9BJBQ== dependencies: - "@puppeteer/browsers" "2.13.2" + "@puppeteer/browsers" "2.13.0" chromium-bidi "14.0.0" cosmiconfig "^9.0.0" - devtools-protocol "0.0.1608973" - puppeteer-core "24.43.1" - typed-query-selector "^2.12.2" + devtools-protocol "0.0.1581282" + puppeteer-core "24.40.0" + typed-query-selector "^2.12.1" pure-rand@^6.0.0: version "6.1.0" resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz" integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== -qs@^6.11.0, qs@^6.7.0, qs@~6.14.0: +qs@^6.11.0, qs@^6.7.0, qs@^6.9.4, qs@~6.14.0: version "6.14.2" resolved "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz" integrity sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q== dependencies: side-channel "^1.1.0" -qs@^6.14.1: - version "6.15.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.1.tgz#bdb55aed06bfac257a90c44a446a73fba5575c8f" - integrity sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg== - dependencies: - side-channel "^1.1.0" - qs@~6.5.2: version "6.5.5" resolved "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz" @@ -9344,7 +9091,33 @@ react-is@^18.0.0: resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== -readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@^2.3.5, readable-stream@~2.3.6: +readable-stream@^2.0.2: + version "2.3.8" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^2.2.2: + version "2.3.8" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^2.3.5: version "2.3.8" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -9376,6 +9149,19 @@ readable-stream@~1.1.9: isarray "0.0.1" string_decoder "~0.10.x" +readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" @@ -9383,6 +9169,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +readline@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz" + integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== + readline2@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz" @@ -9392,11 +9183,6 @@ readline2@^1.0.1: is-fullwidth-code-point "^1.0.0" mute-stream "0.0.5" -readline@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz" - integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" @@ -9447,7 +9233,7 @@ regenerator-runtime@^0.14.0: resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== -regexp-clone@1.0.0, regexp-clone@^1.0.0: +regexp-clone@^1.0.0, regexp-clone@1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz" integrity sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw== @@ -9482,9 +9268,7 @@ regjsgen@^0.8.0: integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== regjsparser@^0.13.0: - version "0.13.1" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.13.1.tgz#0593cbacb27527927692030928ae4d3b878d6f8d" - integrity sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw== + version "0.13.0" dependencies: jsesc "~3.1.0" @@ -9574,25 +9358,17 @@ resolve.exports@^2.0.0: resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz" integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== -resolve@^1.1.6, resolve@^1.20.0, resolve@^1.22.11, resolve@^1.22.8: - version "1.22.12" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.12.tgz#f5b2a680897c69c238a13cd16b15671f8b73549f" - integrity sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA== +resolve@^1.1.6, resolve@^1.20.0, resolve@^1.22.10, resolve@^1.22.4, resolve@^1.22.8: + version "1.22.11" dependencies: - es-errors "^1.3.0" is-core-module "^2.16.1" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^2.0.0-next.5, resolve@^2.0.0-next.6: - version "2.0.0-next.6" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.6.tgz#b3961812be69ace7b3bc35d5bf259434681294af" - integrity sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA== +resolve@^2.0.0-next.5: + version "2.0.0-next.5" dependencies: - es-errors "^1.3.0" - is-core-module "^2.16.1" - node-exports-info "^1.6.0" - object-keys "^1.1.1" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -9627,13 +9403,6 @@ rfdc@^1.4.1: resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz" integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== -"rimraf@2.5.2 - 2.7.1": - version "2.7.1" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" @@ -9648,6 +9417,13 @@ rimraf@~2.6.2: dependencies: glob "^7.1.3" +"rimraf@2.5.2 - 2.7.1": + version "2.7.1" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + run-async@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz" @@ -9667,7 +9443,7 @@ rx-lite@^3.1.2: resolved "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz" integrity sha512-1I1+G2gteLB8Tkt8YI1sJvSIfa0lWuRtC8GjvtyPBcLSF5jBCCJJqKrpER5JU5r6Bhe+i9/pK3VMuUcXu0kdwQ== -safe-array-concat@^1.1.3: +safe-array-concat@^1.1.2, safe-array-concat@^1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz" integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== @@ -9678,15 +9454,20 @@ safe-array-concat@^1.1.3: has-symbols "^1.1.0" isarray "^2.0.5" -safe-buffer@5.1.2, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0, safe-buffer@~5.2.1, safe-buffer@5.2.1: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0, safe-buffer@~5.2.1: - version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-buffer@5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-push-apply@^1.0.0: version "1.0.0" @@ -9705,21 +9486,18 @@ safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: es-errors "^1.3.0" is-regex "^1.2.1" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +safer-buffer@^2.0.2, safer-buffer@^2.1.0, "safer-buffer@>= 2.1.2 < 3", safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sanitize-html@^2.16.0: - version "2.17.4" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.17.4.tgz#7db8b73b0024ccf543978c2a44da8223c4740cb1" - integrity sha512-2HW7v2ol/uAM7sX4hbD8Z59OGWmAPrvjL8E71UWlBcj6m+kcF6ilQBLny+cIgY214QJeJT5tQuxKKqX0SQqjGQ== + version "2.17.0" dependencies: deepmerge "^4.2.2" escape-string-regexp "^4.0.0" - htmlparser2 "^10.1.0" + htmlparser2 "^8.0.0" is-plain-object "^5.0.0" - launder "^1.7.1" parse-srcset "^1.0.2" postcss "^8.3.11" @@ -9730,7 +9508,7 @@ saslprep@^1.0.0: dependencies: sparse-bitfield "^3.0.3" -sax@1.2.1, sax@1.2.x, sax@>=0.6.0: +sax@>=0.6.0, sax@1.2.1, sax@1.2.x: version "1.2.1" resolved "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz" integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== @@ -9745,49 +9523,65 @@ semver@^5.6.0, semver@^5.7.0: resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: +semver@^5.7.0: + version "5.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.0.0: version "6.3.1" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.7.3: - version "7.8.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.0.tgz#ed0661039fcbcda2ce71f01fa6adbefaa77040df" - integrity sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA== +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5: + version "7.7.3" + +semver@^7.3.8: + version "7.7.3" + +semver@^7.5.3: + version "7.7.3" + +semver@^7.5.4: + version "7.7.3" + +semver@^7.7.3: + version "7.7.3" semver@^7.7.4: version "7.7.4" resolved "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz" integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== -send@~0.19.0, send@~0.19.1: - version "0.19.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.19.2.tgz#59bc0da1b4ea7ad42736fd642b1c4294e114ff29" - integrity sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg== +send@~0.19.0, send@0.19.0: + version "0.19.0" dependencies: debug "2.6.9" depd "2.0.0" destroy "1.2.0" - encodeurl "~2.0.0" + encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - fresh "~0.5.2" - http-errors "~2.0.1" + fresh "0.5.2" + http-errors "2.0.0" mime "1.6.0" ms "2.1.3" - on-finished "~2.4.1" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~2.0.2" + statuses "2.0.1" serve-static@~1.16.2: - version "1.16.3" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.3.tgz#a97b74d955778583f3862a4f0b841eb4d5d78cf9" - integrity sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA== + version "1.16.2" dependencies: encodeurl "~2.0.0" escape-html "~1.0.3" parseurl "~1.3.3" - send "~0.19.1" + send "0.19.0" set-function-length@^1.2.2: version "1.2.2" @@ -9820,7 +9614,7 @@ set-proto@^1.0.0: es-errors "^1.3.0" es-object-atoms "^1.0.0" -setprototypeof@1.2.0, setprototypeof@~1.2.0: +setprototypeof@~1.2.0, setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== @@ -9888,12 +9682,10 @@ shelljs@^0.7.5: rechoir "^0.6.2" side-channel-list@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.1.tgz#c2e0b5a14a540aebee3bbc6c3f8666cc9b509127" - integrity sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w== + version "1.0.0" dependencies: es-errors "^1.3.0" - object-inspect "^1.13.4" + object-inspect "^1.13.3" side-channel-map@^1.0.1: version "1.0.1" @@ -9964,11 +9756,6 @@ slash@^3.0.0: resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz" - integrity sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw== - slice-ansi@^7.1.0: version "7.1.2" resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz" @@ -9977,13 +9764,10 @@ slice-ansi@^7.1.0: ansi-styles "^6.2.1" is-fullwidth-code-point "^5.0.0" -slice-ansi@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-8.0.0.tgz#22d0b66d18bc5c57f488bfcf36cbde3bef731537" - integrity sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg== - dependencies: - ansi-styles "^6.2.3" - is-fullwidth-code-point "^5.1.0" +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz" + integrity sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw== sliced@1.0.1: version "1.0.1" @@ -9996,30 +9780,24 @@ smart-buffer@^4.2.0: integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== socket.io-adapter@~2.5.2: - version "2.5.6" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz#c697f609d36a676a46749782274607d8df52c1d8" - integrity sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ== + version "2.5.5" dependencies: - debug "~4.4.1" - ws "~8.18.3" + debug "~4.3.4" + ws "~8.17.1" socket.io-parser@~4.2.4: - version "4.2.6" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.6.tgz#19156bf179af3931abd05260cfb1491822578a6f" - integrity sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg== + version "4.2.4" dependencies: "@socket.io/component-emitter" "~3.1.0" - debug "~4.4.1" + debug "~4.3.1" socket.io@^4.8.1: - version "4.8.3" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.8.3.tgz#ca6ba1431c69532e1e0a6f496deebeb601dbc4df" - integrity sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A== + version "4.8.1" dependencies: accepts "~1.3.4" base64id "~2.0.0" cors "~2.8.5" - debug "~4.4.1" + debug "~4.3.2" engine.io "~6.6.0" socket.io-adapter "~2.5.2" socket.io-parser "~4.2.4" @@ -10051,14 +9829,6 @@ source-map-js@^1.2.1: resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@^0.5.16: version "0.5.21" resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" @@ -10067,6 +9837,14 @@ source-map-support@^0.5.16: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" @@ -10084,16 +9862,16 @@ sparse-bitfield@^3.0.3: dependencies: memory-pager "^1.0.2" -sprintf-js@1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz" - integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +sprintf-js@1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz" + integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== + sshpk@^1.7.0: version "1.18.0" resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz" @@ -10116,7 +9894,10 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" -statuses@~2.0.1, statuses@~2.0.2: +statuses@~2.0.1, statuses@2.0.1: + version "2.0.1" + +statuses@~2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz" integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== @@ -10153,6 +9934,25 @@ strict-event-emitter@^0.5.1: resolved "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz" integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + string-argv@^0.3.2: version "0.3.2" resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz" @@ -10183,7 +9983,16 @@ string-width@^2.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -10201,13 +10010,11 @@ string-width@^7.0.0: get-east-asian-width "^1.0.0" strip-ansi "^7.1.0" -string-width@^8.2.0: - version "8.2.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-8.2.1.tgz#165089cfa527cc88fbc23dd73313f5e334af1ea1" - integrity sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA== +string-width@^8.0.0: + version "8.1.0" dependencies: - get-east-asian-width "^1.5.0" - strip-ansi "^7.1.2" + get-east-asian-width "^1.3.0" + strip-ansi "^7.1.0" string.prototype.includes@^2.0.1: version "2.0.1" @@ -10277,25 +10084,6 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" @@ -10317,12 +10105,10 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.1.0, strip-ansi@^7.1.2: - version "7.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.2.0.tgz#d22a269522836a627af8d04b5c3fd2c7fa3e32e3" - integrity sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w== +strip-ansi@^7.1.0: + version "7.1.2" dependencies: - ansi-regex "^6.2.2" + ansi-regex "^6.0.1" strip-bom@^3.0.0: version "3.0.0" @@ -10349,10 +10135,8 @@ strip-json-comments@~2.0.1: resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== -strnum@^2.1.0, strnum@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.3.0.tgz#81bfbfef53db8c3217ea62a98c026886ec4a2761" - integrity sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q== +strnum@^2.1.0: + version "2.1.1" superagent@^8.1.2: version "8.1.2" @@ -10488,6 +10272,11 @@ text-table@^0.2.0, text-table@~0.2.0: resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +through@^2.3.6: + version "2.3.8" + resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + through2@^2.0.0: version "2.0.5" resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" @@ -10496,11 +10285,6 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through@^2.3.6: - version "2.3.8" - resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - time-stamp@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz" @@ -10516,11 +10300,6 @@ tiny-warning@^1.0.3: resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== -tinyexec@^1.0.4: - version "1.1.2" - resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.1.2.tgz#11feef204b706d4668ca4013db29f3bd64f5c4dc" - integrity sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA== - tlds@^1.234.0: version "1.261.0" resolved "https://registry.npmjs.org/tlds/-/tlds-1.261.0.tgz" @@ -10543,7 +10322,7 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -toidentifier@~1.0.1: +toidentifier@~1.0.1, toidentifier@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== @@ -10581,7 +10360,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@2.8.1, tslib@^2.0.1, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.8.0, tslib@^2.8.1: +tslib@^2.0.1, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.8.0, tslib@^2.8.1, tslib@2.8.1: version "2.8.1" resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -10599,15 +10378,13 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== twilio@^5.10.2: - version "5.13.1" - resolved "https://registry.yarnpkg.com/twilio/-/twilio-5.13.1.tgz#ecfdad46644b58045b6d47cf973bd0124c632c4f" - integrity sha512-sT+PkhptF4Mf7t8eXFFvPQx4w5VHnBIPXbltGPMFRe+R2GxfRdMuFbuNA/cEm0aQR6LFQOn33+fhClg+TjRVqQ== + version "5.10.4" dependencies: - axios "^1.13.5" + axios "^1.12.0" dayjs "^1.11.9" https-proxy-agent "^5.0.0" - jsonwebtoken "^9.0.3" - qs "^6.14.1" + jsonwebtoken "^9.0.2" + qs "^6.9.4" scmp "^2.1.0" xmlbuilder "^13.0.2" @@ -10698,10 +10475,10 @@ typed-array-length@^1.0.7: possible-typed-array-names "^1.0.0" reflect.getprototypeof "^1.0.6" -typed-query-selector@^2.12.2: - version "2.12.2" - resolved "https://registry.yarnpkg.com/typed-query-selector/-/typed-query-selector-2.12.2.tgz#65e2462ac6b0aecfae1bfac1a4f3027070dbabaa" - integrity sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ== +typed-query-selector@^2.12.1: + version "2.12.1" + resolved "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.1.tgz" + integrity sha512-uzR+FzI8qrUEIu96oaeBJmd9E7CFEiQ3goA5qCVgc4s5llSubcfGHq9yUstZx/k4s9dXHVKsE35YWoFyvEqEHA== typedarray@^0.0.6: version "0.0.6" @@ -10737,10 +10514,8 @@ undefsafe@^2.0.5: resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz" integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== -undici-types@~7.21.0: - version "7.21.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.21.0.tgz#433f7dd1b5daa9ab4dacb721a5e11a8de51eadda" - integrity sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ== +undici-types@~7.16.0: + version "7.16.0" unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.1" @@ -10791,10 +10566,8 @@ unpipe@~1.0.0: resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-browserslist-db@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" - integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== +update-browserslist-db@^1.1.4: + version "1.1.4" dependencies: escalade "^3.2.0" picocolors "^1.1.1" @@ -10847,21 +10620,31 @@ utils-merge@1.0.1: resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== +uuid@^3.3.2, uuid@^3.4.0: + version "3.4.0" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.0.0: + version "8.3.2" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +uuid@^8.3.1: + version "8.3.2" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + uuid@8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz" integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== -uuid@8.3.2, uuid@^8.0.0, uuid@^8.3.1: +uuid@8.3.2: version "8.3.2" resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -uuid@^3.3.2, uuid@^3.4.0: - version "3.4.0" - resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - v8-to-istanbul@^9.0.1: version "9.3.0" resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz" @@ -10883,10 +10666,8 @@ validator@^10.4.0: resolved "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz" integrity sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw== -validator@~13.15.23: - version "13.15.35" - resolved "https://registry.yarnpkg.com/validator/-/validator-13.15.35.tgz#81cf455c51f15b69d8d340be5914f3fab00dbf7f" - integrity sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw== +validator@~13.15.15: + version "13.15.20" vary@^1, vary@~1.1.2: version "1.1.2" @@ -10982,9 +10763,7 @@ which-collection@^1.0.2: is-weakset "^2.0.3" which-typed-array@^1.1.16, which-typed-array@^1.1.19, which-typed-array@^1.1.2: - version "1.1.20" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.20.tgz#3fdb7adfafe0ea69157b1509f3a1cd892bd1d122" - integrity sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg== + version "1.1.19" dependencies: available-typed-arrays "^1.0.7" call-bind "^1.0.8" @@ -11044,30 +10823,18 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" -ws@^7.4.6: - version "7.5.10" - resolved "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== - -ws@^8.17.1, ws@^8.18.3: +ws@*, ws@^8.17.1, ws@^8.18.3, ws@^8.19.0: version "8.19.0" resolved "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz" integrity sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg== -ws@^8.20.0: - version "8.20.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.20.1.tgz#91a9ae2b312ccf98e0a85ec499b48cef45ab0ddb" - integrity sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w== - -ws@~8.18.3: - version "8.18.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" - integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== +ws@^7.4.6: + version "7.5.10" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== -xml-naming@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/xml-naming/-/xml-naming-0.1.0.tgz#8ab7106c5b8d23caa2fabac1cadf17136379fbd8" - integrity sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw== +ws@~8.17.1: + version "8.17.1" xml2js@0.6.2: version "0.6.2" @@ -11077,11 +10844,6 @@ xml2js@0.6.2: sax ">=0.6.0" xmlbuilder "~11.0.0" -xmlbuilder@8.2.x: - version "8.2.2" - resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz" - integrity sha512-eKRAFz04jghooy8muekqzo8uCSVNeyRedbuJrp0fovbLIi7wlsYtdUn3vBAAPq2Y3/0xMz2WMEUQ8yhVVO9Stw== - xmlbuilder@^13.0.2: version "13.0.2" resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz" @@ -11092,6 +10854,11 @@ xmlbuilder@~11.0.0: resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== +xmlbuilder@8.2.x: + version "8.2.2" + resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz" + integrity sha512-eKRAFz04jghooy8muekqzo8uCSVNeyRedbuJrp0fovbLIi7wlsYtdUn3vBAAPq2Y3/0xMz2WMEUQ8yhVVO9Stw== + xmlrpc@^1.3.2: version "1.3.2" resolved "https://registry.npmjs.org/xmlrpc/-/xmlrpc-1.3.2.tgz" @@ -11110,20 +10877,23 @@ y18n@^5.0.5: resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@4.0.0, yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - yallist@^3.0.2: version "3.1.1" resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yaml@^2.8.2: - version "2.9.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.9.0.tgz#78274afd93598a1dfdd6130df6a566defcbf9aa4" - integrity sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yallist@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^2.8.1: + version "2.8.1" yargs-parser@^21.1.1: version "21.1.1" @@ -11143,7 +10913,7 @@ yargs@^17.3.1, yargs@^17.7.2: y18n "^5.0.5" yargs-parser "^21.1.1" -"yauzl@2.9.2 - 2.10.0", yauzl@^2.10.0: +yauzl@^2.10.0, "yauzl@2.9.2 - 2.10.0": version "2.10.0" resolved "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz" integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== @@ -11156,7 +10926,12 @@ yocto-queue@^0.1.0: resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zod@^3.23.8, zod@^3.24.1: +zod@^3.23.8: + version "3.25.76" + resolved "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz" + integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== + +zod@^3.24.1: version "3.25.76" resolved "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz" integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==