diff --git a/.env.sample b/.env.sample index efbdd12e..23a5e3be 100644 --- a/.env.sample +++ b/.env.sample @@ -35,10 +35,6 @@ PLAYGROUND_ENABLE=false # AMQP URL AMQP_URL=amqp://guest:guest@rabbitmq -# Billing settings -BILLING_DEBUG=true -BILLING_COMPANY_EMAIL="team@hawk.so" - ### Accounting module ### # Accounting service URL # CODEX_ACCOUNTING_URL=http://accounting:3999/graphql diff --git a/.env.test b/.env.test index 4ae39491..640d5377 100644 --- a/.env.test +++ b/.env.test @@ -46,10 +46,6 @@ SMTP_SENDER_ADDRESS= # AMQP URL AMQP_URL=amqp://guest:guest@rabbitmq:5672/ -# Billing settings -BILLING_DEBUG=true -BILLING_COMPANY_EMAIL="team@hawk.so" - ### Accounting module ### # Accounting service URL # CODEX_ACCOUNTING_URL= diff --git a/jest.config.js b/jest.config.js index 7cfa2195..212d114a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -15,6 +15,11 @@ module.exports = { */ preset: '@shelf/jest-mongodb', + /** + * Setup file to provide global APIs needed by MongoDB driver + */ + setupFilesAfterEnv: ['/test/setup.ts'], + /** * TypeScript support */ diff --git a/package.json b/package.json index d710f56c..347f350d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hawk.api", - "version": "1.2.31", + "version": "1.2.32", "main": "index.ts", "license": "BUSL-1.1", "scripts": { @@ -20,7 +20,8 @@ "test:integration:down": "docker compose -f docker-compose.test.yml down --volumes" }, "devDependencies": { - "@shelf/jest-mongodb": "^1.2.2", + "@shelf/jest-mongodb": "^6.0.2", + "@swc/core": "^1.3.0", "@types/jest": "^26.0.8", "eslint": "^6.7.2", "eslint-config-codex": "1.2.4", @@ -43,7 +44,6 @@ "@hawk.so/types": "^0.1.37", "@n1ru4l/json-patch-plus": "^0.2.0", "@types/amqp-connection-manager": "^2.0.4", - "@types/bson": "^4.0.5", "@types/debug": "^4.1.5", "@types/escape-html": "^1.0.0", "@types/graphql-upload": "^8.0.11", @@ -51,7 +51,6 @@ "@types/lodash.clonedeep": "^4.5.9", "@types/lodash.mergewith": "^4.6.9", "@types/mime-types": "^2.1.0", - "@types/mongodb": "^3.6.20", "@types/morgan": "^1.9.10", "@types/node": "^16.11.46", "@types/safe-regex": "^1.1.6", @@ -64,7 +63,6 @@ "aws-sdk": "^2.1174.0", "axios": "^0.27.2", "body-parser": "^1.19.0", - "bson": "^4.6.5", "cloudpayments": "^6.0.1", "codex-accounting-sdk": "https://github.com/codex-team/codex-accounting-sdk.git", "dataloader": "^2.0.0", @@ -81,7 +79,7 @@ "lodash.mergewith": "^4.6.2", "migrate-mongo": "^7.0.1", "mime-types": "^2.1.25", - "mongodb": "^3.7.3", + "mongodb": "^6.0.0", "morgan": "^1.10.1", "prom-client": "^15.1.3", "redis": "^4.7.0", @@ -89,5 +87,8 @@ "ts-node-dev": "^2.0.0", "uuid": "^8.3.2", "zod": "^3.25.76" + }, + "resolutions": { + "bson": "^6.7.0" } } diff --git a/src/dataLoaders.ts b/src/dataLoaders.ts index c41a5458..377bd702 100644 --- a/src/dataLoaders.ts +++ b/src/dataLoaders.ts @@ -1,5 +1,5 @@ import DataLoader from 'dataloader'; -import { Db, ObjectId } from 'mongodb'; +import { Db, ObjectId, WithId } from 'mongodb'; import { PlanDBScheme, UserDBScheme, WorkspaceDBScheme, ProjectDBScheme, EventData, EventAddons } from '@hawk.so/types'; type EventDbScheme = { @@ -47,7 +47,7 @@ export default class DataLoaders { */ public userByEmail = new DataLoader( (userEmails) => - this.batchByField('users', userEmails, 'email'), + this.batchByField('users', 'email', userEmails), { cache: false } ); @@ -69,41 +69,51 @@ export default class DataLoaders { * @param collectionName - collection name to get entities * @param ids - ids for resolving */ - private async batchByIds(collectionName: string, ids: ReadonlyArray): Promise<(T | null | Error)[]> { - return this.batchByField(collectionName, ids.map(id => new ObjectId(id)), '_id'); + private async batchByIds( + collectionName: string, + ids: ReadonlyArray + ): Promise<(WithId | null)[]> { + return this.batchByField(collectionName, '_id', ids.map(id => new ObjectId(id))); } /** * Batching function for resolving entities by certain field * @param collectionName - collection name to get entities - * @param values - values for resolving * @param fieldName - field name to resolve + * @param values - values for resolving */ private async batchByField< - // eslint-disable-next-line @typescript-eslint/no-explicit-any - T extends { [key: string]: any }, - FieldType extends ObjectId | string - >(collectionName: string, values: ReadonlyArray, fieldName: string): Promise<(T | null | Error)[]> { + T extends Record, + FieldType extends keyof T + >( + collectionName: string, + fieldName: FieldType, + values: ReadonlyArray + ): Promise<(WithId | null)[]> { + type Doc = WithId; const valuesMap = new Map(); for (const value of values) { valuesMap.set(value.toString(), value); } - const queryResult = await this.dbConnection.collection(collectionName) + const queryResult = await this.dbConnection + .collection(collectionName) .find({ [fieldName]: { $in: Array.from(valuesMap.values()) }, - }) + } as any) .toArray(); /** * Map for making associations between given id and fetched entity * It's because MongoDB `find` mixed all entities */ - const entitiesMap: Record = {}; + const entitiesMap: Record = {}; + + queryResult.forEach((entity) => { + const key = entity[fieldName as keyof Doc]; - queryResult.forEach((entity: T) => { - entitiesMap[entity[fieldName].toString()] = entity; + entitiesMap[key.toString()] = entity; }, {}); return values.map((field) => entitiesMap[field.toString()] || null); diff --git a/src/metrics/mongodb.ts b/src/metrics/mongodb.ts index f13087b4..7f14b680 100644 --- a/src/metrics/mongodb.ts +++ b/src/metrics/mongodb.ts @@ -317,7 +317,11 @@ export function setupMongoMetrics(client: MongoClient): void { .observe(duration); // Track error - const errorCode = event.failure?.code?.toString() || 'unknown'; + /** + * MongoDB failure objects may have additional properties like 'code' + * that aren't part of the standard Error type + */ + const errorCode = (event.failure as any)?.code?.toString() || 'unknown'; mongoCommandErrors .labels(metadata.commandName, errorCode) diff --git a/src/models/abstactModelFactory.ts b/src/models/abstactModelFactory.ts index 16d337cd..9ca87d65 100644 --- a/src/models/abstactModelFactory.ts +++ b/src/models/abstactModelFactory.ts @@ -1,10 +1,10 @@ -import { Collection, Db, ObjectID } from 'mongodb'; +import { Collection, Db, Document, ObjectId } from 'mongodb'; import AbstractModel, { ModelConstructor } from './abstractModel'; /** * Model Factory class */ -export default abstract class AbstractModelFactory> { +export default abstract class AbstractModelFactory> { /** * Database connection to interact with */ @@ -17,11 +17,8 @@ export default abstract class AbstractModelFactory; /** * Creates factory instance @@ -44,7 +41,12 @@ export default abstract class AbstractModelFactory, but Model constructor expects DBScheme. + * Since WithId is DBScheme & { _id: ObjectId } and DBScheme already + * includes _id: ObjectId, they are structurally compatible. + */ + return new this.Model(searchResult as DBScheme); } /** @@ -53,13 +55,18 @@ export default abstract class AbstractModelFactory { const searchResult = await this.collection.findOne({ - _id: new ObjectID(id), - }); + _id: new ObjectId(id), + } as any); if (!searchResult) { return null; } - return new this.Model(searchResult); + /** + * MongoDB returns WithId, but Model constructor expects DBScheme. + * Since WithId is DBScheme & { _id: ObjectId } and DBScheme already + * includes _id: ObjectId, they are structurally compatible. + */ + return new this.Model(searchResult as DBScheme); } } diff --git a/src/models/abstractModel.ts b/src/models/abstractModel.ts index 2b12a4f9..9c8830c0 100644 --- a/src/models/abstractModel.ts +++ b/src/models/abstractModel.ts @@ -1,15 +1,15 @@ -import { Collection, Db } from 'mongodb'; +import { Collection, Db, Document } from 'mongodb'; import { databases } from '../mongo'; /** * Model constructor type */ -export type ModelConstructor> = new (modelData: DBScheme) => Model; +export type ModelConstructor> = new (modelData: DBScheme) => Model; /** * Base model */ -export default abstract class AbstractModel { +export default abstract class AbstractModel { /** * Database connection to interact with DB */ @@ -19,7 +19,7 @@ export default abstract class AbstractModel { /** * Model's collection */ - protected abstract collection: Collection; + protected abstract collection: Collection; /** * Creates model instance @@ -32,10 +32,16 @@ export default abstract class AbstractModel { /** * Update entity data * @param query - query to match - * @param data - update data + * @param data - update data (supports MongoDB dot notation for nested fields) * @return number of documents modified */ - public async update(query: object, data: object): Promise { - return (await this.collection.updateOne(query, { $set: data })).modifiedCount; + public async update(query: object, data: Partial | Record): Promise { + /** + * Type assertion is needed because MongoDB's updateOne accepts both + * Partial (for regular updates) and Record + * (for dot notation like 'identities.workspaceId.saml.id'), but the + * type system requires MatchKeysAndValues. + */ + return (await this.collection.updateOne(query, { $set: data as any })).modifiedCount; } } diff --git a/src/models/eventsFactory.js b/src/models/eventsFactory.js index 383387be..bf3efb13 100644 --- a/src/models/eventsFactory.js +++ b/src/models/eventsFactory.js @@ -7,7 +7,7 @@ import ChartDataService from '../services/chartDataService'; const Factory = require('./modelFactory'); const mongo = require('../mongo'); const Event = require('../models/event'); -const { ObjectID } = require('mongodb'); +const { ObjectId } = require('mongodb'); const { composeEventPayloadByRepetition } = require('../utils/merge'); const MAX_DB_READ_BATCH_SIZE = Number(process.env.MAX_DB_READ_BATCH_SIZE); @@ -174,7 +174,7 @@ class EventsFactory extends Factory { /** * Find event by id * - * @param {string|ObjectID} id - event's id + * @param {string|ObjectId} id - event's id * @returns {Event|null} */ async findById(id) { @@ -282,7 +282,7 @@ class EventsFactory extends Factory { $and: [ { groupingTimestamp: paginationCursor.groupingTimestampBoundary }, { [sort]: paginationCursor.sortValueBoundary }, - { _id: { $lte: new ObjectID(paginationCursor.idBoundary) } }, + { _id: { $lte: new ObjectId(paginationCursor.idBoundary) } }, ], }, ], @@ -654,7 +654,7 @@ class EventsFactory extends Factory { /** * Returns Event repetitions * - * @param {string|ObjectID} originalEventId - id of the original event + * @param {string|ObjectId} originalEventId - id of the original event * @param {Number} limit - count limitations * @param {Number} cursor - pointer to the next repetition * @@ -663,7 +663,7 @@ class EventsFactory extends Factory { async getEventRepetitions(originalEventId, limit = 10, cursor = null) { limit = this.validateLimit(limit); - cursor = cursor ? new ObjectID(cursor) : null; + cursor = cursor ? new ObjectId(cursor) : null; const result = { repetitions: [], @@ -766,7 +766,7 @@ class EventsFactory extends Factory { */ const repetition = await this.getCollection(this.TYPES.REPETITIONS) .findOne({ - _id: ObjectID(repetitionId), + _id: new ObjectId(repetitionId), }); const originalEvent = await this.eventsDataLoader.load(originalEventId); @@ -828,8 +828,8 @@ class EventsFactory extends Factory { async visitEvent(eventId, userId) { const result = await this.getCollection(this.TYPES.EVENTS) .updateOne( - { _id: new ObjectID(eventId) }, - { $addToSet: { visitedBy: new ObjectID(userId) } } + { _id: new ObjectId(eventId) }, + { $addToSet: { visitedBy: new ObjectId(userId) } } ); if (result.matchedCount === 0) { @@ -856,7 +856,7 @@ class EventsFactory extends Factory { throw new Error(`Event not found for eventId: ${eventId}`); } - const query = { _id: new ObjectID(event._id) }; + const query = { _id: new ObjectId(event._id) }; const markKey = `marks.${mark}`; @@ -908,7 +908,7 @@ class EventsFactory extends Factory { async updateAssignee(eventId, assignee) { const collection = this.getCollection(this.TYPES.EVENTS); - const query = { _id: new ObjectID(eventId) }; + const query = { _id: new ObjectId(eventId) }; const update = { $set: { assignee: assignee }, diff --git a/src/models/model.js b/src/models/model.js index f2624a3c..cd4e381f 100644 --- a/src/models/model.js +++ b/src/models/model.js @@ -1,9 +1,9 @@ const mongodbDriver = require('mongodb'); -const ObjectID = mongodbDriver.ObjectID; +const ObjectId = mongodbDriver.ObjectId; /** * @typedef {Object} BaseModel - * @typedef {string|ObjectID} id - record id + * @typedef {string|ObjectId} id - record id */ /** @@ -44,7 +44,7 @@ class Model { */ static async findById(id) { const searchResult = await this.collection.findOne({ - _id: new ObjectID(id), + _id: new ObjectId(id), }); return new this({ diff --git a/src/models/notify.js b/src/models/notify.js index 729d6aef..a32d8f1a 100644 --- a/src/models/notify.js +++ b/src/models/notify.js @@ -7,8 +7,8 @@ /** * @typedef {Object} NotificationSettingsSchema - * @property {ObjectID|string} id - notify ID - * @property {ObjectID|string} [userId] - user ID + * @property {ObjectId|string} id - notify ID + * @property {ObjectId|string} [userId] - user ID * @property {ReceiveTypes} receiveType * @property {string} words - filter words when action type is INCLUDING * @property {ProviderSettings[]} providers - notify settings @@ -50,7 +50,7 @@ class Notify { } /** - * @return {string|ObjectID} + * @return {string|ObjectId} */ get id() { return this._id; diff --git a/src/models/paymentRequest.js b/src/models/paymentRequest.js deleted file mode 100644 index 92978f8c..00000000 --- a/src/models/paymentRequest.js +++ /dev/null @@ -1,86 +0,0 @@ -const crypto = require('crypto'); -const User = require('../models/user').default; - -const EmailCompany = process.env.BILLING_COMPANY_EMAIL; -const OSNTaxation = 'osn'; -const TaxNone = 'none'; -const PaymentDescription = 'Card check payment. It will be refunded.'; - -/** - * PaymentRequest model - */ -class PaymentRequest { - /** - * Return payment request JSON object - * @param {Object} paymentRequest - payment params - * @param {UserSchema} userData - user's data - * @param {String} orderId - unique order identifier - */ - static generatePaymentObject(paymentRequest, userData) { - return { - Amount: paymentRequest.amount, - OrderId: paymentRequest.orderId, - Recurrent: paymentRequest.recurrent, - Language: paymentRequest.language, - CustomerKey: userData.id, - Description: PaymentDescription, - Receipt: { - Email: userData.email, - EmailCompany, - Taxation: OSNTaxation, - Items: [ { - Name: 'Deposit', - Price: paymentRequest.amount, - Quantity: 1, - Amount: paymentRequest.amount, - Tax: TaxNone, - } ], - }, - PayType: 'T', - DATA: paymentRequest.data, - }; - } - - /** - * Generate unique payment Id - * @return {string} - */ - static generateOrderId() { - return crypto.randomBytes(8).toString('hex'); - } - - /** - * Create new payment - * @param {String} userId - user's id - * @param {Object} paymentQuery - payment query params - * @returns {Object} - payment object - */ - static async create(userId, paymentQuery) { - const userData = await User.findById(userId); - const paymentObject = PaymentRequest.generatePaymentObject(paymentQuery, userData); - - console.log('INIT =>', paymentObject); - - return paymentObject; - } - - /** - * Run API Init action - * @param {String} userId - user's id - * @param {Object} paymentInitQuery - payment params - * @return {Object} - payment response object from bank - */ - static async apiInitPayment(userId, paymentInitQuery) { - // const paymentRequest = await PaymentRequest.create(userId, paymentInitQuery); - const result = {}; // Init payment request to API - - console.log(`Got result for Init payment: ${JSON.stringify(result)}`); - if (!result.Success) { - throw Error(`Merchant API error: ${result.Message} ${result.Details}`); - } - - return result; - } -} - -module.exports = PaymentRequest; diff --git a/src/models/paymentTransaction.js b/src/models/paymentTransaction.js deleted file mode 100644 index fbf4ff42..00000000 --- a/src/models/paymentTransaction.js +++ /dev/null @@ -1,55 +0,0 @@ -const mongo = require('../mongo'); -const Model = require('./model'); - -/** - * @typedef {Object} PaymentTransaction - * @property {string} id - transaction unique id - * @property {string} userId - user id - * @property {string} workspaceId - workspace id - * @property {number} amount - payment amount in kopecs - * @property {string} orderId - order id (local) - * @property {string} paymentId - payment id (Tinkoff side) - * @property {number} timestamp - create timestamp - */ - -/** - * PaymentTransaction model - */ -class PaymentTransaction extends Model { - /** - * Creates PaymentTransaction instance - * @param {PaymentTransaction} transactionData - transaction data - */ - constructor(transactionData) { - super(); - this.id = transactionData.id; - this.userId = transactionData.userId; - this.workspaceId = transactionData.workspaceId; - this.amount = transactionData.amount; - this.orderId = transactionData.orderId; - this.paymentId = transactionData.paymentId; - this.paymentType = transactionData.paymentType; - this.timestamp = transactionData.timestamp; - this.status = transactionData.status; - this.cardId = transactionData.cardId; - } - - /** - * Model's collection - * @return {Collection} - */ - static get collection() { - return mongo.databases.hawk.collection('paymentTransactions'); - } - - /** - * Creates new payment transaction - * @param {PaymentTransaction} transactionData - transaction data - * @returns {Promise} - created transaction - */ - static async create(transactionData) { - return new PaymentTransaction(transactionData); - } -} - -module.exports = PaymentTransaction; diff --git a/src/models/project.ts b/src/models/project.ts index d6b7350a..ad82451c 100644 --- a/src/models/project.ts +++ b/src/models/project.ts @@ -393,11 +393,11 @@ export default class ProjectModel extends AbstractModel impleme }, }, { - returnOriginal: false, + returnDocument: 'after', } ); - return result.value?.notifications.find(doc => doc._id.toString() === payload.ruleId) || null; + return result?.notifications.find((doc: any) => doc._id.toString() === payload.ruleId) || null; } /** @@ -417,10 +417,10 @@ export default class ProjectModel extends AbstractModel impleme }, }, { - returnOriginal: false, + returnDocument: 'after', }); - return result.value?.notifications.find(doc => doc._id.toString() === ruleId) || null; + return result?.notifications.find((doc: any) => doc._id.toString() === ruleId) || null; } /** @@ -456,11 +456,11 @@ export default class ProjectModel extends AbstractModel impleme }, }, { - returnOriginal: false, + returnDocument: 'after', } ); - return result.value?.notifications.find(doc => doc._id.toString() === ruleId) || null; + return result?.notifications.find((doc) => doc._id.toString() === ruleId) || null; } /** @@ -476,16 +476,16 @@ export default class ProjectModel extends AbstractModel impleme { $set: projectData, }, - { returnOriginal: false } + { returnDocument: 'after' } ); } catch (e) { throw new Error('Can\'t update project'); } - if (!result.value) { + if (!result) { throw new Error('There is no project with provided id'); } - return result.value; + return result; } /** diff --git a/src/models/projectToWorkspace.js b/src/models/projectToWorkspace.js index 02e2384d..a51ba738 100644 --- a/src/models/projectToWorkspace.js +++ b/src/models/projectToWorkspace.js @@ -1,10 +1,10 @@ const mongo = require('../mongo'); -const { ObjectID } = require('mongodb'); +const { ObjectId } = require('mongodb'); /** * @typedef {Object} ProjectToWorkspaceSchema - * @property {string|ObjectID} id - ProjectWorkspace ID - * @property {string|ObjectID} projectId - project ID + * @property {string|ObjectId} id - ProjectWorkspace ID + * @property {string|ObjectId} projectId - project ID * @property {string} [projectUri] - project unique URI */ @@ -15,10 +15,10 @@ const { ObjectID } = require('mongodb'); class ProjectToWorkspace { /** * Creates an instance of ProjectToWorkspace - * @param {string|ObjectID} workspaceId + * @param {string|ObjectId} workspaceId */ constructor(workspaceId) { - this.workspaceId = new ObjectID(workspaceId); + this.workspaceId = new ObjectId(workspaceId); this.collection = mongo.databases.hawk.collection( 'projects:' + workspaceId ); @@ -47,12 +47,12 @@ class ProjectToWorkspace { /** * Find projectWorkspace by ID * - * @param {string|ObjectID} projectWorkspaceId + * @param {string|ObjectId} projectWorkspaceId * @returns {Promise} */ async findById(projectWorkspaceId) { const projectWorkspace = await this.collection.findOne({ - _id: new ObjectID(projectWorkspaceId), + _id: new ObjectId(projectWorkspaceId), }); if (!projectWorkspace) { @@ -68,24 +68,19 @@ class ProjectToWorkspace { /** * Creates new projects: document * - * @param {{projectId: ObjectID}} projectToWorkspaceData - * @returns {Promise} + * @param {{projectId: ObjectId}} projectToWorkspaceData + * @returns {Promise} */ async add(projectToWorkspaceData) { - const projectToWorkspace = await this.collection.insertOne( - projectToWorkspaceData - ); + const projectToWorkspaceResult = await this.collection.insertOne(projectToWorkspaceData); - return { - id: projectToWorkspace.insertedId, - ...projectToWorkspace, - }; + return projectToWorkspaceResult.acknowledged; } /** * Remove project from workspace * - * @param {ObjectID} projectId - project Id for removing + * @param {ObjectId} projectId - project Id for removing * * @return {Promise} */ @@ -97,11 +92,11 @@ class ProjectToWorkspace { * Gets projects in workspace. * If ids were not passed, returns all projects in workspace. * - * @param {string[]|ObjectID[]} ids - project(s) id(s) + * @param {string[]|ObjectId[]} ids - project(s) id(s) * @returns {ProjectSchema[]} */ async getProjects(ids = []) { - ids = ids.map(id => new ObjectID(id)); + ids = ids.map(id => new ObjectId(id)); const pipleine = [ { diff --git a/src/models/user.ts b/src/models/user.ts index 45fc6c17..d22549a5 100644 --- a/src/models/user.ts +++ b/src/models/user.ts @@ -1,8 +1,7 @@ import argon2 from 'argon2'; import crypto from 'crypto'; import jwt, { Secret } from 'jsonwebtoken'; -import { OptionalId } from '../mongo'; -import { Collection, ObjectId } from 'mongodb'; +import { Collection, ObjectId, OptionalId } from 'mongodb'; import AbstractModel from './abstractModel'; import objectHasOnlyProps from '../utils/objectHasOnlyProps'; import { NotificationsChannelsDBScheme } from '../types/notification-channels'; @@ -80,7 +79,7 @@ type UserProjectsLastVisitDBScheme = Record; /** * User model */ -export default class UserModel extends AbstractModel implements UserDBScheme { +export default class UserModel extends AbstractModel> implements UserDBScheme { /** * User's id */ @@ -145,13 +144,13 @@ export default class UserModel extends AbstractModel implements Us /** * Model's collection */ - protected collection: Collection; + protected collection: Collection>; /** * Model constructor * @param modelData - user data */ - constructor(modelData: UserDBScheme) { + constructor(modelData: OptionalId) { /** * Fallback for name using email */ @@ -161,7 +160,7 @@ export default class UserModel extends AbstractModel implements Us super(modelData); - this.collection = this.dbConnection.collection('users'); + this.collection = this.dbConnection.collection('users'); } /** @@ -374,6 +373,7 @@ export default class UserModel extends AbstractModel implements Us if (!this.workspaces) { return []; } + return Object.keys(this.workspaces); } diff --git a/src/models/userCard.js b/src/models/userCard.js deleted file mode 100644 index 09ba2249..00000000 --- a/src/models/userCard.js +++ /dev/null @@ -1,85 +0,0 @@ -const mongo = require('../mongo'); -const Model = require('./model'); -const { ObjectID } = require('mongodb'); - -/** - * @typedef {Object} UserCardSchema - * @property {string} userId - user's id - * @property {string} pan - card's pan - * @property {Number} rebillId - card's rebill id for recurrent payments - * @property {string} expDate - card's expiration date - */ - -/** - * UserCard model - */ -class UserCard extends Model { - /** - * Creates userCard instance - * @param {UserSchema} userCardData - user's card data - */ - constructor(userCardData) { - super(); - this.userId = userCardData.userId; - this.pan = userCardData.pan; - this.rebillId = userCardData.rebillId; - this.cardId = userCardData.cardId; - this.expDate = userCardData.expDate; - } - - /** - * Model's collection - * @return {Collection} - */ - static get collection() { - return mongo.databases.hawk.collection('userCards'); - } - - /** - * Get all user's cards - * @param {string} userId - user's id - * @return {Promise} - */ - static async findByUserId(userId) { - return (await this.collection.find({ userId: new ObjectID(userId) })).toArray(); - } - - /** - * Get card info - * @param {string} userId - user's id - * @param {Number} cardId - card's id - * @return {Promise} - */ - static async find(userId, cardId) { - return this.collection.findOne({ - userId: new ObjectID(userId), - cardId, - }); - } - - /** - * Creates new UserCard in DB - * @param {UserCardSchema} userCardData - user's card data - * @returns {Promise} - user details - */ - static async create(userCardData) { - await this.collection.insertOne(userCardData); - - return new UserCard(userCardData); - } - - /** - * Remove UserCard from DB - * @param {Number} cardNumber - user's card number - * @param {string} userId - user's ID - * @returns {Promise} - remove result - */ - static async remove({ cardNumber, userId }) { - return this.collection.deleteOne({ - cardNumber, - userId, - }); - } -} - -module.exports = UserCard; diff --git a/src/models/usersFactory.ts b/src/models/usersFactory.ts index f3c6ff70..0c25979e 100644 --- a/src/models/usersFactory.ts +++ b/src/models/usersFactory.ts @@ -1,6 +1,6 @@ import AbstractModelFactory from './abstactModelFactory'; import UserModel from './user'; -import { Collection, Db } from 'mongodb'; +import { Collection, Db, OptionalId } from 'mongodb'; import DataLoaders from '../dataLoaders'; import { UserDBScheme } from '@hawk.so/types'; import { Analytics, AnalyticsEventTypes } from '../utils/analytics'; @@ -8,11 +8,11 @@ import { Analytics, AnalyticsEventTypes } from '../utils/analytics'; /** * Users factory to work with User Model */ -export default class UsersFactory extends AbstractModelFactory { +export default class UsersFactory extends AbstractModelFactory, UserModel> { /** * DataBase collection to work with */ - protected collection: Collection; + protected collection: Collection>; /** * DataLoaders for fetching data from database @@ -72,7 +72,7 @@ export default class UsersFactory extends AbstractModelFactory = { + const userData: OptionalId = { email, password: hashedPassword, notifications: UserModel.generateDefaultNotificationsSettings(email), @@ -121,7 +121,7 @@ export default class UsersFactory extends AbstractModelFactory { - const { result } = await this.collection.deleteOne({ email: email }); + const result = await this.collection.deleteOne({ email: email }); - return !!result.ok; + return result.acknowledged; } } diff --git a/src/models/workspace.ts b/src/models/workspace.ts index 2e6886a6..72bc2e6a 100644 --- a/src/models/workspace.ts +++ b/src/models/workspace.ts @@ -5,6 +5,11 @@ import UserModel from './user'; import { ConfirmedMemberDBScheme, MemberDBScheme, PendingMemberDBScheme, WorkspaceDBScheme } from '@hawk.so/types'; import crypto from 'crypto'; +/** + * Used for inserts into team collection which should not have '_id' field + */ +type MemberDBSchemeWithoutId = Omit | Omit; + /** * Workspace model */ @@ -46,6 +51,7 @@ export default class WorkspaceModel extends AbstractModel imp /** * Workspace balance + * @deprecated NOT USED */ public balance!: number; @@ -84,7 +90,7 @@ export default class WorkspaceModel extends AbstractModel imp /** * Collection with information about team for workspace */ - protected teamCollection: Collection; + protected teamCollection: Collection; /** * Creates Workspace instance @@ -94,7 +100,7 @@ export default class WorkspaceModel extends AbstractModel imp constructor(workspaceData: WorkspaceDBScheme) { super(workspaceData); this.collection = this.dbConnection.collection('workspaces'); - this.teamCollection = this.dbConnection.collection('team:' + this._id.toString()); + this.teamCollection = this.dbConnection.collection('team:' + this._id.toString()); } /** @@ -103,7 +109,7 @@ export default class WorkspaceModel extends AbstractModel imp public static generateInviteHash(): string { return crypto .createHash('sha256') - .update(crypto.randomBytes(256)) + .update(crypto.randomBytes(256).toString('hex')) .digest('hex'); } diff --git a/src/mongo.ts b/src/mongo.ts index 43b4d202..06d39ee6 100644 --- a/src/mongo.ts +++ b/src/mongo.ts @@ -54,10 +54,11 @@ export const mongoClients: MongoClients = { /** * Common params for all connections */ -const connectionConfig: MongoClientOptions = withMongoMetrics({ - useNewUrlParser: true, - useUnifiedTopology: true, -}); +/** + * Common params for all connections + * Note: useNewUrlParser and useUnifiedTopology are deprecated in mongodb 6.x and removed + */ +const connectionConfig: MongoClientOptions = withMongoMetrics({}); /** * Setups connections to the databases (hawk api and events databases) diff --git a/src/resolvers/billing.js b/src/resolvers/billing.js deleted file mode 100644 index 00c3e109..00000000 --- a/src/resolvers/billing.js +++ /dev/null @@ -1,75 +0,0 @@ -const PaymentRequest = require('../models/paymentRequest'); -const UserCard = require('../models/userCard'); -const rabbitmq = require('../rabbitmq'); -const PaymentTransaction = require('../models/paymentTransaction'); - -/** - * @typedef {Object} PaymentQuery - * @property {Number} amount - total payment amount in kopecs - * @property {string} workspaceId - workspace identifier - * @property {string} cardId - card identifier from bank - */ - -/** - * @typedef {Object} PaymentLink - * @property {Number} amount - total payment amount in kopecs - * @property {string} status - payment status - * @property {string} success - if the payment is successfull - * @property {string} paymentURL - URL to the payment page - */ - -/** - * See all types and fields here {@link ../typeDefs/billing.graphql} - */ -module.exports = { - Mutation: { - /** - * API Mutation method for card detach - * @param {ResolverObj} _obj - * @param {Number} cardId - card's identifier - * @param {Object} user - current user object - * @return {Promise} - */ - async removeCard(_obj, { cardId }, { user }) { - return (await UserCard.remove({ - cardId, - userId: user.id, - })).deletedCount === 1; - }, - - /** - * Mutation for getting payment link - * @param {ResolverObj} _obj - * @param {string} language - * @param {Object} user - current user object - * @return {Promise} - */ - async attachCard(_obj, { language }, { user }) { - const orderId = PaymentRequest.generateOrderId(); - const result = await PaymentRequest.apiInitPayment(user.id, { - recurrent: 'Y', - language: language || 'en', - data: { - UserId: user.id, - }, - amount: 100, - orderId: orderId, - }); - const transaction = await PaymentTransaction.create({ - userId: user.id, - amount: result.Amount, - orderId: orderId, - paymentId: result.PaymentId, - status: result.Status, - timestamp: parseInt((Date.now() / 1000).toFixed(0)), - }); - - await rabbitmq.publish('merchant', 'merchant/initialized', JSON.stringify({ - paymentURL: result.PaymentURL, - ...transaction, - })); - - return result; - }, - }, -}; diff --git a/src/resolvers/event.js b/src/resolvers/event.js index 08aee5c7..c3c44971 100644 --- a/src/resolvers/event.js +++ b/src/resolvers/event.js @@ -131,9 +131,9 @@ module.exports = { async visitEvent(_obj, { projectId, eventId }, { user, ...context }) { const factory = getEventsFactory(context, projectId); - const { result } = await factory.visitEvent(eventId, user.id); + const result = await factory.visitEvent(eventId, user.id); - return !!result.ok; + return !!result.acknowledged; }, /** @@ -148,9 +148,9 @@ module.exports = { async toggleEventMark(_obj, { project, eventId, mark }, context) { const factory = getEventsFactory(context, project); - const { result } = await factory.toggleEventMark(eventId, mark); + const result = await factory.toggleEventMark(eventId, mark); - return !!result.ok; + return !!result.acknowledged; }, /** @@ -192,7 +192,7 @@ module.exports = { }; } - const { result } = await factory.updateAssignee(eventId, assignee); + const result = await factory.updateAssignee(eventId, assignee); const assigneeData = await factories.usersFactory.dataLoaders.userById.load(assignee); @@ -207,7 +207,7 @@ module.exports = { }); return { - success: !!result.ok, + success: !!result.acknowledged, record: assigneeData, }; }, @@ -224,10 +224,10 @@ module.exports = { const { projectId, eventId } = input; const factory = getEventsFactory(context, projectId); - const { result } = await factory.updateAssignee(eventId, ''); + const result = await factory.updateAssignee(eventId, ''); return { - success: !!result.ok, + success: !!result.acknowledged, }; }, }, diff --git a/test/integration/api.env b/test/integration/api.env index 8598b55f..1c068643 100644 --- a/test/integration/api.env +++ b/test/integration/api.env @@ -53,10 +53,6 @@ SMTP_SENDER_ADDRESS= # AMQP URL AMQP_URL=amqp://guest:guest@rabbitmq:5672/ -# Billing settings -BILLING_DEBUG=true -BILLING_COMPANY_EMAIL="team@hawk.so" - ### Accounting module ### # Accounting service URL CODEX_ACCOUNTING_URL=http://accounting:3999/graphql diff --git a/test/integration/cases/billing/check.test.ts b/test/integration/cases/billing/check.test.ts index 2af26fcd..ad199354 100644 --- a/test/integration/cases/billing/check.test.ts +++ b/test/integration/cases/billing/check.test.ts @@ -20,8 +20,8 @@ describe('Check webhook', () => { let businessOperationsCollection: Collection; let workspacesCollection: Collection; - let plans: Collection; - let users: Collection; + let plans: Collection>; + let users: Collection>; let workspace: WorkspaceDBScheme; let externalUser: UserDBScheme; @@ -33,48 +33,77 @@ describe('Check webhook', () => { accountsDb = await global.mongoClient.db('hawk'); workspacesCollection = await accountsDb.collection('workspaces'); - users = await accountsDb.collection('users'); - plans = await accountsDb.collection('plans'); + users = await accountsDb.collection>('users'); + plans = await accountsDb.collection>('plans'); businessOperationsCollection = await accountsDb.collection('businessOperations'); }); beforeEach(async () => { - const currentPlan = (await plans.insertOne({ + const currentPlanId = (await plans.insertOne({ name: 'CurrentTestPlan', monthlyCharge: 10, monthlyChargeCurrency: 'USD', eventsLimit: 1000, isDefault: false, - })).ops[0]; + })).insertedId; + const currentPlan = await plans.findOne({ _id: currentPlanId }); + if (!currentPlan) { + throw new Error('Failed to create currentPlan'); + } - workspace = (await workspacesCollection.insertOne({ + const workspaceId = (await workspacesCollection.insertOne({ name: 'BillingTest', accountId: '123', tariffPlanId: currentPlan._id, - } as WorkspaceDBScheme)).ops[0]; - - externalUser = (await users.insertOne({ + } as WorkspaceDBScheme)).insertedId; + const workspaceResult = await workspacesCollection.findOne({ _id: workspaceId }); + if (!workspaceResult) { + throw new Error('Failed to create workspace'); + } + workspace = workspaceResult as WorkspaceDBScheme; + + const externalUserId = (await users.insertOne({ email: 'user@billing.test', - })).ops[0]; - - member = (await users.insertOne({ + })).insertedId; + const externalUserResult = await users.findOne({ _id: externalUserId }); + if (!externalUserResult) { + throw new Error('Failed to create externalUser'); + } + externalUser = externalUserResult as UserDBScheme; + + const memberId = (await users.insertOne({ email: 'member@billing.test', - })).ops[0]; - - admin = (await users.insertOne({ + })).insertedId; + const memberResult = await users.findOne({ _id: memberId }); + if (!memberResult) { + throw new Error('Failed to create member'); + } + member = memberResult as UserDBScheme; + + const adminId = (await users.insertOne({ email: 'admin@billing.test', - })).ops[0]; - - planToChange = (await plans.insertOne({ + })).insertedId; + const adminResult = await users.findOne({ _id: adminId }); + if (!adminResult) { + throw new Error('Failed to create admin'); + } + admin = adminResult as UserDBScheme; + + const planToChangeId = (await plans.insertOne({ name: 'BasicTest', monthlyCharge: 20, monthlyChargeCurrency: 'USD', eventsLimit: 10000, isDefault: false, - })).ops[0]; - - const team = await accountsDb.collection(`team:${workspace._id.toString()}`); + })).insertedId; + const planToChangeResult = await plans.findOne({ _id: planToChangeId }); + if (!planToChangeResult) { + throw new Error('Failed to create planToChange'); + } + planToChange = planToChangeResult as PlanDBScheme; + + const team = await accountsDb.collection>(`team:${workspace._id.toString()}`); await team.insertOne({ userId: member._id, diff --git a/test/setup.ts b/test/setup.ts new file mode 100644 index 00000000..7e4a13a0 --- /dev/null +++ b/test/setup.ts @@ -0,0 +1,12 @@ +/** + * Jest setup file to provide global APIs needed by MongoDB driver + */ + +import { performance } from 'perf_hooks'; + +/** + * MongoDB 6.x requires global performance API + * Node.js provides it via perf_hooks module + */ +global.performance = performance as any; + diff --git a/yarn.lock b/yarn.lock index 0782faeb..63f57b57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -560,6 +560,13 @@ slash "^3.0.0" strip-ansi "^6.0.0" +"@jest/create-cache-key-function@^30.0.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-30.2.0.tgz#86dbaf8cce43e8a0266180a5236b6f0b3be9d09b" + integrity sha512-44F4l4Enf+MirJN8X/NhdGkl71k5rBYiwdVlo4HxOwbu0sHV8QKrGEedb1VUU4K3W7fBKE0HGfbn7eZm0Ti3zg== + dependencies: + "@jest/types" "30.2.0" + "@jest/environment@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" @@ -591,6 +598,14 @@ "@jest/types" "^26.6.2" expect "^26.6.2" +"@jest/pattern@30.0.1": + version "30.0.1" + resolved "https://registry.yarnpkg.com/@jest/pattern/-/pattern-30.0.1.tgz#d5304147f49a052900b4b853dedb111d080e199f" + integrity sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA== + dependencies: + "@types/node" "*" + jest-regex-util "30.0.1" + "@jest/reporters@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" @@ -623,6 +638,13 @@ optionalDependencies: node-notifier "^8.0.0" +"@jest/schemas@30.0.5": + version "30.0.5" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-30.0.5.tgz#7bdf69fc5a368a5abdb49fd91036c55225846473" + integrity sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA== + dependencies: + "@sinclair/typebox" "^0.34.0" + "@jest/source-map@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" @@ -674,6 +696,19 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" +"@jest/types@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-30.2.0.tgz#1c678a7924b8f59eafd4c77d56b6d0ba976d62b8" + integrity sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg== + dependencies: + "@jest/pattern" "30.0.1" + "@jest/schemas" "30.0.5" + "@types/istanbul-lib-coverage" "^2.0.6" + "@types/istanbul-reports" "^3.0.4" + "@types/node" "*" + "@types/yargs" "^17.0.33" + chalk "^4.1.2" + "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" @@ -753,6 +788,13 @@ semver "^7.3.5" tar "^6.1.11" +"@mongodb-js/saslprep@^1.3.0": + version "1.4.4" + resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.4.4.tgz#34a946ff6ae142e8f2259b87f2935f8284ba874d" + integrity sha512-p7X/ytJDIdwUfFL/CLOhKgdfJe1Fa8uw9seJYvdOmnP9JBWGWHW69HkOixXS6Wy9yvGf1MbhcS6lVmrhy4jm2g== + dependencies: + sparse-bitfield "^3.0.3" + "@n1ru4l/json-patch-plus@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@n1ru4l/json-patch-plus/-/json-patch-plus-0.2.0.tgz#b8fa09fd980c3460dfdc109a7c4cc5590157aa6b" @@ -855,14 +897,19 @@ resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.1.0.tgz#cba454c05ec201bd5547aaf55286d44682ac8eb5" integrity sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g== -"@shelf/jest-mongodb@^1.2.2": - version "1.3.4" - resolved "https://registry.yarnpkg.com/@shelf/jest-mongodb/-/jest-mongodb-1.3.4.tgz#200bac386cf513bed2d41952b1857689f0b88f31" - integrity sha512-PQe/5jN8wHr30d8422+2CV+XzbJTCFLGxzb0OrwbxrRiNdZA+FFXOqVak1vd3dqk4qogmmqEVQFkwQ4PNHzNgA== +"@shelf/jest-mongodb@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@shelf/jest-mongodb/-/jest-mongodb-6.0.2.tgz#4a78de55120071b1cbf57cd9f153b1501ecb2586" + integrity sha512-lULA6h73jdKjUwVDQu6r0qzQ8mgLGsBAXdqgNZoAQiEpKcom+RuyDbbMfmn4b5aqImUKnc7wC/AbYpGjdMEX0Q== dependencies: - debug "4.3.2" - mongodb-memory-server "6.9.6" - uuid "8.3.2" + "@swc/jest" "0.2.39" + debug "4.4.1" + mongodb-memory-server "10.3.0" + +"@sinclair/typebox@^0.34.0": + version "0.34.41" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.41.tgz#aa51a6c1946df2c5a11494a2cdb9318e026db16c" + integrity sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g== "@sinonjs/commons@^1.7.0": version "1.8.3" @@ -883,6 +930,96 @@ resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c" integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA== +"@swc/core-darwin-arm64@1.15.7": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.7.tgz#b7ac4660d2d4df324f4f5a6f58a0c3d44d71ff1c" + integrity sha512-+hNVUfezUid7LeSHqnhoC6Gh3BROABxjlDNInuZ/fie1RUxaEX4qzDwdTgozJELgHhvYxyPIg1ro8ibnKtgO4g== + +"@swc/core-darwin-x64@1.15.7": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.15.7.tgz#4500d361b389459e32a5acacf89426d4865761c2" + integrity sha512-ZAFuvtSYZTuXPcrhanaD5eyp27H8LlDzx2NAeVyH0FchYcuXf0h5/k3GL9ZU6Jw9eQ63R1E8KBgpXEJlgRwZUQ== + +"@swc/core-linux-arm-gnueabihf@1.15.7": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.7.tgz#2f7a8dcdf1880a03f38f0a4a2814a254bdf07684" + integrity sha512-K3HTYocpqnOw8KcD8SBFxiDHjIma7G/X+bLdfWqf+qzETNBrzOub/IEkq9UaeupaJiZJkPptr/2EhEXXWryS/A== + +"@swc/core-linux-arm64-gnu@1.15.7": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.7.tgz#dba63e6a5ae6139588312049f1897208c2d94c14" + integrity sha512-HCnVIlsLnCtQ3uXcXgWrvQ6SAraskLA9QJo9ykTnqTH6TvUYqEta+TdTdGjzngD6TOE7XjlAiUs/RBtU8Z0t+Q== + +"@swc/core-linux-arm64-musl@1.15.7": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.7.tgz#f23572b6d2f6d18e691111f1f238d32861e22528" + integrity sha512-/OOp9UZBg4v2q9+x/U21Jtld0Wb8ghzBScwhscI7YvoSh4E8RALaJ1msV8V8AKkBkZH7FUAFB7Vbv0oVzZsezA== + +"@swc/core-linux-x64-gnu@1.15.7": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.7.tgz#7efa998cb3199f282583f5055ae3396daba0ba81" + integrity sha512-VBbs4gtD4XQxrHuQ2/2+TDZpPQQgrOHYRnS6SyJW+dw0Nj/OomRqH+n5Z4e/TgKRRbieufipeIGvADYC/90PYQ== + +"@swc/core-linux-x64-musl@1.15.7": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.7.tgz#d5c88a8c367baf9f6b4215e8f6c9eae680451087" + integrity sha512-kVuy2unodso6p0rMauS2zby8/bhzoGRYxBDyD6i2tls/fEYAE74oP0VPFzxIyHaIjK1SN6u5TgvV9MpyJ5xVug== + +"@swc/core-win32-arm64-msvc@1.15.7": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.7.tgz#08e175725f0796337e3299b94b701ebb7bfdc14f" + integrity sha512-uddYoo5Xmo1XKLhAnh4NBIyy5d0xk33x1sX3nIJboFySLNz878ksCFCZ3IBqrt1Za0gaoIWoOSSSk0eNhAc/sw== + +"@swc/core-win32-ia32-msvc@1.15.7": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.7.tgz#6ad4aeff1bd39f0482e905719f8390d53b072854" + integrity sha512-rqq8JjNMLx3QNlh0aPTtN/4+BGLEHC94rj9mkH1stoNRf3ra6IksNHMHy+V1HUqElEgcZyx+0yeXx3eLOTcoFw== + +"@swc/core-win32-x64-msvc@1.15.7": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.7.tgz#52f7d558144cee9a3cc43ba7e6bd8b83a8acae77" + integrity sha512-4BK06EGdPnuplgcNhmSbOIiLdRgHYX3v1nl4HXo5uo4GZMfllXaCyBUes+0ePRfwbn9OFgVhCWPcYYjMT6hycQ== + +"@swc/core@^1.3.0": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.15.7.tgz#630a90c5801c7ed3dfd25d94da6b1eab22e52971" + integrity sha512-kTGB8XI7P+pTKW83tnUEDVP4zduF951u3UAOn5eTi0vyW6MvL56A3+ggMdfuVFtDI0/DsbSzf5z34HVBbuScWw== + dependencies: + "@swc/counter" "^0.1.3" + "@swc/types" "^0.1.25" + optionalDependencies: + "@swc/core-darwin-arm64" "1.15.7" + "@swc/core-darwin-x64" "1.15.7" + "@swc/core-linux-arm-gnueabihf" "1.15.7" + "@swc/core-linux-arm64-gnu" "1.15.7" + "@swc/core-linux-arm64-musl" "1.15.7" + "@swc/core-linux-x64-gnu" "1.15.7" + "@swc/core-linux-x64-musl" "1.15.7" + "@swc/core-win32-arm64-msvc" "1.15.7" + "@swc/core-win32-ia32-msvc" "1.15.7" + "@swc/core-win32-x64-msvc" "1.15.7" + +"@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/jest@0.2.39": + version "0.2.39" + resolved "https://registry.yarnpkg.com/@swc/jest/-/jest-0.2.39.tgz#482bee0adb0726fab1487a4f902a278ec563a6b7" + integrity sha512-eyokjOwYd0Q8RnMHri+8/FS1HIrIUKK/sRrFp8c1dThUOfNeCWbLmBP1P5VsKdvmkd25JaH+OKYwEYiAYg9YAA== + dependencies: + "@jest/create-cache-key-function" "^30.0.0" + "@swc/counter" "^0.1.3" + jsonc-parser "^3.2.0" + +"@swc/types@^0.1.25": + version "0.1.25" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.25.tgz#b517b2a60feb37dd933e542d93093719e4cf1078" + integrity sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g== + dependencies: + "@swc/counter" "^0.1.3" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -976,7 +1113,7 @@ "@types/connect" "*" "@types/node" "*" -"@types/bson@*", "@types/bson@^4.0.5": +"@types/bson@*": version "4.2.0" resolved "https://registry.yarnpkg.com/@types/bson/-/bson-4.2.0.tgz#a2f71e933ff54b2c3bf267b67fa221e295a33337" integrity sha512-ELCPqAdroMdcuxqwMgUpifQyRoTpyYCNr1V9xKyF40VsBobsj+BbWNRvwGchMgBPGqkw655ypkjj2MEF5ywVwg== @@ -1094,6 +1231,11 @@ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== +"@types/istanbul-lib-coverage@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + "@types/istanbul-lib-report@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" @@ -1108,6 +1250,13 @@ dependencies: "@types/istanbul-lib-report" "*" +"@types/istanbul-reports@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/jest@^26.0.8": version "26.0.24" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a" @@ -1193,7 +1342,7 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.0.tgz#e9a9903894405c6a6551f1774df4e64d9804d69c" integrity sha512-fccbsHKqFDXClBZTDLA43zl0+TbxyIwyzIzwwhvoJvhNjOErCdeX2xJbURimv2EbSVUGav001PaCJg4mZxMl4w== -"@types/mongodb@^3.5.34", "@types/mongodb@^3.6.20": +"@types/mongodb@^3.5.34": version "3.6.20" resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-3.6.20.tgz#b7c5c580644f6364002b649af1c06c3c0454e1d2" integrity sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ== @@ -1314,6 +1463,18 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== +"@types/webidl-conversions@*": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz#1306dbfa53768bcbcfc95a1c8cde367975581859" + integrity sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA== + +"@types/whatwg-url@^11.0.2": + version "11.0.5" + resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-11.0.5.tgz#aaa2546e60f0c99209ca13360c32c78caf2c409f" + integrity sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ== + dependencies: + "@types/webidl-conversions" "*" + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -1326,6 +1487,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yargs@^17.0.33": + version "17.0.35" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.35.tgz#07013e46aa4d7d7d50a49e15604c1c5340d4eb24" + integrity sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg== + dependencies: + "@types/yargs-parser" "*" + "@typescript-eslint/eslint-plugin@^2.12.0": version "2.34.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9" @@ -1432,6 +1600,11 @@ agent-base@6: dependencies: debug "4" +agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== + ai@^5.0.89: version "5.0.89" resolved "https://registry.yarnpkg.com/ai/-/ai-5.0.89.tgz#8929fbc18f247aa9e4442836a12aa84191edf2a4" @@ -1704,6 +1877,13 @@ async-mutex@^0.3.0: dependencies: tslib "^2.3.1" +async-mutex@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.5.0.tgz#353c69a0b9e75250971a64ac203b0ebfddd75482" + integrity sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA== + dependencies: + tslib "^2.4.0" + async-retry@^1.2.1: version "1.3.3" resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" @@ -1769,6 +1949,11 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" +b4a@^1.6.4: + version "1.7.3" + resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.7.3.tgz#24cf7ccda28f5465b66aec2bac69e32809bf112f" + integrity sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q== + babel-jest@^26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" @@ -1835,6 +2020,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +bare-events@^2.7.0: + version "2.8.2" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.8.2.tgz#7b3e10bd8e1fc80daf38bb516921678f566ab89f" + integrity sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ== + base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -1979,17 +2169,10 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -bson@*, bson@^4.6.5: - version "4.6.5" - resolved "https://registry.yarnpkg.com/bson/-/bson-4.6.5.tgz#1a410148c20eef4e40d484878a037a7036e840fb" - integrity sha512-uqrgcjyOaZsHfz7ea8zLRCLe1u+QGUSzMZmvXqO24CDW7DWoW1qiN9folSwa7hSneTSgM2ykDIzF5kcQQ8cwNw== - dependencies: - buffer "^5.6.0" - -bson@^1.1.4: - version "1.1.6" - resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.6.tgz#fb819be9a60cd677e0853aee4ca712a785d6618a" - integrity sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg== +bson@*, bson@^1.1.4, bson@^6.10.4, bson@^6.7.0: + version "6.10.4" + resolved "https://registry.yarnpkg.com/bson/-/bson-6.10.4.tgz#d530733bb5bb16fb25c162e01a3344fab332fd2b" + integrity sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng== buffer-crc32@~0.2.3: version "0.2.13" @@ -2020,7 +2203,7 @@ buffer@4.9.2: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.5.0, buffer@^5.6.0: +buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2089,7 +2272,7 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0, camelcase@^6.1.0: +camelcase@^6.0.0, camelcase@^6.1.0, camelcase@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -2115,7 +2298,7 @@ chalk@^2.0.0, chalk@^2.1.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2396,15 +2579,6 @@ cross-spawn@^7.0.0: shebang-command "^2.0.0" which "^2.0.1" -cross-spawn@^7.0.3: - version "7.0.6" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" - integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - cssfilter@0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" @@ -2460,12 +2634,12 @@ debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "2.1.2" -debug@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== +debug@4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== dependencies: - ms "2.1.2" + ms "^2.1.3" debug@^3.2.7: version "3.2.7" @@ -2481,6 +2655,13 @@ debug@^4.2.0: dependencies: ms "^2.1.3" +debug@^4.3.4, debug@^4.4.3: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -3007,6 +3188,13 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +events-universal@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/events-universal/-/events-universal-1.0.1.tgz#b56a84fd611b6610e0a2d0f09f80fdf931e2dfe6" + integrity sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw== + dependencies: + bare-events "^2.7.0" + events@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -3160,6 +3348,11 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-fifo@^1.2.0, fast-fifo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== + fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -3228,7 +3421,7 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" -find-cache-dir@^3.3.1: +find-cache-dir@^3.3.1, find-cache-dir@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== @@ -3286,6 +3479,11 @@ follow-redirects@^1.14.0, follow-redirects@^1.14.9: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== +follow-redirects@^1.15.11: + version "1.15.11" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340" + integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== + for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -3725,6 +3923,14 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +https-proxy-agent@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== + dependencies: + agent-base "^7.1.2" + debug "4" + human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -4382,6 +4588,11 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== +jest-regex-util@30.0.1: + version "30.0.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-30.0.1.tgz#f17c1de3958b67dfe485354f5a10093298f2a49b" + integrity sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA== + jest-regex-util@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" @@ -4642,6 +4853,11 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" +jsonc-parser@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.3.1.tgz#f2a524b4f7fd11e3d791e559977ad60b98b798b4" + integrity sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ== + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -4756,13 +4972,6 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lockfile@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609" - integrity sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA== - dependencies: - signal-exit "^3.0.2" - lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -5021,6 +5230,32 @@ mkdirp@^0.5.1: dependencies: minimist "^1.2.6" +mongodb-connection-string-url@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz#e223089dfa0a5fa9bf505f8aedcbc67b077b33e7" + integrity sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA== + dependencies: + "@types/whatwg-url" "^11.0.2" + whatwg-url "^14.1.0 || ^13.0.0" + +mongodb-memory-server-core@10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/mongodb-memory-server-core/-/mongodb-memory-server-core-10.3.0.tgz#4d7aace17395525e899d5d57477339fe3b693a86" + integrity sha512-tp+ZfTBAPqHXjROhAFg6HcVVzXaEhh/iHcbY7QPOIiLwr94OkBFAw4pixyGSfP5wI2SZeEA13lXyRmBAhugWgA== + dependencies: + async-mutex "^0.5.0" + camelcase "^6.3.0" + debug "^4.4.3" + find-cache-dir "^3.3.2" + follow-redirects "^1.15.11" + https-proxy-agent "^7.0.6" + mongodb "^6.9.0" + new-find-package-json "^2.0.0" + semver "^7.7.3" + tar-stream "^3.1.7" + tslib "^2.8.1" + yauzl "^3.2.0" + mongodb-memory-server-core@6.10.0: version "6.10.0" resolved "https://registry.yarnpkg.com/mongodb-memory-server-core/-/mongodb-memory-server-core-6.10.0.tgz#9239c7941e5b0a225b50494563f0fc528c056690" @@ -5044,36 +5279,13 @@ mongodb-memory-server-core@6.10.0: uuid "^8.3.1" yauzl "^2.10.0" -mongodb-memory-server-core@6.9.6: - version "6.9.6" - resolved "https://registry.yarnpkg.com/mongodb-memory-server-core/-/mongodb-memory-server-core-6.9.6.tgz#90ef0562bea675ef68bd687533792da02bcc81f3" - integrity sha512-ZcXHTI2TccH3L5N9JyAMGm8bbAsfLn8SUWOeYGHx/vDx7vu4qshyaNXTIxeHjpUQA29N+Z1LtTXA6vXjl1eg6w== - dependencies: - "@types/tmp" "^0.2.0" - camelcase "^6.0.0" - cross-spawn "^7.0.3" - debug "^4.2.0" - find-cache-dir "^3.3.1" - find-package-json "^1.2.0" - get-port "^5.1.1" - https-proxy-agent "^5.0.0" - lockfile "^1.0.4" - md5-file "^5.0.0" - mkdirp "^1.0.4" - semver "^7.3.2" - tar-stream "^2.1.4" - tmp "^0.2.1" - uuid "^8.3.0" - yauzl "^2.10.0" - optionalDependencies: - mongodb "^3.6.2" - -mongodb-memory-server@6.9.6: - version "6.9.6" - resolved "https://registry.yarnpkg.com/mongodb-memory-server/-/mongodb-memory-server-6.9.6.tgz#ced1a100f58363317a562efaf8821726c433cfd2" - integrity sha512-BjGPPh5f61lMueG7px9DneBIrRR/GoWUHDvLWVAXhQhKVcwMMXxgeEba6zdDolZHfYAu6aYGPzhOuYKIKPgpBQ== +mongodb-memory-server@10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/mongodb-memory-server/-/mongodb-memory-server-10.3.0.tgz#c8496c73ea73c8d87fe168b3c8b89434c2fb43b8" + integrity sha512-dRNr2uEhMgjEe6kgqS+ITBKBbl2cz0DNBjNZ12BGUckvEOAHbhd3R7q/lFPSZrZ6AMKa2EOUJdAmFF1WlqSbsA== dependencies: - mongodb-memory-server-core "6.9.6" + mongodb-memory-server-core "10.3.0" + tslib "^2.8.1" mongodb-memory-server@^6.6.1: version "6.10.0" @@ -5096,7 +5308,7 @@ mongodb@3.5.9: optionalDependencies: saslprep "^1.0.0" -mongodb@^3.6.2, mongodb@^3.6.9: +mongodb@^3.6.9: version "3.7.4" resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.7.4.tgz#119530d826361c3e12ac409b769796d6977037a4" integrity sha512-K5q8aBqEXMwWdVNh94UQTwZ6BejVbFhh1uB6c5FKtPE9eUMZPUO3sRZdgIEcHSrAWmxzpG/FeODDKL388sqRmw== @@ -5109,18 +5321,14 @@ mongodb@^3.6.2, mongodb@^3.6.9: optionalDependencies: saslprep "^1.0.0" -mongodb@^3.7.3: - version "3.7.3" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.7.3.tgz#b7949cfd0adc4cc7d32d3f2034214d4475f175a5" - integrity sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw== +mongodb@^6.0.0, mongodb@^6.9.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.21.0.tgz#f83355905900f2e7a912593f0315d5e2e0bda576" + integrity sha512-URyb/VXMjJ4da46OeSXg+puO39XH9DeQpWCslifrRn9JWugy0D+DvvBvkm2WxmHe61O/H19JM66p1z7RHVkZ6A== dependencies: - bl "^2.2.1" - bson "^1.1.4" - denque "^1.4.1" - optional-require "^1.1.8" - safe-buffer "^5.1.2" - optionalDependencies: - saslprep "^1.0.0" + "@mongodb-js/saslprep" "^1.3.0" + bson "^6.10.4" + mongodb-connection-string-url "^3.0.2" morgan@^1.10.1: version "1.10.1" @@ -5180,6 +5388,13 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +new-find-package-json@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/new-find-package-json/-/new-find-package-json-2.0.0.tgz#96553638781db35061f351e8ccb4d07126b6407d" + integrity sha512-lDcBsjBSMlj3LXH2v/FW3txlh2pYTjmbOXPYJD93HI5EwuLzI11tdHSIpUMmfq/IOsldj4Ps8M8flhm+pCK4Ew== + dependencies: + debug "^4.3.4" + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -5689,6 +5904,11 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + qs@6.10.3: version "6.10.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" @@ -6086,6 +6306,11 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.7.3: + version "7.7.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== + semver@~7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" @@ -6406,6 +6631,15 @@ streamsearch@0.1.2: resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" integrity sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA== +streamx@^2.15.0: + version "2.23.0" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.23.0.tgz#7d0f3d00d4a6c5de5728aecd6422b4008d66fd0b" + integrity sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg== + dependencies: + events-universal "^1.0.0" + fast-fifo "^1.3.2" + text-decoder "^1.1.0" + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -6566,6 +6800,15 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" +tar-stream@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" + integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== + dependencies: + b4a "^1.6.4" + fast-fifo "^1.2.0" + streamx "^2.15.0" + tar@^6.1.11: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" @@ -6602,6 +6845,13 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-decoder@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65" + integrity sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA== + dependencies: + b4a "^1.6.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -6699,6 +6949,13 @@ tr46@^2.1.0: dependencies: punycode "^2.1.1" +tr46@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.1.1.tgz#96ae867cddb8fdb64a49cc3059a8d428bcf238ca" + integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw== + dependencies: + punycode "^2.3.1" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -6790,7 +7047,7 @@ tslib@^2.1.0, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== -tslib@^2.3.0, tslib@^2.3.1: +tslib@^2.3.0, tslib@^2.3.1, tslib@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -6980,7 +7237,7 @@ uuid@8.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== -uuid@8.3.2, uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.1, uuid@^8.3.2: +uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.1, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -7058,6 +7315,11 @@ webidl-conversions@^6.1.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" @@ -7075,6 +7337,14 @@ whatwg-mimetype@^3.0.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== +"whatwg-url@^14.1.0 || ^13.0.0": + version "14.2.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.2.0.tgz#4ee02d5d725155dae004f6ae95c73e7ef5d95663" + integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw== + dependencies: + tr46 "^5.1.0" + webidl-conversions "^7.0.0" + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -7266,6 +7536,14 @@ yauzl@^2.10.0: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" +yauzl@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-3.2.0.tgz#7b6cb548f09a48a6177ea0be8ece48deb7da45c0" + integrity sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w== + dependencies: + buffer-crc32 "~0.2.3" + pend "~1.2.0" + yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"