diff --git a/__tests__/ComprehensiveController.test.js b/__tests__/ComprehensiveController.test.js
deleted file mode 100644
index 484fb65..0000000
--- a/__tests__/ComprehensiveController.test.js
+++ /dev/null
@@ -1,173 +0,0 @@
-const { createFinancialReport } = require('../controllers/financialReportingController');
-const FinancialReport = require('../models/financialReport');
-const httpMocks = require('node-mocks-http');
-const mongoose = require('mongoose');
-
-// Mock the entire model
-jest.mock('../models/financialReport');
-
-describe('createFinancialReport Controller', () => {
- let req, res, next;
-
- beforeEach(() => {
- req = httpMocks.createRequest();
- res = httpMocks.createResponse();
- next = jest.fn();
- jest.clearAllMocks();
- });
-
- const validTestData = {
- ReportID: 'test-id',
- Type: 'Annual',
- Data: {
- revenue: { q1: 250000, q2: 250000, q3: 250000, q4: 250000 },
- expenses: { q1: 125000, q2: 125000, q3: 125000, q4: 125000 }
- },
- TotalRevenue: '1000000.00',
- TotalExpenses: '500000.00',
- NetIncome: '500000.00',
- EquitySummary: ['uuid1', 'uuid2'],
- Timestamp: new Date().toISOString()
- };
-
- describe('Successful Operations', () => {
- it('should create a new financial report and return 201 status', async () => {
- req.body = validTestData;
- const mockSave = jest.fn().mockResolvedValue(validTestData);
- FinancialReport.mockImplementation(() => ({ save: mockSave }));
-
- await createFinancialReport(req, res, next);
-
- const responseData = JSON.parse(res._getData());
- expect(FinancialReport).toHaveBeenCalledWith(validTestData);
- expect(mockSave).toHaveBeenCalled();
- expect(res.statusCode).toBe(201);
- expect(responseData).toEqual(validTestData);
- expect(next).not.toHaveBeenCalled();
- });
-
- it('should handle quarterly reports correctly', async () => {
- const quarterlyData = { ...validTestData, Type: 'Quarterly' };
- req.body = quarterlyData;
- const mockSave = jest.fn().mockResolvedValue(quarterlyData);
- FinancialReport.mockImplementation(() => ({ save: mockSave }));
-
- await createFinancialReport(req, res, next);
-
- expect(res.statusCode).toBe(201);
- expect(JSON.parse(res._getData())).toEqual(quarterlyData);
- });
- });
-
- describe('Validation Errors', () => {
- it('should handle invalid report type', async () => {
- const invalidData = { ...validTestData, Type: 'Monthly' };
- req.body = invalidData;
-
- const validationError = new mongoose.Error.ValidationError();
- validationError.errors.Type = new mongoose.Error.ValidatorError({
- message: 'Invalid report type. Must be either Annual or Quarterly',
- path: 'Type'
- });
-
- const mockSave = jest.fn().mockRejectedValue(validationError);
- FinancialReport.mockImplementation(() => ({ save: mockSave }));
-
- await createFinancialReport(req, res, next);
-
- expect(next).toHaveBeenCalledWith(expect.objectContaining({
- name: 'ValidationError'
- }));
- });
-
- it('should handle missing required fields', async () => {
- const { TotalRevenue, ...incompleteData } = validTestData;
- req.body = incompleteData;
-
- const validationError = new mongoose.Error.ValidationError();
- validationError.errors.TotalRevenue = new mongoose.Error.ValidatorError({
- message: 'TotalRevenue is required',
- path: 'TotalRevenue'
- });
-
- const mockSave = jest.fn().mockRejectedValue(validationError);
- FinancialReport.mockImplementation(() => ({ save: mockSave }));
-
- await createFinancialReport(req, res, next);
-
- expect(next).toHaveBeenCalledWith(expect.objectContaining({
- name: 'ValidationError'
- }));
- });
- });
-
- describe('Data Integrity', () => {
- it('should handle duplicate ReportID', async () => {
- req.body = validTestData;
-
- // Create a duplicate key error that matches Mongoose's error structure
- const duplicateError = new Error('E11000 duplicate key error');
- duplicateError.code = 11000;
- duplicateError.index = 0;
- duplicateError.keyPattern = { ReportID: 1 };
- duplicateError.keyValue = { ReportID: validTestData.ReportID };
-
- const mockSave = jest.fn().mockRejectedValue(duplicateError);
- FinancialReport.mockImplementation(() => ({ save: mockSave }));
-
- await createFinancialReport(req, res, next);
-
- expect(next).toHaveBeenCalledWith(expect.objectContaining({
- code: 11000,
- keyPattern: { ReportID: 1 },
- keyValue: { ReportID: validTestData.ReportID }
- }));
- });
-
- it('should verify financial calculations', async () => {
- const invalidCalculations = {
- ...validTestData,
- TotalRevenue: '1000000.00',
- TotalExpenses: '500000.00',
- NetIncome: '400000.00' // Incorrect net income
- };
- req.body = invalidCalculations;
-
- const validationError = new Error('Net income does not match revenue minus expenses');
- const mockSave = jest.fn().mockRejectedValue(validationError);
- FinancialReport.mockImplementation(() => ({ save: mockSave }));
-
- await createFinancialReport(req, res, next);
-
- expect(next).toHaveBeenCalledWith(expect.objectContaining({
- message: 'Net income does not match revenue minus expenses'
- }));
- });
- });
-
- describe('Error Handling', () => {
- it('should handle database connection errors', async () => {
- req.body = validTestData;
-
- const dbError = new Error('Database connection failed');
- const mockSave = jest.fn().mockRejectedValue(dbError);
- FinancialReport.mockImplementation(() => ({ save: mockSave }));
-
- await createFinancialReport(req, res, next);
-
- expect(next).toHaveBeenCalledWith(dbError);
- });
-
- it('should handle unexpected errors', async () => {
- req.body = validTestData;
-
- const unexpectedError = new Error('Unexpected server error');
- const mockSave = jest.fn().mockRejectedValue(unexpectedError);
- FinancialReport.mockImplementation(() => ({ save: mockSave }));
-
- await createFinancialReport(req, res, next);
-
- expect(next).toHaveBeenCalledWith(unexpectedError);
- });
- });
-});
\ No newline at end of file
diff --git a/__tests__/app.test.js b/__tests__/app.test.js
index 7c9c8be..13c7144 100644
--- a/__tests__/app.test.js
+++ b/__tests__/app.test.js
@@ -1,20 +1,22 @@
-const { connectDB, disconnectDB } = require('../db');
-const app = require('../app');
+// __tests__/setup/test-app.js
+const express = require('express');
+const mongoose = require('mongoose');
+const financialReportingRoutes = require('../../routes/financialReportingRoutes');
-let server;
+const app = express();
-beforeAll(async () => {
- await connectDB();
- server = app.listen(5001);
-});
+// Middleware
+app.use(express.json());
-afterAll(async () => {
- await server.close();
- await disconnectDB();
-});
+// Routes - match the path from your main app.js
+app.use('/api/financial-reports', financialReportingRoutes);
-describe('App Tests', () => {
- it('should run the server', async () => {
- expect(server).toBeDefined();
+// Error handling middleware - match your main app.js format
+app.use((err, req, res, next) => {
+ console.error('Error:', err.message);
+ res.status(err.statusCode || 500).json({
+ error: err.message || 'Internal Server Error',
});
});
+
+module.exports = app;
\ No newline at end of file
diff --git a/__tests__/backup.test.js b/__tests__/backup.test.js
new file mode 100644
index 0000000..63b437d
--- /dev/null
+++ b/__tests__/backup.test.js
@@ -0,0 +1,187 @@
+const mongoose = require('mongoose');
+const request = require('supertest');
+const { MongoMemoryServer } = require('mongodb-memory-server');
+const app = require('./test-app');
+const FinancialReport = require('../models/financialReport');
+const auth = require('../utils/auth');
+
+describe('Financial Report API Integration', () => {
+ let mongoServer;
+ let adminToken;
+ let testUserId;
+
+ beforeAll(async () => {
+ mongoServer = await MongoMemoryServer.create();
+ const mongoUri = await mongoServer.getUri();
+
+ await mongoose.connect(mongoUri, {
+ useNewUrlParser: true,
+ useUnifiedTopology: true,
+ useCreateIndex: true // Suppresses the ensureIndex deprecation warning
+ });
+
+ testUserId = new mongoose.Types.ObjectId();
+ adminToken = auth.generateToken({
+ id: testUserId.toString(),
+ role: 'admin',
+ permissions: ['create:reports', 'read:reports', 'update:reports', 'delete:reports']
+ });
+ });
+
+ afterAll(async () => {
+ await mongoose.disconnect();
+ await mongoServer.stop();
+ });
+
+ describe('GET /api/financial-reports', () => {
+ beforeEach(async () => {
+ await FinancialReport.deleteMany({});
+ });
+
+ it('should have the correct response structure when empty', async () => {
+ const response = await request(app)
+ .get('/api/financial-reports')
+ .set('Authorization', `Bearer ${adminToken}`)
+ .expect(200);
+
+ expect(response.body).toMatchObject({
+ reports: expect.any(Array),
+ totalCount: 0,
+ currentPage: 1,
+ totalPages: 0,
+ limit: 10
+ });
+ });
+
+ it('should require authentication', async () => {
+ const response = await request(app)
+ .get('/api/financial-reports')
+ .expect(401);
+
+ expect(response.body).toHaveProperty('error');
+ });
+
+ it('should reject invalid token', async () => {
+ const response = await request(app)
+ .get('/api/financial-reports')
+ .set('Authorization', 'Bearer invalid-token')
+ .expect(401);
+
+ expect(response.body).toHaveProperty('error');
+ });
+
+ it('should create and return a quarterly report', async () => {
+ try {
+ const report = new FinancialReport({
+ ReportID: 'TEST-2024-Q1',
+ Type: 'Quarterly',
+ TotalRevenue: 100000,
+ TotalExpenses: 75000,
+ NetIncome: 25000,
+ EquitySummary: ['Initial equity test'],
+ Timestamp: new Date(),
+ userId: testUserId,
+ lastModifiedBy: testUserId
+ });
+
+ report.Data = {
+ revenue: new Map().set('q1', 100000),
+ expenses: new Map().set('q1', 75000)
+ };
+
+ console.log('Pre-save state:', {
+ type: report.Type,
+ data: {
+ revenue: report.Data.revenue instanceof Map ?
+ Array.from(report.Data.revenue.entries()) : report.Data.revenue,
+ expenses: report.Data.expenses instanceof Map ?
+ Array.from(report.Data.expenses.entries()) : report.Data.expenses
+ }
+ });
+
+ await report.save();
+
+ const response = await request(app)
+ .get('/api/financial-reports')
+ .set('Authorization', `Bearer ${adminToken}`)
+ .expect(200);
+
+ expect(response.body.reports).toHaveLength(1);
+ expect(response.body.reports[0]).toMatchObject({
+ ReportID: report.ReportID,
+ Type: report.Type,
+ TotalRevenue: 100000,
+ TotalExpenses: 75000,
+ NetIncome: 25000
+ });
+
+ } catch (error) {
+ console.log('Error details:', error);
+ throw error;
+ }
+ });
+
+ it('should create and return an annual report with full quarterly data', async () => {
+ try {
+ const report = new FinancialReport({
+ ReportID: 'TEST-2024-ANNUAL',
+ Type: 'Annual',
+ TotalRevenue: 400000,
+ TotalExpenses: 300000,
+ NetIncome: 100000,
+ EquitySummary: ['Year-end equity summary'],
+ Timestamp: new Date(),
+ userId: testUserId,
+ lastModifiedBy: testUserId
+ });
+
+ report.Data = {
+ revenue: new Map([['q1', 100000], ['q2', 100000], ['q3', 100000], ['q4', 100000]]),
+ expenses: new Map([['q1', 75000], ['q2', 75000], ['q3', 75000], ['q4', 75000]])
+ };
+
+ await report.save();
+
+ const response = await request(app)
+ .get('/api/financial-reports')
+ .set('Authorization', `Bearer ${adminToken}`)
+ .expect(200);
+
+ expect(response.body.reports).toHaveLength(1);
+ expect(response.body.reports[0]).toMatchObject({
+ ReportID: report.ReportID,
+ Type: report.Type,
+ TotalRevenue: 400000,
+ TotalExpenses: 300000,
+ NetIncome: 100000
+ });
+
+ } catch (error) {
+ console.log('Error details:', error);
+ throw error;
+ }
+ });
+
+ // New test: Verify validation for missing fields in financial report creation
+ it('should not create a report with missing required fields', async () => {
+ const invalidReportData = {
+ Type: 'Quarterly',
+ TotalRevenue: 50000,
+ // Missing TotalExpenses and NetIncome
+ EquitySummary: ['Partial equity summary'],
+ Timestamp: new Date(),
+ userId: testUserId,
+ lastModifiedBy: testUserId
+ };
+
+ const response = await request(app)
+ .post('/api/financial-reports')
+ .set('Authorization', `Bearer ${adminToken}`)
+ .send(invalidReportData)
+ .expect(400);
+
+ expect(response.body).toHaveProperty('error');
+ expect(response.body.error).toContain('Missing required fields');
+ });
+ });
+});
diff --git a/__tests__/financialReportCRUD.test.js b/__tests__/financialReportCRUD.test.js
index 4129861..0339e63 100644
--- a/__tests__/financialReportCRUD.test.js
+++ b/__tests__/financialReportCRUD.test.js
@@ -1,166 +1,264 @@
// __tests__/financialReportCRUD.test.js
const {
- createFinancialReport,
- getFinancialReport,
- listFinancialReports,
- updateFinancialReport,
- deleteFinancialReport
- } = require('../controllers/financialReportCrudController');
- const FinancialReport = require('../models/financialReport');
- const httpMocks = require('node-mocks-http');
-
- jest.mock('../models/financialReport');
-
- describe('Financial Report CRUD Operations', () => {
- let req, res, next;
-
- beforeEach(() => {
- req = httpMocks.createRequest();
- res = httpMocks.createResponse();
- next = jest.fn();
- jest.clearAllMocks();
- });
+ createFinancialReport,
+ getFinancialReport,
+ listFinancialReports,
+ updateFinancialReport,
+ deleteFinancialReport
+} = require('../controllers/financialReportCrudController');
+const FinancialReport = require('../models/financialReport');
+const httpMocks = require('node-mocks-http');
+
+jest.mock('../models/financialReport');
+
+describe('Financial Report CRUD Operations', () => {
+ let req, res, next;
- const sampleReport = {
- ReportID: 'test-id-123',
- Type: 'Annual',
- Data: {
- revenue: { q1: 250000, q2: 250000, q3: 250000, q4: 250000 },
- expenses: { q1: 125000, q2: 125000, q3: 125000, q4: 125000 }
- },
- TotalRevenue: '1000000.00',
- TotalExpenses: '500000.00',
- NetIncome: '500000.00',
- EquitySummary: ['uuid1', 'uuid2'],
- Timestamp: new Date().toISOString()
- };
-
- describe('READ Operations', () => {
- it('should get a single financial report by ID', async () => {
- const reportId = 'test-id-123';
- req.params = { id: reportId };
-
- FinancialReport.findOne = jest.fn().mockResolvedValue(sampleReport);
-
- await getFinancialReport(req, res, next);
-
- expect(FinancialReport.findOne).toHaveBeenCalledWith({ ReportID: reportId });
- expect(res.statusCode).toBe(200);
- expect(JSON.parse(res._getData())).toEqual(sampleReport);
+ beforeEach(() => {
+ req = httpMocks.createRequest();
+ res = httpMocks.createResponse();
+ next = jest.fn();
+ jest.clearAllMocks();
+ });
+
+ const sampleReport = {
+ ReportID: 'test-id-123',
+ Type: 'Annual',
+ Data: {
+ revenue: { q1: 250000, q2: 250000, q3: 250000, q4: 250000 },
+ expenses: { q1: 125000, q2: 125000, q3: 125000, q4: 125000 }
+ },
+ TotalRevenue: '1000000.00',
+ TotalExpenses: '500000.00',
+ NetIncome: '500000.00',
+ EquitySummary: ['uuid1', 'uuid2'],
+ Timestamp: new Date().toISOString()
+ };
+
+ describe('CREATE Operations', () => {
+ it('should create a new financial report', async () => {
+ const newReport = { ...sampleReport };
+ req.body = newReport;
+
+ FinancialReport.prototype.save = jest.fn().mockResolvedValue(newReport);
+
+ await createFinancialReport(req, res, next);
+
+ expect(res.statusCode).toBe(201);
+ expect(JSON.parse(res._getData())).toEqual(newReport);
+ });
+
+ it('should handle validation errors during creation', async () => {
+ const invalidReport = { ...sampleReport };
+ delete invalidReport.Type;
+ req.body = invalidReport;
+
+ await createFinancialReport(req, res, next);
+
+ expect(res.statusCode).toBe(400);
+ expect(JSON.parse(res._getData())).toEqual({
+ error: 'Missing required fields: Type'
});
+ });
+
+ it('should handle duplicate ReportID', async () => {
+ req.body = sampleReport;
+
+ const duplicateError = new Error('Duplicate key error');
+ duplicateError.code = 11000;
+
+ FinancialReport.prototype.save = jest.fn().mockRejectedValue(duplicateError);
+
+ await createFinancialReport(req, res, next);
+
+ expect(next).toHaveBeenCalledWith(duplicateError);
+ });
+ });
+
+ describe('READ Operations', () => {
+ it('should list financial reports with pagination', async () => {
+ req.query = { page: 1, limit: 10 };
+ const reports = [sampleReport, { ...sampleReport, ReportID: 'test-id-456' }];
- it('should handle non-existent report', async () => {
- req.params = { id: 'non-existent-id' };
-
- FinancialReport.findOne = jest.fn().mockResolvedValue(null);
+ FinancialReport.find = jest.fn().mockReturnThis();
+ FinancialReport.skip = jest.fn().mockReturnThis();
+ FinancialReport.limit = jest.fn().mockResolvedValue(reports);
+ FinancialReport.countDocuments = jest.fn().mockResolvedValue(2);
- await getFinancialReport(req, res, next);
+ await listFinancialReports(req, res, next);
- expect(res.statusCode).toBe(404);
- expect(JSON.parse(res._getData())).toEqual({
- message: 'Financial report not found'
- });
+ expect(res.statusCode).toBe(200);
+ expect(JSON.parse(res._getData())).toEqual({
+ reports: reports,
+ totalCount: 2,
+ currentPage: 1,
+ totalPages: 1
});
- it('should list all financial reports with pagination', async () => {
- req.query = { page: 1, limit: 10 };
- const reports = [sampleReport, { ...sampleReport, ReportID: 'test-id-456' }];
- const totalCount = 2;
-
- FinancialReport.find = jest.fn().mockReturnThis();
- FinancialReport.skip = jest.fn().mockReturnThis();
- FinancialReport.limit = jest.fn().mockResolvedValue(reports);
- FinancialReport.countDocuments = jest.fn().mockResolvedValue(totalCount);
-
- await listFinancialReports(req, res, next);
-
- expect(res.statusCode).toBe(200);
- expect(JSON.parse(res._getData())).toEqual({
- reports,
- totalCount,
- currentPage: 1,
- totalPages: 1
- });
- });
+ expect(FinancialReport.find).toHaveBeenCalled();
+ expect(FinancialReport.skip).toHaveBeenCalledWith(0);
+ expect(FinancialReport.limit).toHaveBeenCalledWith(10);
});
- describe('UPDATE Operations', () => {
- it('should update an existing financial report', async () => {
- const reportId = 'test-id-123';
- const updatedData = {
- ...sampleReport,
- TotalRevenue: '1100000.00',
- TotalExpenses: '600000.00',
- NetIncome: '500000.00'
- };
-
- req.params = { id: reportId };
- req.body = updatedData;
-
- FinancialReport.findOneAndUpdate = jest.fn()
- .mockResolvedValue(updatedData);
-
- await updateFinancialReport(req, res, next);
-
- expect(FinancialReport.findOneAndUpdate).toHaveBeenCalledWith(
- { ReportID: reportId },
- updatedData,
- { new: true, runValidators: true }
- );
- expect(res.statusCode).toBe(200);
- expect(JSON.parse(res._getData())).toEqual(updatedData);
+ it('should handle edge case pagination parameters', async () => {
+ req.query = { page: -1, limit: 'invalid' };
+
+ const mockReports = [];
+ FinancialReport.find = jest.fn().mockReturnValue({
+ skip: jest.fn().mockReturnValue({
+ limit: jest.fn().mockResolvedValue(mockReports)
+ })
});
+ FinancialReport.countDocuments = jest.fn().mockResolvedValue(0);
- it('should handle update validation errors', async () => {
- const reportId = 'test-id-123';
- const invalidData = {
- ...sampleReport,
- TotalRevenue: '-1000000.00' // Invalid negative value
- };
+ await listFinancialReports(req, res, next);
- req.params = { id: reportId };
- req.body = invalidData;
-
- await updateFinancialReport(req, res, next);
-
- expect(res.statusCode).toBe(400);
- expect(JSON.parse(res._getData())).toEqual({
- error: 'Financial values cannot be negative'
- });
+ expect(res.statusCode).toBe(200);
+ expect(JSON.parse(res._getData())).toEqual({
+ reports: [], // Ensure empty array instead of empty object
+ totalCount: 0,
+ currentPage: -1,
+ totalPages: 0
});
});
- describe('DELETE Operations', () => {
- it('should delete an existing financial report', async () => {
- const reportId = 'test-id-123';
- req.params = { id: reportId };
+ it('should list all financial reports with pagination', async () => {
+ req.query = { page: 1, limit: 10 };
+ const reports = [sampleReport, { ...sampleReport, ReportID: 'test-id-456' }];
+ const totalCount = 2;
- FinancialReport.findOneAndDelete = jest.fn()
- .mockResolvedValue(sampleReport);
+ FinancialReport.find = jest.fn().mockReturnValue({
+ skip: jest.fn().mockReturnValue({
+ limit: jest.fn().mockResolvedValue(reports)
+ })
+ });
+ FinancialReport.countDocuments = jest.fn().mockResolvedValue(totalCount);
- await deleteFinancialReport(req, res, next);
+ await listFinancialReports(req, res, next);
- expect(FinancialReport.findOneAndDelete)
- .toHaveBeenCalledWith({ ReportID: reportId });
- expect(res.statusCode).toBe(200);
- expect(JSON.parse(res._getData())).toEqual({
- message: 'Financial report deleted successfully',
- report: sampleReport
- });
+ expect(res.statusCode).toBe(200);
+ expect(JSON.parse(res._getData())).toEqual({
+ reports,
+ totalCount,
+ currentPage: 1,
+ totalPages: 1
});
- it('should handle deletion of non-existent report', async () => {
- req.params = { id: 'non-existent-id' };
+ const skip = (1 - 1) * 10;
+ expect(FinancialReport.find().skip).toHaveBeenCalledWith(skip);
+ expect(FinancialReport.find().skip().limit).toHaveBeenCalledWith(10);
+ });
- FinancialReport.findOneAndDelete = jest.fn()
- .mockResolvedValue(null);
+ it('should handle database errors during read', async () => {
+ req.params = { id: 'test-id' };
+
+ const dbError = new Error('Database connection lost');
+ FinancialReport.findOne = jest.fn().mockRejectedValue(dbError);
- await deleteFinancialReport(req, res, next);
+ await getFinancialReport(req, res, next);
- expect(res.statusCode).toBe(404);
- expect(JSON.parse(res._getData())).toEqual({
- message: 'Financial report not found'
- });
+ expect(next).toHaveBeenCalledWith(dbError);
+ });
+ });
+
+ describe('UPDATE Operations', () => {
+ it('should update an existing financial report', async () => {
+ const reportId = 'test-id-123';
+ const updatedData = {
+ ...sampleReport,
+ TotalRevenue: '1100000.00',
+ TotalExpenses: '600000.00',
+ NetIncome: '500000.00'
+ };
+
+ req.params = { id: reportId };
+ req.body = updatedData;
+
+ FinancialReport.findOneAndUpdate = jest.fn().mockResolvedValue(updatedData);
+
+ await updateFinancialReport(req, res, next);
+
+ expect(FinancialReport.findOneAndUpdate).toHaveBeenCalledWith(
+ { ReportID: reportId },
+ updatedData,
+ { new: true, runValidators: true }
+ );
+ expect(res.statusCode).toBe(200);
+ expect(JSON.parse(res._getData())).toEqual(updatedData);
+ });
+
+ it('should handle validation errors during update', async () => {
+ const reportId = 'test-id-123';
+ const invalidData = {
+ TotalRevenue: '1100000.00' // Missing required fields
+ };
+
+ req.params = { id: reportId };
+ req.body = invalidData;
+
+ await updateFinancialReport(req, res, next);
+
+ expect(res.statusCode).toBe(400);
+ expect(JSON.parse(res._getData())).toEqual({
+ error: 'Missing required fields: ReportID, Type, Data, TotalExpenses, NetIncome, Timestamp'
});
});
- });
\ No newline at end of file
+
+ it('should handle non-existent report update', async () => {
+ const reportId = 'non-existent-id';
+ req.params = { id: reportId };
+ req.body = sampleReport;
+
+ FinancialReport.findOneAndUpdate = jest.fn().mockResolvedValue(null);
+
+ await updateFinancialReport(req, res, next);
+
+ expect(res.statusCode).toBe(404);
+ expect(JSON.parse(res._getData())).toEqual({
+ message: 'Financial report not found'
+ });
+ });
+ });
+
+ describe('DELETE Operations', () => {
+ it('should delete an existing financial report', async () => {
+ const reportId = 'test-id-123';
+ req.params = { id: reportId };
+
+ FinancialReport.findOneAndDelete = jest.fn().mockResolvedValue(sampleReport);
+
+ await deleteFinancialReport(req, res, next);
+
+ expect(FinancialReport.findOneAndDelete).toHaveBeenCalledWith({ ReportID: reportId });
+ expect(res.statusCode).toBe(200);
+ expect(JSON.parse(res._getData())).toEqual({
+ message: 'Financial report deleted successfully',
+ report: sampleReport
+ });
+ });
+
+ it('should handle deletion of non-existent report', async () => {
+ req.params = { id: 'non-existent-id' };
+
+ FinancialReport.findOneAndDelete = jest.fn().mockResolvedValue(null);
+
+ await deleteFinancialReport(req, res, next);
+
+ expect(res.statusCode).toBe(404);
+ expect(JSON.parse(res._getData())).toEqual({
+ message: 'Financial report not found'
+ });
+ });
+
+ it('should handle database errors during deletion', async () => {
+ req.params = { id: 'test-id' };
+
+ const dbError = new Error('Database error');
+ FinancialReport.findOneAndDelete = jest.fn().mockRejectedValue(dbError);
+
+ await deleteFinancialReport(req, res, next);
+
+ expect(next).toHaveBeenCalledWith(dbError);
+ });
+ });
+});
\ No newline at end of file
diff --git a/__tests__/financialReportIntegration.test.js b/__tests__/financialReportIntegration.test.js
index 63b437d..eeb8ed5 100644
--- a/__tests__/financialReportIntegration.test.js
+++ b/__tests__/financialReportIntegration.test.js
@@ -17,14 +17,15 @@ describe('Financial Report API Integration', () => {
await mongoose.connect(mongoUri, {
useNewUrlParser: true,
useUnifiedTopology: true,
- useCreateIndex: true // Suppresses the ensureIndex deprecation warning
+ useCreateIndex: true,
+ useFindAndModify: false,
});
testUserId = new mongoose.Types.ObjectId();
adminToken = auth.generateToken({
id: testUserId.toString(),
role: 'admin',
- permissions: ['create:reports', 'read:reports', 'update:reports', 'delete:reports']
+ permissions: ['create:reports', 'read:reports', 'update:reports', 'delete:reports'],
});
});
@@ -49,7 +50,7 @@ describe('Financial Report API Integration', () => {
totalCount: 0,
currentPage: 1,
totalPages: 0,
- limit: 10
+ limit: 10,
});
});
@@ -71,107 +72,86 @@ describe('Financial Report API Integration', () => {
});
it('should create and return a quarterly report', async () => {
- try {
- const report = new FinancialReport({
- ReportID: 'TEST-2024-Q1',
- Type: 'Quarterly',
- TotalRevenue: 100000,
- TotalExpenses: 75000,
- NetIncome: 25000,
- EquitySummary: ['Initial equity test'],
- Timestamp: new Date(),
- userId: testUserId,
- lastModifiedBy: testUserId
- });
-
- report.Data = {
- revenue: new Map().set('q1', 100000),
- expenses: new Map().set('q1', 75000)
- };
-
- console.log('Pre-save state:', {
- type: report.Type,
- data: {
- revenue: report.Data.revenue instanceof Map ?
- Array.from(report.Data.revenue.entries()) : report.Data.revenue,
- expenses: report.Data.expenses instanceof Map ?
- Array.from(report.Data.expenses.entries()) : report.Data.expenses
- }
- });
-
- await report.save();
-
- const response = await request(app)
- .get('/api/financial-reports')
- .set('Authorization', `Bearer ${adminToken}`)
- .expect(200);
-
- expect(response.body.reports).toHaveLength(1);
- expect(response.body.reports[0]).toMatchObject({
- ReportID: report.ReportID,
- Type: report.Type,
- TotalRevenue: 100000,
- TotalExpenses: 75000,
- NetIncome: 25000
- });
-
- } catch (error) {
- console.log('Error details:', error);
- throw error;
- }
+ const report = new FinancialReport({
+ ReportID: 'TEST-2024-Q1',
+ Type: 'Quarterly',
+ TotalRevenue: 100000,
+ TotalExpenses: 75000,
+ NetIncome: 25000,
+ EquitySummary: ['Initial equity test'],
+ Timestamp: new Date(),
+ userId: testUserId,
+ lastModifiedBy: testUserId,
+ Data: {
+ revenue: { q1: 100000 },
+ expenses: { q1: 75000 },
+ },
+ });
+
+ console.log('Pre-save state:', {
+ type: report.Type,
+ data: report.Data,
+ });
+
+ await report.save();
+
+ const response = await request(app)
+ .get('/api/financial-reports')
+ .set('Authorization', `Bearer ${adminToken}`)
+ .expect(200);
+
+ expect(response.body.reports).toHaveLength(1);
+ expect(response.body.reports[0]).toMatchObject({
+ ReportID: report.ReportID,
+ Type: report.Type,
+ TotalRevenue: 100000,
+ TotalExpenses: 75000,
+ NetIncome: 25000,
+ });
});
it('should create and return an annual report with full quarterly data', async () => {
- try {
- const report = new FinancialReport({
- ReportID: 'TEST-2024-ANNUAL',
- Type: 'Annual',
- TotalRevenue: 400000,
- TotalExpenses: 300000,
- NetIncome: 100000,
- EquitySummary: ['Year-end equity summary'],
- Timestamp: new Date(),
- userId: testUserId,
- lastModifiedBy: testUserId
- });
-
- report.Data = {
- revenue: new Map([['q1', 100000], ['q2', 100000], ['q3', 100000], ['q4', 100000]]),
- expenses: new Map([['q1', 75000], ['q2', 75000], ['q3', 75000], ['q4', 75000]])
- };
-
- await report.save();
-
- const response = await request(app)
- .get('/api/financial-reports')
- .set('Authorization', `Bearer ${adminToken}`)
- .expect(200);
-
- expect(response.body.reports).toHaveLength(1);
- expect(response.body.reports[0]).toMatchObject({
- ReportID: report.ReportID,
- Type: report.Type,
- TotalRevenue: 400000,
- TotalExpenses: 300000,
- NetIncome: 100000
- });
-
- } catch (error) {
- console.log('Error details:', error);
- throw error;
- }
+ const report = new FinancialReport({
+ ReportID: 'TEST-2024-ANNUAL',
+ Type: 'Annual',
+ TotalRevenue: 400000,
+ TotalExpenses: 300000,
+ NetIncome: 100000,
+ EquitySummary: ['Year-end equity summary'],
+ Timestamp: new Date(),
+ userId: testUserId,
+ lastModifiedBy: testUserId,
+ Data: {
+ revenue: { q1: 100000, q2: 100000, q3: 100000, q4: 100000 },
+ expenses: { q1: 75000, q2: 75000, q3: 75000, q4: 75000 },
+ },
+ });
+
+ await report.save();
+
+ const response = await request(app)
+ .get('/api/financial-reports')
+ .set('Authorization', `Bearer ${adminToken}`)
+ .expect(200);
+
+ expect(response.body.reports).toHaveLength(1);
+ expect(response.body.reports[0]).toMatchObject({
+ ReportID: report.ReportID,
+ Type: report.Type,
+ TotalRevenue: 400000,
+ TotalExpenses: 300000,
+ NetIncome: 100000,
+ });
});
- // New test: Verify validation for missing fields in financial report creation
it('should not create a report with missing required fields', async () => {
const invalidReportData = {
Type: 'Quarterly',
TotalRevenue: 50000,
- // Missing TotalExpenses and NetIncome
EquitySummary: ['Partial equity summary'],
Timestamp: new Date(),
userId: testUserId,
- lastModifiedBy: testUserId
+ lastModifiedBy: testUserId,
};
const response = await request(app)
@@ -183,5 +163,52 @@ describe('Financial Report API Integration', () => {
expect(response.body).toHaveProperty('error');
expect(response.body.error).toContain('Missing required fields');
});
+
+ it('should update an existing financial report', async () => {
+ const report = new FinancialReport({
+ ReportID: 'TEST-2024-Q1',
+ Type: 'Quarterly',
+ TotalRevenue: 100000,
+ TotalExpenses: 75000,
+ NetIncome: 25000,
+ EquitySummary: ['Initial equity test'],
+ Timestamp: new Date(),
+ userId: testUserId,
+ lastModifiedBy: testUserId,
+ Data: {
+ revenue: { q1: 100000 },
+ expenses: { q1: 75000 },
+ },
+ });
+ await report.save();
+
+ const updatedData = {
+ ReportID: report.ReportID,
+ Type: 'Quarterly',
+ TotalRevenue: 120000,
+ TotalExpenses: 80000,
+ NetIncome: 40000,
+ EquitySummary: ['Updated equity test'],
+ Data: {
+ revenue: { q1: 120000 },
+ expenses: { q1: 80000 },
+ },
+ Timestamp: report.Timestamp,
+ userId: testUserId,
+ lastModifiedBy: testUserId
+ };
+
+ await request(app)
+ .put(`/api/financial-reports/${report.ReportID}`)
+ .set('Authorization', `Bearer ${adminToken}`)
+ .send(updatedData)
+ .expect(200);
+
+ const updatedReport = await FinancialReport.findOne({ ReportID: report.ReportID });
+ expect(updatedReport).toBeTruthy();
+ expect(updatedReport.TotalRevenue).toBe(`${updatedData.TotalRevenue}.00`);
+ expect(updatedReport.TotalExpenses).toBe(`${updatedData.TotalExpenses}.00`);
+ expect(updatedReport.NetIncome).toBe(`${updatedData.NetIncome}.00`);
+ });
});
-});
+});
\ No newline at end of file
diff --git a/__tests__/financialReportingController.test.js b/__tests__/financialReportingController.test.js
deleted file mode 100644
index 7e018bd..0000000
--- a/__tests__/financialReportingController.test.js
+++ /dev/null
@@ -1,80 +0,0 @@
-const { createFinancialReport } = require('../controllers/financialReportingController');
-const FinancialReport = require('../models/financialReport');
-const httpMocks = require('node-mocks-http');
-
-// Mock the entire model
-jest.mock('../models/financialReport');
-
-describe('createFinancialReport Controller', () => {
- let req, res, next;
-
- beforeEach(() => {
- req = httpMocks.createRequest();
- res = httpMocks.createResponse();
- next = jest.fn();
- jest.clearAllMocks();
- });
-
- it('should create a new financial report and return 201 status', async () => {
- // Setup request body with fixed timestamp
- const testData = {
- ReportID: 'test-id',
- Type: 'Annual',
- Data: { key: 'test-data' },
- TotalRevenue: '1000.00',
- TotalExpenses: '500.00',
- NetIncome: '500.00',
- EquitySummary: ['uuid1', 'uuid2'],
- Timestamp: new Date().toISOString() // Convert to ISO string format
- };
-
- req.body = testData;
-
- // Mock the constructor and save method
- const mockSave = jest.fn().mockResolvedValue(testData);
- const mockInstance = { save: mockSave };
- FinancialReport.mockImplementation(() => mockInstance);
-
- // Execute controller
- await createFinancialReport(req, res, next);
-
- // Get response data and parse it
- const responseData = JSON.parse(res._getData());
-
- // Assertions
- expect(FinancialReport).toHaveBeenCalledWith(testData);
- expect(mockSave).toHaveBeenCalled();
- expect(res.statusCode).toBe(201);
- expect(responseData).toEqual(testData); // Compare with the original test data
- expect(next).not.toHaveBeenCalled();
- });
-
- it('should handle errors and pass them to the error handling middleware', async () => {
- // Setup request body with fixed timestamp
- const testData = {
- ReportID: 'test-id',
- Type: 'Annual',
- Data: { key: 'test-data' },
- TotalRevenue: '1000.00',
- TotalExpenses: '500.00',
- NetIncome: '500.00',
- EquitySummary: ['uuid1', 'uuid2'],
- Timestamp: new Date().toISOString() // Convert to ISO string format
- };
-
- req.body = testData;
-
- // Mock constructor and save method to throw error
- const error = new Error('Failed to create financial report');
- const mockSave = jest.fn().mockRejectedValue(error);
- FinancialReport.mockImplementation(() => ({ save: mockSave }));
-
- // Execute controller
- await createFinancialReport(req, res, next);
-
- // Assertions
- expect(FinancialReport).toHaveBeenCalledWith(testData);
- expect(mockSave).toHaveBeenCalled();
- expect(next).toHaveBeenCalledWith(error);
- });
-});
\ No newline at end of file
diff --git a/__tests__/setup/jest.setup.js b/__tests__/setup/jest.setup.js
new file mode 100644
index 0000000..0922d4c
--- /dev/null
+++ b/__tests__/setup/jest.setup.js
@@ -0,0 +1,14 @@
+// __tests__/setup/jest.setup.js
+process.env.NODE_ENV = 'test';
+process.env.JWT_SECRET = 'test-secret';
+process.env.MONGODB_URI = 'mongodb://localhost:27017/test';
+
+jest.setTimeout(30000);
+
+beforeAll(async () => {
+ console.log('Test setup initialized');
+});
+
+afterAll(async () => {
+ await new Promise(resolve => setTimeout(resolve, 500));
+});
\ No newline at end of file
diff --git a/__tests__/setup/test-config.js b/__tests__/setup/test-config.js
new file mode 100644
index 0000000..b0569af
--- /dev/null
+++ b/__tests__/setup/test-config.js
@@ -0,0 +1,6 @@
+// __tests__/setup/test-config.js
+module.exports = {
+ JWT_SECRET: 'test-secret',
+ API_BASE_PATH: '/api/financial-reports',
+ VALID_API_KEY: 'valid-key'
+ };
\ No newline at end of file
diff --git a/babel.config b/babel.config
index 1320b9a..41c48fe 100644
--- a/babel.config
+++ b/babel.config
@@ -1,3 +1,6 @@
-{
- "presets": ["@babel/preset-env"]
-}
+
+module.exports = {
+ presets: [
+ ['@babel/preset-env', { targets: { node: 'current' } }]
+ ]
+};
\ No newline at end of file
diff --git a/client/DashboardMain.jsx b/client/DashboardMain.jsx
new file mode 100644
index 0000000..965391f
--- /dev/null
+++ b/client/DashboardMain.jsx
@@ -0,0 +1,132 @@
+import React from 'react';
+
+const Dashboard = () => {
+ const sidebarItems = [
+ 'Overview', 'Captable', 'Stakeholders', 'Share classes', 'Equity plans',
+ 'Securities', 'Fundraise', 'Documents', 'Updates', 'Reports', 'Audits',
+ 'Settings', 'Form 3921', '409A Valuation'
+ ];
+
+ const ownershipData = [
+ { name: 'Allen Smith', percentage: 27 },
+ { name: 'Toby Mornin', percentage: 25 },
+ { name: 'Others', percentage: 18 },
+ { name: 'Equity Plan', percentage: 15 },
+ { name: 'USA Ventures', percentage: 10 },
+ ];
+
+ const activities = [
+ { user: 'Allen Smith', action: 'uploaded a document', document: '2023 W-2.pdf', time: 'a day ago' },
+ { user: 'Allen Smith', action: 'uploaded a document', document: 'yc-post-money-safe-with-discount.pdf', time: '2 days ago' },
+ { user: 'Allen Smith', action: 'uploaded a document', document: 'Atlas-Articles-of-Incorporation.pdf', time: '3 days ago' },
+ { user: 'Allen Smith', action: 'uploaded a document', document: 'Atlas-Corp-Operating-Agreement.pdf', time: '3 days ago' },
+ ];
+
+ const summaryData = [
+ { shareClass: 'Common shares', authorizedShares: '7,000,000', dilutedShares: '4,500,000', ownership: '53%', amountRaised: '$10,000,000' },
+ { shareClass: 'Preferred (Series A)', authorizedShares: '2,000,000', dilutedShares: '1,500,000', ownership: '15%', amountRaised: '$18,000,000' },
+ { shareClass: 'Preferred (Convertible note)', authorizedShares: '1,000,000', dilutedShares: '500,000', ownership: '7%', amountRaised: '$7,000,000' },
+ ];
+
+ return (
+
+ {/* Sidebar */}
+
+
Musa Capital
+
+
+
+ {/* Main Content */}
+
+
Overview View your company's captable
+
+ {/* Statistics */}
+
+ {[
+ { label: 'Amount raised', value: '$25.00M' },
+ { label: 'Diluted shares', value: '7.56M' },
+ { label: 'Stakeholders', value: '4' }
+ ].map((stat, index) => (
+
+
{stat.label}
+
{stat.value}
+
+ ))}
+
+
+ {/* Ownership Chart */}
+
+
Ownership by Stakeholders
+
+
+ {ownershipData.map((item, index) => (
+
+ {item.name}
+ {item.percentage}%
+
+ ))}
+
+
+
+
+
+ {/* Activities */}
+
+
Activities
+
+ {activities.map((activity, index) => (
+
+ {activity.user} {activity.action}:{' '}
+ {activity.document}{' '}
+ {activity.time}
+
+ ))}
+
+
+
+
+ {/* Summary Table */}
+
+
Summary of your company's captable
+
+
+
+
+ Share class |
+ Authorized shares |
+ Diluted shares |
+ Ownership |
+ Amount raised |
+
+
+
+ {summaryData.map((row, index) => (
+
+ {row.shareClass} |
+ {row.authorizedShares} |
+ {row.dilutedShares} |
+ {row.ownership} |
+ {row.amountRaised} |
+
+ ))}
+
+
+
+
+
+
+ );
+};
+
+export default Dashboard;
\ No newline at end of file
diff --git a/client/DashboardMain2.jsx b/client/DashboardMain2.jsx
new file mode 100644
index 0000000..2690ecf
--- /dev/null
+++ b/client/DashboardMain2.jsx
@@ -0,0 +1,157 @@
+import React from 'react';
+import {
+ Card,
+ CardContent,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import { Button } from "@/components/ui/button";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+
+const Dashboard = () => {
+ const sidebarItems = [
+ 'Overview', 'Captable', 'Stakeholders', 'Share classes', 'Equity plans',
+ 'Securities', 'Fundraise', 'Documents', 'Updates', 'Reports', 'Audits',
+ 'Settings', 'Form 3921', '409A Valuation'
+ ];
+
+ const ownershipData = [
+ { name: 'Allen Smith', percentage: 27 },
+ { name: 'Toby Mornin', percentage: 25 },
+ { name: 'Others', percentage: 18 },
+ { name: 'Equity Plan', percentage: 15 },
+ { name: 'USA Ventures', percentage: 10 },
+ ];
+
+ const activities = [
+ { user: 'Allen Smith', action: 'uploaded a document', document: '2023 W-2.pdf', time: 'a day ago' },
+ { user: 'Allen Smith', action: 'uploaded a document', document: 'yc-post-money-safe-with-discount.pdf', time: '2 days ago' },
+ { user: 'Allen Smith', action: 'uploaded a document', document: 'Atlas-Articles-of-Incorporation.pdf', time: '3 days ago' },
+ { user: 'Allen Smith', action: 'uploaded a document', document: 'Atlas-Corp-Operating-Agreement.pdf', time: '3 days ago' },
+ ];
+
+ const summaryData = [
+ { shareClass: 'Common shares', authorizedShares: '7,000,000', dilutedShares: '4,500,000', ownership: '53%', amountRaised: '$10,000,000' },
+ { shareClass: 'Preferred (Series A)', authorizedShares: '2,000,000', dilutedShares: '1,500,000', ownership: '15%', amountRaised: '$18,000,000' },
+ { shareClass: 'Preferred (Convertible note)', authorizedShares: '1,000,000', dilutedShares: '500,000', ownership: '7%', amountRaised: '$7,000,000' },
+ ];
+
+ return (
+
+ {/* Sidebar */}
+
+
Musa Capital
+
+
+
+ {/* Main Content */}
+
+
Overview View your company's captable
+
+ {/* Statistics */}
+
+ {[
+ { label: 'Amount raised', value: '$25.00M' },
+ { label: 'Diluted shares', value: '7.56M' },
+ { label: 'Stakeholders', value: '4' }
+ ].map((stat, index) => (
+
+
+ {stat.label}
+ {stat.value}
+
+
+ ))}
+
+
+ {/* Ownership Chart */}
+
+
+ Ownership by Stakeholders
+
+
+
+
+ {ownershipData.map((item, index) => (
+
+ {item.name}
+ {item.percentage}%
+
+ ))}
+
+
+
+
+
+
+ {/* Activities */}
+
+
+ Activities
+
+
+
+ {activities.map((activity, index) => (
+
+ {activity.user} {activity.action}:{' '}
+ {activity.document}{' '}
+ {activity.time}
+
+ ))}
+
+
+
+
+
+ {/* Summary Table */}
+
+
+ Summary of your company's captable
+
+
+
+
+
+ Share class
+ Authorized shares
+ Diluted shares
+ Ownership
+ Amount raised
+
+
+
+ {summaryData.map((row, index) => (
+
+ {row.shareClass}
+ {row.authorizedShares}
+ {row.dilutedShares}
+ {row.ownership}
+ {row.amountRaised}
+
+ ))}
+
+
+
+
+
+
+ );
+};
+
+export default Dashboard;
\ No newline at end of file
diff --git a/client/components/Activities.jsx b/client/components/Activities.jsx
new file mode 100644
index 0000000..f6e74a9
--- /dev/null
+++ b/client/components/Activities.jsx
@@ -0,0 +1,56 @@
+import React from 'react';
+import styled from 'styled-components';
+
+const ActivitiesContainer = styled.div`
+ margin-bottom: 16px;
+`;
+
+const ActivityTitle = styled.h2`
+ font-size: 18px;
+ margin-bottom: 8px;
+`;
+
+const ActivityList = styled.div`
+ display: flex;
+ flex-direction: column;
+`;
+
+const ActivityItem = styled.div`
+ margin-bottom: 8px;
+ font-size: 14px;
+`;
+
+const ViewAllButton = styled.button`
+ background-color: #f0f0f0;
+ border: none;
+ padding: 8px 16px;
+ cursor: pointer;
+ &:hover {
+ background-color: #e0e0e0;
+ }
+`;
+
+const Activities: React.FC = () => {
+ const activities = [
+ { user: 'Allen Smith', action: 'uploaded a document', document: '2023 W-2.pdf', time: 'a day ago' },
+ { user: 'Allen Smith', action: 'uploaded a document', document: 'yc-post-money-safe-with-discount.pdf', time: '2 days ago' },
+ { user: 'Allen Smith', action: 'uploaded a document', document: 'Atlas-Articles-of-Incorporation.pdf', time: '3 days ago' },
+ { user: 'Allen Smith', action: 'uploaded a document', document: 'Atlas-Corp-Operating-Agreement.pdf', time: '3 days ago' },
+ ];
+
+ return (
+
+ Activities
+
+ {activities.map((activity, index) => (
+
+ {activity.user} {activity.action}: {activity.document} {activity.time}
+
+ ))}
+
+ View all activity
+
+ );
+};
+
+export default Activities;
\ No newline at end of file
diff --git a/client/components/Dashboard.jsx b/client/components/Dashboard.jsx
new file mode 100644
index 0000000..902e82a
--- /dev/null
+++ b/client/components/Dashboard.jsx
@@ -0,0 +1,21 @@
+import React from 'react';
+import styled from 'styled-components';
+import Sidebar from './Sidebar';
+import MainContent from './MainContent';
+
+const DashboardContainer = styled.div`
+ display: flex;
+ width: 1228px;
+ height: 768px;
+`;
+
+const Dashboard: React.FC = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default Dashboard;
\ No newline at end of file
diff --git a/client/components/MainContent.jsx b/client/components/MainContent.jsx
new file mode 100644
index 0000000..8f99a4b
--- /dev/null
+++ b/client/components/MainContent.jsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import styled from 'styled-components';
+import Statistics from './Statistics';
+import OwnershipChart from './OwnershipChart';
+import Activities from './Activities';
+import Summary from './Summary';
+
+const MainContentContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ padding: 16px;
+ width: 1028px;
+ height: 768px;
+`;
+
+const Title = styled.h1`
+ font-size: 24px;
+ margin-bottom: 16px;
+`;
+
+const MainContent: React.FC = () => {
+ return (
+
+ Overview View your company's captable
+
+
+
+
+
+ );
+};
+
+export default MainContent;
\ No newline at end of file
diff --git a/client/components/OwnershipChart.jsx b/client/components/OwnershipChart.jsx
new file mode 100644
index 0000000..c3e1987
--- /dev/null
+++ b/client/components/OwnershipChart.jsx
@@ -0,0 +1,53 @@
+import React from 'react';
+import styled from 'styled-components';
+
+const ChartContainer = styled.div`
+ display: flex;
+ margin-bottom: 16px;
+`;
+
+const OwnershipList = styled.div`
+ flex: 1;
+`;
+
+const OwnershipItem = styled.div`
+ margin-bottom: 8px;
+`;
+
+const PieChart = styled.div`
+ width: 200px;
+ height: 200px;
+ border-radius: 50%;
+ background: conic-gradient(
+ #6666ff 0deg 97.2deg,
+ #9999ff 97.2deg 187.2deg,
+ #ccccff 187.2deg 252deg,
+ #ffcccc 252deg 306deg,
+ #ffeecc 306deg 360deg
+ );
+`;
+
+const OwnershipChart: React.FC = () => {
+ const ownershipData = [
+ { name: 'Allen Smith', percentage: 27 },
+ { name: 'Toby Mornin', percentage: 25 },
+ { name: 'Others', percentage: 18 },
+ { name: 'Equity Plan', percentage: 15 },
+ { name: 'USA Ventures', percentage: 10 },
+ ];
+
+ return (
+
+
+ {ownershipData.map((item, index) => (
+
+ {item.name} {item.percentage}%
+
+ ))}
+
+
+
+ );
+};
+
+export default OwnershipChart;
\ No newline at end of file
diff --git a/client/components/Sidebar.jsx b/client/components/Sidebar.jsx
new file mode 100644
index 0000000..085cf6b
--- /dev/null
+++ b/client/components/Sidebar.jsx
@@ -0,0 +1,44 @@
+import React from 'react';
+import styled from 'styled-components';
+
+const SidebarContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ padding: 16px;
+ width: 200px;
+ height: 768px;
+ background-color: #f0f0f0;
+`;
+
+const Logo = styled.div`
+ font-size: 24px;
+ font-weight: bold;
+ margin-bottom: 16px;
+`;
+
+const NavItem = styled.div`
+ margin-bottom: 8px;
+ cursor: pointer;
+ &:hover {
+ color: #0066cc;
+ }
+`;
+
+const Sidebar: React.FC = () => {
+ const navItems = [
+ 'Overview', 'Captable', 'Stakeholders', 'Share classes', 'Equity plans',
+ 'Securities', 'Fundraise', 'Documents', 'Updates', 'Reports', 'Audits',
+ 'Settings', 'Form 3921', '409A Valuation'
+ ];
+
+ return (
+
+ Musa Capital
+ {navItems.map((item, index) => (
+ {item}
+ ))}
+
+ );
+};
+
+export default Sidebar;
\ No newline at end of file
diff --git a/client/components/Statistics.jsx b/client/components/Statistics.jsx
new file mode 100644
index 0000000..da30afe
--- /dev/null
+++ b/client/components/Statistics.jsx
@@ -0,0 +1,44 @@
+import React from 'react';
+import styled from 'styled-components';
+
+const StatisticsContainer = styled.div`
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 16px;
+`;
+
+const StatItem = styled.div`
+ display: flex;
+ flex-direction: column;
+`;
+
+const StatLabel = styled.span`
+ font-size: 14px;
+ color: #666;
+`;
+
+const StatValue = styled.span`
+ font-size: 24px;
+ font-weight: bold;
+`;
+
+const Statistics: React.FC = () => {
+ return (
+
+
+ Amount raised
+ $25.00M
+
+
+ Diluted shares
+ 7.56M
+
+
+ Stakeholders
+ 4
+
+
+ );
+};
+
+export default Statistics;
\ No newline at end of file
diff --git a/client/components/Summary.jsx b/client/components/Summary.jsx
new file mode 100644
index 0000000..e3dddf7
--- /dev/null
+++ b/client/components/Summary.jsx
@@ -0,0 +1,65 @@
+import React from 'react';
+import styled from 'styled-components';
+
+const SummaryContainer = styled.div`
+ margin-bottom: 16px;
+`;
+
+const SummaryTitle = styled.h2`
+ font-size: 18px;
+ margin-bottom: 8px;
+`;
+
+const SummaryTable = styled.table`
+ width: 100%;
+ border-collapse: collapse;
+`;
+
+const TableHeader = styled.th`
+ text-align: left;
+ padding: 8px;
+ background-color: #f0f0f0;
+`;
+
+const TableCell = styled.td`
+ padding: 8px;
+ border-bottom: 1px solid #e0e0e0;
+`;
+
+const Summary: React.FC = () => {
+ const summaryData = [
+ { shareClass: 'Common shares', authorizedShares: '7,000,000', dilutedShares: '4,500,000', ownership: '53%', amountRaised: '$10,000,000' },
+ { shareClass: 'Preferred (Series A)', authorizedShares: '2,000,000', dilutedShares: '1,500,000', ownership: '15%', amountRaised: '$18,000,000' },
+ { shareClass: 'Preferred (Convertible note)', authorizedShares: '1,000,000', dilutedShares: '500,000', ownership: '7%', amountRaised: '$7,000,000' },
+ ];
+
+ return (
+
+ Summary of your company's captable
+
+
+
+ Share class
+ Authorized shares
+ Diluted shares
+ Ownership
+ Amount raised
+
+
+
+ {summaryData.map((row, index) => (
+
+ {row.shareClass}
+ {row.authorizedShares}
+ {row.dilutedShares}
+ {row.ownership}
+ {row.amountRaised}
+
+ ))}
+
+
+
+ );
+};
+
+export default Summary;
\ No newline at end of file
diff --git a/config/index.js b/config/index.js
new file mode 100644
index 0000000..5e0225c
--- /dev/null
+++ b/config/index.js
@@ -0,0 +1,18 @@
+// config/index.js
+module.exports = {
+ JWT_SECRET: process.env.JWT_SECRET || 'test-secret',
+ MONGODB_URI: process.env.MONGODB_URI || 'mongodb://localhost:27017/opencap_test',
+ API_VERSION: 'v1',
+ AUTH: {
+ TOKEN_EXPIRATION: '24h',
+ REFRESH_TOKEN_EXPIRATION: '7d',
+ SALT_ROUNDS: 10
+ },
+ PERMISSIONS: {
+ GET: 'read:reports',
+ POST: 'create:reports',
+ PUT: 'update:reports',
+ PATCH: 'update:reports',
+ DELETE: 'delete:reports'
+ }
+};
\ No newline at end of file
diff --git a/controllers/financialReportingController.js b/controllers/financialReportingController.js
index 1ee5075..117f5eb 100644
--- a/controllers/financialReportingController.js
+++ b/controllers/financialReportingController.js
@@ -1,4 +1,3 @@
-// controllers/financialReportingController.js
const FinancialReport = require("../models/financialReport");
const jwt = require('jsonwebtoken');
const config = require('../config');
@@ -187,7 +186,6 @@ class FinancialReportController {
}
}
- // Authorization Methods
static async checkUserPermissions(req, res, next) {
try {
const { user } = req;
@@ -297,10 +295,13 @@ class FinancialReportController {
// CRUD Methods
static async createFinancialReport(req, res, next) {
- const session = await mongoose.startSession();
- session.startTransaction();
-
+ let session;
try {
+ if (mongoose.connection.readyState === 1 && mongoose.connection.db.serverConfig.replset) {
+ session = await mongoose.startSession();
+ session.startTransaction();
+ }
+
const validation = this.validateFinancialReport(req.body);
if (!validation.isValid) {
return res.status(400).json({ error: validation.error });
@@ -308,25 +309,15 @@ class FinancialReportController {
const financialReport = new FinancialReport(req.body);
const newFinancialReport = await financialReport.save({ session });
-
- await session.commitTransaction();
-
- return res.status(201).json({
- ReportID: newFinancialReport.ReportID,
- Type: newFinancialReport.Type,
- Data: newFinancialReport.Data,
- TotalRevenue: newFinancialReport.TotalRevenue,
- TotalExpenses: newFinancialReport.TotalExpenses,
- NetIncome: newFinancialReport.NetIncome,
- EquitySummary: newFinancialReport.EquitySummary,
- Timestamp: newFinancialReport.Timestamp,
- userId: newFinancialReport.userId
- });
+
+ if (session) await session.commitTransaction();
+
+ return res.status(201).json(newFinancialReport);
} catch (error) {
- await session.abortTransaction();
+ if (session) await session.abortTransaction();
next(error);
} finally {
- session.endSession();
+ if (session) session.endSession();
}
}
@@ -374,10 +365,13 @@ class FinancialReportController {
}
static async updateFinancialReport(req, res, next) {
- const session = await mongoose.startSession();
- session.startTransaction();
-
+ let session;
try {
+ if (mongoose.connection.readyState === 1 && mongoose.connection.db.serverConfig.replset) {
+ session = await mongoose.startSession();
+ session.startTransaction();
+ }
+
if (!req.params.id) {
return res.status(400).json({ message: 'Report ID is required' });
}
@@ -387,6 +381,16 @@ class FinancialReportController {
return res.status(400).json({ error: validation.error });
}
+ // Convert Data field to Map if provided as an object
+ if (req.body.Data) {
+ if (req.body.Data.revenue && !(req.body.Data.revenue instanceof Map)) {
+ req.body.Data.revenue = new Map(Object.entries(req.body.Data.revenue));
+ }
+ if (req.body.Data.expenses && !(req.body.Data.expenses instanceof Map)) {
+ req.body.Data.expenses = new Map(Object.entries(req.body.Data.expenses));
+ }
+ }
+
const report = await FinancialReport.findOneAndUpdate(
{ ReportID: req.params.id },
req.body,
@@ -398,25 +402,28 @@ class FinancialReportController {
);
if (!report) {
- await session.abortTransaction();
+ if (session) await session.abortTransaction();
return res.status(404).json({ message: 'Financial report not found' });
}
- await session.commitTransaction();
+ if (session) await session.commitTransaction();
res.status(200).json(report);
} catch (error) {
- await session.abortTransaction();
+ if (session) await session.abortTransaction();
next(error);
} finally {
- session.endSession();
+ if (session) session.endSession();
}
}
static async deleteFinancialReport(req, res, next) {
- const session = await mongoose.startSession();
- session.startTransaction();
-
+ let session;
try {
+ if (mongoose.connection.readyState === 1 && mongoose.connection.db.serverConfig.replset) {
+ session = await mongoose.startSession();
+ session.startTransaction();
+ }
+
if (!req.params.id) {
return res.status(400).json({ message: 'Report ID is required' });
}
@@ -427,44 +434,45 @@ class FinancialReportController {
);
if (!report) {
- await session.abortTransaction();
+ if (session) await session.abortTransaction();
return res.status(404).json({ message: 'Financial report not found' });
}
- await session.commitTransaction();
+ if (session) await session.commitTransaction();
res.status(200).json({
message: 'Financial report deleted successfully',
report
});
} catch (error) {
- await session.abortTransaction();
+ if (session) await session.abortTransaction();
next(error);
} finally {
- session.endSession();
+ if (session) session.endSession();
}
}
static async generateReport(req, res, next) {
- const session = await mongoose.startSession();
- session.startTransaction();
-
+ let session;
try {
- // Validate the report data
+ if (mongoose.connection.readyState === 1 && mongoose.connection.db.serverConfig.replset) {
+ session = await mongoose.startSession();
+ session.startTransaction();
+ }
+
const validation = this.validateFinancialReport(req.body);
if (!validation.isValid) {
return res.status(400).json({ error: validation.error });
}
- // Create the report with transaction support
const report = await FinancialReport.create([req.body], { session });
-
- await session.commitTransaction();
+
+ if (session) await session.commitTransaction();
res.status(201).json(report[0]);
} catch (error) {
- await session.abortTransaction();
+ if (session) await session.abortTransaction();
next(error);
} finally {
- session.endSession();
+ if (session) session.endSession();
}
}
}
@@ -482,4 +490,4 @@ module.exports = {
updateFinancialReport: FinancialReportController.updateFinancialReport.bind(FinancialReportController),
deleteFinancialReport: FinancialReportController.deleteFinancialReport.bind(FinancialReportController),
generateReport: FinancialReportController.generateReport.bind(FinancialReportController)
-};
\ No newline at end of file
+};
diff --git a/jest.config.js b/jest.config.js
index 938702f..b65ddd9 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -1,9 +1,28 @@
+// jest.config.js
+const path = require('path');
+
module.exports = {
- globalSetup: './__tests__/globalSetup.js',
- globalTeardown: './__tests__/globalTeardown.js',
- testMatch: ['**/__tests__/**/*.[jt]s?(x)'],
- testPathIgnorePatterns: ['/node_modules/', '/dist/'],
+ testEnvironment: 'node',
testTimeout: 30000,
+ setupFilesAfterEnv: [
+ path.resolve(__dirname, '__tests__/setup/jest.setup.js')
+ ],
+ moduleFileExtensions: ['js', 'json'],
+ testMatch: [
+ "**/__tests__/**/*.(test|integration.test|unit.test).js"
+ ],
verbose: true,
- detectOpenHandles: true, // Optional, helps find open handles
-};
+ detectOpenHandles: true,
+ forceExit: true,
+ clearMocks: true,
+ restoreMocks: true,
+ moduleNameMapper: {
+ '^@/(.*)$': '/$1',
+ '^@middleware/(.*)$': '/middleware/$1',
+ '^@routes/(.*)$': '/routes/$1',
+ '^@controllers/(.*)$': '/controllers/$1',
+ '^@models/(.*)$': '/models/$1'
+ },
+ roots: [''],
+ modulePaths: [path.resolve(__dirname)]
+};
\ No newline at end of file
diff --git a/models/financialReport.js b/models/financialReport.js
index 9ec06da..af47abf 100644
--- a/models/financialReport.js
+++ b/models/financialReport.js
@@ -1,46 +1,103 @@
-// models/financialReport.js
-
const mongoose = require('mongoose');
const { Schema } = mongoose;
-const { v4: uuidv4 } = require('uuid');
const FinancialReportSchema = new Schema({
- ReportID: {
- type: String,
- default: uuidv4, // Generate a UUID by default
+ ReportID: {
+ type: String,
+ required: true,
unique: true,
- required: true,
+ trim: true
},
- Type: {
- type: String,
- enum: ['Annual', 'Quarterly'], // Enum values
- required: true,
+ Type: {
+ type: String,
+ enum: ['Annual', 'Quarterly'],
+ required: true
},
Data: {
- type: Schema.Types.Mixed, // Stores JSON data
- required: true,
+ revenue: {
+ type: Map,
+ of: Number, // Simplified - just Number instead of object
+ validate: {
+ validator: function(v) {
+ if (!v) return false;
+ if (this.Type === 'Annual') {
+ return ['q1', 'q2', 'q3', 'q4'].every(q => v.has(q));
+ }
+ return v.size === 1; // Use size instead of Object.keys().length
+ },
+ message: props => `Invalid quarters for ${props.value} report type`
+ },
+ required: true,
+ _id: false // Disable _id for subdocuments
+ },
+ expenses: {
+ type: Map,
+ of: Number, // Simplified - just Number instead of object
+ validate: {
+ validator: function(v) {
+ if (!v) return false;
+ if (this.Type === 'Annual') {
+ return ['q1', 'q2', 'q3', 'q4'].every(q => v.has(q));
+ }
+ return v.size === 1; // Use size instead of Object.keys().length
+ },
+ message: props => `Invalid quarters for ${props.value} report type`
+ },
+ required: true,
+ _id: false // Disable _id for subdocuments
+ }
},
- TotalRevenue: {
- type: Schema.Types.Decimal128, // Decimal for monetary values
+ TotalRevenue: {
+ type: Number,
required: true,
+ min: 0,
+ get: v => v.toFixed(2),
+ set: v => parseFloat(v)
},
- TotalExpenses: {
- type: Schema.Types.Decimal128,
+ TotalExpenses: {
+ type: Number,
required: true,
+ min: 0,
+ get: v => v.toFixed(2),
+ set: v => parseFloat(v)
},
- NetIncome: {
- type: Schema.Types.Decimal128,
+ NetIncome: {
+ type: Number,
required: true,
+ get: v => v.toFixed(2),
+ set: v => parseFloat(v)
},
- EquitySummary: {
- type: [String], // Array of UUIDs (shareClassId)
- default: [], // Optional field
+ EquitySummary: [String],
+ Timestamp: {
+ type: Date,
+ required: true,
+ default: Date.now
},
- Timestamp: {
- type: Date,
- default: Date.now,
+ userId: {
+ type: Schema.Types.ObjectId,
+ ref: 'User',
required: true,
+ index: true
},
+ createdAt: { type: Date, default: Date.now },
+ updatedAt: { type: Date, default: Date.now },
+ lastModifiedBy: { type: Schema.Types.ObjectId, ref: 'User' }
+}, {
+ timestamps: true,
+ strict: false // Allow flexible Map contents
});
-module.exports = mongoose.model('FinancialReport', FinancialReportSchema);
+// Indexes
+FinancialReportSchema.index({ ReportID: 1 }, { unique: true });
+FinancialReportSchema.index({ Timestamp: -1 });
+
+// Methods
+FinancialReportSchema.methods.calculateTotals = function() {
+ const revenue = Array.from(this.Data.revenue.values()).reduce((a, b) => a + b, 0);
+ const expenses = Array.from(this.Data.expenses.values()).reduce((a, b) => a + b, 0);
+ this.TotalRevenue = revenue;
+ this.TotalExpenses = expenses;
+ this.NetIncome = revenue - expenses;
+};
+
+module.exports = mongoose.model('FinancialReport', FinancialReportSchema);
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 4c502a8..5570328 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -38,7 +38,7 @@
"chai": "^4.2.0",
"hest": "^1.0.5",
"jest": "^29.7.0",
- "mongodb-memory-server": "^9.4.1",
+ "mongodb-memory-server": "^9.5.0",
"supertest": "^6.3.4"
}
},
@@ -57,13 +57,14 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz",
- "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==",
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
+ "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/highlight": "^7.25.7",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
},
"engines": {
@@ -71,9 +72,9 @@
}
},
"node_modules/@babel/compat-data": {
- "version": "7.25.8",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz",
- "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==",
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz",
+ "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -81,22 +82,22 @@
}
},
"node_modules/@babel/core": {
- "version": "7.25.8",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.8.tgz",
- "integrity": "sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz",
+ "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.25.7",
- "@babel/generator": "^7.25.7",
- "@babel/helper-compilation-targets": "^7.25.7",
- "@babel/helper-module-transforms": "^7.25.7",
- "@babel/helpers": "^7.25.7",
- "@babel/parser": "^7.25.8",
- "@babel/template": "^7.25.7",
- "@babel/traverse": "^7.25.7",
- "@babel/types": "^7.25.8",
+ "@babel/code-frame": "^7.26.0",
+ "@babel/generator": "^7.26.0",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.0",
+ "@babel/parser": "^7.26.0",
+ "@babel/template": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.26.0",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -140,13 +141,14 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz",
- "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==",
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz",
+ "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.7",
+ "@babel/parser": "^7.26.2",
+ "@babel/types": "^7.26.0",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2"
@@ -156,14 +158,14 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz",
- "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz",
+ "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.25.7",
- "@babel/helper-validator-option": "^7.25.7",
+ "@babel/compat-data": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
"browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
@@ -183,30 +185,29 @@
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz",
- "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+ "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.7",
- "@babel/types": "^7.25.7"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz",
- "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
+ "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.25.7",
- "@babel/helper-simple-access": "^7.25.7",
- "@babel/helper-validator-identifier": "^7.25.7",
- "@babel/traverse": "^7.25.7"
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -216,33 +217,19 @@
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz",
- "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-simple-access": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz",
- "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz",
+ "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.25.7",
- "@babel/types": "^7.25.7"
- },
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz",
- "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -250,9 +237,9 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz",
- "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -260,9 +247,9 @@
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz",
- "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
+ "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -270,121 +257,27 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz",
- "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.25.7",
- "@babel/types": "^7.25.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz",
- "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz",
+ "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.25.7",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.26.0"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/highlight/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/@babel/highlight/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/@babel/highlight/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/@babel/parser": {
- "version": "7.25.8",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz",
- "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==",
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz",
+ "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.8"
+ "@babel/types": "^7.26.0"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -449,13 +342,13 @@
}
},
"node_modules/@babel/plugin-syntax-import-attributes": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz",
- "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz",
+ "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -491,13 +384,13 @@
}
},
"node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.7.tgz",
- "integrity": "sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
+ "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -617,13 +510,13 @@
}
},
"node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz",
- "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz",
+ "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -633,32 +526,32 @@
}
},
"node_modules/@babel/template": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz",
- "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
+ "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.25.7",
- "@babel/parser": "^7.25.7",
- "@babel/types": "^7.25.7"
+ "@babel/code-frame": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz",
- "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz",
+ "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.25.7",
- "@babel/generator": "^7.25.7",
- "@babel/parser": "^7.25.7",
- "@babel/template": "^7.25.7",
- "@babel/types": "^7.25.7",
+ "@babel/code-frame": "^7.25.9",
+ "@babel/generator": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.25.9",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -685,15 +578,14 @@
}
},
"node_modules/@babel/types": {
- "version": "7.25.8",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz",
- "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
+ "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.25.7",
- "@babel/helper-validator-identifier": "^7.25.7",
- "to-fast-properties": "^2.0.0"
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -709,7 +601,8 @@
"node_modules/@data-forge/serialization": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@data-forge/serialization/-/serialization-1.0.1.tgz",
- "integrity": "sha512-EP7IWimh5JcDOISVoXvNIjUAqcPN1FkNWvuvjY3uzcswErxB8j93ldlUBvgvGEszqFRwMM3fpMF0HrISg5iBSQ=="
+ "integrity": "sha512-EP7IWimh5JcDOISVoXvNIjUAqcPN1FkNWvuvjY3uzcswErxB8j93ldlUBvgvGEszqFRwMM3fpMF0HrISg5iBSQ==",
+ "license": "MIT"
},
"node_modules/@hapi/code": {
"version": "9.0.3",
@@ -721,9 +614,9 @@
}
},
"node_modules/@hapi/hoek": {
- "version": "11.0.4",
- "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.4.tgz",
- "integrity": "sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ==",
+ "version": "11.0.6",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.6.tgz",
+ "integrity": "sha512-mu8He+jghTDJ+la/uGBT4b1rqQdqFADZiXhzd98b3XW5nb/c+5woXx3FiNco2nm4wPJFHQVRGxYeWeSDPIYpYw==",
"license": "BSD-3-Clause"
},
"node_modules/@istanbuljs/load-nyc-config": {
@@ -1292,12 +1185,12 @@
}
},
"node_modules/@types/node": {
- "version": "22.7.5",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
- "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
+ "version": "22.9.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz",
+ "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==",
"license": "MIT",
"dependencies": {
- "undici-types": "~6.19.2"
+ "undici-types": "~6.19.8"
}
},
"node_modules/@types/stack-utils": {
@@ -1346,6 +1239,7 @@
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz",
"integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==",
+ "license": "(Unlicense OR Apache-2.0)",
"optional": true
},
"node_modules/abbrev": {
@@ -1478,20 +1372,6 @@
"node": ">=10"
}
},
- "node_modules/are-we-there-yet/node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/argon2": {
"version": "0.40.3",
"resolved": "https://registry.npmjs.org/argon2/-/argon2-0.40.3.tgz",
@@ -1541,7 +1421,8 @@
"node_modules/async": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
- "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="
+ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+ "license": "MIT"
},
"node_modules/async-mutex": {
"version": "0.4.1",
@@ -1563,6 +1444,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "license": "MIT",
"dependencies": {
"possible-typed-array-names": "^1.0.0"
},
@@ -1577,6 +1459,7 @@
"version": "1.7.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
+ "license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
@@ -1801,27 +1684,45 @@
"safe-buffer": "^5.1.1"
}
},
+ "node_modules/bl/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
+ "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"
+ }
+ },
+ "node_modules/bl/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/bl/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
"node_modules/block-stream2": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz",
"integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==",
+ "license": "MIT",
"dependencies": {
"readable-stream": "^3.4.0"
}
},
- "node_modules/block-stream2/node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/bluebird": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
@@ -1876,7 +1777,8 @@
"node_modules/browser-or-node": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz",
- "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg=="
+ "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==",
+ "license": "MIT"
},
"node_modules/browser-stdout": {
"version": "1.3.1",
@@ -1885,9 +1787,9 @@
"license": "ISC"
},
"node_modules/browserslist": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
- "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
+ "version": "4.24.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
+ "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==",
"dev": true,
"funding": [
{
@@ -1905,10 +1807,10 @@
],
"license": "MIT",
"dependencies": {
- "caniuse-lite": "^1.0.30001663",
- "electron-to-chromium": "^1.5.28",
+ "caniuse-lite": "^1.0.30001669",
+ "electron-to-chromium": "^1.5.41",
"node-releases": "^2.0.18",
- "update-browserslist-db": "^1.1.0"
+ "update-browserslist-db": "^1.1.1"
},
"bin": {
"browserslist": "cli.js"
@@ -1937,13 +1839,12 @@
}
},
"node_modules/buffer-crc32": {
- "version": "0.2.13",
- "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
- "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
- "dev": true,
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz",
+ "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==",
"license": "MIT",
"engines": {
- "node": "*"
+ "node": ">=8.0.0"
}
},
"node_modules/buffer-equal-constant-time": {
@@ -2008,9 +1909,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001668",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz",
- "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==",
+ "version": "1.0.30001679",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001679.tgz",
+ "integrity": "sha512-j2YqID/YwpLnKzCmBOS4tlZdWprXm3ZmQLBH9ZBXFOhoxLA46fwyBvx6toCBWBmnuwUY/qB3kEU6gFx8qgCroA==",
"dev": true,
"funding": [
{
@@ -2185,6 +2086,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "license": "MIT",
"optional": true,
"engines": {
"node": ">=0.8"
@@ -2399,9 +2301,9 @@
}
},
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz",
+ "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2418,6 +2320,7 @@
"resolved": "https://registry.npmjs.org/data-forge/-/data-forge-1.10.2.tgz",
"integrity": "sha512-VZv8NV5laRC+VXGkA6cccl5Hwkkbt1sUuphVPcICLMMhiRWzVcVEowfcaplhb/kzmDsuohpruzHZp3y5w9OnuA==",
"hasInstallScript": true,
+ "license": "MIT",
"dependencies": {
"@data-forge/serialization": "^1.0.0",
"dayjs": "^1.8.12",
@@ -2432,6 +2335,7 @@
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/data-forge-fs/-/data-forge-fs-0.0.9.tgz",
"integrity": "sha512-7VzK9DbvYqJk/AlQckIh4OMX0iNcvY4Za8vWXh6LT+TGekAs791XUjB2OsEDlRcmRr3DdQ7aecVBRZ+wevjhnA==",
+ "license": "MIT",
"dependencies": {
"chai": "^4.1.2"
},
@@ -2442,7 +2346,8 @@
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
- "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
+ "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
+ "license": "MIT"
},
"node_modules/debug": {
"version": "2.6.9",
@@ -2475,6 +2380,7 @@
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
"integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
+ "license": "MIT",
"engines": {
"node": ">=0.10"
}
@@ -2520,6 +2426,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
"integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "license": "MIT",
"optional": true,
"dependencies": {
"clone": "^1.0.2"
@@ -2652,6 +2559,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.1.0.tgz",
"integrity": "sha512-oq33hWOSSnl2Hoh00tZWaIPi1ievrD9aFG82/IgjlycAnW9hHx5PkJiXpxPsgEE+H7BsbVQXFVFST8TEXS6/pA==",
+ "license": "MIT",
"optionalDependencies": {
"wcwidth": ">=1.0.1"
}
@@ -2672,9 +2580,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
- "version": "1.5.38",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.38.tgz",
- "integrity": "sha512-VbeVexmZ1IFh+5EfrYz1I0HTzHVIlJa112UEWhciPyeOcKJGeTv6N8WnG4wsQB81DGCaVEGhpSb6o6a8WYFXXg==",
+ "version": "1.5.55",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.55.tgz",
+ "integrity": "sha512-6maZ2ASDOTBtjt9FhqYPRnbvKU5tjG0IN9SztUOWYw2AzNDNpKJYLJmlK0/En4Hs/aiWnB+JZ+gW19PIGszgKg==",
"dev": true,
"license": "ISC"
},
@@ -2790,7 +2698,8 @@
"node_modules/eventemitter3": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
- "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "license": "MIT"
},
"node_modules/execa": {
"version": "5.1.1",
@@ -2930,6 +2839,7 @@
"url": "https://paypal.me/naturalintelligence"
}
],
+ "license": "MIT",
"dependencies": {
"strnum": "^1.0.5"
},
@@ -2963,6 +2873,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
"integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -3050,6 +2961,7 @@
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "license": "MIT",
"dependencies": {
"is-callable": "^1.1.3"
}
@@ -3069,13 +2981,13 @@
}
},
"node_modules/formidable": {
- "version": "3.5.1",
- "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz",
- "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==",
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.2.tgz",
+ "integrity": "sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==",
"license": "MIT",
"dependencies": {
"dezalgo": "^1.0.4",
- "hexoid": "^1.0.0",
+ "hexoid": "^2.0.0",
"once": "^1.4.0"
},
"funding": {
@@ -3503,6 +3415,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
@@ -3551,9 +3464,9 @@
}
},
"node_modules/hexoid": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
- "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-2.0.0.tgz",
+ "integrity": "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==",
"license": "MIT",
"engines": {
"node": ">=8"
@@ -3722,18 +3635,19 @@
}
},
"node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
+ "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==",
"license": "MIT",
"engines": {
- "node": ">= 0.10"
+ "node": ">= 10"
}
},
"node_modules/is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "license": "MIT",
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -3768,6 +3682,7 @@
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -3823,6 +3738,7 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
"integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "license": "MIT",
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@@ -3907,6 +3823,7 @@
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
"integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
+ "license": "MIT",
"dependencies": {
"which-typed-array": "^1.1.14"
},
@@ -5263,16 +5180,17 @@
"license": "MIT"
},
"node_modules/minio": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/minio/-/minio-8.0.1.tgz",
- "integrity": "sha512-FzDO6yGnqLtm8sp3mXafWtiRUOslJSSg/aI0v9YbN5vjw5KLoODKAROCyi766NIvTSxcfHBrbhCSGk1A+MOzDg==",
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/minio/-/minio-8.0.2.tgz",
+ "integrity": "sha512-7ipWbtgzzboctf+McK+2cXwCrNOhuboTA/O1g9iWa0gH8R4GkeyFWwk12aVDEHdzjPiG8wxnjwfHS7pgraKuHw==",
+ "license": "Apache-2.0",
"dependencies": {
"async": "^3.2.4",
"block-stream2": "^2.1.0",
"browser-or-node": "^2.1.1",
"buffer-crc32": "^1.0.0",
"eventemitter3": "^5.0.1",
- "fast-xml-parser": "^4.2.2",
+ "fast-xml-parser": "^4.4.1",
"ipaddr.js": "^2.0.1",
"lodash": "^4.17.21",
"mime-types": "^2.1.35",
@@ -5280,28 +5198,12 @@
"stream-json": "^1.8.0",
"through2": "^4.0.2",
"web-encoding": "^1.1.5",
- "xml2js": "^0.5.0"
+ "xml2js": "^0.5.0 || ^0.6.2"
},
"engines": {
"node": "^16 || ^18 || >=20"
}
},
- "node_modules/minio/node_modules/buffer-crc32": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz",
- "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==",
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/minio/node_modules/ipaddr.js": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
- "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==",
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/minipass": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
@@ -5358,9 +5260,9 @@
}
},
"node_modules/mocha": {
- "version": "10.7.3",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz",
- "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==",
+ "version": "10.8.2",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz",
+ "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==",
"license": "MIT",
"dependencies": {
"ansi-colors": "^4.1.3",
@@ -5646,14 +5548,14 @@
}
},
"node_modules/mongodb-memory-server": {
- "version": "9.4.1",
- "resolved": "https://registry.npmjs.org/mongodb-memory-server/-/mongodb-memory-server-9.4.1.tgz",
- "integrity": "sha512-qONlW4sKPbtk9pqFnlPn7R73G3Q4TuebJJ5pHfoiKTqVJquojQ8xWmkCyz+/YnpA2vYBo/jib+nXvjfKwh7cjg==",
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/mongodb-memory-server/-/mongodb-memory-server-9.5.0.tgz",
+ "integrity": "sha512-In3zRT40cLlVtpy7FK6b96Lby6JBAdXj8Kf9YrH4p1Aa2X4ptojq7SmiRR3x47Lo0/UCXXIwhJpkdbYY8kRZAw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
- "mongodb-memory-server-core": "9.4.1",
+ "mongodb-memory-server-core": "9.5.0",
"tslib": "^2.6.3"
},
"engines": {
@@ -5661,21 +5563,21 @@
}
},
"node_modules/mongodb-memory-server-core": {
- "version": "9.4.1",
- "resolved": "https://registry.npmjs.org/mongodb-memory-server-core/-/mongodb-memory-server-core-9.4.1.tgz",
- "integrity": "sha512-lobapXaysH64zrn521NTkmqHc3krSPUFkuuZ8A/BmQV8ON7p2SzAEvpoJPDXIeJkxIzYw06dYL6Gn5OcZdEElA==",
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/mongodb-memory-server-core/-/mongodb-memory-server-core-9.5.0.tgz",
+ "integrity": "sha512-Jb/V80JeYAKWaF4bPFme7SmTR6ew1PWgkpPUepLDfRraeN49i1cruxICeA4zz4T33W/o31N+zazP8wI8ebf7yw==",
"dev": true,
"license": "MIT",
"dependencies": {
"async-mutex": "^0.4.1",
"camelcase": "^6.3.0",
- "debug": "^4.3.5",
+ "debug": "^4.3.7",
"find-cache-dir": "^3.3.2",
- "follow-redirects": "^1.15.6",
- "https-proxy-agent": "^7.0.4",
+ "follow-redirects": "^1.15.9",
+ "https-proxy-agent": "^7.0.5",
"mongodb": "^5.9.2",
"new-find-package-json": "^2.0.0",
- "semver": "^7.6.2",
+ "semver": "^7.6.3",
"tar-stream": "^3.1.7",
"tslib": "^2.6.3",
"yauzl": "^3.1.3"
@@ -5963,9 +5865,9 @@
}
},
"node_modules/nise/node_modules/@sinonjs/fake-timers": {
- "version": "13.0.2",
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz",
- "integrity": "sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==",
+ "version": "13.0.5",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz",
+ "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==",
"license": "BSD-3-Clause",
"dependencies": {
"@sinonjs/commons": "^3.0.1"
@@ -5981,9 +5883,9 @@
}
},
"node_modules/node-addon-api": {
- "version": "8.2.1",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.2.1.tgz",
- "integrity": "sha512-vmEOvxwiH8tlOcv4SyE8RH34rI5/nWVaigUeAUPawC6f0+HoDthwI0vkMu4tbtsZrXq6QXFfrkhjofzKEs5tpA==",
+ "version": "8.2.2",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.2.2.tgz",
+ "integrity": "sha512-9emqXAKhVoNrQ792nLI/wpzPpJ/bj/YXxW0CvAau1+RdGBcCRF1Dmz7719zgVsQNrzHl9Tzn3ImZ4qWFarWL0A==",
"license": "MIT",
"engines": {
"node": "^18 || ^20 || >= 21"
@@ -6130,6 +6032,7 @@
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz",
"integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==",
+ "license": "MIT",
"engines": {
"node": "*"
}
@@ -6258,7 +6161,8 @@
"node_modules/papaparse": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.2.0.tgz",
- "integrity": "sha512-ylq1wgUSnagU+MKQtNeVqrPhZuMYBvOSL00DHycFTCxownF95gpLAk1HiHdUW77N8yxRq1qHXLdlIPyBSG9NSA=="
+ "integrity": "sha512-ylq1wgUSnagU+MKQtNeVqrPhZuMYBvOSL00DHycFTCxownF95gpLAk1HiHdUW77N8yxRq1qHXLdlIPyBSG9NSA==",
+ "license": "MIT"
},
"node_modules/parse-json": {
"version": "5.2.0",
@@ -6346,9 +6250,10 @@
"license": "MIT"
},
"node_modules/pg": {
- "version": "8.13.0",
- "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.0.tgz",
- "integrity": "sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==",
+ "version": "8.13.1",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz",
+ "integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==",
+ "license": "MIT",
"dependencies": {
"pg-connection-string": "^2.7.0",
"pg-pool": "^3.7.0",
@@ -6375,17 +6280,20 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz",
"integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==",
+ "license": "MIT",
"optional": true
},
"node_modules/pg-connection-string": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz",
- "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA=="
+ "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==",
+ "license": "MIT"
},
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
+ "license": "ISC",
"engines": {
"node": ">=4.0.0"
}
@@ -6394,6 +6302,7 @@
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.0.tgz",
"integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==",
+ "license": "MIT",
"peerDependencies": {
"pg": ">=8.0"
}
@@ -6401,12 +6310,14 @@
"node_modules/pg-protocol": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.0.tgz",
- "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ=="
+ "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==",
+ "license": "MIT"
},
"node_modules/pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
+ "license": "MIT",
"dependencies": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
@@ -6422,14 +6333,15 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
"integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
+ "license": "MIT",
"dependencies": {
"split2": "^4.1.0"
}
},
"node_modules/picocolors": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
- "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
@@ -6472,6 +6384,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
"integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
}
@@ -6480,6 +6393,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
+ "license": "MIT",
"engines": {
"node": ">=4"
}
@@ -6488,6 +6402,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
"integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -6496,6 +6411,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -6504,6 +6420,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+ "license": "MIT",
"dependencies": {
"xtend": "^4.0.0"
},
@@ -6572,10 +6489,20 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-addr/node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
},
"node_modules/punycode": {
"version": "2.3.1",
@@ -6623,6 +6550,7 @@
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
"integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==",
+ "license": "MIT",
"dependencies": {
"decode-uri-component": "^0.2.2",
"filter-obj": "^1.1.0",
@@ -6684,26 +6612,19 @@
"license": "MIT"
},
"node_modules/readable-stream": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
- "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"license": "MIT",
"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"
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
}
},
- "node_modules/readable-stream/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "license": "MIT"
- },
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -6849,7 +6770,8 @@
"node_modules/sax": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
- "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
+ "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
+ "license": "ISC"
},
"node_modules/semver": {
"version": "7.6.3",
@@ -7129,6 +7051,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
"integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -7137,6 +7060,7 @@
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "license": "ISC",
"engines": {
"node": ">= 10.x"
}
@@ -7183,12 +7107,14 @@
"node_modules/stream-chain": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz",
- "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA=="
+ "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==",
+ "license": "BSD-3-Clause"
},
"node_modules/stream-json": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.8.0.tgz",
- "integrity": "sha512-HZfXngYHUAr1exT4fxlbc1IOce1RYxp2ldeaf97LYCOPSoOqY/1Psp7iGvpb+6JIOgkra9zDYnPX01hGAHzEPw==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.0.tgz",
+ "integrity": "sha512-TqnfW7hRTKje7UobBzXZJ2qOEDJvdcSVgVIK/fopC03xINFuFqQs8RVjyDT4ry7TmOo2ueAXwpXXXG4tNgtvoQ==",
+ "license": "BSD-3-Clause",
"dependencies": {
"stream-chain": "^2.2.5"
}
@@ -7212,25 +7138,20 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
"integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==",
+ "license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "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==",
"license": "MIT",
"dependencies": {
- "safe-buffer": "~5.1.0"
+ "safe-buffer": "~5.2.0"
}
},
- "node_modules/string_decoder/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "license": "MIT"
- },
"node_modules/string-length": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
@@ -7306,7 +7227,8 @@
"node_modules/strnum": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
- "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
+ "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==",
+ "license": "MIT"
},
"node_modules/super-regex": {
"version": "0.2.0",
@@ -7422,6 +7344,16 @@
"url": "https://ko-fi.com/tunnckoCore/commissions"
}
},
+ "node_modules/supertest/node_modules/hexoid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
+ "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/supertest/node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
@@ -7570,36 +7502,21 @@
}
},
"node_modules/text-decoder": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz",
- "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.1.tgz",
+ "integrity": "sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ==",
"dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "b4a": "^1.6.4"
- }
+ "license": "Apache-2.0"
},
"node_modules/through2": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
"integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
+ "license": "MIT",
"dependencies": {
"readable-stream": "3"
}
},
- "node_modules/through2/node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/time-span": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/time-span/-/time-span-5.1.0.tgz",
@@ -7622,16 +7539,6 @@
"dev": true,
"license": "BSD-3-Clause"
},
- "node_modules/to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/to-iso-string": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz",
@@ -7668,9 +7575,9 @@
"license": "MIT"
},
"node_modules/tslib": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
- "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD"
},
@@ -7712,7 +7619,8 @@
"node_modules/typy": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/typy/-/typy-3.3.0.tgz",
- "integrity": "sha512-Du53deMF9X9pSM3gVXDjLBq14BUfZWSGKfmmR1kTlg953RaIZehfc8fQuoAiW+SRO6bJsP+59mv1tsH8vwKghg=="
+ "integrity": "sha512-Du53deMF9X9pSM3gVXDjLBq14BUfZWSGKfmmR1kTlg953RaIZehfc8fQuoAiW+SRO6bJsP+59mv1tsH8vwKghg==",
+ "license": "MIT"
},
"node_modules/undici-types": {
"version": "6.19.8",
@@ -7764,6 +7672,7 @@
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
+ "license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
@@ -7838,6 +7747,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
"integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "license": "MIT",
"optional": true,
"dependencies": {
"defaults": "^1.0.3"
@@ -7847,6 +7757,7 @@
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz",
"integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==",
+ "license": "MIT",
"dependencies": {
"util": "^0.12.3"
},
@@ -7897,6 +7808,7 @@
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
"integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
+ "license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.7",
@@ -7964,9 +7876,10 @@
}
},
"node_modules/xml2js": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
- "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
+ "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
+ "license": "MIT",
"dependencies": {
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
@@ -7979,6 +7892,7 @@
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "license": "MIT",
"engines": {
"node": ">=4.0"
}
@@ -7987,6 +7901,7 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "license": "MIT",
"engines": {
"node": ">=0.4"
}
@@ -8073,9 +7988,9 @@
}
},
"node_modules/yauzl": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.1.3.tgz",
- "integrity": "sha512-JCCdmlJJWv7L0q/KylOekyRaUrdEoUxWkWVcgorosTROCFWiS9p2NNPE9Yb91ak7b1N5SxAZEliWpspbZccivw==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.2.0.tgz",
+ "integrity": "sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8086,6 +8001,16 @@
"node": ">=12"
}
},
+ "node_modules/yauzl/node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/package.json b/package.json
index 69f4907..59daf59 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,18 @@
{
"name": "opencap",
"version": "1.0.0",
- "description": "Your project description here",
+ "description": "OpenCap Financial Management System",
"main": "app.js",
"scripts": {
- "test": "jest --config=jest.config.js"
+ "start": "node app.js",
+ "dev": "nodemon app.js",
+ "test": "jest --config=jest.config.js --detectOpenHandles --runInBand",
+ "test:watch": "jest --config=jest.config.js --watch",
+ "test:coverage": "jest --config=jest.config.js --coverage",
+ "test:integration": "jest --config=jest.config.js --detectOpenHandles --runInBand '__tests__/**/*.integration.test.js'",
+ "test:unit": "jest --config=jest.config.js '__tests__/**/*.unit.test.js'",
+ "lint": "eslint .",
+ "format": "prettier --write ."
},
"dependencies": {
"@hapi/code": "^9.0.3",
@@ -34,10 +42,40 @@
"sinon": "^18.0.0"
},
"devDependencies": {
+ "@babel/core": "^7.24.0",
+ "@babel/preset-env": "^7.24.0",
+ "@types/jest": "^29.5.11",
+ "babel-jest": "^29.7.0",
"chai": "^4.2.0",
+ "eslint": "^8.56.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-jest": "^27.6.0",
"hest": "^1.0.5",
"jest": "^29.7.0",
- "mongodb-memory-server": "^9.4.1",
- "supertest": "^6.3.4"
- }
-}
+ "jest-environment-node": "^29.7.0",
+ "mongodb-memory-server": "^9.5.0",
+ "supertest": "^6.3.4",
+ "nodemon": "^3.0.2",
+ "prettier": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=14.0.0",
+ "npm": ">=6.0.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/yourusername/opencap.git"
+ },
+ "keywords": [
+ "financial",
+ "reporting",
+ "management",
+ "api"
+ ],
+ "author": "Your Name",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/yourusername/opencap/issues"
+ },
+ "homepage": "https://github.com/yourusername/opencap#readme"
+}
\ No newline at end of file
diff --git a/utils/dataProcessing.js b/utils/dataProcessing.js
index fba30de..f13bc87 100644
--- a/utils/dataProcessing.js
+++ b/utils/dataProcessing.js
@@ -16,4 +16,5 @@ const processDataset = (datasetPath) => {
return processedData;
};
+
module.exports = { processDataset };